Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
fa76472d
authored
Oct 27, 2025
by
Jony.L
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新支付功能测试4.0,继续回调测试
parent
26ab13ea
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
660 additions
and
32 deletions
+660
-32
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourceorder/ResourceOrderController.java
+160
-0
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourceorder/vo/WpgjPayNotifyDTO.java
+84
-0
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourceorder/vo/WpgjPayNotifyRespDTO.java
+24
-0
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/enums/WpgjOrderStatusEnum.java
+50
-0
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourceorder/ResourceOrderServiceImpl.java
+1
-1
computility-module-pay/src/main/java/com/luhu/computility/module/pay/api/order/PayOrderApi.java
+8
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/api/order/PayOrderApiImpl.java
+5
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/PayNotifyController.java
+1
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/WpgjPayController.java
+126
-29
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/vo/WpgjPayNotifyDTO.java
+84
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/vo/WpgjPayNotifyRespDTO.java
+24
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/enums/order/WpgjOrderStatusEnum.java
+50
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/framework/pay/core/client/impl/wpgj/WpgjPayProperties.java
+6
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/service/order/PayOrderService.java
+8
-0
computility-module-pay/src/main/java/com/luhu/computility/module/pay/service/order/PayOrderServiceImpl.java
+27
-1
computility-server/src/main/resources/application-dev.yaml
+2
-1
No files found.
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourceorder/ResourceOrderController.java
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
compute
.
controller
.
admin
.
resourceorder
;
package
com
.
luhu
.
computility
.
module
.
compute
.
controller
.
admin
.
resourceorder
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.luhu.computility.framework.common.exception.ServiceException
;
import
com.luhu.computility.framework.common.exception.ServiceException
;
import
com.luhu.computility.framework.common.pojo.CommonResult
;
import
com.luhu.computility.framework.common.pojo.CommonResult
;
import
com.luhu.computility.framework.common.pojo.PageResult
;
import
com.luhu.computility.framework.common.pojo.PageResult
;
import
com.luhu.computility.framework.common.util.json.JsonUtils
;
import
com.luhu.computility.module.compute.controller.admin.resourceorder.vo.WpgjPayNotifyDTO
;
import
com.luhu.computility.module.compute.controller.admin.resourceorder.vo.WpgjPayNotifyRespDTO
;
import
com.luhu.computility.module.compute.enums.WpgjOrderStatusEnum
;
import
com.luhu.computility.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO
;
import
com.luhu.computility.module.pay.framework.pay.core.client.impl.wpgj.WpgjPayProperties
;
import
com.luhu.computility.module.pay.service.order.PayOrderService
;
import
com.luhu.computility.module.compute.controller.admin.resourceorder.vo.*
;
import
com.luhu.computility.module.compute.controller.admin.resourceorder.vo.*
;
import
com.luhu.computility.module.compute.enums.ResourceOrderInvoiceStatus
;
import
com.luhu.computility.module.compute.enums.ResourceOrderInvoiceStatus
;
import
com.luhu.computility.module.compute.enums.ResourceOrderStatus
;
import
com.luhu.computility.module.compute.enums.ResourceOrderStatus
;
...
@@ -11,6 +19,8 @@ import io.swagger.v3.oas.annotations.Parameter;
...
@@ -11,6 +19,8 @@ import io.swagger.v3.oas.annotations.Parameter;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.List
;
import
java.util.List
;
import
com.luhu.computility.framework.excel.core.util.ExcelUtils
;
import
com.luhu.computility.framework.excel.core.util.ExcelUtils
;
...
@@ -32,6 +42,7 @@ import org.springframework.validation.annotation.Validated;
...
@@ -32,6 +42,7 @@ import org.springframework.validation.annotation.Validated;
import
static
com
.
luhu
.
computility
.
framework
.
common
.
pojo
.
CommonResult
.
success
;
import
static
com
.
luhu
.
computility
.
framework
.
common
.
pojo
.
CommonResult
.
success
;
import
com.luhu.computility.framework.common.util.object.BeanUtils
;
import
com.luhu.computility.framework.common.util.object.BeanUtils
;
import
com.luhu.computility.framework.tenant.core.aop.TenantIgnore
;
@Tag
(
name
=
"管理后台 - 算力资源订单"
)
@Tag
(
name
=
"管理后台 - 算力资源订单"
)
@RestController
@RestController
...
@@ -43,6 +54,12 @@ public class ResourceOrderController {
...
@@ -43,6 +54,12 @@ public class ResourceOrderController {
@Resource
@Resource
private
ResourceOrderService
resourceOrderService
;
private
ResourceOrderService
resourceOrderService
;
@Resource
private
PayOrderService
payOrderService
;
@Resource
private
WpgjPayProperties
wpgjPayProperties
;
/**
/**
* 内部支付任务回调
* 内部支付任务回调
*/
*/
...
@@ -55,6 +72,149 @@ public class ResourceOrderController {
...
@@ -55,6 +72,149 @@ public class ResourceOrderController {
return
success
(
true
);
return
success
(
true
);
}
}
/**
* WPGJ旺铺聚合支付回调通知
*/
@PostMapping
(
"/pay/wpgj-notify"
)
@PermitAll
@TenantIgnore
@Operation
(
summary
=
"WPGJ支付异步回调通知"
)
public
WpgjPayNotifyRespDTO
notifyWpgjPay
(
@RequestBody
WpgjPayNotifyDTO
notifyDTO
)
{
WpgjPayNotifyRespDTO
response
=
new
WpgjPayNotifyRespDTO
();
try
{
log
.
info
(
"[notifyWpgjPay] 收到WPGJ支付回调: {}"
,
JsonUtils
.
toJsonString
(
notifyDTO
));
// 1. 验证签名
if
(!
verifyWpgjSignature
(
notifyDTO
))
{
log
.
error
(
"[notifyWpgjPay] WPGJ回调签名验证失败"
);
response
.
setCode
(
"99"
);
response
.
setMsg
(
"签名验证失败"
);
response
.
setTimestamp
(
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmssSSS"
)));
return
response
;
}
// 2. 解析回调数据,构造PayOrderRespDTO
PayOrderRespDTO
notify
=
parseWpgjNotifyData
(
notifyDTO
);
// 3. 处理支付结果通知
// 由于WPGJ是特殊渠道,直接调用内部处理方法
payOrderService
.
notifyOrder
(-
1L
,
notify
);
// 使用-1表示WPGJ特殊渠道
log
.
info
(
"[notifyWpgjPay] WPGJ支付回调处理完成"
);
response
.
setCode
(
"00"
);
response
.
setMsg
(
"成功"
);
response
.
setTimestamp
(
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmssSSS"
)));
return
response
;
}
catch
(
Exception
e
)
{
log
.
error
(
"[notifyWpgjPay] WPGJ支付回调处理失败"
,
e
);
response
.
setCode
(
"99"
);
response
.
setMsg
(
"处理失败"
);
response
.
setTimestamp
(
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmssSSS"
)));
return
response
;
}
}
/**
* 验证WPGJ回调签名
*/
private
boolean
verifyWpgjSignature
(
WpgjPayNotifyDTO
notifyDTO
)
{
try
{
// 1. 构建待签名字符串 - 按照WPGJ文档要求的ASCII码排序
StringBuilder
sb
=
new
StringBuilder
();
// 严格按照ASCII码排序的所有参数
appendParam
(
sb
,
"act_amt"
,
notifyDTO
.
getActAmt
());
appendParam
(
sb
,
"buyer_id"
,
notifyDTO
.
getBuyerId
());
appendParam
(
sb
,
"card_type"
,
notifyDTO
.
getCardType
());
appendParam
(
sb
,
"device_no"
,
notifyDTO
.
getDeviceNo
());
appendParam
(
sb
,
"fee"
,
notifyDTO
.
getFee
());
appendParam
(
sb
,
"gateway_mer_order_id"
,
notifyDTO
.
getGatewayMerOrderId
());
appendParam
(
sb
,
"mer_code"
,
notifyDTO
.
getMerCode
());
appendParam
(
sb
,
"mer_no"
,
notifyDTO
.
getMerNo
());
appendParam
(
sb
,
"mer_order_id"
,
notifyDTO
.
getMerOrderId
());
appendParam
(
sb
,
"order_amt"
,
notifyDTO
.
getOrderAmt
());
appendParam
(
sb
,
"order_id"
,
notifyDTO
.
getOrderId
());
appendParam
(
sb
,
"order_status"
,
notifyDTO
.
getOrderStatus
());
appendParam
(
sb
,
"order_time"
,
notifyDTO
.
getOrderTime
());
appendParam
(
sb
,
"order_title"
,
notifyDTO
.
getOrderTitle
());
appendParam
(
sb
,
"payway_code"
,
notifyDTO
.
getPaywayCode
());
appendParam
(
sb
,
"trade_no"
,
notifyDTO
.
getTradeNo
());
appendParam
(
sb
,
"trade_time"
,
notifyDTO
.
getTradeTime
());
appendParam
(
sb
,
"trade_top_no"
,
notifyDTO
.
getTradeTopNo
());
// 3. 添加key
String
signKey
=
wpgjPayProperties
.
getSignKey
();
// 签名密钥
sb
.
append
(
"&key="
).
append
(
signKey
);
// 4. 计算MD5签名
String
signStr
=
sb
.
toString
();
String
calculatedSign
=
cn
.
hutool
.
crypto
.
digest
.
DigestUtil
.
md5Hex
(
signStr
).
toUpperCase
();
log
.
info
(
"[verifyWpgjSignature] 待签名字符串: {}"
,
signStr
);
log
.
info
(
"[verifyWpgjSignature] 计算签名: {}"
,
calculatedSign
);
log
.
info
(
"[verifyWpgjSignature] 原始签名: {}"
,
notifyDTO
.
getSign
());
// 5. 验证签名
return
calculatedSign
.
equals
(
notifyDTO
.
getSign
());
}
catch
(
Exception
e
)
{
log
.
error
(
"[verifyWpgjSignature] 签名验证异常"
,
e
);
return
false
;
}
}
/**
* 追加参数到签名字符串
*/
private
void
appendParam
(
StringBuilder
sb
,
String
key
,
String
value
)
{
if
(
StrUtil
.
isNotBlank
(
value
))
{
if
(
sb
.
length
()
>
0
)
{
sb
.
append
(
"&"
);
}
sb
.
append
(
key
).
append
(
"="
).
append
(
value
);
}
}
/**
* 解析WPGJ回调数据为PayOrderRespDTO
*/
private
PayOrderRespDTO
parseWpgjNotifyData
(
WpgjPayNotifyDTO
notifyDTO
)
{
PayOrderRespDTO
notify
=
new
PayOrderRespDTO
();
// 根据WPGJ回调文档解析字段
notify
.
setOutTradeNo
(
notifyDTO
.
getMerOrderId
());
// 商户订单号
notify
.
setChannelOrderNo
(
notifyDTO
.
getTradeNo
());
// 第三方交易号
notify
.
setStatus
(
parseWpgjStatus
(
notifyDTO
.
getOrderStatus
()));
// 交易状态
// 设置支付成功时间
if
(
WpgjOrderStatusEnum
.
isSuccess
(
notifyDTO
.
getOrderStatus
()))
{
notify
.
setSuccessTime
(
java
.
time
.
LocalDateTime
.
now
());
}
// 设置其他必要的字段
notify
.
setChannelCode
(
"wpgj_dynamic"
);
notify
.
setChannelErrorCode
(
null
);
// 成功时没有错误码
notify
.
setChannelErrorMsg
(
null
);
notify
.
setRawData
(
JsonUtils
.
toJsonString
(
notifyDTO
));
// 保存原始数据
return
notify
;
}
/**
* 解析WPGJ交易状态
*/
private
Integer
parseWpgjStatus
(
String
orderStatus
)
{
if
(
WpgjOrderStatusEnum
.
isSuccess
(
orderStatus
))
{
// 1-成功
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
SUCCESS
.
getStatus
();
}
else
if
(
WpgjOrderStatusEnum
.
isFailedOrClosed
(
orderStatus
))
{
// 0-处理中 2-失败
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
CLOSED
.
getStatus
();
}
else
{
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
WAITING
.
getStatus
();
}
}
@PostMapping
(
"/create"
)
@PostMapping
(
"/create"
)
@Operation
(
summary
=
"创建算力资源订单"
)
@Operation
(
summary
=
"创建算力资源订单"
)
@PreAuthorize
(
"@ss.hasPermission('compute:resource-order:create')"
)
@PreAuthorize
(
"@ss.hasPermission('compute:resource-order:create')"
)
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourceorder/vo/WpgjPayNotifyDTO.java
0 → 100644
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
compute
.
controller
.
admin
.
resourceorder
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
/**
* WPGJ旺铺聚合支付回调DTO
*
* @author jonyl
*/
@Schema
(
description
=
"WPGJ旺铺聚合支付回调DTO"
)
@Data
public
class
WpgjPayNotifyDTO
{
@Schema
(
description
=
"旺铺平台唯一设备SN号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"设备编号不能为空"
)
private
String
deviceNo
;
@Schema
(
description
=
"内部商户号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"商户号不能为空"
)
private
String
merNo
;
@Schema
(
description
=
"商户代码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"商户代码不能为空"
)
private
String
merCode
;
@Schema
(
description
=
"支付通道代码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"支付通道代码不能为空"
)
private
String
paywayCode
;
@Schema
(
description
=
"旺铺订单号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"旺铺订单号不能为空"
)
private
String
orderId
;
@Schema
(
description
=
"商户订单id,系统唯一"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"商户订单号不能为空"
)
private
String
merOrderId
;
@Schema
(
description
=
"网关商户订单号"
)
private
String
gatewayMerOrderId
;
@Schema
(
description
=
"下单时间"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"下单时间不能为空"
)
private
String
orderTime
;
@Schema
(
description
=
"订单金额"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"订单金额不能为空"
)
private
String
orderAmt
;
@Schema
(
description
=
"订单状态"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"订单状态不能为空"
)
private
String
orderStatus
;
@Schema
(
description
=
"通道交易流水号"
)
private
String
tradeNo
;
@Schema
(
description
=
"交易时间,支付成功返回"
)
private
String
tradeTime
;
@Schema
(
description
=
"订单标题"
)
private
String
orderTitle
;
@Schema
(
description
=
"订单手续费"
)
private
String
fee
;
@Schema
(
description
=
"结算金额"
)
private
String
actAmt
;
@Schema
(
description
=
"买家用户号"
)
private
String
buyerId
;
@Schema
(
description
=
"对应微信、支付宝小票上交易单号"
)
private
String
tradeTopNo
;
@Schema
(
description
=
"交易账户类型 C-贷记卡,D-借记卡,U-未知"
)
private
String
cardType
;
@Schema
(
description
=
"报文签名值"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"签名不能为空"
)
private
String
sign
;
}
\ No newline at end of file
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourceorder/vo/WpgjPayNotifyRespDTO.java
0 → 100644
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
compute
.
controller
.
admin
.
resourceorder
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
/**
* WPGJ旺铺聚合支付回调响应DTO
*
* @author jonyl
*/
@Schema
(
description
=
"WPGJ旺铺聚合支付回调响应DTO"
)
@Data
public
class
WpgjPayNotifyRespDTO
{
@Schema
(
description
=
"应答码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"00"
)
private
String
code
;
@Schema
(
description
=
"对应code码内容描述"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"成功"
)
private
String
msg
;
@Schema
(
description
=
"对应时间戳"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"20251027123456789"
)
private
String
timestamp
;
}
\ No newline at end of file
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/enums/WpgjOrderStatusEnum.java
0 → 100644
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
compute
.
enums
;
import
com.luhu.computility.framework.common.core.ArrayValuable
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
/**
* WPGJ旺铺聚合支付订单状态枚举
*
* @author jonyl
*/
@Getter
@AllArgsConstructor
public
enum
WpgjOrderStatusEnum
implements
ArrayValuable
<
String
>
{
PROCESSING
(
"0"
,
"处理中"
),
SUCCESS
(
"1"
,
"支付成功"
),
FAILED
(
"2"
,
"支付失败"
),
;
private
final
String
status
;
private
final
String
name
;
@Override
public
String
[]
array
()
{
return
new
String
[
0
];
}
/**
* 判断是否支付成功
*
* @param status 状态
* @return 是否支付成功
*/
public
static
boolean
isSuccess
(
String
status
)
{
return
SUCCESS
.
getStatus
().
equals
(
status
);
}
/**
* 判断是否支付失败或关闭
*
* @param status 状态
* @return 是否支付失败或关闭
*/
public
static
boolean
isFailedOrClosed
(
String
status
)
{
return
PROCESSING
.
getStatus
().
equals
(
status
)
||
FAILED
.
getStatus
().
equals
(
status
);
}
}
\ No newline at end of file
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourceorder/ResourceOrderServiceImpl.java
View file @
fa76472d
...
@@ -485,7 +485,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
...
@@ -485,7 +485,7 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
payOrderCreateReqDTO
.
setPrice
(
order
.
getPaymentPrice
().
intValue
())
payOrderCreateReqDTO
.
setPrice
(
order
.
getPaymentPrice
().
intValue
())
.
setExpireTime
(
addTime
(
resourceOrderProperties
.
getPayExpireTime
()));
.
setExpireTime
(
addTime
(
resourceOrderProperties
.
getPayExpireTime
()));
Long
payOrderId
=
payOrderApi
.
createOrder
(
payOrderCreateReqDTO
);
Long
payOrderId
=
payOrderApi
.
createOrder
Wpgj
(
payOrderCreateReqDTO
);
// 2. 提交支付订单(使用旺铺聚合支付)
// 2. 提交支付订单(使用旺铺聚合支付)
AppPayOrderSubmitReqVO
submitReqDTO
=
new
AppPayOrderSubmitReqVO
();
AppPayOrderSubmitReqVO
submitReqDTO
=
new
AppPayOrderSubmitReqVO
();
...
...
computility-module-pay/src/main/java/com/luhu/computility/module/pay/api/order/PayOrderApi.java
View file @
fa76472d
...
@@ -22,6 +22,14 @@ public interface PayOrderApi {
...
@@ -22,6 +22,14 @@ public interface PayOrderApi {
Long
createOrder
(
@Valid
PayOrderCreateReqDTO
reqDTO
);
Long
createOrder
(
@Valid
PayOrderCreateReqDTO
reqDTO
);
/**
/**
* 创建WPGJ旺铺聚合支付单
*
* @param reqDTO 创建请求
* @return 支付单编号
*/
Long
createOrderWpgj
(
@Valid
PayOrderCreateReqDTO
reqDTO
);
/**
* 获得支付单
* 获得支付单
*
*
* @param id 支付单编号
* @param id 支付单编号
...
...
computility-module-pay/src/main/java/com/luhu/computility/module/pay/api/order/PayOrderApiImpl.java
View file @
fa76472d
...
@@ -26,6 +26,11 @@ public class PayOrderApiImpl implements PayOrderApi {
...
@@ -26,6 +26,11 @@ public class PayOrderApiImpl implements PayOrderApi {
}
}
@Override
@Override
public
Long
createOrderWpgj
(
PayOrderCreateReqDTO
reqDTO
)
{
return
payOrderService
.
createOrderWpgj
(
reqDTO
);
}
@Override
public
PayOrderRespDTO
getOrder
(
Long
id
)
{
public
PayOrderRespDTO
getOrder
(
Long
id
)
{
PayOrderDO
order
=
payOrderService
.
getOrder
(
id
);
PayOrderDO
order
=
payOrderService
.
getOrder
(
id
);
return
PayOrderConvert
.
INSTANCE
.
convert2
(
order
);
return
PayOrderConvert
.
INSTANCE
.
convert2
(
order
);
...
...
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/PayNotifyController.java
View file @
fa76472d
...
@@ -21,6 +21,7 @@ import com.luhu.computility.module.pay.service.notify.PayNotifyService;
...
@@ -21,6 +21,7 @@ import com.luhu.computility.module.pay.service.notify.PayNotifyService;
import
com.luhu.computility.module.pay.service.order.PayOrderService
;
import
com.luhu.computility.module.pay.service.order.PayOrderService
;
import
com.luhu.computility.module.pay.service.refund.PayRefundService
;
import
com.luhu.computility.module.pay.service.refund.PayRefundService
;
import
com.luhu.computility.module.pay.service.transfer.PayTransferService
;
import
com.luhu.computility.module.pay.service.transfer.PayTransferService
;
import
com.luhu.computility.module.pay.framework.pay.core.client.impl.wpgj.WpgjPayProperties
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Parameter
;
import
io.swagger.v3.oas.annotations.Parameter
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
...
...
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/WpgjPayController.java
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
pay
.
controller
.
admin
.
notify
;
package
com
.
luhu
.
computility
.
module
.
pay
.
controller
.
admin
.
notify
;
import
c
om.luhu.computility.framework.common.pojo.CommonResult
;
import
c
n.hutool.core.util.StrUtil
;
import
com.luhu.computility.framework.common.util.json.JsonUtils
;
import
com.luhu.computility.framework.common.util.json.JsonUtils
;
import
com.luhu.computility.module.pay.controller.admin.notify.vo.WpgjPayNotifyDTO
;
import
com.luhu.computility.module.pay.controller.admin.notify.vo.WpgjPayNotifyRespDTO
;
import
com.luhu.computility.module.pay.enums.order.WpgjOrderStatusEnum
;
import
com.luhu.computility.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO
;
import
com.luhu.computility.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO
;
import
com.luhu.computility.module.pay.framework.pay.core.client.impl.wpgj.WpgjCryptoUtils
;
import
com.luhu.computility.module.pay.framework.pay.core.client.impl.wpgj.WpgjPayProperties
;
import
com.luhu.computility.module.pay.framework.pay.core.client.impl.wpgj.WpgjPayProperties
;
import
com.luhu.computility.module.pay.service.order.PayOrderService
;
import
com.luhu.computility.module.pay.service.order.PayOrderService
;
import
cn.hutool.json.JSONUtil
;
import
cn.hutool.json.JSONObject
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.annotation.security.PermitAll
;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.Map
;
import
java.util.Map
;
import
static
com
.
luhu
.
computility
.
framework
.
common
.
pojo
.
CommonResult
.
success
;
/**
/**
* WPGJ旺铺聚合支付回调Controller
* WPGJ旺铺聚合支付回调Controller
*
*
...
@@ -25,7 +29,7 @@ import static com.luhu.computility.framework.common.pojo.CommonResult.success;
...
@@ -25,7 +29,7 @@ import static com.luhu.computility.framework.common.pojo.CommonResult.success;
*/
*/
@Tag
(
name
=
"管理后台 - WPGJ旺铺聚合支付回调"
)
@Tag
(
name
=
"管理后台 - WPGJ旺铺聚合支付回调"
)
@RestController
@RestController
@RequestMapping
(
"/
admin-api/
pay/wpgj"
)
@RequestMapping
(
"/pay/wpgj"
)
@Slf4j
@Slf4j
public
class
WpgjPayController
{
public
class
WpgjPayController
{
...
@@ -36,47 +40,140 @@ public class WpgjPayController {
...
@@ -36,47 +40,140 @@ public class WpgjPayController {
private
WpgjPayProperties
wpgjPayProperties
;
private
WpgjPayProperties
wpgjPayProperties
;
@PostMapping
(
"/notify"
)
@PostMapping
(
"/notify"
)
@PermitAll
@Operation
(
summary
=
"WPGJ支付异步回调通知"
)
@Operation
(
summary
=
"WPGJ支付异步回调通知"
)
public
CommonResult
<
String
>
notifyWpgjPay
(
@RequestBody
String
encryptedData
)
{
public
WpgjPayNotifyRespDTO
notifyWpgjPay
(
@RequestBody
WpgjPayNotifyDTO
notifyDTO
)
{
try
{
WpgjPayNotifyRespDTO
response
=
new
WpgjPayNotifyRespDTO
();
log
.
info
(
"[notifyWpgjPay] 收到WPGJ支付回调,加密数据: {}"
,
encryptedData
);
// 1. 解密回调数据
try
{
JSONObject
decryptedResponse
=
WpgjCryptoUtils
.
decryptResponse
(
encryptedData
,
wpgjPayProperties
.
getPrivateKey
());
log
.
info
(
"[notifyWpgjPay] 收到WPGJ支付回调: {}"
,
JsonUtils
.
toJsonString
(
notifyDTO
));
Map
<
String
,
Object
>
decryptedData
=
decryptedResponse
.
get
(
"data"
)
!=
null
?
(
Map
<
String
,
Object
>)
decryptedResponse
.
get
(
"data"
)
:
decryptedResponse
;
// 1. 验证签名
if
(!
verifyWpgjSignature
(
notifyDTO
))
{
log
.
info
(
"[notifyWpgjPay] 解密后的回调数据: {}"
,
JsonUtils
.
toJsonString
(
decryptedData
));
log
.
error
(
"[notifyWpgjPay] WPGJ回调签名验证失败"
);
response
.
setCode
(
"99"
);
response
.
setMsg
(
"签名验证失败"
);
response
.
setTimestamp
(
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmssSSS"
)));
return
response
;
}
// 2. 解析回调数据,构造PayOrderRespDTO
// 2. 解析回调数据,构造PayOrderRespDTO
PayOrderRespDTO
notify
=
parseWpgjNotifyData
(
decryptedData
);
PayOrderRespDTO
notify
=
parseWpgjNotifyData
(
notifyDTO
);
// 3. 处理支付结果通知
// 3. 处理支付结果通知
// 由于WPGJ是特殊渠道,直接调用内部处理方法
// 由于WPGJ是特殊渠道,直接调用内部处理方法
payOrderService
.
notifyOrder
(-
1L
,
notify
);
// 使用-1表示WPGJ特殊渠道
payOrderService
.
notifyOrder
(-
1L
,
notify
);
// 使用-1表示WPGJ特殊渠道
log
.
info
(
"[notifyWpgjPay] WPGJ支付回调处理完成"
);
log
.
info
(
"[notifyWpgjPay] WPGJ支付回调处理完成"
);
return
success
(
"success"
);
response
.
setCode
(
"00"
);
response
.
setMsg
(
"成功"
);
response
.
setTimestamp
(
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmssSSS"
)));
return
response
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"[notifyWpgjPay] WPGJ支付回调处理失败"
,
e
);
log
.
error
(
"[notifyWpgjPay] WPGJ支付回调处理失败"
,
e
);
return
success
(
"fail"
);
response
.
setCode
(
"99"
);
response
.
setMsg
(
"处理失败"
);
response
.
setTimestamp
(
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyyMMddHHmmssSSS"
)));
return
response
;
}
}
/**
* 验证WPGJ回调签名
*/
private
boolean
verifyWpgjSignature
(
WpgjPayNotifyDTO
notifyDTO
)
{
try
{
// 1. 构建待签名字符串
StringBuilder
sb
=
new
StringBuilder
();
// 按照字段名ASCII码排序
Map
<
String
,
String
>
sortedParams
=
new
java
.
util
.
TreeMap
<>();
sortedParams
.
put
(
"device_no"
,
notifyDTO
.
getDeviceNo
());
sortedParams
.
put
(
"mer_no"
,
notifyDTO
.
getMerNo
());
sortedParams
.
put
(
"payway_code"
,
notifyDTO
.
getPaywayCode
());
sortedParams
.
put
(
"order_id"
,
notifyDTO
.
getOrderId
());
sortedParams
.
put
(
"mer_order_id"
,
notifyDTO
.
getMerOrderId
());
sortedParams
.
put
(
"order_time"
,
notifyDTO
.
getOrderTime
());
sortedParams
.
put
(
"order_amt"
,
notifyDTO
.
getOrderAmt
());
sortedParams
.
put
(
"order_status"
,
notifyDTO
.
getOrderStatus
());
// 可选字段(非空才加入)
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getMerCode
()))
{
sortedParams
.
put
(
"mer_code"
,
notifyDTO
.
getMerCode
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getGatewayMerOrderId
()))
{
sortedParams
.
put
(
"gateway_mer_order_id"
,
notifyDTO
.
getGatewayMerOrderId
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getTradeNo
()))
{
sortedParams
.
put
(
"trade_no"
,
notifyDTO
.
getTradeNo
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getTradeTime
()))
{
sortedParams
.
put
(
"trade_time"
,
notifyDTO
.
getTradeTime
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getOrderTitle
()))
{
sortedParams
.
put
(
"order_title"
,
notifyDTO
.
getOrderTitle
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getFee
()))
{
sortedParams
.
put
(
"fee"
,
notifyDTO
.
getFee
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getActAmt
()))
{
sortedParams
.
put
(
"act_amt"
,
notifyDTO
.
getActAmt
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getBuyerId
()))
{
sortedParams
.
put
(
"buyer_id"
,
notifyDTO
.
getBuyerId
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getTradeTopNo
()))
{
sortedParams
.
put
(
"trade_top_no"
,
notifyDTO
.
getTradeTopNo
());
}
if
(
StrUtil
.
isNotBlank
(
notifyDTO
.
getCardType
()))
{
sortedParams
.
put
(
"card_type"
,
notifyDTO
.
getCardType
());
}
// 2. 构建签名字符串
for
(
Map
.
Entry
<
String
,
String
>
entry
:
sortedParams
.
entrySet
())
{
if
(
StrUtil
.
isNotBlank
(
entry
.
getValue
()))
{
if
(
sb
.
length
()
>
0
)
{
sb
.
append
(
"&"
);
}
sb
.
append
(
entry
.
getKey
()).
append
(
"="
).
append
(
entry
.
getValue
());
}
}
// 3. 添加key
String
signKey
=
wpgjPayProperties
.
getSignKey
();
// 签名密钥
sb
.
append
(
"&key="
).
append
(
signKey
);
// 4. 计算MD5签名
String
signStr
=
sb
.
toString
();
String
calculatedSign
=
cn
.
hutool
.
crypto
.
digest
.
DigestUtil
.
md5Hex
(
signStr
).
toUpperCase
();
log
.
info
(
"[verifyWpgjSignature] 待签名字符串: {}"
,
signStr
);
log
.
info
(
"[verifyWpgjSignature] 计算签名: {}"
,
calculatedSign
);
log
.
info
(
"[verifyWpgjSignature] 原始签名: {}"
,
notifyDTO
.
getSign
());
// 5. 验证签名
return
calculatedSign
.
equals
(
notifyDTO
.
getSign
());
}
catch
(
Exception
e
)
{
log
.
error
(
"[verifyWpgjSignature] 签名验证异常"
,
e
);
return
false
;
}
}
}
}
/**
/**
* 解析WPGJ回调数据为PayOrderRespDTO
* 解析WPGJ回调数据为PayOrderRespDTO
*/
*/
private
PayOrderRespDTO
parseWpgjNotifyData
(
Map
<
String
,
Object
>
data
)
{
private
PayOrderRespDTO
parseWpgjNotifyData
(
WpgjPayNotifyDTO
notifyDTO
)
{
PayOrderRespDTO
notify
=
new
PayOrderRespDTO
();
PayOrderRespDTO
notify
=
new
PayOrderRespDTO
();
// 根据WPGJ回调文档解析字段
// 根据WPGJ回调文档解析字段
notify
.
setOutTradeNo
(
(
String
)
data
.
get
(
"mer_order_id"
));
// 商户订单号
notify
.
setOutTradeNo
(
notifyDTO
.
getMerOrderId
(
));
// 商户订单号
notify
.
setChannelOrderNo
(
(
String
)
data
.
get
(
"transaction_id"
));
// 第三方交易号
notify
.
setChannelOrderNo
(
notifyDTO
.
getTradeNo
(
));
// 第三方交易号
notify
.
setStatus
(
parseWpgjStatus
(
(
String
)
data
.
get
(
"trade_state"
)));
// 交易状态
notify
.
setStatus
(
parseWpgjStatus
(
notifyDTO
.
getOrderStatus
(
)));
// 交易状态
// 设置支付成功时间
// 设置支付成功时间
if
(
"SUCCESS"
.
equals
(
data
.
get
(
"trade_state"
)))
{
if
(
WpgjOrderStatusEnum
.
isSuccess
(
notifyDTO
.
getOrderStatus
(
)))
{
notify
.
setSuccessTime
(
java
.
time
.
LocalDateTime
.
now
());
notify
.
setSuccessTime
(
java
.
time
.
LocalDateTime
.
now
());
}
}
...
@@ -84,7 +181,7 @@ public class WpgjPayController {
...
@@ -84,7 +181,7 @@ public class WpgjPayController {
notify
.
setChannelCode
(
"wpgj_dynamic"
);
notify
.
setChannelCode
(
"wpgj_dynamic"
);
notify
.
setChannelErrorCode
(
null
);
// 成功时没有错误码
notify
.
setChannelErrorCode
(
null
);
// 成功时没有错误码
notify
.
setChannelErrorMsg
(
null
);
notify
.
setChannelErrorMsg
(
null
);
notify
.
setRawData
(
JsonUtils
.
toJsonString
(
data
));
// 保存原始数据
notify
.
setRawData
(
JsonUtils
.
toJsonString
(
notifyDTO
));
// 保存原始数据
return
notify
;
return
notify
;
}
}
...
@@ -92,10 +189,10 @@ public class WpgjPayController {
...
@@ -92,10 +189,10 @@ public class WpgjPayController {
/**
/**
* 解析WPGJ交易状态
* 解析WPGJ交易状态
*/
*/
private
Integer
parseWpgjStatus
(
String
tradeState
)
{
private
Integer
parseWpgjStatus
(
String
orderStatus
)
{
if
(
"SUCCESS"
.
equals
(
tradeState
))
{
if
(
WpgjOrderStatusEnum
.
isSuccess
(
orderStatus
))
{
// 1-成功
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
SUCCESS
.
getStatus
();
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
SUCCESS
.
getStatus
();
}
else
if
(
"CLOSED"
.
equals
(
tradeState
)
||
"REVOKED"
.
equals
(
tradeState
))
{
}
else
if
(
WpgjOrderStatusEnum
.
isFailedOrClosed
(
orderStatus
))
{
// 0-处理中 2-失败
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
CLOSED
.
getStatus
();
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
CLOSED
.
getStatus
();
}
else
{
}
else
{
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
WAITING
.
getStatus
();
return
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
.
PayOrderStatusEnum
.
WAITING
.
getStatus
();
...
...
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/vo/WpgjPayNotifyDTO.java
0 → 100644
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
pay
.
controller
.
admin
.
notify
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
/**
* WPGJ旺铺聚合支付回调DTO
*
* @author jonyl
*/
@Schema
(
description
=
"WPGJ旺铺聚合支付回调DTO"
)
@Data
public
class
WpgjPayNotifyDTO
{
@Schema
(
description
=
"旺铺平台唯一设备SN号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"设备编号不能为空"
)
private
String
deviceNo
;
@Schema
(
description
=
"内部商户号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"商户号不能为空"
)
private
String
merNo
;
@Schema
(
description
=
"商户代码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"商户代码不能为空"
)
private
String
merCode
;
@Schema
(
description
=
"支付通道代码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"支付通道代码不能为空"
)
private
String
paywayCode
;
@Schema
(
description
=
"旺铺订单号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"旺铺订单号不能为空"
)
private
String
orderId
;
@Schema
(
description
=
"商户订单id,系统唯一"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"商户订单号不能为空"
)
private
String
merOrderId
;
@Schema
(
description
=
"网关商户订单号"
)
private
String
gatewayMerOrderId
;
@Schema
(
description
=
"下单时间"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"下单时间不能为空"
)
private
String
orderTime
;
@Schema
(
description
=
"订单金额"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"订单金额不能为空"
)
private
String
orderAmt
;
@Schema
(
description
=
"订单状态"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"订单状态不能为空"
)
private
String
orderStatus
;
@Schema
(
description
=
"通道交易流水号"
)
private
String
tradeNo
;
@Schema
(
description
=
"交易时间,支付成功返回"
)
private
String
tradeTime
;
@Schema
(
description
=
"订单标题"
)
private
String
orderTitle
;
@Schema
(
description
=
"订单手续费"
)
private
String
fee
;
@Schema
(
description
=
"结算金额"
)
private
String
actAmt
;
@Schema
(
description
=
"买家用户号"
)
private
String
buyerId
;
@Schema
(
description
=
"对应微信、支付宝小票上交易单号"
)
private
String
tradeTopNo
;
@Schema
(
description
=
"交易账户类型 C-贷记卡,D-借记卡,U-未知"
)
private
String
cardType
;
@Schema
(
description
=
"报文签名值"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotBlank
(
message
=
"签名不能为空"
)
private
String
sign
;
}
\ No newline at end of file
computility-module-pay/src/main/java/com/luhu/computility/module/pay/controller/admin/notify/vo/WpgjPayNotifyRespDTO.java
0 → 100644
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
pay
.
controller
.
admin
.
notify
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
/**
* WPGJ旺铺聚合支付回调响应DTO
*
* @author jonyl
*/
@Schema
(
description
=
"WPGJ旺铺聚合支付回调响应DTO"
)
@Data
public
class
WpgjPayNotifyRespDTO
{
@Schema
(
description
=
"应答码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"00"
)
private
String
code
;
@Schema
(
description
=
"对应code码内容描述"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"成功"
)
private
String
msg
;
@Schema
(
description
=
"对应时间戳"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"20251027123456789"
)
private
String
timestamp
;
}
\ No newline at end of file
computility-module-pay/src/main/java/com/luhu/computility/module/pay/enums/order/WpgjOrderStatusEnum.java
0 → 100644
View file @
fa76472d
package
com
.
luhu
.
computility
.
module
.
pay
.
enums
.
order
;
import
com.luhu.computility.framework.common.core.ArrayValuable
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
/**
* WPGJ旺铺聚合支付订单状态枚举
*
* @author jonyl
*/
@Getter
@AllArgsConstructor
public
enum
WpgjOrderStatusEnum
implements
ArrayValuable
<
String
>
{
PROCESSING
(
"0"
,
"处理中"
),
SUCCESS
(
"1"
,
"支付成功"
),
FAILED
(
"2"
,
"支付失败"
),
;
private
final
String
status
;
private
final
String
name
;
@Override
public
String
[]
array
()
{
return
new
String
[
0
];
}
/**
* 判断是否支付成功
*
* @param status 状态
* @return 是否支付成功
*/
public
static
boolean
isSuccess
(
String
status
)
{
return
SUCCESS
.
getStatus
().
equals
(
status
);
}
/**
* 判断是否支付失败或关闭
*
* @param status 状态
* @return 是否支付失败或关闭
*/
public
static
boolean
isFailedOrClosed
(
String
status
)
{
return
PROCESSING
.
getStatus
().
equals
(
status
)
||
FAILED
.
getStatus
().
equals
(
status
);
}
}
\ No newline at end of file
computility-module-pay/src/main/java/com/luhu/computility/module/pay/framework/pay/core/client/impl/wpgj/WpgjPayProperties.java
View file @
fa76472d
...
@@ -53,4 +53,9 @@ public class WpgjPayProperties {
...
@@ -53,4 +53,9 @@ public class WpgjPayProperties {
* 私钥
* 私钥
*/
*/
private
String
privateKey
;
private
String
privateKey
;
/**
* 签名密钥(用于回调验证)
*/
private
String
signKey
;
}
}
\ No newline at end of file
computility-module-pay/src/main/java/com/luhu/computility/module/pay/service/order/PayOrderService.java
View file @
fa76472d
...
@@ -83,6 +83,14 @@ public interface PayOrderService {
...
@@ -83,6 +83,14 @@ public interface PayOrderService {
Long
createOrder
(
@Valid
PayOrderCreateReqDTO
reqDTO
);
Long
createOrder
(
@Valid
PayOrderCreateReqDTO
reqDTO
);
/**
/**
* 创建WPGJ旺铺聚合支付单
*
* @param reqDTO 创建请求
* @return 支付单编号
*/
Long
createOrderWpgj
(
@Valid
PayOrderCreateReqDTO
reqDTO
);
/**
* 提交支付
* 提交支付
* 此时,会发起支付渠道的调用
* 此时,会发起支付渠道的调用
*
*
...
...
computility-module-pay/src/main/java/com/luhu/computility/module/pay/service/order/PayOrderServiceImpl.java
View file @
fa76472d
...
@@ -144,6 +144,32 @@ public class PayOrderServiceImpl implements PayOrderService {
...
@@ -144,6 +144,32 @@ public class PayOrderServiceImpl implements PayOrderService {
return
order
.
getId
();
return
order
.
getId
();
}
}
@Override
public
Long
createOrderWpgj
(
PayOrderCreateReqDTO
reqDTO
)
{
// 校验 App
PayAppDO
app
=
appService
.
validPayApp
(
reqDTO
.
getAppKey
());
// 查询对应的支付交易单是否已经存在。如果是,则直接返回
PayOrderDO
order
=
payOrderMapper
.
selectByAppIdAndMerchantOrderId
(
app
.
getId
(),
reqDTO
.
getMerchantOrderId
());
if
(
order
!=
null
)
{
log
.
warn
(
"[createOrderWpgj][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]"
,
order
.
getAppId
(),
order
.
getMerchantOrderId
(),
toJsonString
(
order
));
// 理论来说,不会出现这个情况
return
order
.
getId
();
}
// 创建WPGJ支付交易单,使用WPGJ专用回调URL
order
=
PayOrderConvert
.
INSTANCE
.
convert
(
reqDTO
).
setAppId
(
app
.
getId
())
// 商户相关字段 - 使用WPGJ专用回调URL
.
setNotifyUrl
(
wpgjPayProperties
.
getNotifyUrl
())
// 订单相关字段
.
setStatus
(
PayOrderStatusEnum
.
WAITING
.
getStatus
())
// 退款相关字段
.
setRefundPrice
(
0
);
payOrderMapper
.
insert
(
order
);
return
order
.
getId
();
}
@Override
// 注意,这里不能添加事务注解,避免调用支付渠道失败时,将 PayOrderExtensionDO 回滚了
@Override
// 注意,这里不能添加事务注解,避免调用支付渠道失败时,将 PayOrderExtensionDO 回滚了
public
PayOrderSubmitRespVO
submitOrder
(
PayOrderSubmitReqVO
reqVO
,
String
userIp
)
{
public
PayOrderSubmitRespVO
submitOrder
(
PayOrderSubmitReqVO
reqVO
,
String
userIp
)
{
// 1.1 获得 PayOrderDO ,并校验其是否存在
// 1.1 获得 PayOrderDO ,并校验其是否存在
...
@@ -275,13 +301,13 @@ public class PayOrderServiceImpl implements PayOrderService {
...
@@ -275,13 +301,13 @@ public class PayOrderServiceImpl implements PayOrderService {
}
}
String
responseData
=
response
.
body
();
String
responseData
=
response
.
body
();
log
.
info
(
"[callWpgjApi] WPGJ API调用成功,响应: {}"
,
responseData
);
// 6. 解析响应结果 - 需要解密
// 6. 解析响应结果 - 需要解密
JSONObject
responseJson
=
new
JSONObject
(
responseData
);
JSONObject
responseJson
=
new
JSONObject
(
responseData
);
if
(
"0000"
.
equals
(
responseJson
.
getStr
(
"code"
)))
{
if
(
"0000"
.
equals
(
responseJson
.
getStr
(
"code"
)))
{
// 解密响应数据
// 解密响应数据
JSONObject
decryptedResponse
=
WpgjCryptoUtils
.
decryptResponse
(
responseData
,
wpgjPayProperties
.
getPrivateKey
());
JSONObject
decryptedResponse
=
WpgjCryptoUtils
.
decryptResponse
(
responseData
,
wpgjPayProperties
.
getPrivateKey
());
log
.
info
(
"[callWpgjApi] WPGJ API解密后的完整响应: {}"
,
decryptedResponse
);
return
parseWpgjApiResponse
(
decryptedResponse
,
orderExtension
.
getNo
());
return
parseWpgjApiResponse
(
decryptedResponse
,
orderExtension
.
getNo
());
}
else
{
}
else
{
// 处理错误响应
// 处理错误响应
...
...
computility-server/src/main/resources/application-dev.yaml
View file @
fa76472d
...
@@ -175,7 +175,8 @@ computility:
...
@@ -175,7 +175,8 @@ computility:
mer-code
:
K20241200111267
mer-code
:
K20241200111267
term-code
:
1011215692596
term-code
:
1011215692596
api-url
:
https://stg5-qr.wpgjcs.com/industrial/payment/dynamic
api-url
:
https://stg5-qr.wpgjcs.com/industrial/payment/dynamic
notify-url
:
https://phslgld.hnluchuan.com/admin-api/pay/wpgj/notify
notify-url
:
https://phslgld.hnluchuan.com/admin-api/compute/resource-order/pay/wpgj-notify
sign-key
:
07714583f82b4db8b675b32cd5e0969743
# WPGJ回调签名密钥(测试用,实际需要向WPGJ确认)
public-key
:
|
public-key
:
|
-----BEGIN PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvS43wZPiULrGVcXLIsTRcPZn1ZH3P5DN/IxdWUTijPMkruLu36Q1Dh+8x/oGnQBJFckp31YTptyXa2CxC7wxodAc7I4umDp1h43vDFItsPb0DBDtYUTdjw7YFBppwgyr8soUUfc9fDShgYbza/pqOzsvgXECubKrtpeBii0BGShfs20H/Rawzn2WXMUq5l+Cw7pXwJ87FT8rbJ/KJRmtMTiy5yczWikBETCGv/b7Wxw10c7w0NBeWW/vjj6FoJQOcoo3QEcjPAAx0pC4HBZiE4T3ouvsWjxyhq2CZ6FFVT05jPezw2/FZI26DOKm3pStXne3gsXzcuxPGIrzccrgjQIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvS43wZPiULrGVcXLIsTRcPZn1ZH3P5DN/IxdWUTijPMkruLu36Q1Dh+8x/oGnQBJFckp31YTptyXa2CxC7wxodAc7I4umDp1h43vDFItsPb0DBDtYUTdjw7YFBppwgyr8soUUfc9fDShgYbza/pqOzsvgXECubKrtpeBii0BGShfs20H/Rawzn2WXMUq5l+Cw7pXwJ87FT8rbJ/KJRmtMTiy5yczWikBETCGv/b7Wxw10c7w0NBeWW/vjj6FoJQOcoo3QEcjPAAx0pC4HBZiE4T3ouvsWjxyhq2CZ6FFVT05jPezw2/FZI26DOKm3pStXne3gsXzcuxPGIrzccrgjQIDAQAB
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment