From 5ea91081ebd8af4755d2e22ca981b9f23723250a Mon Sep 17 00:00:00 2001 From: bootx Date: Thu, 8 Feb 2024 00:55:25 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E9=80=80=E6=AC=BE=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=97=B6=E5=AE=8C=E6=88=90=E6=97=B6=E9=97=B4=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?,=20=E9=80=9A=E9=81=93=E9=80=80=E6=AC=BE=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=8F=AF=E9=80=80=E4=BD=99=E9=A2=9D=E4=B8=8D=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=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 --- README.md | 9 +- daxpay-single-sdk/pom.xml | 139 ++++++++++++++++++ .../daxpay/sdk/code/RefundSyncStatusEnum.java | 22 +++ .../sdk/model/divide/DivideOrderModel.java | 20 +++ .../sdk/model/pay/QueryPayChannelOrder.java | 43 ++++++ .../sdk/model/pay/QueryPayOrderModel.java | 66 +++++++++ ...java => QueryRefundChannelOrderModel.java} | 18 ++- ...Result.java => QueryRefundOrderModel.java} | 24 +-- .../daxpay/sdk/model/sync/PaySyncModel.java | 9 +- .../sdk/model/sync/RefundSyncModel.java | 31 ++++ .../daxpay/sdk/net/DaxPayRequest.java | 3 +- .../sdk/param/divide/DivideOrderParam.java | 41 ++++++ .../daxpay/sdk/param/pay/QueryPayParam.java | 41 ++++++ .../sdk/param/refund/QueryRefundParam.java | 41 ++++++ .../sdk/param/sync/RefundSyncParam.java | 44 ++++++ .../platform/daxpay/sdk/util/PaySignUtil.java | 8 +- .../sdk/{ => payment}/PayCloseOrderTest.java | 2 +- .../sdk/{ => payment}/PayOrderSyncTest.java | 2 +- .../sdk/{ => payment}/PayOrderTest.java | 2 +- .../sdk/payment/RefundOrderSyncTest.java | 40 +++++ .../sdk/{ => payment}/RefundOrderTest.java | 2 +- .../sdk/{ => payment}/SimplePayOrderTest.java | 4 +- .../daxpay/sdk/query/QueryPayOrderTest.java | 38 +++++ .../sdk/query/QueryRefundOrderTest.java | 38 +++++ .../daxpay/sdk/util/PayParamSignTest.java | 55 +++++++ .../order/PayRefundOrderController.java | 2 - .../daxpay/param/pay/PayCommonParam.java | 3 +- ...Result.java => PayChannelOrderResult.java} | 2 +- .../daxpay/result/order/PayOrderResult.java | 14 +- .../order/RefundChannelOrderResult.java | 19 +++ .../result/order/RefundOrderResult.java | 26 ++-- .../daxpay/result/pay/SyncResult.java | 6 - .../LocalDateTimeToTimestampSerializer.java | 27 ++++ .../TimestampToLocalDateTimeDeserializer.java | 4 +- .../gateway/controller/UniPayController.java | 29 +--- .../controller/UniQueryController.java | 49 ++++++ .../service/common/context/RequestLocal.java | 2 + .../alipay/service/AliPayRefundService.java | 11 +- .../order/pay/convert/PayOrderConvert.java | 4 +- .../pay/service/PayChannelOrderService.java | 6 +- .../pay/service/PayOrderQueryService.java | 5 +- .../service/PayRefundOrderQueryService.java | 1 + .../common/aop/PaymentVerifySignAop.java | 4 +- .../common/service/PaymentSignService.java | 1 - .../service/PayRefundAssistService.java | 6 +- .../refund/service/PayRefundService.java | 6 +- .../repair/service/RefundRepairService.java | 10 +- .../refund/AliRefundRepairStrategy.java | 17 +++ .../refund/WeChatRefundRepairStrategy.java | 17 +++ .../sync/service/PayRefundSyncService.java | 15 +- .../payment/sync/service/PaySyncService.java | 14 +- .../service/func/AbsRefundStrategy.java | 8 +- daxpay-single/daxpay-single-start/pom.xml | 3 + 53 files changed, 924 insertions(+), 129 deletions(-) create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/code/RefundSyncStatusEnum.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/divide/DivideOrderModel.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayChannelOrder.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayOrderModel.java rename daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/{RefundChannelOrderModel.java => QueryRefundChannelOrderModel.java} (56%) rename daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/{RefundOrderResult.java => QueryRefundOrderModel.java} (82%) create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/RefundSyncModel.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/divide/DivideOrderParam.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/pay/QueryPayParam.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/refund/QueryRefundParam.java create mode 100644 daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/sync/RefundSyncParam.java rename daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/{ => payment}/PayCloseOrderTest.java (95%) rename daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/{ => payment}/PayOrderSyncTest.java (95%) rename daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/{ => payment}/PayOrderTest.java (97%) create mode 100644 daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderSyncTest.java rename daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/{ => payment}/RefundOrderTest.java (98%) rename daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/{ => payment}/SimplePayOrderTest.java (96%) create mode 100644 daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryPayOrderTest.java create mode 100644 daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryRefundOrderTest.java create mode 100644 daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/util/PayParamSignTest.java rename daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/{PayOrderChannelResult.java => PayChannelOrderResult.java} (96%) create mode 100644 daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/LocalDateTimeToTimestampSerializer.java create mode 100644 daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniQueryController.java diff --git a/README.md b/README.md index 2329f8bbf..041d6318f 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,12 @@ ## 🍒文档和演示地址 ### 文档地址 -在 [Bootx开源文档站](https://bootx.gitee.io/) 下的`支付网关(DaxPay)`模块下可以进行差异相关文档,具体链接地址如下 -[快速指南](https://bootx.gitee.io/daxpay/guides/overview/项目介绍.html)、 -[支付对接](https://bootx.gitee.io/daxpay/gateway/overview/接口清单.html)、 +在 [Bootx开源文档站](https://bootx.gitee.io/) 下的**支付网关(DaxPay)**模块下可以进行查阅相关文档,具体链接地址如下: + +[快速指南](https://bootx.gitee.io/daxpay/guides/overview/项目介绍.html) + +[支付对接](https://bootx.gitee.io/daxpay/gateway/overview/接口清单.html) + [平台配置](https://bootx.gitee.io/daxpay/admin/config/平台配置.html) diff --git a/daxpay-single-sdk/pom.xml b/daxpay-single-sdk/pom.xml index 284de099b..702ebd851 100644 --- a/daxpay-single-sdk/pom.xml +++ b/daxpay-single-sdk/pom.xml @@ -9,9 +9,40 @@ 2.0.0 jar + + bootx-platform + bootx-platform 基于Spring Boot框架打造,针对单体式应用进行专门设计,提供整套服务模块,努力为打造全方位企业级开发解决方案 + https://gitee.com/bootx/bootx-platform + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + + bootx + xxm1995@outlook.com + bootx + https://gitee.com/bootx/bootx-platform + + + + + scm:git:git@gitee.com:bootx/bootx-platform.git + scm:git:git@gitee.com:bootx/bootx-platform.git + https://gitee.com/bootx/bootx-platform + + 8 8 + 1.8 UTF-8 1.2.7 5.8.25 @@ -29,6 +60,7 @@ ch.qos.logback logback-classic ${logback-classic.version} + provided org.projectlombok @@ -44,4 +76,111 @@ + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.0 + + false + none + + + + attach-javadocs + + jar + + package + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + + sonatype + + https://s01.oss.sonatype.org/ + + + + + + + + + + src/main/resources + + **/* + + true + + + + src/main/java + + + + + + + + sonatype + OSS Snapshots Repository + https://s01.oss.sonatype.org/content/repositories/snapshots/ + + + sonatype + OSS Staging Repository + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + + diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/code/RefundSyncStatusEnum.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/code/RefundSyncStatusEnum.java new file mode 100644 index 000000000..58cbcc428 --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/code/RefundSyncStatusEnum.java @@ -0,0 +1,22 @@ +package cn.bootx.platform.daxpay.sdk.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 退款同步状态枚举 + * @author xxm + * @since 2024/1/29 + */ +@Getter +@AllArgsConstructor +public enum RefundSyncStatusEnum { + SUCCESS("refund_success","退款成功"), + FAIL("refund_fail","退款失败"), + PROGRESS("refund_progress","退款中"); + + /** 编码 */ + private final String code; + /** 名称 */ + private final String name; +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/divide/DivideOrderModel.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/divide/DivideOrderModel.java new file mode 100644 index 000000000..efc5275f7 --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/divide/DivideOrderModel.java @@ -0,0 +1,20 @@ +package cn.bootx.platform.daxpay.sdk.model.divide; + +import cn.bootx.platform.daxpay.sdk.net.DaxPayResponseModel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * 分账结果(目前未支持) + * @author xxm + * @since 2024/2/7 + */ +@Getter +@Setter +@ToString +public class DivideOrderModel extends DaxPayResponseModel { + + /** 分账状态 */ + private String status; +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayChannelOrder.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayChannelOrder.java new file mode 100644 index 000000000..3b37fa13a --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayChannelOrder.java @@ -0,0 +1,43 @@ +package cn.bootx.platform.daxpay.sdk.model.pay; + +import cn.bootx.platform.daxpay.sdk.code.PayStatusEnum; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * 支付订单通道响应参数 + * @author xxm + * @since 2024/1/16 + */ +@Getter +@Setter +@ToString +public class QueryPayChannelOrder { + + /** 是否为异步支付通道 */ + private boolean async; + + /** 支付通道 */ + private String channel; + + /** 支付方式 */ + private String payWay; + + /** + * 网关订单号, 用与将记录关联起来 + */ + private String gatewayOrderNo; + + /** + * 支付状态 + * @see PayStatusEnum + */ + private String status; + + /** 金额 */ + private Integer amount; + + /** 可退款金额 */ + private Integer refundableBalance; +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayOrderModel.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayOrderModel.java new file mode 100644 index 000000000..21101338b --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/pay/QueryPayOrderModel.java @@ -0,0 +1,66 @@ +package cn.bootx.platform.daxpay.sdk.model.pay; + +import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum; +import cn.bootx.platform.daxpay.sdk.code.PayStatusEnum; +import cn.bootx.platform.daxpay.sdk.net.DaxPayResponseModel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +/** + * 支付订单查询响应参数 + * @author xxm + * @since 2024/1/16 + */ +@Getter +@Setter +@ToString +public class QueryPayOrderModel extends DaxPayResponseModel { + + /** 支付ID */ + private Long paymentId; + + /** 业务号 */ + private String businessNo; + + /** 标题 */ + private String title; + + /** 描述 */ + private String description; + + /** 是否是异步支付 */ + private boolean asyncPay; + + /** 是否是组合支付 */ + private boolean combinationPay; + + /** + * 异步支付通道 + * @see PayChannelEnum + */ + private String asyncChannel; + + /** 金额 */ + private Integer amount; + + /** 可退款余额 */ + private Integer refundableBalance; + + /** + * 支付状态 + * @see PayStatusEnum + */ + private String status; + + /** 支付时间(秒级时间戳) */ + private Integer payTime; + + /** 过期时间(秒级时间戳) */ + private Integer expiredTime; + + /** 支付通道列表 */ + private List channels; +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/RefundChannelOrderModel.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/QueryRefundChannelOrderModel.java similarity index 56% rename from daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/RefundChannelOrderModel.java rename to daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/QueryRefundChannelOrderModel.java index c3faebaf8..1bc7cf95e 100644 --- a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/RefundChannelOrderModel.java +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/QueryRefundChannelOrderModel.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.sdk.model.refund; -import cn.bootx.platform.daxpay.sdk.net.DaxPayResponseModel; +import cn.bootx.platform.daxpay.sdk.code.RefundStatusEnum; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -13,7 +13,7 @@ import lombok.ToString; @Getter @Setter @ToString -public class RefundChannelOrderModel extends DaxPayResponseModel { +public class QueryRefundChannelOrderModel { /** 通道 */ private String channel; @@ -24,9 +24,21 @@ public class RefundChannelOrderModel extends DaxPayResponseModel { /** 异步支付方式 */ private boolean async; - /** 订单金额" */ + /** 订单金额 */ private Integer orderAmount; /** 退款金额 */ private Integer amount; + + /** 剩余可退余额 */ + private Integer refundableAmount; + + /** + * 退款状态 + * @see RefundStatusEnum + */ + private String status; + + /** 退款完成时间(秒级时间戳) */ + private Long refundTime; } diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/RefundOrderResult.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/QueryRefundOrderModel.java similarity index 82% rename from daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/RefundOrderResult.java rename to daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/QueryRefundOrderModel.java index a17559a71..c075dd4d3 100644 --- a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/RefundOrderResult.java +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/refund/QueryRefundOrderModel.java @@ -18,17 +18,20 @@ import java.util.List; @Getter @Setter @ToString -public class RefundOrderResult extends DaxPayResponseModel { +public class QueryRefundOrderModel extends DaxPayResponseModel { - /** 支付号 */ - private Long paymentId; - - /** 关联的业务id */ - private String businessNo; + /** 退款id */ + private Long refundId; /** 退款号 */ private String refundNo; + /** 关联支付号 */ + private Long paymentId; + + /** 关联业务号 */ + private String businessNo; + /** 标题 */ private String title; @@ -43,12 +46,6 @@ public class RefundOrderResult extends DaxPayResponseModel { */ private String gatewayOrderNo; - /** 通道退款订单 */ - private List channels; - - /** 退款终端ip */ - private String clientIp; - /** 退款时间 */ private LocalDateTime refundTime; @@ -57,4 +54,7 @@ public class RefundOrderResult extends DaxPayResponseModel { * @see RefundStatusEnum */ private String status; + + /** 通道退款订单 */ + private List channels; } diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/PaySyncModel.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/PaySyncModel.java index 31e4dde3c..ad9efef92 100644 --- a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/PaySyncModel.java +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/PaySyncModel.java @@ -1,5 +1,6 @@ package cn.bootx.platform.daxpay.sdk.model.sync; +import cn.bootx.platform.daxpay.sdk.code.PaySyncStatusEnum; import cn.bootx.platform.daxpay.sdk.net.DaxPayResponseModel; import lombok.Getter; import lombok.Setter; @@ -16,21 +17,15 @@ import lombok.ToString; public class PaySyncModel extends DaxPayResponseModel { /** - * 支付网关同步状态 + * 支付网关同步结果 * @see PaySyncStatusEnum */ private String gatewayStatus; - /** 是否同步成功 */ - private boolean success; - /** 是否进行了修复 */ private boolean repair; /** 修复号 */ private String repairOrderNo; - /** 失败原因 */ - private String errorMsg; - } diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/RefundSyncModel.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/RefundSyncModel.java new file mode 100644 index 000000000..83d4b9ca2 --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/model/sync/RefundSyncModel.java @@ -0,0 +1,31 @@ +package cn.bootx.platform.daxpay.sdk.model.sync; + +import cn.bootx.platform.daxpay.sdk.code.RefundSyncStatusEnum; +import cn.bootx.platform.daxpay.sdk.net.DaxPayResponseModel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * 退款信息同步结果 + * @author xxm + * @since 2024/2/7 + */ +@Getter +@Setter +@ToString +public class RefundSyncModel extends DaxPayResponseModel { + + /** + * 支付网关同步结果 + * @see RefundSyncStatusEnum + */ + private String gatewayStatus; + + /** 是否进行了修复 */ + private boolean repair; + + /** 修复号 */ + private String repairOrderNo; + +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/net/DaxPayRequest.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/net/DaxPayRequest.java index 762f2bf05..1a2b32209 100644 --- a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/net/DaxPayRequest.java +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/net/DaxPayRequest.java @@ -1,6 +1,7 @@ package cn.bootx.platform.daxpay.sdk.net; import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import cn.hutool.core.date.DateUtil; import lombok.Getter; import lombok.Setter; @@ -47,6 +48,6 @@ public abstract class DaxPayRequest { private String version = "1.0"; /** 请求时间,传输时间戳 */ - private Long reqTime; + private Long reqTime = DateUtil.currentSeconds(); } diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/divide/DivideOrderParam.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/divide/DivideOrderParam.java new file mode 100644 index 000000000..c049bfa9d --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/divide/DivideOrderParam.java @@ -0,0 +1,41 @@ +package cn.bootx.platform.daxpay.sdk.param.divide; + +import cn.bootx.platform.daxpay.sdk.model.divide.DivideOrderModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayRequest; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import cn.hutool.core.lang.TypeReference; +import cn.hutool.json.JSONUtil; +import lombok.Getter; +import lombok.Setter; + +/** + * 分账请求接口(目前未支持) + * @author xxm + * @since 2024/2/7 + */ +@Getter +@Setter +public class DivideOrderParam extends DaxPayRequest { + + /** 支付ID */ + private Long paymentId; + + /** 业务号 */ + private String businessNo; + + /** + * 方法请求路径 + */ + @Override + public String path() { + return "/unipay/divide"; + } + + /** + * 将请求返回结果反序列化为实体类 + */ + @Override + public DaxPayResult toModel(String json) { + return JSONUtil.toBean(json, new TypeReference>() {}, false); + } +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/pay/QueryPayParam.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/pay/QueryPayParam.java new file mode 100644 index 000000000..e830ca982 --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/pay/QueryPayParam.java @@ -0,0 +1,41 @@ +package cn.bootx.platform.daxpay.sdk.param.pay; + +import cn.bootx.platform.daxpay.sdk.model.pay.QueryPayOrderModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayRequest; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import cn.hutool.core.lang.TypeReference; +import cn.hutool.json.JSONUtil; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 支付单查询参数 + * @author xxm + * @since 2024/1/16 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class QueryPayParam extends DaxPayRequest { + + /** 支付ID */ + private Long paymentId; + + /** 业务号 */ + private String businessNo; + + /** + * 方法请求路径 + */ + @Override + public String path() { + return "/uni/query/payOrder"; + } + + /** + * 将请求返回结果反序列化为实体类 + */ + @Override + public DaxPayResult toModel(String json) { + return JSONUtil.toBean(json, new TypeReference>() {}, false); + } +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/refund/QueryRefundParam.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/refund/QueryRefundParam.java new file mode 100644 index 000000000..15c3c38e7 --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/refund/QueryRefundParam.java @@ -0,0 +1,41 @@ +package cn.bootx.platform.daxpay.sdk.param.refund; + +import cn.bootx.platform.daxpay.sdk.model.refund.QueryRefundOrderModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayRequest; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import cn.hutool.core.lang.TypeReference; +import cn.hutool.json.JSONUtil; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 查询退款订单参数类 + * @author xxm + * @since 2024/1/16 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class QueryRefundParam extends DaxPayRequest { + + /** 退款ID */ + private Long refundId; + + /** 退款号 */ + private String refundNo; + + /** + * 方法请求路径 + */ + @Override + public String path() { + return "/uni/query/refundOrder"; + } + + /** + * 将请求返回结果反序列化为实体类 + */ + @Override + public DaxPayResult toModel(String json) { + return JSONUtil.toBean(json, new TypeReference>() {}, false); + } +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/sync/RefundSyncParam.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/sync/RefundSyncParam.java new file mode 100644 index 000000000..11e3a041a --- /dev/null +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/param/sync/RefundSyncParam.java @@ -0,0 +1,44 @@ +package cn.bootx.platform.daxpay.sdk.param.sync; + +import cn.bootx.platform.daxpay.sdk.model.sync.RefundSyncModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayRequest; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import cn.hutool.core.lang.TypeReference; +import cn.hutool.json.JSONUtil; +import lombok.Getter; +import lombok.Setter; + +/** + * 退款同步参数 + * @author xxm + * @since 2024/2/7 + */ +@Getter +@Setter +public class RefundSyncParam extends DaxPayRequest { + /** + * 退款ID,refundId和refundNo 必传一个, 同时传输时,以 refundId 为准 + */ + private Long refundId; + + /** + * 退款号,refundId和refundNo 必传一个,同时传输时,以 refundId 为准 + */ + private String refundNo; + + /** + * 方法请求路径 + */ + @Override + public String path() { + return "/unipay/syncRefund"; + } + + /** + * 将请求返回结果反序列化为实体类 + */ + @Override + public DaxPayResult toModel(String json) { + return JSONUtil.toBean(json, new TypeReference>() {}, false); + } +} diff --git a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/util/PaySignUtil.java b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/util/PaySignUtil.java index b08744d9c..9ad1f5640 100644 --- a/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/util/PaySignUtil.java +++ b/daxpay-single-sdk/src/main/java/cn/bootx/platform/daxpay/sdk/util/PaySignUtil.java @@ -15,10 +15,10 @@ import java.util.stream.Collectors; /** * 如果需要进行签名, * 1. 参数名ASCII码从小到大排序(字典序) - * 2. 如果参数的值为空不参与签名 - * 3. 参数名不区分大小写 - * 4. 嵌套对象转换成先转换成MAP再序列化为字符串 - * 5. 支持两层嵌套, 更多层级嵌套未测试, 可能会导致不可预知的问题 + * * 2. 如果参数的值为空不参与签名 + * * 3. 参数名不区分大小写 + * * 4. 嵌套对象转换成先转换成MAP再序列化为字符串 + * * 5. 支持两层嵌套, 更多层级嵌套未测试, 可能会导致不可预知的问题 */ @UtilityClass public class PaySignUtil { diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayCloseOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayCloseOrderTest.java similarity index 95% rename from daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayCloseOrderTest.java rename to daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayCloseOrderTest.java index a1c1408c4..c65ce5862 100644 --- a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayCloseOrderTest.java +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayCloseOrderTest.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.sdk; +package cn.bootx.platform.daxpay.sdk.payment; import cn.bootx.platform.daxpay.sdk.model.pay.PayCloseModel; import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig; diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayOrderSyncTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayOrderSyncTest.java similarity index 95% rename from daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayOrderSyncTest.java rename to daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayOrderSyncTest.java index 1dfb7cc03..89ec9cf68 100644 --- a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayOrderSyncTest.java +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayOrderSyncTest.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.sdk; +package cn.bootx.platform.daxpay.sdk.payment; import cn.bootx.platform.daxpay.sdk.model.sync.PaySyncModel; import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig; diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayOrderTest.java similarity index 97% rename from daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayOrderTest.java rename to daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayOrderTest.java index c64b2e8fd..ebeb8c548 100644 --- a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/PayOrderTest.java +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/PayOrderTest.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.sdk; +package cn.bootx.platform.daxpay.sdk.payment; import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum; import cn.bootx.platform.daxpay.sdk.code.PayWayEnum; diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderSyncTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderSyncTest.java new file mode 100644 index 000000000..be665b119 --- /dev/null +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderSyncTest.java @@ -0,0 +1,40 @@ +package cn.bootx.platform.daxpay.sdk.payment; + +import cn.bootx.platform.daxpay.sdk.model.sync.RefundSyncModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig; +import cn.bootx.platform.daxpay.sdk.net.DaxPayKit; +import cn.bootx.platform.daxpay.sdk.param.sync.RefundSyncParam; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import org.junit.Before; +import org.junit.Test; + +/** + * 退款同步接口 + * @author xxm + * @since 2024/2/5 + */ +public class RefundOrderSyncTest { + + + @Before + public void init() { + // 初始化支付配置 + DaxPayConfig config = DaxPayConfig.builder() + .serviceUrl("http://127.0.0.1:9000") + .signSecret("123456") + .build(); + DaxPayKit.initConfig(config); + } + + @Test + public void testPay() { + RefundSyncParam param = new RefundSyncParam(); + + param.setRefundNo("R0001"); + + DaxPayResult execute = DaxPayKit.execute(param); + System.out.println(execute); + System.out.println(execute.getData()); + } + +} diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/RefundOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderTest.java similarity index 98% rename from daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/RefundOrderTest.java rename to daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderTest.java index 7346c2648..19a3602a3 100644 --- a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/RefundOrderTest.java +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/RefundOrderTest.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.sdk; +package cn.bootx.platform.daxpay.sdk.payment; import cn.bootx.platform.daxpay.sdk.model.refund.RefundModel; import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig; diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/SimplePayOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java similarity index 96% rename from daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/SimplePayOrderTest.java rename to daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java index 5ba1c7b45..00d93afbf 100644 --- a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/SimplePayOrderTest.java +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/payment/SimplePayOrderTest.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.sdk; +package cn.bootx.platform.daxpay.sdk.payment; import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum; import cn.bootx.platform.daxpay.sdk.code.PayWayEnum; @@ -17,8 +17,6 @@ import org.junit.Test; */ public class SimplePayOrderTest { - - @Before public void init() { // 初始化支付配置 diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryPayOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryPayOrderTest.java new file mode 100644 index 000000000..5152271c8 --- /dev/null +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryPayOrderTest.java @@ -0,0 +1,38 @@ +package cn.bootx.platform.daxpay.sdk.query; + +import cn.bootx.platform.daxpay.sdk.model.pay.QueryPayOrderModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig; +import cn.bootx.platform.daxpay.sdk.net.DaxPayKit; +import cn.bootx.platform.daxpay.sdk.param.pay.QueryPayParam; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import org.junit.Before; +import org.junit.Test; + +/** + * 查询支付订单测试类 + * @author xxm + * @since 2024/2/7 + */ +public class QueryPayOrderTest { + + @Before + public void init() { + // 初始化支付配置 + DaxPayConfig config = DaxPayConfig.builder() + .serviceUrl("http://127.0.0.1:9000") + .signSecret("123456") + .build(); + DaxPayKit.initConfig(config); + } + + @Test + public void testPay() { + QueryPayParam param = new QueryPayParam(); + + param.setBusinessNo("2"); + + DaxPayResult execute = DaxPayKit.execute(param); + System.out.println(execute); + System.out.println(execute.getData()); + } +} diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryRefundOrderTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryRefundOrderTest.java new file mode 100644 index 000000000..54c5e4305 --- /dev/null +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/query/QueryRefundOrderTest.java @@ -0,0 +1,38 @@ +package cn.bootx.platform.daxpay.sdk.query; + +import cn.bootx.platform.daxpay.sdk.model.refund.QueryRefundOrderModel; +import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig; +import cn.bootx.platform.daxpay.sdk.net.DaxPayKit; +import cn.bootx.platform.daxpay.sdk.param.refund.QueryRefundParam; +import cn.bootx.platform.daxpay.sdk.response.DaxPayResult; +import org.junit.Before; +import org.junit.Test; + +/** + * 退款订单查询接口 + * @author xxm + * @since 2024/2/7 + */ +public class QueryRefundOrderTest { + + @Before + public void init() { + // 初始化支付配置 + DaxPayConfig config = DaxPayConfig.builder() + .serviceUrl("http://127.0.0.1:9000") + .signSecret("123456") + .build(); + DaxPayKit.initConfig(config); + } + + @Test + public void testPay() { + QueryRefundParam param = new QueryRefundParam(); + + param.setRefundId(1755263825769361408L); + + DaxPayResult execute = DaxPayKit.execute(param); + System.out.println(execute); + System.out.println(execute.getData()); + } +} diff --git a/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/util/PayParamSignTest.java b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/util/PayParamSignTest.java new file mode 100644 index 000000000..04e8c130e --- /dev/null +++ b/daxpay-single-sdk/src/test/java/cn/bootx/platform/daxpay/sdk/util/PayParamSignTest.java @@ -0,0 +1,55 @@ +package cn.bootx.platform.daxpay.sdk.util; + +import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum; +import cn.bootx.platform.daxpay.sdk.code.PayWayEnum; +import cn.bootx.platform.daxpay.sdk.param.pay.PayChannelParam; +import cn.bootx.platform.daxpay.sdk.param.pay.PayParam; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * 参数签名测试类 + * @author xxm + * @since 2024/2/7 + */ +@Slf4j +public class PayParamSignTest { + + /** + * 签名测试 + */ + @Test + public void sign(){ + + PayParam param = new PayParam(); + param.setClientIp("127.0.0.1"); + param.setNotNotify(true); + param.setNotReturn(true); + + param.setBusinessNo("P0001"); + param.setTitle("测试接口支付"); + PayChannelParam payChannelParam = new PayChannelParam(); + payChannelParam.setChannel(PayChannelEnum.WECHAT.getCode()); + payChannelParam.setWay(PayWayEnum.QRCODE.getCode()); + payChannelParam.setAmount(1); + + List payChannels = Collections.singletonList(payChannelParam); + param.setPayChannels(payChannels); + + Map map = PaySignUtil.toMap(param); + log.info("转换为有序MAP后的内容: {}",map); + String data = PaySignUtil.createLinkString(map); + log.info("将MAP拼接字符串: {}",data); + String sign = "123456"; + data += "&sign="+sign; + data = data.toUpperCase(); + log.info("添加秘钥并转换为大写的字符串: {}",data); + log.info("MD5: {}",PaySignUtil.md5(data)); + log.info("HmacSHA256: {}",PaySignUtil.hmacSha256(data,sign)); + } + +} diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayRefundOrderController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayRefundOrderController.java index e32b3d2dc..b82e2d160 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayRefundOrderController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayRefundOrderController.java @@ -15,7 +15,6 @@ import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto; import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto; import cn.bootx.platform.daxpay.service.param.order.PayOrderRefundParam; import cn.bootx.platform.daxpay.service.param.order.PayRefundOrderQuery; -import cn.hutool.core.util.IdUtil; import cn.hutool.extra.servlet.ServletUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -74,7 +73,6 @@ public class PayRefundOrderController { .orElse("未知"); RefundParam refundParam = new RefundParam(); - refundParam.setRefundNo(IdUtil.getSnowflakeNextIdStr()); refundParam.setPaymentId(param.getPaymentId()); refundParam.setRefundChannels(param.getRefundChannels()); refundParam.setReqTime(LocalDateTime.now()); diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java index 60f5e210d..54833749f 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @@ -53,7 +52,7 @@ public abstract class PayCommonParam { /** 请求时间,时间戳转时间 */ @Schema(description = "请求时间,传输时间戳") -// @NotNull(message = "请求时间必填") + @NotNull(message = "请求时间必填") @JsonDeserialize(using = TimestampToLocalDateTimeDeserializer.class) private LocalDateTime reqTime; diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderChannelResult.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayChannelOrderResult.java similarity index 96% rename from daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderChannelResult.java rename to daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayChannelOrderResult.java index 7d4c4c6d3..ee8074d8f 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderChannelResult.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayChannelOrderResult.java @@ -11,7 +11,7 @@ import lombok.Data; */ @Data @Schema(title = "支付订单通道响应参数") -public class PayOrderChannelResult { +public class PayChannelOrderResult { @Schema(description = "异步支付方式") diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderResult.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderResult.java index 1efae4f67..6f73307e3 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderResult.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/PayOrderResult.java @@ -3,6 +3,8 @@ package cn.bootx.platform.daxpay.result.order; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.result.CommonResult; +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.EqualsAndHashCode; @@ -22,8 +24,12 @@ import java.util.List; @Schema(title = "支付单响应参数") public class PayOrderResult extends CommonResult { - /** 关联的业务号 */ - @Schema(description = "关联的业务号") + /** 支付ID */ + @Schema(description = "支付ID") + private Long paymentId; + + /** 业务号 */ + @Schema(description = "业务号") private String businessNo; /** 标题 */ @@ -66,12 +72,14 @@ public class PayOrderResult extends CommonResult { /** 支付时间 */ @Schema(description = "支付时间") + @JsonSerialize(using = LocalDateTimeToTimestampSerializer.class) private LocalDateTime payTime; /** 过期时间 */ @Schema(description = "过期时间") + @JsonSerialize(using = LocalDateTimeToTimestampSerializer.class) private LocalDateTime expiredTime; @Schema(description = "支付通道列表") - private List channels; + private List channels; } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundChannelOrderResult.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundChannelOrderResult.java index d60466d97..e9a889a3e 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundChannelOrderResult.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundChannelOrderResult.java @@ -1,9 +1,14 @@ package cn.bootx.platform.daxpay.result.order; +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; +import java.time.LocalDateTime; + /** * 支付退款通道明细数据 * @author xxm @@ -28,4 +33,18 @@ public class RefundChannelOrderResult { @Schema(description = "退款金额") private Integer amount; + + @Schema(description = "剩余可退余额") + private Integer refundableAmount; + + /** + * @see RefundStatusEnum + */ + @Schema(description = "退款状态") + private String status; + + @Schema(description = "退款完成时间") + @JsonSerialize(using = LocalDateTimeToTimestampSerializer.class) + private LocalDateTime refundTime; + } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundOrderResult.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundOrderResult.java index e5c5a4a97..159c30841 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundOrderResult.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/order/RefundOrderResult.java @@ -1,6 +1,8 @@ package cn.bootx.platform.daxpay.result.order; 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; @@ -18,15 +20,19 @@ import java.util.List; @Accessors(chain = true) @Schema(title = "退款订单数据") public class RefundOrderResult { - @Schema(description = "支付号") - private Long paymentId; - @Schema(description = "关联的业务id") - private String businessNo; + @Schema(description = "退款ID") + private Long refundId; @Schema(description = "退款号") private String refundNo; + @Schema(description = "关联支付ID") + private Long paymentId; + + @Schema(description = "关联支付业务号") + private String businessNo; + @Schema(description = "标题") private String title; @@ -42,13 +48,8 @@ public class RefundOrderResult { @Schema(description = "支付网关订单号") private String gatewayOrderNo; - @Schema(description = "通道退款订单") - private List channels; - - @Schema(description = "退款终端ip") - private String clientIp; - - @Schema(description = "退款时间") + @Schema(description = "退款完成时间") + @JsonSerialize(using = LocalDateTimeToTimestampSerializer.class) private LocalDateTime refundTime; /** @@ -56,4 +57,7 @@ public class RefundOrderResult { */ @Schema(description = "退款状态") private String status; + + @Schema(description = "通道退款订单") + private List channels; } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/SyncResult.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/SyncResult.java index 92795c776..115064b1f 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/SyncResult.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/SyncResult.java @@ -29,16 +29,10 @@ public class SyncResult extends CommonResult { @Schema(description = "支付网关同步状态") private String gatewayStatus = FAIL.getCode(); - @Schema(description = "是否同步成功") - private boolean success; - @Schema(description = "是否进行了修复") private boolean repair; @Schema(description = "修复号") private String repairOrderNo; - @Schema(description = "失败原因") - private String errorMsg; - } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/LocalDateTimeToTimestampSerializer.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/LocalDateTimeToTimestampSerializer.java new file mode 100644 index 000000000..44c7c7b19 --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/LocalDateTimeToTimestampSerializer.java @@ -0,0 +1,27 @@ +package cn.bootx.platform.daxpay.serializer; + +import cn.bootx.platform.common.core.util.LocalDateTimeUtil; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * Java8时间类型序列化为时间戳 (10位秒级时间戳) + * @author xxm + * @since 2024/2/7 + */ +public class LocalDateTimeToTimestampSerializer extends JsonSerializer { + @Override + public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (Objects.nonNull(value)){ + long timestamp = LocalDateTimeUtil.timestamp(value)/1000; + gen.writeNumber(timestamp); + } else { + gen.writeNull(); + } + } +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java index 1633da2a7..aa7aa1a0b 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java @@ -10,7 +10,7 @@ import java.io.IOException; import java.time.LocalDateTime; /** - * 时间戳转LocalDateTime + * 时间戳转LocalDateTime(10位秒级时间戳) * @author xxm * @since 2023/12/25 */ @@ -22,7 +22,7 @@ public class TimestampToLocalDateTimeDeserializer extends JsonDeserializer syncRefund(@RequestBody RefundSyncParam param){ return DaxRes.ok(payRefundSyncService.sync(param)); } - - @CountTime - @PaymentApi("queryPayOrder") - @Operation(summary = "查询支付订单") - @PostMapping("/queryPayOrder") - public DaxResult queryPayOrder(@RequestBody QueryPayParam param){ - return DaxRes.ok(PayOrderQueryService.queryPayOrder(param)); - } - - @CountTime - @PaymentApi("queryRefundOrder") - @Operation(summary = "查询退款订单") - @PostMapping("/queryRefundOrder") - public DaxResult queryRefundOrder(@RequestBody QueryRefundParam param){ - return DaxRes.ok(payRefundQueryService.queryRefundOrder(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 new file mode 100644 index 000000000..7d97e537c --- /dev/null +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniQueryController.java @@ -0,0 +1,49 @@ +package cn.bootx.platform.daxpay.gateway.controller; + +import cn.bootx.platform.common.core.annotation.CountTime; +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.PayRefundOrderQueryService; +import cn.bootx.platform.daxpay.util.DaxRes; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 统一查询接口 + * @author xxm + * @since 2024/2/7 + */ +@Tag(name = "统一查询接口") +@RestController +@RequestMapping("/uni/query") +@RequiredArgsConstructor +public class UniQueryController { + + private final cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService PayOrderQueryService; + private final PayRefundOrderQueryService payRefundQueryService; + + @CountTime + @PaymentApi("queryPayOrder") + @Operation(summary = "查询支付订单") + @PostMapping("/payOrder") + public DaxResult queryPayOrder(@RequestBody QueryPayParam param){ + return DaxRes.ok(PayOrderQueryService.queryPayOrder(param)); + } + + @CountTime + @PaymentApi("queryRefundOrder") + @Operation(summary = "查询退款订单") + @PostMapping("/refundOrder") + public DaxResult queryRefundOrder(@RequestBody QueryRefundParam param){ + return DaxRes.ok(payRefundQueryService.queryRefundOrder(param)); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RequestLocal.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RequestLocal.java index 15b0d040c..9425c5a77 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RequestLocal.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/RequestLocal.java @@ -14,6 +14,8 @@ import java.time.LocalDateTime; @Accessors(chain = true) public class RequestLocal { + /** 接口信息 */ + /** 客户端ip */ private String clientIp; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRefundService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRefundService.java index 4cf8127e9..518b0bfa9 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRefundService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayRefundService.java @@ -47,13 +47,14 @@ public class AliPayRefundService { log.error("网关返回退款失败: {}", response.getSubMsg()); throw new PayFailureException(response.getSubMsg()); } - // 接口返回fund_change=Y为退款成功,fund_change=N或无此字段值返回时需通过退款查询接口进一步确认退款状态 - if (response.getFundChange().equals("Y")){ -// refundInfo.setStatus(RefundStatusEnum.SUCCESS) -// .setGatewayOrderNo(response.getTradeNo()); - } + // 默认为退款中状态 refundInfo.setStatus(RefundStatusEnum.PROGRESS) .setGatewayOrderNo(response.getTradeNo()); + + // 接口返回fund_change=Y为退款成功,fund_change=N或无此字段值返回时需通过退款查询接口进一步确认退款状态 + if (response.getFundChange().equals("Y")){ + refundInfo.setStatus(RefundStatusEnum.SUCCESS); + } } catch (AlipayApiException e) { log.error("订单退款失败:", e); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/convert/PayOrderConvert.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/convert/PayOrderConvert.java index 385c19232..4a85027c7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/convert/PayOrderConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/convert/PayOrderConvert.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.service.core.order.pay.convert; -import cn.bootx.platform.daxpay.result.order.PayOrderChannelResult; +import cn.bootx.platform.daxpay.result.order.PayChannelOrderResult; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra; @@ -25,5 +25,5 @@ public interface PayOrderConvert { PayChannelOrderDto convert(PayChannelOrder in); - PayOrderChannelResult convertResult(PayChannelOrder in); + PayChannelOrderResult convertResult(PayChannelOrder in); } 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 059479c30..c0bde41a7 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 @@ -87,12 +87,10 @@ public class PayChannelOrderService { * 更新异步支付通道退款余额和状态 */ public void updateAsyncPayRefund(PayChannelOrder payChannelOrder, PayRefundChannelOrder refundChannelOrder){ - // 支付通道订单可退余额 - int refundableBalance = payChannelOrder.getRefundableBalance() - refundChannelOrder.getAmount(); - payChannelOrder.setRefundableBalance(refundableBalance); // 支付通道订单状态 if (Objects.equals(refundChannelOrder.getStatus(), RefundStatusEnum.SUCCESS.getCode())){ - PayStatusEnum status = refundableBalance == 0 ? PayStatusEnum.REFUNDED : PayStatusEnum.PARTIAL_REFUND; + // 如果可退金额为0说明已经全部退款 + PayStatusEnum status = payChannelOrder.getRefundableBalance() == 0 ? PayStatusEnum.REFUNDED : PayStatusEnum.PARTIAL_REFUND; payChannelOrder.setStatus(status.getCode()); refundChannelOrder.setRefundTime(LocalDateTime.now()); } else { diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayOrderQueryService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayOrderQueryService.java index ce6860ec1..ce447c989 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayOrderQueryService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/service/PayOrderQueryService.java @@ -7,7 +7,7 @@ import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.param.pay.QueryPayParam; -import cn.bootx.platform.daxpay.result.order.PayOrderChannelResult; +import cn.bootx.platform.daxpay.result.order.PayChannelOrderResult; import cn.bootx.platform.daxpay.result.order.PayOrderResult; import cn.bootx.platform.daxpay.service.core.order.pay.convert.PayOrderConvert; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; @@ -92,12 +92,13 @@ public class PayOrderQueryService { // 查询通道数据 List orderChannelList = payChannelOrderManager.findAllByPaymentId(payOrder.getId()); - List channels = orderChannelList.stream() + List channels = orderChannelList.stream() .map(PayOrderConvert.CONVERT::convertResult) .collect(Collectors.toList()); PayOrderResult payOrderResult = new PayOrderResult(); BeanUtil.copyProperties(payOrder, payOrderResult); + payOrderResult.setPaymentId(payOrder.getId()); payOrderResult.setDescription(payOrderExtra.getDescription()) .setChannels(channels); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/PayRefundOrderQueryService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/PayRefundOrderQueryService.java index 982b0bdef..ffa3d72e6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/PayRefundOrderQueryService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/PayRefundOrderQueryService.java @@ -102,6 +102,7 @@ public class PayRefundOrderQueryService { .collect(Collectors.toList()); RefundOrderResult refundOrderResult = PayRefundOrderConvert.CONVERT.convertResult(refundOrder); + refundOrderResult.setRefundId(refundOrder.getId()); refundOrderResult.setChannels(channels); return refundOrderResult; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/aop/PaymentVerifySignAop.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/aop/PaymentVerifySignAop.java index 131981a89..18e45b826 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/aop/PaymentVerifySignAop.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/aop/PaymentVerifySignAop.java @@ -1,10 +1,10 @@ package cn.bootx.platform.daxpay.service.core.payment.common.aop; import cn.bootx.platform.common.core.util.ValidationUtil; -import cn.bootx.platform.daxpay.service.annotation.PaymentApi; -import cn.bootx.platform.daxpay.service.core.payment.common.service.PaymentSignService; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.param.pay.PayCommonParam; +import cn.bootx.platform.daxpay.service.annotation.PaymentApi; +import cn.bootx.platform.daxpay.service.core.payment.common.service.PaymentSignService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentSignService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentSignService.java index eb698fb18..aa8fe2865 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentSignService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/common/service/PaymentSignService.java @@ -23,7 +23,6 @@ import java.util.Objects; @RequiredArgsConstructor public class PaymentSignService { - private final PaymentAssistService paymentAssistService;; /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundAssistService.java index 2b6b4a96f..616e9aa61 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundAssistService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundAssistService.java @@ -98,9 +98,9 @@ public class PayRefundAssistService { if (CollUtil.isEmpty(param.getRefundChannels())) { throw new ValidationFailedException("退款通道参数不能为空"); } - if (Objects.isNull(param.getRefundNo())) { - throw new ValidationFailedException("部分退款时退款单号必传"); - } +// if (Objects.isNull(param.getRefundNo())) { +// throw new ValidationFailedException("部分退款时退款单号必传"); +// } } // 简单退款校验 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundService.java index 214f3efe7..103ab320c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/service/PayRefundService.java @@ -152,8 +152,8 @@ public class PayRefundService { refundStrategy.initRefundParam(payOrder, refundParam, payChannelOrder); } - // 对通道支付订单进行预扣款 - payRefundStrategies.forEach(AbsRefundStrategy::doPreDeductOrderHandler); + // 生成通道退款订单对象 + payRefundStrategies.forEach(AbsRefundStrategy::generateChannelOrder); // 退款操作的预处理, 使用独立的新事物进行发起, 返回创建成功的退款订单, 成功后才可以进行下一阶段的操作 PayRefundOrder refundOrder = SpringUtil.getBean(this.getClass()).preRefundMethod(refundParam, payOrder, payRefundStrategies); @@ -193,7 +193,7 @@ public class PayRefundService { public PayRefundOrder preRefundMethod(RefundParam refundParam, PayOrder payOrder, List payRefundStrategies) { // --------------------------- 支付订单 ------------------------------------- // 预扣支付相关订单要退款的金额并进行更新 - payRefundStrategies.forEach(AbsRefundStrategy::generateChannelOrder); + payRefundStrategies.forEach(AbsRefundStrategy::doPreDeductOrderHandler); List channelOrders = payRefundStrategies.stream() .map(AbsRefundStrategy::getPayChannelOrder) .collect(Collectors.toList()); 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 56c41b1d0..a41c323ac 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 @@ -1,10 +1,11 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.service; import cn.bootx.platform.common.core.function.CollectorsFunction; -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.service.code.PaymentTypeEnum; import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum; +import cn.bootx.platform.daxpay.service.common.context.RepairLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; @@ -102,7 +103,7 @@ public class RefundRepairService { * 退款成功, 更新退款单和支付单 */ private RefundRepairResult success(PayRefundOrder refundOrder, PayOrder payOrder, List repairStrategies) { - + RepairLocal repairInfo = PaymentContextLocal.get().getRepairInfo(); // 订单相关状态 PayStatusEnum beforePayStatus = PayStatusEnum.findByCode(refundOrder.getStatus()); PayStatusEnum afterPayRefundStatus; @@ -114,8 +115,9 @@ public class RefundRepairService { } else { afterPayRefundStatus = PayStatusEnum.PARTIAL_REFUND; } - // 设置退款为完成状态 - refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode()); + // 设置退款为完成状态和完成时间 + refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode()) + .setRefundTime(repairInfo.getFinishTime()); payOrder.setStatus(afterPayRefundStatus.getCode()); // 执行退款成功逻辑 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/AliRefundRepairStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/AliRefundRepairStrategy.java index bc6018656..037604641 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/AliRefundRepairStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/AliRefundRepairStrategy.java @@ -1,12 +1,15 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.strategy.refund; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.func.AbsRefundRepairStrategy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; + import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** @@ -27,4 +30,18 @@ public class AliRefundRepairStrategy extends AbsRefundRepairStrategy { public PayChannelEnum getChannel() { return PayChannelEnum.ALI; } + + /** + * 退款成功修复 + */ + @Override + public void doSuccessHandler() { + LocalDateTime finishTime = PaymentContextLocal.get() + .getRepairInfo() + .getFinishTime(); + // 首先执行父类的修复逻辑 + super.doSuccessHandler(); + // 异步支付需要追加完成时间 + this.getRefundChannelOrder().setRefundTime(finishTime); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/WeChatRefundRepairStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/WeChatRefundRepairStrategy.java index a6813354f..e13d7ac55 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/WeChatRefundRepairStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/refund/WeChatRefundRepairStrategy.java @@ -1,12 +1,15 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.strategy.refund; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.func.AbsRefundRepairStrategy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; + import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** @@ -26,4 +29,18 @@ public class WeChatRefundRepairStrategy extends AbsRefundRepairStrategy { public PayChannelEnum getChannel() { return PayChannelEnum.WECHAT; } + + /** + * 退款成功修复 + */ + @Override + public void doSuccessHandler() { + LocalDateTime finishTime = PaymentContextLocal.get() + .getRepairInfo() + .getFinishTime(); + // 首先执行父类的修复逻辑 + super.doSuccessHandler(); + // 异步支付需要追加完成时间 + this.getRefundChannelOrder().setRefundTime(finishTime); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PayRefundSyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PayRefundSyncService.java index 7477665df..c91949cb4 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PayRefundSyncService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PayRefundSyncService.java @@ -64,11 +64,13 @@ public class PayRefundSyncService { } // 如果不是异步支付, 直接返回返回 if (!refundOrder.isAsyncPay()){ - return new SyncResult().setSuccess(false).setRepair(false).setErrorMsg("订单没有异步通道的退款,不需要同步"); +// return new SyncResult().setSuccess(false).setRepair(false).setErrorMsg("订单没有异步通道的退款,不需要同步"); + throw new PayFailureException("订单没有异步通道的退款,不需要同步"); } // 如果订单已经关闭, 直接返回失败 if (Objects.equals(refundOrder.getStatus(), RefundStatusEnum.CLOSE.getCode())){ - return new SyncResult().setSuccess(false).setRepair(false).setErrorMsg("订单已经关闭,不需要同步"); +// return new SyncResult().setSuccess(false).setRepair(false). setErrorMsg("订单已经关闭,不需要同步"); + throw new PayFailureException("订单已经关闭,不需要同步"); } return this.syncRefundOrder(refundOrder); } @@ -95,7 +97,9 @@ public class PayRefundSyncService { // 判断是否同步成功 if (Objects.equals(syncResult.getSyncStatus(), RefundSyncStatusEnum.FAIL)) { // 同步失败, 返回失败响应, 同时记录失败的日志 - return new SyncResult().setErrorMsg(syncResult.getErrorMsg()); +// return new SyncResult().setErrorMsg(syncResult.getErrorMsg()); + this.saveRecord(refundOrder, syncResult, false, null, syncResult.getErrorMsg()); + throw new PayFailureException(syncResult.getErrorMsg()); } // 支付订单的网关订单号是否一致, 不一致进行更新 if (Objects.nonNull(syncResult.getGatewayOrderNo()) && !Objects.equals(syncResult.getGatewayOrderNo(), refundOrder.getGatewayOrderNo())){ @@ -120,13 +124,12 @@ public class PayRefundSyncService { // 同步失败, 返回失败响应, 同时记录失败的日志 syncResult.setSyncStatus(RefundSyncStatusEnum.FAIL); this.saveRecord(refundOrder, syncResult, false, null, e.getMessage()); - return new SyncResult().setErrorMsg(e.getMessage()); + throw e; } // 同步成功记录日志 this.saveRecord(refundOrder, syncResult, !statusSync, repairResult.getRepairNo(), null); return new SyncResult() .setGatewayStatus(syncResult.getSyncStatus().getCode()) - .setSuccess(true) .setRepair(!statusSync) .setRepairOrderNo(repairResult.getRepairNo()); } finally { @@ -175,7 +178,7 @@ public class PayRefundSyncService { repair = repairService.repair(order, RefundRepairWayEnum.SUCCESS); break; case PROGRESS: - // 不进行处理 TODO 添加重试 + // 不进行处理 log.warn("退款状态同步接口调用出错"); break; case FAIL: { diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java index 4bb9b23ab..0ea788be6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java @@ -74,7 +74,8 @@ public class PaySyncService { } // 如果不是异步支付, 直接返回返回 if (!payOrder.isAsyncPay()){ - return new SyncResult().setSuccess(false).setRepair(false).setErrorMsg("订单没有异步支付方式,不需要同步"); +// return new SyncResult().setSuccess(false).setRepair(false).setErrorMsg("订单没有异步支付方式,不需要同步"); + throw new PayFailureException("订单没有异步支付方式,不需要同步"); } // 执行订单同步逻辑 return this.syncPayOrder(payOrder); @@ -103,7 +104,8 @@ public class PaySyncService { if (Objects.equals(syncResult.getSyncStatus(), PaySyncStatusEnum.FAIL)){ // 同步失败, 返回失败响应, 同时记录失败的日志 this.saveRecord(payOrder, syncResult, false, null, syncResult.getErrorMsg()); - return new SyncResult().setErrorMsg(syncResult.getErrorMsg()); +// return new SyncResult().setErrorMsg(syncResult.getErrorMsg()); + throw new PayFailureException(syncResult.getErrorMsg()); } // 支付订单的网关订单号是否一致, 不一致进行更新 if (Objects.nonNull(syncResult.getGatewayOrderNo()) && !Objects.equals(syncResult.getGatewayOrderNo(), payOrder.getGatewayOrderNo())){ @@ -129,14 +131,14 @@ public class PaySyncService { // 同步失败, 返回失败响应, 同时记录失败的日志 syncResult.setSyncStatus(PaySyncStatusEnum.FAIL); this.saveRecord(payOrder, syncResult, false, null, e.getMessage()); - return new SyncResult().setErrorMsg(e.getMessage()); +// return new SyncResult().setErrorMsg(e.getMessage()); + throw e; } // 同步成功记录日志 this.saveRecord( payOrder, syncResult, !statusSync, repairResult.getRepairNo(), null); return new SyncResult() .setGatewayStatus(syncResult.getSyncStatus().getCode()) - .setSuccess(true) .setRepair(!statusSync) .setRepairOrderNo(repairResult.getRepairNo()); } finally { @@ -180,7 +182,7 @@ public class PaySyncService { return true; } - // TODO 退款比对 + // 退款比对状态不做额外处理, 需要通过退款接口进行处理 if (orderStatus.equals(PayStatusEnum.REFUNDED.getCode()) && syncStatus.equals(PaySyncStatusEnum.REFUND)){ return true; } @@ -221,7 +223,7 @@ public class PaySyncService { } // 调用出错 case FAIL: { - // 不进行处理 TODO 添加重试 + // 不进行处理 log.warn("支付状态同步接口调用出错"); break; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundStrategy.java index 04e53726b..0c80801da 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundStrategy.java @@ -75,12 +75,14 @@ public abstract class AbsRefundStrategy implements PayStrategy{ * 退款发起成功操作, 异步支付通道需要进行重写 */ public void doSuccessHandler() { - // 更新退款订单数据状态 - this.refundChannelOrder.setStatus(RefundStatusEnum.SUCCESS.getCode()).setRefundTime(LocalDateTime.now()); + // 更新退款订单数据状态和完成时间 + this.refundChannelOrder + .setStatus(RefundStatusEnum.SUCCESS.getCode()). + setRefundTime(LocalDateTime.now()); // 支付通道订单可退余额 int refundableBalance = this.getPayChannelOrder().getRefundableBalance() - this.refundChannelOrder.getAmount(); - // 支付通道订单状态 + // 如果可退金额为0说明已经全部退款 PayStatusEnum status = refundableBalance == 0 ? PayStatusEnum.REFUNDED : PayStatusEnum.PARTIAL_REFUND; this.payChannelOrder.setRefundableBalance(refundableBalance) .setStatus(status.getCode()); diff --git a/daxpay-single/daxpay-single-start/pom.xml b/daxpay-single/daxpay-single-start/pom.xml index 14a997638..44ab94d0e 100644 --- a/daxpay-single/daxpay-single-start/pom.xml +++ b/daxpay-single/daxpay-single-start/pom.xml @@ -34,6 +34,9 @@ cn.bootx.platform common-starter-code-gen + + +