From 536d3c61917120426b048df4ce73971f07772ca3 Mon Sep 17 00:00:00 2001 From: bootx Date: Sun, 25 Feb 2024 21:54:14 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E5=AE=A2=E6=88=B7=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E8=81=94=E8=B0=83,=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E5=8F=91=E8=B5=B7=E9=80=80=E6=AC=BE=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E6=9C=AA=E8=BF=9B=E8=A1=8C=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E7=9A=84=E9=97=AE=E9=A2=98,=20=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=B0=8F=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _doc/Task.md | 6 +- .../ClientNoticeReceiveController.java | 2 +- .../daxpay/demo/service/AggregateService.java | 4 +- .../sdk/payment/SimplePayOrderTest.java | 2 +- .../order/RefundOrderController.java | 34 ++--- .../platform/daxpay/code/PaymentApiCode.java | 34 +++++ .../controller/UniPayAssistController.java | 5 +- .../gateway/controller/UniPayController.java | 15 ++- .../controller/UniQueryController.java | 9 +- .../service/code/AliPayRecordTypeEnum.java | 3 +- .../service/code/WechatPayRecordTypeEnum.java | 22 ++++ .../service/common/context/PayLocal.java | 3 +- .../service/common/context/RefundLocal.java | 14 ++ .../common/local/PaymentContextLocal.java | 20 --- .../alipay/service/AliPayRecordService.java | 2 +- .../wechat/entity/WeChatPayRecord.java | 4 +- .../service/WeChatPayRecordService.java | 6 +- .../pay/service/PayChannelOrderService.java | 6 +- .../core/order/refund/entity/RefundOrder.java | 15 ++- ...ryService.java => RefundOrderService.java} | 44 ++++++- .../common/service/PaymentAssistService.java | 1 - .../notice/result/RefundNoticeResult.java | 4 + .../service/ClientNoticeAssistService.java | 121 ++++++++++++++++++ .../notice/service/ClientNoticeService.java | 118 +++-------------- .../payment/pay/service/PayAssistService.java | 2 +- .../payment/pay/strategy/AliPayStrategy.java | 8 ++ .../service/PayReconcileService.java | 3 - .../refund/service/RefundAssistService.java | 10 +- .../payment/refund/service/RefundService.java | 12 +- .../repair/service/RefundRepairService.java | 4 +- .../task/notice/entity/ClientNoticeTask.java | 3 + .../dto/order/refund/RefundOrderDto.java | 14 +- .../service/handler/PayApiCheckHandler.java | 21 ++- .../src/main/resources/application-dev.yml | 2 +- 34 files changed, 348 insertions(+), 225 deletions(-) create mode 100644 daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaymentApiCode.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/WechatPayRecordTypeEnum.java rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/{RefundOrderQueryService.java => RefundOrderService.java} (68%) create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeAssistService.java diff --git a/_doc/Task.md b/_doc/Task.md index af7678526..ba9c14e58 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -3,11 +3,11 @@ - [x] 现金支付, 现金流水 - [x] 钱包支付, 钱包流水 - [x] 储值卡支付, 储值卡流水 -- [ ] 支付回调通知和退款回调通知功能 +- [x] 支付回调通知和退款回调通知功能 - [x] 回调任务发起 - - [ ] 回调调用记录 + - [x] 回调调用记录 - [x] SDK接收对象编写 - - [ ] Demo模块接收回调演示 + - [x] Demo模块接收回调演示 - [x] 通道配置启用停用配置生效 - [x] 支付对账的序列化生成器有问题,待platform更新 diff --git a/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/controller/ClientNoticeReceiveController.java b/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/controller/ClientNoticeReceiveController.java index 44c3fa235..0352fcbcd 100644 --- a/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/controller/ClientNoticeReceiveController.java +++ b/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/controller/ClientNoticeReceiveController.java @@ -49,7 +49,7 @@ public class ClientNoticeReceiveController { return "SUCCESS"; } - @Operation(summary = "退款消息()") + @Operation(summary = "退款消息(对象)") @PostMapping("/refundObject") public String refund(@RequestBody RefundNoticeModel map) { log.info("接收到退款回调消息: {}",map); diff --git a/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/service/AggregateService.java b/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/service/AggregateService.java index df638f874..f81f1a631 100644 --- a/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/service/AggregateService.java +++ b/daxpay-single-demo/src/main/java/cn/bootx/platform/daxpay/demo/service/AggregateService.java @@ -187,7 +187,7 @@ public class AggregateService { // 支付成功同步回调地址 simplePayParam.setReturnUrl(StrUtil.format("{}/result/success", daxPayDemoProperties.getFrontH5Url())); // 中途退出 目前经测试不生效 - simplePayParam.setQuitUrl(String.format("{}/result/error", daxPayDemoProperties.getFrontH5Url())); + simplePayParam.setQuitUrl(StrUtil.format("{}/result/error", daxPayDemoProperties.getFrontH5Url())); DaxPayResult execute = DaxPayKit.execute(simplePayParam); @@ -222,8 +222,6 @@ public class AggregateService { .map(ServletUtil::getClientIP) .orElse("127.0.0.1"); simplePayParam.setClientIp(ip); - // 异步回调地址 - simplePayParam.setNotNotify(true); DaxPayResult execute = DaxPayKit.execute(simplePayParam); diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java index cc999b353..589f5676e 100644 --- a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java @@ -35,7 +35,7 @@ public class SimplePayOrderTest { public void simplePay() { // 简单支付参数 SimplePayParam param = new SimplePayParam(); - param.setBusinessNo("1"); + param.setBusinessNo("P"+ RandomUtil.randomNumbers(5)); param.setAmount(1); param.setTitle("测试接口支付"); param.setChannel(PayChannelEnum.ALI.getCode()); diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/RefundOrderController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/RefundOrderController.java index 994c49b96..966082cae 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/RefundOrderController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/RefundOrderController.java @@ -4,26 +4,20 @@ import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; import cn.bootx.platform.common.core.rest.param.PageParam; -import cn.bootx.platform.common.spring.util.WebServletUtil; -import cn.bootx.platform.daxpay.param.pay.RefundParam; import cn.bootx.platform.daxpay.param.pay.RefundSyncParam; import cn.bootx.platform.daxpay.result.pay.SyncResult; -import cn.bootx.platform.daxpay.service.core.order.refund.service.RefundOrderQueryService; -import cn.bootx.platform.daxpay.service.core.payment.refund.service.RefundService; +import cn.bootx.platform.daxpay.service.core.order.refund.service.RefundOrderService; import cn.bootx.platform.daxpay.service.core.payment.sync.service.RefundSyncService; -import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderDto; import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto; +import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderDto; import cn.bootx.platform.daxpay.service.param.order.PayOrderRefundParam; import cn.bootx.platform.daxpay.service.param.order.RefundOrderQuery; -import cn.hutool.extra.servlet.ServletUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; import java.util.List; -import java.util.Optional; /** * 支付退款控制器 @@ -35,49 +29,39 @@ import java.util.Optional; @RequestMapping("/order/refund") @RequiredArgsConstructor public class RefundOrderController { - private final RefundOrderQueryService payRefundQueryService; - private final RefundService refundService; + private final RefundOrderService refundOrderService; private final RefundSyncService refundSyncService; + @Operation(summary = "分页查询") @GetMapping("/page") public ResResult> page(PageParam pageParam, RefundOrderQuery query){ - return Res.ok(payRefundQueryService.page(pageParam, query)); + return Res.ok(refundOrderService.page(pageParam, query)); } @Operation(summary = "查询单条") @GetMapping("/findById") public ResResult findById(Long id){ - return Res.ok(payRefundQueryService.findById(id)); + return Res.ok(refundOrderService.findById(id)); } @Operation(summary = "通道退款订单列表查询") @GetMapping("/listByChannel") public ResResult> listByChannel(Long refundId){ - return Res.ok(payRefundQueryService.listByChannel(refundId)); + return Res.ok(refundOrderService.listByChannel(refundId)); } @Operation(summary = "查询通道退款订单详情") @GetMapping("/findChannelById") public ResResult findChannelById(Long id){ - return Res.ok(payRefundQueryService.findChannelById(id)); + return Res.ok(refundOrderService.findChannelById(id)); } @Operation(summary = "手动发起退款") @PostMapping("/refund") public ResResult refund(@RequestBody PayOrderRefundParam param){ - - String ip = Optional.ofNullable(WebServletUtil.getRequest()) - .map(ServletUtil::getClientIP) - .orElse("未知"); - - RefundParam refundParam = new RefundParam(); - refundParam.setPaymentId(param.getPaymentId()); - refundParam.setRefundChannels(param.getRefundChannels()); - refundParam.setReqTime(LocalDateTime.now()); - refundParam.setClientIp(ip); - refundService.refund(refundParam); + refundOrderService.refund(param); return Res.ok(); } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaymentApiCode.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaymentApiCode.java new file mode 100644 index 000000000..d4d090e50 --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaymentApiCode.java @@ -0,0 +1,34 @@ +package cn.bootx.platform.daxpay.code; + +/** + * 支付接口编码清单 + * @author xxm + * @since 2024/2/25 + */ +public interface PaymentApiCode { + + String PAY = "pay"; + + String SIMPLE_PAY = "simplePay"; + + String REFUND = "refund"; + + String SIMPLE_REFUND = "simpleRefund"; + + String CLOSE = "close"; + + String SYNC_PAY = "syncPay"; + + String SYNC_REFUND = "syncRefund"; + + String QUERY_PAY_ORDER = "queryPayOrder"; + + String QUERY_REFUND_ORDER = "queryRefundOrder"; + + String GET_WX_AUTH_URL = "getWxAuthUrl"; + + String GET_WX_ACCESS_TOKEN = "getWxAccessToken"; + + + +} diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayAssistController.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayAssistController.java index f8a6cf697..391fac2bb 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayAssistController.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayAssistController.java @@ -4,6 +4,7 @@ import cn.bootx.platform.common.core.annotation.CountTime; import cn.bootx.platform.common.core.annotation.IgnoreAuth; import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; +import cn.bootx.platform.daxpay.code.PaymentApiCode; import cn.bootx.platform.daxpay.param.assist.WxAccessTokenParam; import cn.bootx.platform.daxpay.param.assist.WxAuthUrlParam; import cn.bootx.platform.daxpay.result.DaxResult; @@ -34,7 +35,7 @@ public class UniPayAssistController { private final UniPayAssistService uniPayAssistService; @CountTime - @PaymentApi("getWxAuthUrl") + @PaymentApi(PaymentApiCode.GET_WX_AUTH_URL) @Operation(summary = "获取微信OAuth2授权链接") @PostMapping("/getWxAuthUrl") public DaxResult getWxAuthUrl(@RequestBody WxAuthUrlParam param){ @@ -42,7 +43,7 @@ public class UniPayAssistController { } @CountTime - @PaymentApi("getWxAccessToken") + @PaymentApi(PaymentApiCode.GET_WX_ACCESS_TOKEN) @Operation(summary = "获取微信AccessToken") @PostMapping("/getWxAccessToken") public ResResult getWxAccessToken(@RequestBody WxAccessTokenParam param){ diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java index 0cc0701f5..ae076ae68 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java @@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.gateway.controller; import cn.bootx.platform.common.core.annotation.CountTime; import cn.bootx.platform.common.core.annotation.IgnoreAuth; +import cn.bootx.platform.daxpay.code.PaymentApiCode; import cn.bootx.platform.daxpay.param.pay.*; import cn.bootx.platform.daxpay.result.DaxResult; import cn.bootx.platform.daxpay.result.pay.PayResult; @@ -41,7 +42,7 @@ public class UniPayController { @CountTime - @PaymentApi("pay") + @PaymentApi(PaymentApiCode.PAY) @Operation(summary = "统一支付接口") @PostMapping("/pay") public DaxResult pay(@RequestBody PayParam payParam){ @@ -49,7 +50,7 @@ public class UniPayController { } @CountTime - @PaymentApi("simplePay") + @PaymentApi(PaymentApiCode.SIMPLE_PAY) @Operation(summary = "简单支付接口") @PostMapping("/simplePay") public DaxResult simplePay(@RequestBody SimplePayParam payParam){ @@ -57,7 +58,7 @@ public class UniPayController { } @CountTime - @PaymentApi("close") + @PaymentApi(PaymentApiCode.CLOSE) @Operation(summary = "支付关闭接口") @PostMapping("/close") public DaxResult close(@RequestBody PayCloseParam param){ @@ -66,7 +67,7 @@ public class UniPayController { } @CountTime - @PaymentApi("refund") + @PaymentApi(PaymentApiCode.REFUND) @Operation(summary = "统一退款接口") @PostMapping("/refund") public DaxResult refund(@RequestBody RefundParam param){ @@ -74,7 +75,7 @@ public class UniPayController { } @CountTime - @PaymentApi("simpleRefund") + @PaymentApi(PaymentApiCode.SIMPLE_REFUND) @Operation(summary = "简单退款接口") @PostMapping("/simpleRefund") public DaxResult simpleRefund(@RequestBody SimpleRefundParam param){ @@ -82,7 +83,7 @@ public class UniPayController { } @CountTime - @PaymentApi("syncPay") + @PaymentApi(PaymentApiCode.SYNC_PAY) @Operation(summary = "支付同步接口") @PostMapping("/syncPay") public DaxResult syncPay(@RequestBody PaySyncParam param){ @@ -90,7 +91,7 @@ public class UniPayController { } @CountTime - @PaymentApi("syncRefund") + @PaymentApi(PaymentApiCode.SYNC_REFUND) @Operation(summary = "退款同步接口") @PostMapping("/syncRefund") public DaxResult syncRefund(@RequestBody RefundSyncParam param){ diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniQueryController.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniQueryController.java index b7196eb01..b0e004707 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniQueryController.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniQueryController.java @@ -2,13 +2,14 @@ package cn.bootx.platform.daxpay.gateway.controller; import cn.bootx.platform.common.core.annotation.CountTime; import cn.bootx.platform.common.core.annotation.IgnoreAuth; +import cn.bootx.platform.daxpay.code.PaymentApiCode; import cn.bootx.platform.daxpay.param.pay.QueryPayParam; import cn.bootx.platform.daxpay.param.pay.QueryRefundParam; import cn.bootx.platform.daxpay.result.DaxResult; import cn.bootx.platform.daxpay.result.order.PayOrderResult; import cn.bootx.platform.daxpay.result.order.RefundOrderResult; import cn.bootx.platform.daxpay.service.annotation.PaymentApi; -import cn.bootx.platform.daxpay.service.core.order.refund.service.RefundOrderQueryService; +import cn.bootx.platform.daxpay.service.core.order.refund.service.RefundOrderService; import cn.bootx.platform.daxpay.util.DaxRes; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -31,10 +32,10 @@ import org.springframework.web.bind.annotation.RestController; public class UniQueryController { private final cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService PayOrderQueryService; - private final RefundOrderQueryService payRefundQueryService; + private final RefundOrderService payRefundQueryService; @CountTime - @PaymentApi("queryPayOrder") + @PaymentApi(PaymentApiCode.QUERY_PAY_ORDER) @Operation(summary = "支付订单查询接口") @PostMapping("/payOrder") public DaxResult queryPayOrder(@RequestBody QueryPayParam param){ @@ -42,7 +43,7 @@ public class UniQueryController { } @CountTime - @PaymentApi("queryRefundOrder") + @PaymentApi(PaymentApiCode.QUERY_REFUND_ORDER) @Operation(summary = "退款订单查询接口") @PostMapping("/refundOrder") public DaxResult queryRefundOrder(@RequestBody QueryRefundParam param){ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayRecordTypeEnum.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayRecordTypeEnum.java index 45e933fbd..aace17fd8 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayRecordTypeEnum.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayRecordTypeEnum.java @@ -13,8 +13,7 @@ import lombok.Getter; public enum AliPayRecordTypeEnum { /** 支付 */ - PAY("pay", "支付") - , + PAY("pay", "支付"), /** 退款 */ REFUND("refund", "退款"); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/WechatPayRecordTypeEnum.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/WechatPayRecordTypeEnum.java new file mode 100644 index 000000000..88e851358 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/WechatPayRecordTypeEnum.java @@ -0,0 +1,22 @@ +package cn.bootx.platform.daxpay.service.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 微信支付流水记录类型 + * @author xxm + * @since 2024/2/20 + */ +@Getter +@AllArgsConstructor +public enum WechatPayRecordTypeEnum { + + /** 支付 */ + PAY("pay", "支付"), + /** 退款 */ + REFUND("refund", "退款"); + + private final String code; + private final String name; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/PayLocal.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/PayLocal.java index ae73e58bd..55240900b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/PayLocal.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/PayLocal.java @@ -8,6 +8,7 @@ import lombok.Data; import lombok.experimental.Accessors; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; /** @@ -47,6 +48,6 @@ public class PayLocal { private PayOrderExtra payOrderExtra; /** 通道支付订单 */ - private List payChannelOrders; + private List payChannelOrders = new ArrayList<>(); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RefundLocal.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RefundLocal.java index b1bcfd012..d8248b241 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RefundLocal.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RefundLocal.java @@ -1,9 +1,14 @@ package cn.bootx.platform.daxpay.service.common.context; import cn.bootx.platform.daxpay.code.RefundStatusEnum; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrderExtra; import lombok.Data; import lombok.experimental.Accessors; +import java.util.List; + /** * 异步退款信息 * @author xxm @@ -28,4 +33,13 @@ public class RefundLocal { /** 错误内容 */ private String errorMsg; + + /** 退款订单 */ + private RefundOrder refundOrder; + + /** 退款订单扩展 */ + private RefundOrderExtra runOrderExtra; + + /** 通道退款订单 */ + private List refundChannelOrders; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/local/PaymentContextLocal.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/local/PaymentContextLocal.java index 837b48ebb..4c9c73a28 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/local/PaymentContextLocal.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/local/PaymentContextLocal.java @@ -16,25 +16,6 @@ public final class PaymentContextLocal { private static final ThreadLocal THREAD_LOCAL = new TransmittableThreadLocal<>(); - /** - * 设置 - */ - public static void set(PaymentContext paymentContext){ - THREAD_LOCAL.set(paymentContext); - } - - /** - * 不存在则进行赋值 - */ - public static boolean setIfAbsent(PaymentContext paymentContext){ - if (THREAD_LOCAL.get() == null){ - set(paymentContext); - return true; - } - return false; - } - - /** * 获取 */ @@ -53,5 +34,4 @@ public final class PaymentContextLocal { public static void clear() { THREAD_LOCAL.remove(); } - } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRecordService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRecordService.java index 4e42078bf..74b57216e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRecordService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRecordService.java @@ -47,7 +47,7 @@ public class AliPayRecordService { */ public void refund(RefundOrder order, RefundChannelOrder channelOrder){ AliPayRecord aliPayRecord = new AliPayRecord() - .setType(AliPayRecordTypeEnum.PAY.getCode()) + .setType(AliPayRecordTypeEnum.REFUND.getCode()) .setTitle(order.getTitle()) .setOrderId(order.getId()) .setGatewayOrderNo(order.getGatewayOrderNo()) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java index cc3c6b2b6..9738e9557 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java @@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.service.core.channel.wechat.entity; import cn.bootx.platform.common.core.function.EntityBaseFunction; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; -import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum; +import cn.bootx.platform.daxpay.service.code.WechatPayRecordTypeEnum; import cn.bootx.platform.daxpay.service.core.channel.wechat.convert.WeChatConvert; import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayRecordDto; import cn.bootx.table.modify.annotation.DbColumn; @@ -34,7 +34,7 @@ public class WeChatPayRecord extends MpCreateEntity implements EntityBaseFunctio /** * 业务类型 - * @see AliPayRecordTypeEnum + * @see WechatPayRecordTypeEnum */ @DbColumn(comment = "业务类型") private String type; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java index 33d8b84c9..337831cea 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java @@ -4,7 +4,7 @@ import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; -import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum; +import cn.bootx.platform.daxpay.service.code.WechatPayRecordTypeEnum; import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WeChatPayRecordManager; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayRecord; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; @@ -33,7 +33,7 @@ public class WeChatPayRecordService { */ public void pay(PayOrder order, PayChannelOrder channelOrder){ WeChatPayRecord weChatPayRecord = new WeChatPayRecord() - .setType(AliPayRecordTypeEnum.PAY.getCode()) + .setType(WechatPayRecordTypeEnum.PAY.getCode()) .setTitle(order.getTitle()) .setOrderId(order.getId()) .setGatewayOrderNo(order.getGatewayOrderNo()) @@ -46,7 +46,7 @@ public class WeChatPayRecordService { */ public void refund(RefundOrder order, RefundChannelOrder channelOrder){ WeChatPayRecord weChatPayRecord = new WeChatPayRecord() - .setType(AliPayRecordTypeEnum.PAY.getCode()) + .setType(WechatPayRecordTypeEnum.REFUND.getCode()) .setTitle(order.getTitle()) .setOrderId(order.getId()) .setGatewayOrderNo(order.getGatewayOrderNo()) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayChannelOrderService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayChannelOrderService.java index 7ab262fc6..302927eef 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayChannelOrderService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayChannelOrderService.java @@ -54,9 +54,9 @@ public class PayChannelOrderService { */ @Transactional(rollbackFor = Exception.class) public void switchAsyncPayChannel(PayOrder payOrder, PayChannelParam payChannelParam){ - PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo(); + PayLocal payInfo = PaymentContextLocal.get().getPayInfo(); // 是否支付完成 - PayStatusEnum payStatus = asyncPayInfo.isPayComplete() ? PayStatusEnum.SUCCESS : PayStatusEnum.PROGRESS; + PayStatusEnum payStatus = payInfo.isPayComplete() ? PayStatusEnum.SUCCESS : PayStatusEnum.PROGRESS; // 判断新发起的 Optional payOrderChannelOpt = channelOrderManager.findByPaymentIdAndChannel(payOrder.getId(), payChannelParam.getChannel()); // 扩展信息处理 @@ -80,6 +80,7 @@ public class PayChannelOrderService { .setStatus(payStatus.getCode()); channelOrderManager.deleteByPaymentIdAndAsync(payOrder.getId()); channelOrderManager.save(payChannelOrder); + payInfo.getPayChannelOrders().add(payChannelOrder); } else { // 更新支付通道信息 payOrderChannelOpt.get() @@ -88,6 +89,7 @@ public class PayChannelOrderService { .setChannelExtra(channelParamStr) .setStatus(payStatus.getCode()); channelOrderManager.updateById(payOrderChannelOpt.get()); + payInfo.getPayChannelOrders().add(payOrderChannelOpt.get()); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/RefundOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/RefundOrder.java index 3d415dd8f..6dc22fc9f 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/RefundOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/RefundOrder.java @@ -31,14 +31,18 @@ import java.time.LocalDateTime; @TableName(value = "pay_refund_order", autoResultMap = true) public class RefundOrder extends MpBaseEntity implements EntityBaseFunction { - /** 关联支付id */ - @DbColumn(comment = "关联支付id") + /** 原支付id */ + @DbColumn(comment = "原支付id") private Long paymentId; - /** 关联业务号 */ - @DbColumn(comment = "关联业务号") + /** 原支付业务号 */ + @DbColumn(comment = "原支付业务号") private String businessNo; + /** 原支付标题 */ + @DbColumn(comment = "原支付标题") + private String title; + /** * 需要保证全局唯一 */ @@ -60,9 +64,6 @@ public class RefundOrder extends MpBaseEntity implements EntityBaseFunction new DataNotExistException("未找到统一退款接口信息")); + // 设置接口信息 + apiConfigService.initApiInfo(api); + // 调用统一退款接口 + refundService.refund(refundParam); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentAssistService.java index 2877c2248..a09d16bc2 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentAssistService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentAssistService.java @@ -23,7 +23,6 @@ import org.springframework.stereotype.Service; public class PaymentAssistService { private final PlatformConfigService platformConfigService; - /** * 初始化上下文 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/result/RefundNoticeResult.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/result/RefundNoticeResult.java index 5c909612d..20ec471ad 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/result/RefundNoticeResult.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/result/RefundNoticeResult.java @@ -2,6 +2,8 @@ package cn.bootx.platform.daxpay.service.core.payment.notice.result; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.RefundStatusEnum; +import cn.bootx.platform.daxpay.serializer.LocalDateTimeToTimestampSerializer; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -47,9 +49,11 @@ public class RefundNoticeResult { private String status; @Schema(description = "退款成功时间") + @JsonSerialize(using = LocalDateTimeToTimestampSerializer.class) private LocalDateTime refundTime; @Schema(description = "退款创建时间") + @JsonSerialize(using = LocalDateTimeToTimestampSerializer.class) private LocalDateTime createTime; @Schema(description = "商户扩展参数,回调时会原样返回") diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeAssistService.java new file mode 100644 index 000000000..874d61566 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeAssistService.java @@ -0,0 +1,121 @@ +package cn.bootx.platform.daxpay.service.core.payment.notice.service; + +import cn.bootx.platform.common.jackson.util.JacksonUtil; +import cn.bootx.platform.daxpay.code.PaySignTypeEnum; +import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum; +import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; +import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; +import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrderExtra; +import cn.bootx.platform.daxpay.service.core.payment.notice.result.PayChannelResult; +import cn.bootx.platform.daxpay.service.core.payment.notice.result.PayNoticeResult; +import cn.bootx.platform.daxpay.service.core.payment.notice.result.RefundChannelResult; +import cn.bootx.platform.daxpay.service.core.payment.notice.result.RefundNoticeResult; +import cn.bootx.platform.daxpay.service.core.system.config.entity.PlatformConfig; +import cn.bootx.platform.daxpay.service.core.system.config.service.PlatformConfigService; +import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask; +import cn.bootx.platform.daxpay.util.PaySignUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 客户系统消息通知任务支撑服务 + * @author xxm + * @since 2024/2/25 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class ClientNoticeAssistService { + + private final PlatformConfigService configService; + + + /** + * 构建出支付通知任务对象 + */ + public ClientNoticeTask buildPayTask(PayOrder order, PayOrderExtra orderExtra, List channelOrders){ + // 组装内容 + List channels = channelOrders.stream() + .map(o->new PayChannelResult().setChannel(o.getChannel()).setWay(o.getPayWay()).setAmount(o.getAmount())) + .collect(Collectors.toList()); + + PayNoticeResult payNoticeResult = new PayNoticeResult() + .setPaymentId(order.getId()) + .setAsyncPay(order.isAsyncPay()) + .setBusinessNo(order.getBusinessNo()) + .setAmount(order.getAmount()) + .setPayTime(order.getPayTime()) + .setCloseTime(order.getCloseTime()) + .setCreateTime(order.getCreateTime()) + .setStatus(order.getStatus()) + .setAttach(orderExtra.getAttach()) + .setPayChannels(channels); + + PlatformConfig config = configService.getConfig(); + // 是否需要签名 + if (orderExtra.isNoticeSign()){ + // 签名 + if (Objects.equals(config.getSignType(), PaySignTypeEnum.MD5.getCode())){ + payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,config.getSignSecret())); + } else { + payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret())); + } + } + return new ClientNoticeTask() + .setUrl(orderExtra.getNotifyUrl()) + // 时间序列化进行了重写 + .setContent(JacksonUtil.toJson(payNoticeResult)) + .setType(ClientNoticeTypeEnum.PAY.getType()) + .setSendCount(0) + .setOrderId(order.getId()); + } + + /** + * 构建出退款通知任务对象 + */ + public ClientNoticeTask buildRefundTask(RefundOrder order, RefundOrderExtra orderExtra, List channelOrders){ + // 组装内容 + List channels = channelOrders.stream() + .map(o->new RefundChannelResult().setChannel(o.getChannel()).setAmount(o.getAmount())) + .collect(Collectors.toList()); + + RefundNoticeResult payNoticeResult = new RefundNoticeResult() + .setRefundId(order.getId()) + .setAsyncPay(order.isAsyncPay()) + .setAsyncChannel(order.getAsyncChannel()) + .setRefundNo(order.getRefundNo()) + .setAmount(order.getAmount()) + .setRefundTime(order.getRefundTime()) + .setCreateTime(order.getCreateTime()) + .setStatus(order.getStatus()) + .setAttach(orderExtra.getAttach()) + .setRefundChannels(channels); + + PlatformConfig config = configService.getConfig(); + // 是否需要签名 + if (orderExtra.isNoticeSign()){ + // 签名 + if (Objects.equals(config.getSignType(), PaySignTypeEnum.MD5.getCode())){ + payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,config.getSignSecret())); + } else { + payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret())); + } + } + return new ClientNoticeTask() + .setUrl(orderExtra.getNotifyUrl()) + // 时间序列化进行了重写 + .setContent(JacksonUtil.toJson(payNoticeResult)) + .setType(ClientNoticeTypeEnum.REFUND.getType()) + .setSendCount(0) + .setOrderId(order.getId()); + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeService.java index c18b5232e..a9dd68f54 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/notice/service/ClientNoticeService.java @@ -3,30 +3,22 @@ package cn.bootx.platform.daxpay.service.core.payment.notice.service; import cn.bootx.platform.common.core.exception.RepetitiveOperationException; import cn.bootx.platform.common.core.util.CollUtil; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; -import cn.bootx.platform.common.jackson.util.JacksonUtil; import cn.bootx.platform.common.redis.RedisClient; -import cn.bootx.platform.daxpay.code.PaySignTypeEnum; import cn.bootx.platform.daxpay.service.code.ClientNoticeSendTypeEnum; -import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderExtraManager; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra; import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundChannelOrderManager; +import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderExtraManager; import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder; import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder; -import cn.bootx.platform.daxpay.service.core.payment.notice.result.PayChannelResult; -import cn.bootx.platform.daxpay.service.core.payment.notice.result.PayNoticeResult; -import cn.bootx.platform.daxpay.service.core.payment.notice.result.RefundChannelResult; -import cn.bootx.platform.daxpay.service.core.payment.notice.result.RefundNoticeResult; -import cn.bootx.platform.daxpay.service.core.system.config.entity.PlatformConfig; -import cn.bootx.platform.daxpay.service.core.system.config.service.PlatformConfigService; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrderExtra; import cn.bootx.platform.daxpay.service.core.task.notice.dao.ClientNoticeTaskManager; import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord; import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask; import cn.bootx.platform.daxpay.service.core.task.notice.service.ClientNoticeRecordService; -import cn.bootx.platform.daxpay.util.PaySignUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.ContentType; import cn.hutool.http.HttpResponse; @@ -40,10 +32,9 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; /** - * 消息通知任务服务 + * 客户系统消息通知任务服务 * 如果失败总共会重新发起15次通知,通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h * @author xxm * @since 2024/2/20 @@ -59,7 +50,9 @@ public class ClientNoticeService { private final RefundChannelOrderManager refundChannelOrderManager; - private final PlatformConfigService configService; + private final RefundOrderExtraManager refundOrderExtraManager; + + private final ClientNoticeAssistService clientNoticeAssistService; private final ClientNoticeTaskManager taskManager; @@ -116,6 +109,7 @@ public class ClientNoticeService { // 判断是否需要进行通知 if (StrUtil.isBlank(orderExtra.getNotifyUrl())){ log.info("支付订单无需通知,订单ID:{}",order.getId()); + return; } // 通道支付订单为空则进行查询 @@ -123,7 +117,7 @@ public class ClientNoticeService { channelOrders = payChannelOrderManager.findAllByPaymentId(order.getId()); } // 创建通知任务并保存 - ClientNoticeTask task = this.buildPayTask(order, orderExtra, channelOrders); + ClientNoticeTask task = clientNoticeAssistService.buildPayTask(order, orderExtra, channelOrders); try { taskManager.save(task); } catch (Exception e) { @@ -134,47 +128,6 @@ public class ClientNoticeService { this.sendData(task, LocalDateTime.now()); } - /** - * 构建出支付通知任务对象 - */ - private ClientNoticeTask buildPayTask(PayOrder order, PayOrderExtra orderExtra, List channelOrders){ - // 组装内容 - List channels = channelOrders.stream() - .map(o->new PayChannelResult().setChannel(o.getChannel()).setWay(o.getPayWay()).setAmount(o.getAmount())) - .collect(Collectors.toList()); - - PayNoticeResult payNoticeResult = new PayNoticeResult() - .setPaymentId(order.getId()) - .setAsyncPay(order.isAsyncPay()) - .setBusinessNo(order.getBusinessNo()) - .setAmount(order.getAmount()) - .setPayTime(order.getPayTime()) - .setCloseTime(order.getCloseTime()) - .setCreateTime(order.getCreateTime()) - .setStatus(order.getStatus()) - .setAttach(orderExtra.getAttach()) - .setPayChannels(channels); - - PlatformConfig config = configService.getConfig(); - // 是否需要签名 - if (orderExtra.isNoticeSign()){ - // 签名 - if (Objects.equals(config.getSignType(), PaySignTypeEnum.MD5.getCode())){ - payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,config.getSignSecret())); - } else { - payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret())); - } - } - return new ClientNoticeTask() - .setUrl(orderExtra.getNotifyUrl()) - // 时间序列化进行了重写 - .setContent(JacksonUtil.toJson(payNoticeResult)) - .setType(ClientNoticeTypeEnum.PAY.getType()) - .setSendCount(0) - .setOrderId(order.getId()); - } - - /** * 注册退款消息通知任务 * @param order 退款订单 @@ -182,10 +135,10 @@ public class ClientNoticeService { * @param channelOrders 退款通道订单 */ @Async("bigExecutor") - public void registerRefundNotice(RefundOrder order, PayOrderExtra orderExtra, List channelOrders) { + public void registerRefundNotice(RefundOrder order, RefundOrderExtra orderExtra, List channelOrders) { // 退款订单扩展信息为空则进行查询 if (Objects.isNull(orderExtra)){ - Optional extraOpt = payOrderExtraManager.findById(order.getId()); + Optional extraOpt = refundOrderExtraManager.findById(order.getId()); if (!extraOpt.isPresent()){ log.error("未找到支付扩展信息,数据错误,订单ID:{}",order.getId()); return; @@ -195,6 +148,7 @@ public class ClientNoticeService { // 判断是否需要进行通知 if (StrUtil.isBlank(orderExtra.getNotifyUrl())){ log.info("退款订单无需通知,订单ID:{}",order.getId()); + return; } // 通道退款订单为空则进行查询 @@ -202,7 +156,7 @@ public class ClientNoticeService { channelOrders = refundChannelOrderManager.findAllByRefundId(order.getId()); } // 创建通知任务并保存 - ClientNoticeTask task = this.buildRefundTask(order, orderExtra, channelOrders); + ClientNoticeTask task = clientNoticeAssistService.buildRefundTask(order, orderExtra, channelOrders); try { taskManager.save(task); } catch (Exception e) { @@ -214,47 +168,6 @@ public class ClientNoticeService { this.sendData(task, LocalDateTime.now()); } - /** - * 构建出退款通知任务对象 - */ - private ClientNoticeTask buildRefundTask(RefundOrder order, PayOrderExtra orderExtra, List channelOrders){ - // 组装内容 - List channels = channelOrders.stream() - .map(o->new RefundChannelResult().setChannel(o.getChannel()).setAmount(o.getAmount())) - .collect(Collectors.toList()); - - RefundNoticeResult payNoticeResult = new RefundNoticeResult() - .setRefundId(order.getId()) - .setAsyncPay(order.isAsyncPay()) - .setAsyncChannel(order.getAsyncChannel()) - .setRefundNo(order.getRefundNo()) - .setAmount(order.getAmount()) - .setRefundTime(order.getRefundTime()) - .setCreateTime(order.getCreateTime()) - .setStatus(order.getStatus()) - .setAttach(orderExtra.getAttach()) - .setRefundChannels(channels); - - PlatformConfig config = configService.getConfig(); - // 是否需要签名 - if (orderExtra.isNoticeSign()){ - // 签名 - if (Objects.equals(config.getSignType(), PaySignTypeEnum.MD5.getCode())){ - payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,config.getSignSecret())); - } else { - payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret())); - } - } - return new ClientNoticeTask() - .setUrl(orderExtra.getNotifyUrl()) - // 时间序列化进行了重写 - .setContent(JacksonUtil.toJson(payNoticeResult)) - .setType(ClientNoticeTypeEnum.PAY.getType()) - .setSendCount(0) - .setOrderId(order.getId()); - } - - /** * 从redis中执行任务, 通过定时任务触发 */ @@ -322,7 +235,7 @@ public class ClientNoticeService { } // 如果响应值等于SUCCESS, 说明发送成功, 进行成功处理 if (Objects.equals(body, "SUCCESS")){ - this.successHandler(task); + this.successHandler(task,now); record.setSuccess(true); } else { this.failHandler(task,now); @@ -339,10 +252,9 @@ public class ClientNoticeService { /** * 成功处理 */ - private void successHandler(ClientNoticeTask task){ + private void successHandler(ClientNoticeTask task, LocalDateTime now){ // 记录成功并保存 - task.setSendCount(task.getSendCount() + 1); - task.setSuccess(true); + task.setSendCount(task.getSendCount() + 1).setLatestTime(now).setSuccess(true);; taskManager.updateById(task); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/service/PayAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/service/PayAssistService.java index cbaa4135c..3c62062bf 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/service/PayAssistService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/service/PayAssistService.java @@ -167,7 +167,7 @@ public class PayAssistService { .filter(Objects::nonNull) .collect(Collectors.toList()); payChannelOrderManager.saveAll(channelOrders); - payInfo.setPayChannelOrders(channelOrders); + payInfo.getPayChannelOrders().addAll(channelOrders); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/AliPayStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/AliPayStrategy.java index a0f77a25b..bc9e1f57b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/AliPayStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/AliPayStrategy.java @@ -88,6 +88,14 @@ public class AliPayStrategy extends AbsPayStrategy { aliPayService.pay(this.getOrder(), this.getPayChannelParam(), this.aliPayParam, this.alipayConfig); } + /** + * 不使用默认的生成通道支付单方法, 异步支付通道的支付订单自己管理 + * channelOrderService.switchAsyncPayChannel 进行切换 + */ + @Override + public void generateChannelOrder() { + } + /** * 支付调起成功, 保存或更新通道支付订单 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java index e1ab9f539..bbffcde7b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java @@ -1,7 +1,6 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.service; import cn.bootx.platform.common.core.exception.DataNotExistException; -import cn.bootx.platform.daxpay.service.common.context.PaymentContext; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileDetailManager; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail; @@ -40,8 +39,6 @@ public class PayReconcileService { * 下载对账单并进行保存 */ public void downAndSave(PayReconcileOrder recordOrder) { - // 初始化上下文 - PaymentContextLocal.setIfAbsent(new PaymentContext()); // 构建对账策略 AbsReconcileStrategy absReconcileStrategy = PayReconcileStrategyFactory.create(recordOrder.getChannel()); absReconcileStrategy.initParam(recordOrder); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundAssistService.java index 1be8666ea..a82e17dbd 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundAssistService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundAssistService.java @@ -74,11 +74,11 @@ public class RefundAssistService { // 首先读取请求参数 noticeInfo.setNotifyUrl(param.getNotifyUrl()); // 读取接口配置 - if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){ + if (StrUtil.isBlank(noticeInfo.getNotifyUrl())){ noticeInfo.setNotifyUrl(apiInfo.getNoticeUrl()); } // 读取平台配置 - if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){ + if (StrUtil.isBlank(noticeInfo.getNotifyUrl())){ noticeInfo.setNotifyUrl(platform.getNotifyUrl()); } } @@ -235,9 +235,9 @@ public class RefundAssistService { */ @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void updateOrderByError(RefundOrder refundOrder){ - RefundLocal asyncRefundInfo = PaymentContextLocal.get().getRefundInfo(); - refundOrder.setErrorCode(asyncRefundInfo.getErrorCode()); - refundOrder.setErrorMsg(asyncRefundInfo.getErrorMsg()); + RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); + refundOrder.setErrorCode(refundInfo.getErrorCode()); + refundOrder.setErrorMsg(refundInfo.getErrorMsg()); // 退款失败不保存剩余可退余额, 否则数据看起开会产生困惑 refundOrder.setRefundableBalance(null); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundService.java index 1c19883f0..e497238a9 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/RefundService.java @@ -3,8 +3,8 @@ package cn.bootx.platform.daxpay.service.core.payment.refund.service; import cn.bootx.platform.common.core.exception.RepetitiveOperationException; import cn.bootx.platform.common.core.function.CollectorsFunction; import cn.bootx.platform.common.core.util.ValidationUtil; -import cn.bootx.platform.daxpay.code.RefundStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; +import cn.bootx.platform.daxpay.code.RefundStatusEnum; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException; import cn.bootx.platform.daxpay.param.pay.RefundChannelParam; @@ -218,11 +218,11 @@ public class RefundService { * 成功处理, 更新退款订单, 退款通道订单, 支付订单, 支付通道订单 */ private void successHandler(RefundOrder refundOrder, List refundChannelOrders, PayOrder payOrder) { - RefundLocal asyncRefundInfo = PaymentContextLocal.get().getRefundInfo(); + RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); // 剩余可退款余额 int refundableBalance = refundOrder.getRefundableBalance(); // 设置支付订单状态 - if (asyncRefundInfo.getStatus() == RefundStatusEnum.PROGRESS) { + if (refundInfo.getStatus() == RefundStatusEnum.PROGRESS) { // 设置为退款中 payOrder.setStatus(PayStatusEnum.REFUNDING.getCode()); } else if (refundableBalance == 0) { @@ -238,9 +238,9 @@ public class RefundService { refundAssistService.updateOrderAndChannel(refundOrder,refundChannelOrders); // 发送通知 - List list = Arrays.asList(PayStatusEnum.REFUNDING.getCode(), PayStatusEnum.REFUNDED.getCode()); - if (list.contains(payOrder.getStatus())){ - clientNoticeService.registerRefundNotice(refundOrder, null, refundChannelOrders); + List list = Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode(), RefundStatusEnum.FAIL.getCode()); + if (list.contains(refundOrder.getStatus())){ + clientNoticeService.registerRefundNotice(refundOrder, refundInfo.getRunOrderExtra(), refundChannelOrders); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/RefundRepairService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/RefundRepairService.java index 944eccc34..b623be0e9 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/RefundRepairService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/RefundRepairService.java @@ -145,8 +145,8 @@ public class RefundRepairService { refundChannelOrderManager.updateAllById(refundChannelOrders); // 发送通知 - List list = Arrays.asList(PayStatusEnum.REFUNDING.getCode(), PayStatusEnum.REFUNDED.getCode()); - if (list.contains(payOrder.getStatus())){ + List list = Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode(), RefundStatusEnum.FAIL.getCode()); + if (list.contains(refundOrder.getStatus())){ clientNoticeService.registerRefundNotice(refundOrder, null, refundChannelOrders); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/task/notice/entity/ClientNoticeTask.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/task/notice/entity/ClientNoticeTask.java index c72fe4fd5..e471beee3 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/task/notice/entity/ClientNoticeTask.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/task/notice/entity/ClientNoticeTask.java @@ -7,6 +7,8 @@ import cn.bootx.platform.daxpay.service.core.task.notice.convert.ClientNoticeCon import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeTaskDto; import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbTable; +import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType; +import cn.bootx.table.modify.mysql.constants.MySqlFieldTypeEnum; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -39,6 +41,7 @@ public class ClientNoticeTask extends MpBaseEntity implements EntityBaseFunction /** 消息内容 */ @DbColumn(comment = "消息内容") + @DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT) private String content; /** 是否发送成功 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundOrderDto.java index 327e5120a..089f87c99 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundOrderDto.java @@ -23,12 +23,15 @@ import java.time.LocalDateTime; @Schema(title = "退款记录") public class RefundOrderDto extends BaseDto { - @Schema(description = "支付号") + @Schema(description = "原支付号") private Long paymentId; - @Schema(description = "关联的业务id") + @Schema(description = "原支付业务号") private String businessNo; + @Schema(description = "原支付标题") + private String title; + @Schema(description = "退款号") private String refundNo; @@ -45,9 +48,6 @@ public class RefundOrderDto extends BaseDto { @Schema(description = "支付网关订单号") private String gatewayOrderNo; - @Schema(description = "标题") - private String title; - @Schema(description = "退款金额") private BigDecimal amount; @@ -60,6 +60,10 @@ public class RefundOrderDto extends BaseDto { @Schema(description = "退款时间") private LocalDateTime refundTime; + /** 退款原因 */ + @Schema(description = "退款原因") + private String reason; + /** * @see RefundStatusEnum */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/handler/PayApiCheckHandler.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/handler/PayApiCheckHandler.java index a404e9a66..0e674c0e8 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/handler/PayApiCheckHandler.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/handler/PayApiCheckHandler.java @@ -1,13 +1,11 @@ package cn.bootx.platform.daxpay.service.handler; import cn.bootx.platform.common.core.exception.DataNotExistException; +import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.annotation.PaymentApi; -import cn.bootx.platform.daxpay.service.common.context.PaymentContext; -import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.system.config.dao.PayApiConfigManager; import cn.bootx.platform.daxpay.service.core.system.config.entity.PayApiConfig; import cn.bootx.platform.daxpay.service.core.system.config.service.PayApiConfigService; -import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.starter.auth.service.RouterCheck; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -26,8 +24,8 @@ import java.util.Objects; @Component @RequiredArgsConstructor public class PayApiCheckHandler implements RouterCheck { - private final PayApiConfigManager openApiInfoManager; - private final PayApiConfigService openApiService; + private final PayApiConfigManager apiConfigManager; + private final PayApiConfigService apiConfigService; @Override public int sortNo() { @@ -39,21 +37,18 @@ public class PayApiCheckHandler implements RouterCheck { // 如果请求的接口未启用 if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; - PaymentApi ignoreAuth = handlerMethod.getMethodAnnotation(PaymentApi.class); - if (Objects.isNull(ignoreAuth)){ + PaymentApi paymentApi = handlerMethod.getMethodAnnotation(PaymentApi.class); + if (Objects.isNull(paymentApi)){ return false; } - String code = ignoreAuth.value(); - PayApiConfig api = openApiInfoManager.findByCode(code) + String code = paymentApi.value(); + PayApiConfig api = apiConfigManager.findByCode(code) .orElseThrow(() -> new DataNotExistException("未找到接口信息")); if (!api.isEnable()){ throw new PayFailureException("该接口权限未开放"); } - // 初始化支付上下文 - PaymentContext paymentContext = new PaymentContext(); - PaymentContextLocal.set(paymentContext); // 设置接口信息 - openApiService.initApiInfo(api); + apiConfigService.initApiInfo(api); return true; } return false; diff --git a/daxpay-single/daxpay-single-start/src/main/resources/application-dev.yml b/daxpay-single/daxpay-single-start/src/main/resources/application-dev.yml index 978355636..00f3d3569 100644 --- a/daxpay-single/daxpay-single-start/src/main/resources/application-dev.yml +++ b/daxpay-single/daxpay-single-start/src/main/resources/application-dev.yml @@ -164,7 +164,7 @@ dax-pay: # 演示模块 demo: # 网关地址 - server-url: http://pay1.bootx.cn + server-url: http://pay1.bootx.cn/server # 前端h5地址 front-h5-url: http://pay1.bootx.cn/h5/# # 签名秘钥