Toggle navigation
Toggle navigation
This project
Loading...
Sign in
jiujian
/
client-customer-order-api
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
zhuyifan
2025-11-17 11:10:41 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
a3002524f9413c4bd4eb398c2ec114ece373fd5e
a3002524
1 parent
e63c3acb
feat(order): add support for partial order refund and not serve status
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
324 additions
and
308 deletions
src/main/java/com/infoloop/tianting/controller/PayController.java
src/main/java/com/infoloop/tianting/model/dto/PayDTO.java
src/main/java/com/infoloop/tianting/service/client/OrderServiceRpcClient.java
src/main/java/com/infoloop/tianting/service/client/PayServiceClient.java
src/main/java/com/infoloop/tianting/controller/PayController.java
View file @
a300252
...
...
@@ -60,4 +60,5 @@ public class PayController {
public
String
cancel
(
@Valid
@RequestBody
PayDTO
.
PayRefundRequestDto
payRefundRequestDto
)
{
return
payServiceClient
.
orderPayRefund
(
payRefundRequestDto
);
}
}
\ No newline at end of file
...
...
src/main/java/com/infoloop/tianting/model/dto/PayDTO.java
View file @
a300252
...
...
@@ -9,6 +9,8 @@ import lombok.Builder;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.List
;
@Data
@ApiModel
(
description
=
"支付DTO"
)
public
class
PayDTO
{
...
...
@@ -31,6 +33,7 @@ public class PayDTO {
@AllArgsConstructor
public
static
class
PayRefundRequestDto
{
private
Integer
orderId
;
private
List
<
Integer
>
orderDetailIds
;
private
String
hospitalCode
;
}
...
...
src/main/java/com/infoloop/tianting/service/client/OrderServiceRpcClient.java
View file @
a300252
...
...
@@ -240,6 +240,7 @@ public class OrderServiceRpcClient {
final
var
operator
=
operatorServiceRpcClient
.
getCOperatorById
(
operatorLoginInfo
.
getId
());
final
var
idsOfNeedUpdateMenuDetails
=
new
ArrayList
<
Integer
>();
final
var
idsOfAddCount
=
new
ArrayList
<
Integer
>();
final
var
idsOfNoReject
=
new
ArrayList
<
Integer
>();
List
<
OrderDetailDto
>
originalOrderDetails
=
new
ArrayList
<>();
List
<
OrderDetailDto
>
newOrderDetails
;
final
var
modifications
=
orderDetailBatchUpdateDto
.
getDetails
().
stream
().
map
(
d
->
{
...
...
@@ -280,9 +281,11 @@ public class OrderServiceRpcClient {
.
build
();
}
}
ServeStatusEnum
serveStatus
=
ServeStatusEnum
.
UNKNOWN_SERVE_STATUS
;
if
(
d
.
getShouldUpdateServeStatus
())
{
if
(
d
.
getServeStatus
()
==
ServeStatusEnum
.
SERVE_REJECT
)
{
idsOfNoReject
.
add
(
d
.
getId
());
}
serveStatus
=
d
.
getServeStatus
();
}
Integer
count
=
0
;
...
...
@@ -319,7 +322,8 @@ public class OrderServiceRpcClient {
.
build
();
final
var
totalIds
=
new
ArrayList
<>(
idsOfNeedUpdateMenuDetails
);
totalIds
.
addAll
(
idsOfAddCount
);
if
(!
idsOfNeedUpdateMenuDetails
.
isEmpty
()
||
!
idsOfAddCount
.
isEmpty
())
{
totalIds
.
addAll
(
idsOfNoReject
);
if
(!
totalIds
.
isEmpty
())
{
final
var
orgionalResponseList
=
getClientCustomerOrderDetailsByIds
(
totalIds
);
originalOrderDetails
=
orgionalResponseList
.
stream
().
map
(
d
->
OrderDetailDto
.
builder
()
.
id
(
d
.
getId
())
...
...
@@ -357,7 +361,7 @@ public class OrderServiceRpcClient {
}
final
var
res
=
orderServiceRpcBlockingStub
.
batchUpdateClientCustomerOrderDetails
(
request
);
if
(
res
.
getIsUpdated
())
{
if
(!
idsOfNeedUpdateMenuDetails
.
isEmpty
()
||
!
idsOfAddCount
.
isEmpty
())
{
if
(!
totalIds
.
isEmpty
())
{
final
var
newResponseList
=
getClientCustomerOrderDetailsByIds
(
totalIds
);
newOrderDetails
=
newResponseList
.
stream
().
map
(
d
->
OrderDetailDto
.
builder
()
...
...
@@ -396,7 +400,7 @@ public class OrderServiceRpcClient {
// 替换菜品的操作记录
List
<
SingleOperationDto
>
operations
=
new
ArrayList
<>();
for
(
OrderDetailDto
originalDetail
:
originalOrderDetails
)
{
if
(!
idsOfNeedUpdateMenuDetails
.
contains
(
originalDetail
.
getId
())
&&
!
idsOfAddCount
.
contains
(
originalDetail
.
getId
()))
{
if
(!
totalIds
.
contains
(
originalDetail
.
getId
()))
{
continue
;
}
OrderOperationType
orderOperationType
=
OrderOperationType
.
UNKNOWN_OPERATION_TYPE
;
...
...
@@ -404,6 +408,8 @@ public class OrderServiceRpcClient {
orderOperationType
=
OrderOperationType
.
REPLACE_DISHES
;
}
else
if
(
idsOfAddCount
.
contains
(
originalDetail
.
getId
()))
{
orderOperationType
=
OrderOperationType
.
ADD_DISHES
;
}
else
if
(
idsOfNoReject
.
contains
(
originalDetail
.
getId
()))
{
orderOperationType
=
OrderOperationType
.
NOT_SERVE
;
}
String
originalDetailStr
;
String
newDetailStr
=
""
;
...
...
src/main/java/com/infoloop/tianting/service/client/PayServiceClient.java
View file @
a300252
...
...
@@ -38,6 +38,7 @@ import lombok.RequiredArgsConstructor;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
...
...
@@ -66,333 +67,338 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
(
onConstructor
=
@__
(
@Autowired
))
public
class
PayServiceClient
{
private
final
RestTemplate
restTemplate
;
private
final
RestTemplate
restTemplate
;
private
final
BusinessConfig
businessConfig
;
private
final
BusinessConfig
businessConfig
;
private
final
OrderServiceRpcClient
orderServiceRpcClient
;
private
final
OrderServiceRpcClient
orderServiceRpcClient
;
private
final
ClientResourceTagServiceRpcClient
clientResourceTagServiceRpcClient
;
private
final
ClientResourceTagServiceRpcClient
clientResourceTagServiceRpcClient
;
private
final
EnterpriseResourceServiceRpcClient
enterpriseResourceServiceRpcClient
;
private
final
EnterpriseResourceServiceRpcClient
enterpriseResourceServiceRpcClient
;
private
final
XmlMapper
xmlMapper
=
new
XmlMapper
();
private
final
XmlMapper
xmlMapper
=
new
XmlMapper
();
public
PayResponseDto
payInform
(
PayInformRequestDto
payRequestDto
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
Integer
.
valueOf
(
payRequestDto
.
getOrderId
()));
if
(
orderById
==
null
||
orderById
.
getPayStatus
()
==
PayStatusEnum
.
PAY_CANCELED
||
orderById
.
getStatus
()
==
OrderStatusEnum
.
ORDER_CANCELED
)
{
log
.
info
(
"Order {} not found or canceled, skipping."
,
payRequestDto
.
getOrderId
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_CANCEL
);
}
String
url
=
MessageFormat
.
format
(
businessConfig
.
getPayUrl
(),
businessConfig
.
getPayClientId
());
String
requestDate
=
DateUtil
.
formatDate
(
LocalDateTime
.
now
(),
DateUtil
.
YMDHMS
);
ThirdPartyPayInformRequestDto
jsonData
=
buildRequestData
(
payRequestDto
,
requestDate
);
String
jsonDataString
;
try
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
objectMapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
objectMapper
.
setSerializationInclusion
(
JsonInclude
.
Include
.
NON_NULL
);
objectMapper
.
setPropertyNamingStrategy
(
new
PropertyNamingStrategies
.
UpperCamelCaseStrategy
());
jsonDataString
=
objectMapper
.
writeValueAsString
(
jsonData
);
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to serialize request data"
,
e
);
throw
new
IllegalArgumentException
(
"支付信息获取失败: JSON 解析错误"
);
public
PayResponseDto
payInform
(
PayInformRequestDto
payRequestDto
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
Integer
.
valueOf
(
payRequestDto
.
getOrderId
()));
if
(
orderById
==
null
||
orderById
.
getPayStatus
()
==
PayStatusEnum
.
PAY_CANCELED
||
orderById
.
getStatus
()
==
OrderStatusEnum
.
ORDER_CANCELED
)
{
log
.
info
(
"Order {} not found or canceled, skipping."
,
payRequestDto
.
getOrderId
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_CANCEL
);
}
String
url
=
MessageFormat
.
format
(
businessConfig
.
getPayUrl
(),
businessConfig
.
getPayClientId
());
String
requestDate
=
DateUtil
.
formatDate
(
LocalDateTime
.
now
(),
DateUtil
.
YMDHMS
);
ThirdPartyPayInformRequestDto
jsonData
=
buildRequestData
(
payRequestDto
,
requestDate
);
String
jsonDataString
;
try
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
objectMapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
objectMapper
.
setSerializationInclusion
(
JsonInclude
.
Include
.
NON_NULL
);
objectMapper
.
setPropertyNamingStrategy
(
new
PropertyNamingStrategies
.
UpperCamelCaseStrategy
());
jsonDataString
=
objectMapper
.
writeValueAsString
(
jsonData
);
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to serialize request data"
,
e
);
throw
new
IllegalArgumentException
(
"支付信息获取失败: JSON 解析错误"
);
}
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
jsonDataString
,
createHeaders
());
log
.
info
(
"payInform request: {}"
,
jsonDataString
);
ResponseEntity
<
String
>
responseEntity
=
restTemplate
.
exchange
(
url
,
HttpMethod
.
POST
,
requestEntity
,
String
.
class
);
return
processResponse
(
responseEntity
);
}
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
jsonDataString
,
createHeaders
());
log
.
info
(
"payInform request: {}"
,
jsonDataString
);
ResponseEntity
<
String
>
responseEntity
=
restTemplate
.
exchange
(
url
,
HttpMethod
.
POST
,
requestEntity
,
String
.
class
);
return
processResponse
(
responseEntity
);
}
private
ThirdPartyPayInformRequestDto
buildRequestData
(
PayInformRequestDto
payRequestDto
,
String
requestDate
)
{
ThirdPartyPayInformRequestDto
jsonData
=
new
ThirdPartyPayInformRequestDto
();
jsonData
.
setClientId
(
businessConfig
.
getPayClientId
());
jsonData
.
setTradeId
(
payRequestDto
.
getOrderId
());
jsonData
.
setRequestDate
(
requestDate
);
jsonData
.
setRequestSource
(
"OFWXApplet"
);
jsonData
.
setPayerOpenId
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setHospitalCode
(
payRequestDto
.
getHospitalCode
());
jsonData
.
setPID
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setRemark
(
""
);
jsonData
.
setTransAmount
(
payRequestDto
.
getPrice
());
jsonData
.
setTradeDesc
(
""
);
jsonData
.
setSign
(
EncryptionUtil
.
sha1Encryption
(
businessConfig
.
getPayClientId
()
+
payRequestDto
.
getOrderId
()
+
requestDate
+
businessConfig
.
getPayClientId
()));
return
jsonData
;
}
private
HttpHeaders
createHeaders
()
{
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
return
headers
;
}
private
PayResponseDto
processResponse
(
ResponseEntity
<
String
>
responseEntity
)
{
if
(!
responseEntity
.
getStatusCode
().
is2xxSuccessful
()
||
responseEntity
.
getBody
()
==
null
)
{
log
.
error
(
"payInform failed with response: {}"
,
responseEntity
.
getBody
());
throw
new
IllegalArgumentException
(
"支付信息获取失败"
);
}
try
{
log
.
info
(
"processResponse response: {}"
,
responseEntity
.
getBody
());
return
xmlMapper
.
readValue
(
responseEntity
.
getBody
(),
PayResponseDto
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Failed to parse XML response"
,
e
);
throw
new
RuntimeException
(
"支付信息结果解析失败"
,
e
);
private
ThirdPartyPayInformRequestDto
buildRequestData
(
PayInformRequestDto
payRequestDto
,
String
requestDate
)
{
ThirdPartyPayInformRequestDto
jsonData
=
new
ThirdPartyPayInformRequestDto
();
jsonData
.
setClientId
(
businessConfig
.
getPayClientId
());
jsonData
.
setTradeId
(
payRequestDto
.
getOrderId
());
jsonData
.
setRequestDate
(
requestDate
);
jsonData
.
setRequestSource
(
"OFWXApplet"
);
jsonData
.
setPayerOpenId
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setHospitalCode
(
payRequestDto
.
getHospitalCode
());
jsonData
.
setPID
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setRemark
(
""
);
jsonData
.
setTransAmount
(
payRequestDto
.
getPrice
());
jsonData
.
setTradeDesc
(
""
);
jsonData
.
setSign
(
EncryptionUtil
.
sha1Encryption
(
businessConfig
.
getPayClientId
()
+
payRequestDto
.
getOrderId
()
+
requestDate
+
businessConfig
.
getPayClientId
()));
return
jsonData
;
}
}
public
boolean
callback
(
PaymentCallbackDTO
paymentCallbackDTO
)
{
log
.
info
(
"callback request received: {}"
,
paymentCallbackDTO
);
try
{
final
var
paymentCallbackResult
=
xmlMapper
.
readValue
(
paymentCallbackDTO
.
getPayResult
(),
PaymentCallbackResult
.
class
);
log
.
info
(
"Parsed paymentCallbackResult: {}"
,
paymentCallbackResult
);
final
var
orderId
=
Integer
.
parseInt
(
paymentCallbackResult
.
getTradeId
());
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
return
false
;
}
log
.
info
(
"Order callback, orderId: {}"
,
orderId
);
private
HttpHeaders
createHeaders
()
{
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
return
headers
;
}
final
var
transType
=
paymentCallbackResult
.
getTransType
();
if
(
transType
.
equals
(
"00"
))
{
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
&&
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
IN_PROGRESS
)
{
log
.
error
(
"Order status is not TO_PAY or IN_PROGRESS, orderId: {}"
,
orderId
);
return
true
;
private
PayResponseDto
processResponse
(
ResponseEntity
<
String
>
responseEntity
)
{
if
(!
responseEntity
.
getStatusCode
().
is2xxSuccessful
()
||
responseEntity
.
getBody
()
==
null
)
{
log
.
error
(
"payInform failed with response: {}"
,
responseEntity
.
getBody
());
throw
new
IllegalArgumentException
(
"支付信息获取失败"
);
}
long
payTime
;
try
{
payTime
=
DateUtil
.
parseDate
(
paymentCallbackResult
.
getTransDate
(),
"yyyyMMddHHmmss"
).
getTime
(
);
}
catch
(
Parse
Exception
e
)
{
log
.
error
(
"Failed to parse TransDate: {}"
,
paymentCallbackResult
.
getTransDate
()
,
e
);
throw
new
IllegalArgumentException
(
"支付时间格式错误: "
+
paymentCallbackResult
.
getTransDate
()
,
e
);
log
.
info
(
"processResponse response: {}"
,
responseEntity
.
getBody
());
return
xmlMapper
.
readValue
(
responseEntity
.
getBody
(),
PayResponseDto
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Failed to parse XML response"
,
e
);
throw
new
RuntimeException
(
"支付信息结果解析失败"
,
e
);
}
BigDecimal
realAmount
;
}
public
boolean
callback
(
PaymentCallbackDTO
paymentCallbackDTO
)
{
log
.
info
(
"callback request received: {}"
,
paymentCallbackDTO
);
try
{
realAmount
=
Convert
.
toBigDecimal
(
paymentCallbackResult
.
getRealAmount
());
if
(
realAmount
==
null
)
{
throw
new
NumberFormatException
(
"RealAmount is null or empty"
);
}
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"Invalid RealAmount value: {}"
,
paymentCallbackResult
.
getRealAmount
(),
e
);
throw
new
IllegalArgumentException
(
"支付金额错误: "
+
paymentCallbackResult
.
getRealAmount
(),
e
);
}
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayTime
(
true
)
.
setPayTime
(
payTime
)
.
setShouldUpdatePayPrice
(
true
)
.
setPayPrice
(
realAmount
.
multiply
(
new
BigDecimal
(
"100"
)).
intValue
())
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
SUCCEED
)
.
setShouldUpdateStatus
(
true
)
.
setStatus
(
OrderStatusEnum
.
PREPARING
)
.
setShouldUpdateTransactionId
(
true
)
.
setTransactionId
(
paymentCallbackResult
.
getTradeReferenceNo
())
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"callback updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
if
(
updateResponse
.
getIsUpdated
())
{
String
createdAt
=
Instant
.
ofEpochMilli
(
orderById
.
getCreatedAt
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
String
payTimed
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
final
var
orderPaymentSuccessData
=
OrderPaymentSuccessData
.
builder
()
.
orderId
(
orderById
.
getId
())
.
orderCode
(
orderById
.
getOrderCode
())
.
createTime
(
createdAt
)
.
payTime
(
payTimed
)
.
build
();
final
var
data
=
SocketMessage
.<
OrderPaymentSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
)
.
subject
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
.
getDescription
())
.
message
(
"您的订单:"
+
orderById
.
getOrderCode
()
+
" 支付成功啦,快去查看吧~"
)
.
data
(
orderPaymentSuccessData
)
.
build
();
WebSocketServer
.
sendMessageToUser
(
UserSessionKey
.
builder
()
.
userId
(
orderById
.
getOpenId
())
.
userType
(
UserTypeEnum
.
MICRO
)
.
build
(),
data
);
if
(
LocalDate
.
now
().
equals
(
DateUtil
.
toLocalDate
(
orderById
.
getMealTime
())))
{
final
var
orderCreateSuccessData
=
OrderCreateSuccessData
.
builder
().
orderId
(
orderById
.
getId
()).
build
();
final
var
createOrderData
=
SocketMessage
.<
OrderCreateSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_CREATED
)
.
subject
(
NoticeTypeEnum
.
ORDER_CREATED
.
getDescription
())
.
message
(
"有新的订单下单成功啦,快去查看吧~"
)
.
data
(
orderCreateSuccessData
)
.
build
();
final
var
clientOperatorIds
=
clientResourceTagServiceRpcClient
.
getOperatorIdsByStallIds
(
List
.
of
(
orderById
.
getStallId
())).
stream
()
.
map
(
SingleResourceLabelEntityRefsResponse:
:
getEntityId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
final
var
enterpriseOperatorIds
=
enterpriseResourceServiceRpcClient
.
getOperatorIdsByStallId
(
orderById
.
getEnterpriseId
(),
orderById
.
getStallId
());
final
var
userAuthData
=
new
ArrayList
<
UserAuthData
>();
userAuthData
.
addAll
(
clientOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
()
.
operatorId
(
e
)
.
userType
(
UserTypeEnum
.
CLIENT
)
.
build
())
.
collect
(
Collectors
.
toList
()));
userAuthData
.
addAll
(
enterpriseOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
().
operatorId
(
e
).
userType
(
UserTypeEnum
.
KDS
).
build
())
.
collect
(
Collectors
.
toList
()));
log
.
info
(
"received userAuthData:{}"
,
JsonUtil
.
writeAsJson
(
userAuthData
));
try
{
WebSocketServer
.
sendMessageByUserTypes
(
List
.
of
(
UserTypeEnum
.
CLIENT
,
UserTypeEnum
.
KDS
),
userAuthData
,
createOrderData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"Failed to send message to user"
,
e
);
final
var
paymentCallbackResult
=
xmlMapper
.
readValue
(
paymentCallbackDTO
.
getPayResult
(),
PaymentCallbackResult
.
class
);
log
.
info
(
"Parsed paymentCallbackResult: {}"
,
paymentCallbackResult
);
final
var
orderId
=
Integer
.
parseInt
(
paymentCallbackResult
.
getTradeId
());
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
return
false
;
}
}
log
.
info
(
"Order callback, orderId: {}"
,
orderId
);
final
var
transType
=
paymentCallbackResult
.
getTransType
();
if
(
transType
.
equals
(
"00"
))
{
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
&&
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
IN_PROGRESS
)
{
log
.
error
(
"Order status is not TO_PAY or IN_PROGRESS, orderId: {}"
,
orderId
);
return
true
;
}
long
payTime
;
try
{
payTime
=
DateUtil
.
parseDate
(
paymentCallbackResult
.
getTransDate
(),
"yyyyMMddHHmmss"
).
getTime
();
}
catch
(
ParseException
e
)
{
log
.
error
(
"Failed to parse TransDate: {}"
,
paymentCallbackResult
.
getTransDate
(),
e
);
throw
new
IllegalArgumentException
(
"支付时间格式错误: "
+
paymentCallbackResult
.
getTransDate
(),
e
);
}
BigDecimal
realAmount
;
try
{
realAmount
=
Convert
.
toBigDecimal
(
paymentCallbackResult
.
getRealAmount
());
if
(
realAmount
==
null
)
{
throw
new
NumberFormatException
(
"RealAmount is null or empty"
);
}
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"Invalid RealAmount value: {}"
,
paymentCallbackResult
.
getRealAmount
(),
e
);
throw
new
IllegalArgumentException
(
"支付金额错误: "
+
paymentCallbackResult
.
getRealAmount
(),
e
);
}
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayTime
(
true
)
.
setPayTime
(
payTime
)
.
setShouldUpdatePayPrice
(
true
)
.
setPayPrice
(
realAmount
.
multiply
(
new
BigDecimal
(
"100"
)).
intValue
())
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
SUCCEED
)
.
setShouldUpdateStatus
(
true
)
.
setStatus
(
OrderStatusEnum
.
PREPARING
)
.
setShouldUpdateTransactionId
(
true
)
.
setTransactionId
(
paymentCallbackResult
.
getTradeReferenceNo
())
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"callback updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
if
(
updateResponse
.
getIsUpdated
())
{
String
createdAt
=
Instant
.
ofEpochMilli
(
orderById
.
getCreatedAt
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
String
payTimed
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
final
var
orderPaymentSuccessData
=
OrderPaymentSuccessData
.
builder
()
.
orderId
(
orderById
.
getId
())
.
orderCode
(
orderById
.
getOrderCode
())
.
createTime
(
createdAt
)
.
payTime
(
payTimed
)
.
build
();
final
var
data
=
SocketMessage
.<
OrderPaymentSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
)
.
subject
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
.
getDescription
())
.
message
(
"您的订单:"
+
orderById
.
getOrderCode
()
+
" 支付成功啦,快去查看吧~"
)
.
data
(
orderPaymentSuccessData
)
.
build
();
WebSocketServer
.
sendMessageToUser
(
UserSessionKey
.
builder
()
.
userId
(
orderById
.
getOpenId
())
.
userType
(
UserTypeEnum
.
MICRO
)
.
build
(),
data
);
if
(
LocalDate
.
now
().
equals
(
DateUtil
.
toLocalDate
(
orderById
.
getMealTime
())))
{
final
var
orderCreateSuccessData
=
OrderCreateSuccessData
.
builder
().
orderId
(
orderById
.
getId
()).
build
();
final
var
createOrderData
=
SocketMessage
.<
OrderCreateSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_CREATED
)
.
subject
(
NoticeTypeEnum
.
ORDER_CREATED
.
getDescription
())
.
message
(
"有新的订单下单成功啦,快去查看吧~"
)
.
data
(
orderCreateSuccessData
)
.
build
();
final
var
clientOperatorIds
=
clientResourceTagServiceRpcClient
.
getOperatorIdsByStallIds
(
List
.
of
(
orderById
.
getStallId
())).
stream
()
.
map
(
SingleResourceLabelEntityRefsResponse:
:
getEntityId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
final
var
enterpriseOperatorIds
=
enterpriseResourceServiceRpcClient
.
getOperatorIdsByStallId
(
orderById
.
getEnterpriseId
(),
orderById
.
getStallId
());
final
var
userAuthData
=
new
ArrayList
<
UserAuthData
>();
userAuthData
.
addAll
(
clientOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
()
.
operatorId
(
e
)
.
userType
(
UserTypeEnum
.
CLIENT
)
.
build
())
.
collect
(
Collectors
.
toList
()));
userAuthData
.
addAll
(
enterpriseOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
().
operatorId
(
e
).
userType
(
UserTypeEnum
.
KDS
).
build
())
.
collect
(
Collectors
.
toList
()));
log
.
info
(
"received userAuthData:{}"
,
JsonUtil
.
writeAsJson
(
userAuthData
));
try
{
WebSocketServer
.
sendMessageByUserTypes
(
List
.
of
(
UserTypeEnum
.
CLIENT
,
UserTypeEnum
.
KDS
),
userAuthData
,
createOrderData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"Failed to send message to user"
,
e
);
}
}
}
return
updateResponse
.
getIsUpdated
();
}
else
{
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
REFUND
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"callback updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
return
updateResponse
.
getIsUpdated
();
}
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to parse XML response, raw XML: {}"
,
paymentCallbackDTO
.
getPayResult
(),
e
);
throw
new
RuntimeException
(
"支付/退款通知结果解析失败"
,
e
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Unexpected error in callback, request: {}"
,
paymentCallbackDTO
,
e
);
throw
new
RuntimeException
(
"支付/退款通知处理失败"
,
e
);
}
}
public
boolean
waiting
(
Integer
orderId
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"waiting Order not found, orderId: {}"
,
orderId
);
return
false
;
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
)
{
log
.
info
(
"waiting Order {} already processed, skipping."
,
orderId
);
return
false
;
}
return
updateResponse
.
getIsUpdated
();
}
else
{
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
REFUND
)
.
build
();
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
IN_PROGRESS
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"
callback
updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"
waiting
updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
return
updateResponse
.
getIsUpdated
();
}
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to parse XML response, raw XML: {}"
,
paymentCallbackDTO
.
getPayResult
(),
e
);
throw
new
RuntimeException
(
"支付/退款通知结果解析失败"
,
e
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Unexpected error in callback, request: {}"
,
paymentCallbackDTO
,
e
);
throw
new
RuntimeException
(
"支付/退款通知处理失败"
,
e
);
}
}
public
boolean
waiting
(
Integer
orderId
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"waiting Order not found, orderId: {}"
,
orderId
);
return
false
;
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
)
{
log
.
info
(
"waiting Order {} already processed, skipping."
,
orderId
);
return
false
;
}
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
IN_PROGRESS
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"waiting updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
return
updateResponse
.
getIsUpdated
();
}
public
String
orderPayRefund
(
PayRefundRequestDto
payRefundRequestDto
)
{
Integer
orderId
=
payRefundRequestDto
.
getOrderId
();
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_FOUND
);
}
if
(
orderById
.
getOnlinePay
()
!=
OnlinePayEnum
.
ONLINE
)
{
log
.
info
(
"Order {} is not online pay."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_ONLINE_PAY
);
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
SUCCEED
)
{
log
.
info
(
"Order {} pay is not succeed."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_SUCCESS
);
}
LocalDate
today
=
LocalDate
.
now
();
LocalDate
tomorrow
=
today
.
plusDays
(
1
);
LocalDateTime
tomorrowZero
=
tomorrow
.
atStartOfDay
();
LocalDateTime
orderPayTime
=
DateUtil
.
toLocalDateTime
(
orderById
.
getPayTime
()).
minusHours
(
8
);
if
(!
orderPayTime
.
isBefore
(
tomorrowZero
))
{
log
.
info
(
"Order {} pay is beyond cancel time."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
}
public
String
orderPayRefund
(
PayRefundRequestDto
payRefundRequestDto
)
{
Integer
orderId
=
payRefundRequestDto
.
getOrderId
();
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_FOUND
);
}
if
(
orderById
.
getOnlinePay
()
!=
OnlinePayEnum
.
ONLINE
)
{
log
.
info
(
"Order {} is not online pay."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_ONLINE_PAY
);
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
SUCCEED
)
{
log
.
info
(
"Order {} pay is not succeed."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_SUCCESS
);
}
LocalDate
today
=
LocalDate
.
now
();
LocalDate
tomorrow
=
today
.
plusDays
(
1
);
LocalDateTime
tomorrowZero
=
tomorrow
.
atStartOfDay
();
LocalDateTime
orderPayTime
=
DateUtil
.
toLocalDateTime
(
orderById
.
getPayTime
()).
minusHours
(
8
);
if
(!
orderPayTime
.
isBefore
(
tomorrowZero
))
{
log
.
info
(
"Order {} pay is beyond cancel time."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
}
BigDecimal
detailPrice
=
BigDecimal
.
ZERO
;
if
(
CollectionUtils
.
isNotEmpty
(
payRefundRequestDto
.
getOrderDetailIds
()))
{
final
var
orderDetails
=
orderServiceRpcClient
.
getClientCustomerOrderDetailsByIds
(
payRefundRequestDto
.
getOrderDetailIds
());
detailPrice
=
orderDetails
.
stream
().
filter
(
e
->
e
.
getPrice
()
>
0
).
map
(
e
->
new
BigDecimal
(
e
.
getPrice
()).
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
)).
reduce
(
BigDecimal
.
ZERO
,
BigDecimal:
:
add
);
}
String
appId
=
businessConfig
.
getPayClientId
();
String
appId
=
businessConfig
.
getPayClientId
();
// 构建paycontent
String
payTime
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
YMDHMS
);
// 构建paycontent
String
payTime
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
YMDHMS
);
BigDecimal
price
=
new
BigDecimal
(
orderById
.
getPayPrice
()
)
.
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
)
.
negate
();
BigDecimal
price
=
detailPrice
.
compareTo
(
BigDecimal
.
ZERO
)
==
0
?
new
BigDecimal
(
orderById
.
getPayPrice
()).
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
).
negate
(
)
:
detailPrice
.
negate
();
String
payContentStr
=
orderById
.
getId
()
+
"^"
+
"01"
+
"^"
+
"^"
+
orderById
.
getOpenId
()
+
"^"
+
orderById
.
getOrderCode
()
+
"^"
+
price
+
"^"
+
payTime
+
"^"
+
orderById
.
getTransactionId
()
+
"^"
+
payRefundRequestDto
.
getHospitalCode
()
+
"^"
+
"^"
+
LoginContextHolder
.
getId
()
+
"^"
+
LoginContextHolder
.
getName
();
String
payContent
=
URLEncoder
.
encode
(
Base64
.
encodeBase64String
(
payContentStr
.
getBytes
()),
StandardCharsets
.
UTF_8
);
String
payContentStr
=
orderById
.
getId
()
+
"^"
+
"01"
+
"^"
+
"^"
+
orderById
.
getOpenId
()
+
"^"
+
orderById
.
getOrderCode
()
+
"^"
+
price
+
"^"
+
payTime
+
"^"
+
orderById
.
getTransactionId
()
+
"^"
+
payRefundRequestDto
.
getHospitalCode
()
+
"^"
+
"^"
+
LoginContextHolder
.
getId
()
+
"^"
+
LoginContextHolder
.
getName
();
String
payContent
=
URLEncoder
.
encode
(
Base64
.
encodeBase64String
(
payContentStr
.
getBytes
()),
StandardCharsets
.
UTF_8
);
// 构建signinfo
String
signInfoStr
=
appId
+
orderById
.
getId
()
+
payTime
+
businessConfig
.
getRefundSecurityKey
();
String
signInfo
=
DigestUtils
.
sha1Hex
(
signInfoStr
.
getBytes
());
// 构建signinfo
String
signInfoStr
=
appId
+
orderById
.
getId
()
+
payTime
+
businessConfig
.
getRefundSecurityKey
();
String
signInfo
=
DigestUtils
.
sha1Hex
(
signInfoStr
.
getBytes
());
// 构建请求
try
{
String
url
=
businessConfig
.
getCancelPayUrl
()
+
"?"
+
"appid="
+
appId
+
"&paycontent="
+
payContent
+
"&signinfo="
+
signInfo
;
log
.
info
(
"cancel order pay url:{}"
,
url
);
// 构建请求
try
{
String
url
=
businessConfig
.
getCancelPayUrl
()
+
"?"
+
"appid="
+
appId
+
"&paycontent="
+
payContent
+
"&signinfo="
+
signInfo
;
log
.
info
(
"cancel order pay url:{}"
,
url
);
// Request request =
// new Request.Builder().url(url).get().build();
// Response payResponse = client.newCall(request).execute();
...
...
@@ -400,10 +406,10 @@ public class PayServiceClient {
// throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED);
// }
// String htmlContent = payResponse.body().string();
return
url
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
return
url
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
}
}
}
}
...
...
Please
register
or
login
to post a comment