From 2049905ab9235dd9552d04630e2bfdf12068b896 Mon Sep 17 00:00:00 2001 From: xxm1995 Date: Mon, 29 Jan 2024 16:10:10 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E6=94=AF=E4=BB=98=E9=80=80=E6=AC=BE?= =?UTF-8?q?=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _doc/Task.md | 2 +- .../order/PayRefundOrderController.java | 13 ++- .../daxpay/code/PayRefundSyncStatusEnum.java | 22 ++++ .../daxpay/code/PaySyncStatusEnum.java | 6 +- .../daxpay/param/pay/RefundSyncParam.java | 20 +--- .../daxpay/result/pay/RefundSyncResult.java | 16 +++ .../gateway/controller/UniPayController.java | 4 +- .../daxpay/service/code/AliPayCode.java | 7 +- .../alipay/service/AliPayCallbackService.java | 2 +- .../alipay/service/AliPaySyncService.java | 29 +++-- .../wechat/service/WeChatPaySyncService.java | 23 ++-- .../core/order/pay/entity/PayOrder.java | 8 +- .../pay/service/PayChannelOrderService.java | 9 +- .../refund/entity/PayRefundChannelOrder.java | 8 +- .../order/refund/entity/PayRefundOrder.java | 12 ++ ...e.java => PayRefundOrderQueryService.java} | 2 +- .../refund/service/PayRefundOrderService.java | 33 ++++++ .../payment/pay/service/PayAssistService.java | 3 +- .../service/PayRefundAssistService.java | 35 +++++- .../refund/service/PayRefundService.java | 3 +- .../refund/strategy/AliPayRefundStrategy.java | 2 + .../strategy/WeChatPayRefundStrategy.java | 3 + .../repair/service/PayRepairService.java | 2 + .../repair/service/RefundRepairService.java | 15 ++- .../sync/factory/PaySyncStrategyFactory.java | 4 +- .../factory/RefundSyncStrategyFactory.java | 39 +++++++ .../sync/result/PayGatewaySyncResult.java | 5 +- .../sync/result/RefundGatewaySyncResult.java | 18 +++ .../sync/service/PayRefundSyncService.java | 108 ++++++++++++++++++ .../payment/sync/service/PaySyncService.java | 3 +- .../Refund/AliRefundSyncStrategy.java | 49 ++++++++ .../Refund/WeChatRefundSyncStrategy.java | 38 ++++++ .../{ => pay}/AliPaySyncStrategy.java | 2 +- .../{ => pay}/WeChatPaySyncStrategy.java | 2 +- .../core/timeout/task/PayExpiredTimeTask.java | 11 +- .../timeout/task/PayWaitOrderSyncTask.java | 2 +- .../dto/order/refund/PayRefundOrderDto.java | 11 ++ .../order/refund/RefundChannelOrderDto.java | 8 ++ .../service/func/AbsCallbackStrategy.java | 64 +++++++---- .../service/func/AbsRefundRepairStrategy.java | 10 +- .../service/func/AbsRefundStrategy.java | 5 +- .../service/func/AbsRefundSyncStrategy.java | 6 +- 42 files changed, 546 insertions(+), 118 deletions(-) create mode 100644 daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayRefundSyncStatusEnum.java create mode 100644 daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundSyncResult.java rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/{PayRefundQueryService.java => PayRefundOrderQueryService.java} (99%) create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/service/PayRefundOrderService.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/RefundSyncStrategyFactory.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PayRefundSyncService.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/AliRefundSyncStrategy.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/WeChatRefundSyncStrategy.java rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/{ => pay}/AliPaySyncStrategy.java (99%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/{ => pay}/WeChatPaySyncStrategy.java (99%) diff --git a/_doc/Task.md b/_doc/Task.md index 3103ccaf..c360498b 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -90,8 +90,8 @@ - [x] 支付宝对账单下载异常排查-支付宝每日都会生成对账单, 哪怕为空, 也会生成 - [x] 订单修复记录前端显示调整 - 2044-01-29: - - [ ] 支付通道对出现疑似退款的订单进行报错提醒通过退款同步进行补偿 - [ ] 增加退款同步策略, 对退款中的状态的退款订单进行处理 + - [ ] 支付通道对出现疑似退款的订单进行**报错提醒**, 通过退款同步进行补偿 - **任务池** - [ ] 微信退款状态不一致补偿 - [ ] 支付SDK编写 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 54a291ed..19ff1e1b 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 @@ -6,7 +6,8 @@ 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.service.core.order.refund.service.PayRefundQueryService; +import cn.bootx.platform.daxpay.service.core.order.refund.service.PayRefundOrderQueryService; +import cn.bootx.platform.daxpay.service.core.order.refund.service.PayRefundOrderService; import cn.bootx.platform.daxpay.service.core.payment.refund.service.PayRefundService; import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto; import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto; @@ -33,8 +34,9 @@ import java.util.Optional; @RequestMapping("/order/refund") @RequiredArgsConstructor public class PayRefundOrderController { - private final PayRefundQueryService payRefundQueryService; + private final PayRefundOrderQueryService payRefundQueryService; private final PayRefundService payRefundService; + private final PayRefundOrderService payRefundOrderService; @Operation(summary = "分页查询") @@ -78,4 +80,11 @@ public class PayRefundOrderController { payRefundService.refund(refundParam); return Res.ok(); } + + @Operation(summary = "退款同步") + @PostMapping("/syncById") + public ResResult syncById(Long ID){ + payRefundOrderService.syncById(ID); + return Res.ok(); + } } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayRefundSyncStatusEnum.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayRefundSyncStatusEnum.java new file mode 100644 index 00000000..a9ac042b --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayRefundSyncStatusEnum.java @@ -0,0 +1,22 @@ +package cn.bootx.platform.daxpay.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 退款同步状态枚举 + * @author xxm + * @since 2024/1/29 + */ +@Getter +@AllArgsConstructor +public enum PayRefundSyncStatusEnum { + SUCCESS("success","成功"), + FAIL("fail","失败"), + REFUNDING("refunding","退款中"); + + /** 编码 */ + private final String code; + /** 名称 */ + private final String name; +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaySyncStatusEnum.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaySyncStatusEnum.java index 84541d76..1ae4751c 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaySyncStatusEnum.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PaySyncStatusEnum.java @@ -20,11 +20,7 @@ public enum PaySyncStatusEnum { PAY_SUCCESS("pay_success", "支付成功"), PAY_WAIT("pay_wait", "待支付"), CLOSED("closed", "已关闭"), - REFUNDING("refunding", "退款中"), - /** 部分退款 */ - PARTIAL_REFUND("partial_refund","部分退款"), - /** 全部退款 */ - REFUND("refund", "已退款"), + REFUND("refund", "退款"), NOT_FOUND("not_found", "交易不存在"), /** * 未查询到订单(具体类型未知) diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundSyncParam.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundSyncParam.java index 9298b67f..e3bbf5cf 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundSyncParam.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundSyncParam.java @@ -15,31 +15,15 @@ import lombok.EqualsAndHashCode; public class RefundSyncParam extends PayCommonParam { /** - * 部分退款时 refundId 和 refundNo 必传一个 - * 如果与 businessNo同时传输,以本参数为准 + * 部分退款时 refundId 和 refundNo 必传一个, 同时传输时,以 refundId 为准 */ @Schema(description = "退款订单ID") private Long refundId; /** - * 退款订单号,部分退款时 refundId 和 refundNo 必传一个, - * 如果与 paymentId 和 businessNo 同时传输,以本参数为准 + * 退款订单号,部分退款时 refundId 和 refundNo 必传一个,同时传输时,以 refundId 为准 */ @Schema(description = "退款订单号") private String refundNo; - /** - * 支付单ID, 通常为商户的业务订单号,全部退款时, - * paymentId 和 businessNo可传其中一个,同时传输以前者为准,部分退款可以不进行传输 - */ - @Schema(description = "支付单ID") - private Long paymentId; - - /** - * 支付订单的业务号, 通常为商户的业务订单号,全部退款时, - * paymentId 和 businessNo可传其中一个,同时传输以前者为准,部分退款可以不进行传输 - */ - @Schema(description = "业务号") - private String businessNo; - } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundSyncResult.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundSyncResult.java new file mode 100644 index 00000000..30801e19 --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundSyncResult.java @@ -0,0 +1,16 @@ +package cn.bootx.platform.daxpay.result.pay; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 退款同步结果 + * @author xxm + * @since 2024/1/29 + */ +@Data +@Accessors(chain = true) +@Schema(title = "退款同步结果") +public class RefundSyncResult { +} 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 1519cad5..e197cfcd 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 @@ -11,7 +11,7 @@ import cn.bootx.platform.daxpay.result.pay.PaySyncResult; import cn.bootx.platform.daxpay.result.pay.RefundResult; import cn.bootx.platform.daxpay.service.annotation.PaymentApi; import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService; -import cn.bootx.platform.daxpay.service.core.order.refund.service.PayRefundQueryService; +import cn.bootx.platform.daxpay.service.core.order.refund.service.PayRefundOrderQueryService; import cn.bootx.platform.daxpay.service.core.payment.close.service.PayCloseService; import cn.bootx.platform.daxpay.service.core.payment.pay.service.PayService; import cn.bootx.platform.daxpay.service.core.payment.refund.service.PayRefundService; @@ -38,7 +38,7 @@ public class UniPayController { private final PaySyncService paySyncService; private final PayCloseService payCloseService; private final PayOrderQueryService PayOrderQueryService; - private final PayRefundQueryService payRefundQueryService; + private final PayRefundOrderQueryService payRefundQueryService; @CountTime diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayCode.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayCode.java index 20bdbfad..200a97cb 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayCode.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/AliPayCode.java @@ -53,9 +53,6 @@ public interface AliPayCode { /** 退款业务号 */ String OUT_BIZ_NO = "out_biz_no"; - /** 退款流水号 */ - - /** 退款金额 */ String REFUND_FEE = "refund_fee"; @@ -78,6 +75,10 @@ public interface AliPayCode { /** 交易结束,不可退款 */ String NOTIFY_TRADE_FINISHED = "TRADE_FINISHED"; + // 退款状态 + /** 退款成功 */ + String REFUND_SUCCESS = "REFUND_SUCCESS"; + // 错误提示 /** 交易不存在 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayCallbackService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayCallbackService.java index 7466bcd1..72ef0afe 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayCallbackService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayCallbackService.java @@ -143,7 +143,7 @@ public class AliPayCallbackService extends AbsCallbackStrategy { public PayCallbackTypeEnum getCallbackType() { CallbackLocal callback = PaymentContextLocal.get().getCallbackInfo(); Map callbackParam = callback.getCallbackParam(); - String refundFee = callbackParam.get("refund_fee"); + String refundFee = callbackParam.get(REFUND_FEE); // 如果有退款金额,说明是退款回调 if (StrUtil.isNotBlank(refundFee)){ return PayCallbackTypeEnum.REFUND; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPaySyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPaySyncService.java index e43e5479..dafb77cd 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPaySyncService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPaySyncService.java @@ -1,11 +1,14 @@ package cn.bootx.platform.daxpay.service.core.channel.alipay.service; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; +import cn.bootx.platform.daxpay.code.PayRefundSyncStatusEnum; import cn.bootx.platform.daxpay.code.PaySyncStatusEnum; import cn.bootx.platform.daxpay.service.code.AliPayCode; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder; import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; import cn.hutool.json.JSONUtil; import com.alipay.api.AlipayApiException; import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel; @@ -45,7 +48,6 @@ public class AliPaySyncService { AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel(); queryModel.setOutTradeNo(String.valueOf(payOrder.getId())); // queryModel.setQueryOptions(Collections.singletonList("trade_settle_info")); - // 查询参数 AlipayTradeQueryResponse response = AliPayApi.tradeQueryToResponse(queryModel); String tradeStatus = response.getTradeStatus(); syncResult.setSyncInfo(JSONUtil.toJsonStr(response)); @@ -77,7 +79,7 @@ public class AliPaySyncService { } } catch (AlipayApiException e) { - log.error("查询订单失败:", e); + log.error("支付订单同步失败:", e); syncResult.setErrorMsg(e.getErrMsg()); } return syncResult; @@ -86,10 +88,23 @@ public class AliPaySyncService { /** * 退款同步查询 */ - private void syncRefundStatus(PayOrder payOrder) throws AlipayApiException { - AlipayTradeFastpayRefundQueryModel queryModel = new AlipayTradeFastpayRefundQueryModel(); - queryModel.setOutTradeNo(String.valueOf(payOrder.getId())); - AlipayTradeFastpayRefundQueryResponse response = AliPayApi.tradeRefundQueryToResponse(queryModel); - response.getRefundStatus(); + public RefundGatewaySyncResult syncRefundStatus(PayRefundOrder refundOrder) { + RefundGatewaySyncResult syncResult = new RefundGatewaySyncResult().setSyncStatus(PayRefundSyncStatusEnum.FAIL); + try { + AlipayTradeFastpayRefundQueryModel queryModel = new AlipayTradeFastpayRefundQueryModel(); + queryModel.setOutTradeNo(String.valueOf(refundOrder.getId())); + AlipayTradeFastpayRefundQueryResponse response = AliPayApi.tradeRefundQueryToResponse(queryModel); + + syncResult.setSyncInfo(JSONUtil.toJsonStr(response)); + String tradeStatus = response.getRefundStatus(); + // 成功 + if (Objects.equals(tradeStatus, AliPayCode.NOTIFY_TRADE_SUCCESS)){ + return syncResult.setSyncStatus(PayRefundSyncStatusEnum.SUCCESS); + } + } catch (AlipayApiException e) { + log.error("退款订单同步失败:", e); + syncResult.setErrorMsg(e.getErrMsg()); + } + return syncResult; } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPaySyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPaySyncService.java index 8c71b95c..d1b86891 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPaySyncService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPaySyncService.java @@ -2,15 +2,18 @@ package cn.bootx.platform.daxpay.service.core.channel.wechat.service; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.code.PayRefundSyncStatusEnum; import cn.bootx.platform.daxpay.code.PaySyncStatusEnum; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.code.WeChatPayCode; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; -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.PayOrder; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder; import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; import cn.hutool.core.date.DatePattern; import cn.hutool.json.JSONUtil; import com.ijpay.core.enums.SignType; @@ -82,7 +85,8 @@ public class WeChatPaySyncService { // 已退款/退款中 触发一下退款记录的查询 if (Objects.equals(tradeStatus, WeChatPayCode.PAY_REFUND)) { - this.syncRefundStatus(order, weChatPayConfig); +// this.syncRefundStatus(order, weChatPayConfig); + // TODO 特殊处理, 提示用户走退款同步 } // 已关闭 if (Objects.equals(tradeStatus, WeChatPayCode.PAY_CLOSED) @@ -101,28 +105,25 @@ public class WeChatPaySyncService { /** * 退款查询 */ - private PayGatewaySyncResult syncRefundStatus(PayOrder order, WeChatPayConfig weChatPayConfig){ - PayChannelOrder orderChannel = payChannelOrderManager.findByPaymentIdAndChannel(order.getId(), PayChannelEnum.WECHAT.getCode()) + public RefundGatewaySyncResult syncRefundStatus(PayRefundOrder refundOrder, WeChatPayConfig weChatPayConfig){ + PayChannelOrder orderChannel = payChannelOrderManager.findByPaymentIdAndChannel(refundOrder.getId(), PayChannelEnum.WECHAT.getCode()) .orElseThrow(() -> new PayFailureException("支付订单通道信息不存在")); Map params = UnifiedOrderModel.builder() .appid(weChatPayConfig.getWxAppId()) .mch_id(weChatPayConfig.getWxMchId()) .nonce_str(WxPayKit.generateStr()) - .out_trade_no(String.valueOf(order.getId())) + .out_trade_no(String.valueOf(refundOrder.getId())) .build() .createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256); String xmlResult = WxPayApi.orderRefundQuery(false, params); Map result = WxPayKit.xmlToMap(xmlResult); - // 获取 + // TODO 处理退款同步的情况 - - - // 判断是否全部退款 Integer refundFee = Integer.valueOf(result.get(WeChatPayCode.REFUND_FEE)); if (Objects.equals(refundFee, orderChannel.getAmount())){ - return new PayGatewaySyncResult().setSyncStatus(PaySyncStatusEnum.REFUND); + return new RefundGatewaySyncResult().setSyncStatus(PayRefundSyncStatusEnum.REFUNDING); } - return new PayGatewaySyncResult().setSyncInfo(JSONUtil.toJsonStr(result)); + return new RefundGatewaySyncResult().setSyncInfo(JSONUtil.toJsonStr(result)); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java index fc77a1bc..e07ceabf 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java @@ -38,14 +38,14 @@ public class PayOrder extends MpBaseEntity implements EntityBaseFunction payOrderChannelOpt = - channelOrderManager.findByPaymentIdAndChannel(payOrder.getId(), payChannelParam.getChannel()); + // 判断新发起的 + Optional payOrderChannelOpt = channelOrderManager.findByPaymentIdAndChannel(payOrder.getId(), payChannelParam.getChannel()); if (!payOrderChannelOpt.isPresent()){ PayChannelOrder payChannelOrder = new PayChannelOrder(); // 替换原有的的支付通道信息 @@ -70,7 +70,7 @@ public class PayChannelOrderService { .setPayTime(LocalDateTime.now()) .setChannelExtra(payChannelParam.getChannelExtra()) .setStatus(payStatus.getCode()); - channelOrderManager.deleteByPaymentIdAndAsync(payChannelOrder.getId()); + channelOrderManager.deleteByPaymentIdAndAsync(payOrder.getId()); channelOrderManager.save(payChannelOrder); } else { // 更新支付通道信息 @@ -94,6 +94,7 @@ public class PayChannelOrderService { if (Objects.equals(refundChannelOrder.getStatus(), PayRefundStatusEnum.SUCCESS.getCode())){ PayStatusEnum status = refundableBalance == 0 ? PayStatusEnum.REFUNDED : PayStatusEnum.PARTIAL_REFUND; payChannelOrder.setStatus(status.getCode()); + refundChannelOrder.setRefundTime(LocalDateTime.now()); } else { payChannelOrder.setStatus(PayStatusEnum.REFUNDING.getCode()); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundChannelOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundChannelOrder.java index 01207941..6dae3849 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundChannelOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundChannelOrder.java @@ -1,7 +1,7 @@ package cn.bootx.platform.daxpay.service.core.order.refund.entity; import cn.bootx.platform.common.core.function.EntityBaseFunction; -import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; +import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.platform.daxpay.service.core.order.refund.convert.RefundOrderChannelConvert; import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto; @@ -12,6 +12,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.time.LocalDateTime; + /** * 支付退款订单关联通道信息 * @author xxm @@ -22,7 +24,7 @@ import lombok.experimental.Accessors; @DbTable(comment = "支付退款通道订单") @Accessors(chain = true) @TableName("pay_refund_channel_order") -public class PayRefundChannelOrder extends MpBaseEntity implements EntityBaseFunction { +public class PayRefundChannelOrder extends MpCreateEntity implements EntityBaseFunction { @DbColumn(comment = "关联退款id") private Long refundId; @@ -49,6 +51,8 @@ public class PayRefundChannelOrder extends MpBaseEntity implements EntityBaseFun @DbColumn(comment = "退款状态") private String status; + @DbColumn(comment = "退款时间") + private LocalDateTime refundTime; /** * 转换 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundOrder.java index d6296b2f..12d37f9b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/entity/PayRefundOrder.java @@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.order.refund.entity; import cn.bootx.platform.common.core.function.EntityBaseFunction; import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; +import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.platform.daxpay.service.core.order.refund.convert.PayRefundOrderConvert; import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto; @@ -41,6 +42,17 @@ public class PayRefundOrder extends MpBaseEntity implements EntityBaseFunction

new DataNotExistException("退款订单不存在")); + refundSyncService.syncPayOrder(refundOrder); + } + +} 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 fa4c6010..0ba250f7 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 @@ -192,12 +192,11 @@ public class PayAssistService { // 退款类型状态 tradesStatus = Arrays.asList(REFUNDED.getCode(), PARTIAL_REFUND.getCode(), REFUNDING.getCode()); if (tradesStatus.contains(payOrder.getStatus())) { - throw new PayFailureException("退款中"); + throw new PayFailureException("该订单处于退款状态"); } // 其他状态直接抛出兜底异常 throw new PayFailureException("订单不是待支付状态,请重新确认订单状态"); } return null; } - } 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 2a50c4ef..e54c6756 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 @@ -2,6 +2,8 @@ package cn.bootx.platform.daxpay.service.core.payment.refund.service; import cn.bootx.platform.common.core.exception.ValidationFailedException; import cn.bootx.platform.common.core.util.CollUtil; +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.param.pay.RefundChannelParam; @@ -27,6 +29,7 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; /** * 支付退款支撑服务 @@ -84,9 +87,9 @@ public class PayRefundAssistService { } /** - * 根据退款参数获取支付订单, 并进行检查 + * 检查并处理退款参数 */ - public void checkByRefundParam(RefundParam param, PayOrder payOrder){ + public void checkAndDisposeParam(RefundParam param, PayOrder payOrder){ // 全额退款和部分退款校验 if (!param.isRefundAll()) { if (CollUtil.isEmpty(param.getRefundChannels())) { @@ -112,6 +115,13 @@ public class PayRefundAssistService { throw new PayFailureException("当前状态["+statusEnum.getName()+"]不允许状态非法, 无法退款"); } + // 过滤掉金额为0的退款参数 + List channelParams = param.getRefundChannels() + .stream() + .filter(r -> r.getAmount() > 0) + .collect(Collectors.toList()); + param.setRefundChannels(channelParams); + // 退款号唯一校验 if (StrUtil.isNotBlank(param.getRefundNo()) && payRefundOrderManager.existsByRefundNo(param.getRefundNo())){ @@ -140,11 +150,28 @@ public class PayRefundAssistService { .setRefundTime(LocalDateTime.now()) .setTitle(payOrder.getTitle()) .setGatewayOrderNo(asyncRefundInfo.getGatewayOrderNo()) - .setErrorCode(asyncRefundInfo.getErrorCode()) - .setErrorMsg(asyncRefundInfo.getErrorMsg()) .setStatus(asyncRefundInfo.getStatus().getCode()) .setClientIp(refundParam.getClientIp()) .setReqId(PaymentContextLocal.get().getRequestInfo().getReqId()); + // 错误状态特殊处理 + if (asyncRefundInfo.getStatus() == PayRefundStatusEnum.FAIL){ + refundOrder.setErrorCode(asyncRefundInfo.getErrorCode()); + refundOrder.setErrorMsg(asyncRefundInfo.getErrorMsg()); + // 退款失败不保存剩余可退余额, 否则数据看起开会产生困惑 + refundOrder.setRefundableBalance(null); + } + + // 退款参数中是否存在异步通道 + RefundChannelParam asyncChannel = refundParam.getRefundChannels() + .stream() + .filter(r -> PayChannelEnum.ASYNC_TYPE_CODE.contains(r.getChannel())) + .findFirst() + .orElse(null); + if (Objects.nonNull(asyncChannel)){ + refundOrder.setAsyncChannel(asyncChannel.getChannel()); + refundOrder.setAsyncPay(true); + } + // 主键使用预先生成的ID, 如果有异步通道, 关联的退款号就是这个ID long refundId = asyncRefundInfo.getRefundId(); refundOrder.setId(refundId); 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 c2c98919..941d15a1 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 @@ -86,7 +86,7 @@ public class PayRefundService { // 获取支付订单 PayOrder payOrder = payRefundAssistService.getPayOrder(param); // 第一次检查退款参数, 校验一些特殊情况 - payRefundAssistService.checkByRefundParam(param, payOrder); + payRefundAssistService.checkAndDisposeParam(param, payOrder); // 组装退款参数, 处理全部退款和简单退款情况 List payChannelOrders = payChannelOrderManager.findAllByPaymentId(payOrder.getId()); @@ -126,6 +126,7 @@ public class PayRefundService { /** * 分支付通道进行退款 + * TODO 增加错误处理, 目前出现错误后存储的数据不全 */ public RefundResult refundByChannel(RefundParam refundParam, PayOrder payOrder, List payChannelOrders){ // 0.基础数据准备, 并比对通道支付单是否与可退款记录数量一致 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/AliPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/AliPayRefundStrategy.java index 43a7801c..9ef6a0fb 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/AliPayRefundStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/AliPayRefundStrategy.java @@ -12,6 +12,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; + import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/WeChatPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/WeChatPayRefundStrategy.java index c5d0b19f..6ff42323 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/WeChatPayRefundStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/WeChatPayRefundStrategy.java @@ -12,6 +12,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; + import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** @@ -68,6 +70,7 @@ public class WeChatPayRefundStrategy extends AbsRefundStrategy { .getRefundInfo() .getStatus(); this.getRefundChannelOrder().setStatus(refundStatusEnum.getCode()); + // 更新支付通道订单中的属性 payChannelOrderService.updateAsyncPayRefund(this.getPayChannelOrder(), this.getRefundChannelOrder()); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java index dd85ce17..74b76d99 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java @@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.payment.repair.service; import cn.bootx.platform.common.core.function.CollectorsFunction; import cn.bootx.platform.daxpay.code.PayStatusEnum; +import cn.bootx.platform.daxpay.service.code.PayRepairPayTypeEnum; import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; @@ -160,6 +161,7 @@ public class PayRepairService { .setOrderNo(order.getBusinessNo()) .setBeforeStatus(repairResult.getBeforeStatus().getCode()) .setAfterStatus(afterStatus) + .setRepairType(PayRepairPayTypeEnum.PAY.getCode()) .setRepairSource(source) .setRepairWay(recordType.getCode()); payRepairRecord.setId(repairResult.getRepairId()); 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 63294f2b..58133604 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 @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.Objects; import java.util.Optional; @@ -106,7 +107,8 @@ public class RefundRepairService { } // 设置退款为完成状态 refundOrder.setStatus(PayRefundStatusEnum.SUCCESS.getCode()); - refundChannelOrder.setStatus(PayRefundStatusEnum.SUCCESS.getCode()); + refundChannelOrder.setStatus(PayRefundStatusEnum.SUCCESS.getCode()) + .setRefundTime(LocalDateTime.now()); payOrder.setStatus(afterPayRefundStatus.getCode()); // 更新订单和退款相关订单 payChannelOrderManager.updateById(payChannelOrder); @@ -175,6 +177,8 @@ public class RefundRepairService { /** * 支付订单的修复记录 + * 支付完成 -> 退款 + * 退款 -> 全部退款 */ private PayRepairRecord payRepairRecord(PayOrder order, RefundRepairWayEnum repairType, RefundRepairResult repairResult){ // 修复后的状态 @@ -184,18 +188,20 @@ public class RefundRepairService { .getRepairInfo() .getSource().getCode(); return new PayRepairRecord() + .setRepairId(repairResult.getRepairId()) .setOrderId(order.getId()) .setRepairType(PayRepairPayTypeEnum.PAY.getCode()) + .setRepairSource(source) + .setRepairWay(repairType.getCode()) .setAsyncChannel(order.getAsyncChannel()) .setOrderNo(order.getBusinessNo()) .setBeforeStatus(repairResult.getAfterPayStatus().getCode()) - .setAfterStatus(afterStatus) - .setRepairSource(source) - .setRepairWay(repairType.getCode()); + .setAfterStatus(afterStatus); } /** * 退款订单的修复记录 + * 退款中 -> 退款成功 */ private PayRepairRecord refundRepairRecord(PayRefundOrder refundOrder, RefundRepairWayEnum repairType, RefundRepairResult repairResult){ // 修复后的状态 @@ -206,6 +212,7 @@ public class RefundRepairService { .getSource().getCode(); return new PayRepairRecord() .setOrderId(refundOrder.getId()) + .setRepairId(repairResult.getRepairId()) .setOrderNo(refundOrder.getRefundNo()) .setRepairType(PayRepairPayTypeEnum.REFUND.getCode()) .setBeforeStatus(repairResult.getBeforeRefundStatus().getCode()) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/PaySyncStrategyFactory.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/PaySyncStrategyFactory.java index a7ee58c9..e5620b12 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/PaySyncStrategyFactory.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/PaySyncStrategyFactory.java @@ -3,8 +3,8 @@ package cn.bootx.platform.daxpay.service.core.payment.sync.factory; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.service.func.AbsPaySyncStrategy; -import cn.bootx.platform.daxpay.service.core.payment.sync.strategy.AliPaySyncStrategy; -import cn.bootx.platform.daxpay.service.core.payment.sync.strategy.WeChatPaySyncStrategy; +import cn.bootx.platform.daxpay.service.core.payment.sync.strategy.pay.AliPaySyncStrategy; +import cn.bootx.platform.daxpay.service.core.payment.sync.strategy.pay.WeChatPaySyncStrategy; import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException; import cn.hutool.extra.spring.SpringUtil; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/RefundSyncStrategyFactory.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/RefundSyncStrategyFactory.java new file mode 100644 index 00000000..07484d6f --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/factory/RefundSyncStrategyFactory.java @@ -0,0 +1,39 @@ +package cn.bootx.platform.daxpay.service.core.payment.sync.factory; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException; +import cn.bootx.platform.daxpay.service.core.payment.sync.strategy.Refund.AliRefundSyncStrategy; +import cn.bootx.platform.daxpay.service.core.payment.sync.strategy.Refund.WeChatRefundSyncStrategy; +import cn.bootx.platform.daxpay.service.func.AbsRefundSyncStrategy; +import cn.hutool.extra.spring.SpringUtil; +import lombok.experimental.UtilityClass; + +/** + * 支付退款同步策略工厂 + * @author xxm + * @since 2024/1/29 + */ +@UtilityClass +public class RefundSyncStrategyFactory { + /** + * 获取支付同步策略, 只有异步支付方式才需要这个功能 + * @param channelCode 支付通道编码 + * @return 支付同步策略类 + */ + public static AbsRefundSyncStrategy create(String channelCode) { + AbsRefundSyncStrategy strategy; + PayChannelEnum channelEnum = PayChannelEnum.findByCode(channelCode); + switch (channelEnum) { + case ALI: + strategy = SpringUtil.getBean(AliRefundSyncStrategy.class); + break; + case WECHAT: + strategy = SpringUtil.getBean(WeChatRefundSyncStrategy.class); + break; + default: + throw new PayUnsupportedMethodException(); + } + // noinspection ConstantConditions + return strategy; + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/PayGatewaySyncResult.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/PayGatewaySyncResult.java index 4b9bbb85..f76b0c0a 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/PayGatewaySyncResult.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/PayGatewaySyncResult.java @@ -22,9 +22,12 @@ public class PayGatewaySyncResult { */ private PaySyncStatusEnum syncStatus = FAIL; - /** 同步支付时网关返回的对象, 序列化为json字符串 */ + /** 同步时网关返回的对象, 序列化为json字符串 */ private String syncInfo; + /** 错误提示码 */ + private String errorCode; + /** 错误提示 */ private String errorMsg; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/RefundGatewaySyncResult.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/RefundGatewaySyncResult.java index 0f73100f..f75277f2 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/RefundGatewaySyncResult.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/result/RefundGatewaySyncResult.java @@ -1,8 +1,11 @@ package cn.bootx.platform.daxpay.service.core.payment.sync.result; +import cn.bootx.platform.daxpay.code.PayRefundSyncStatusEnum; import lombok.Data; import lombok.experimental.Accessors; +import static cn.bootx.platform.daxpay.code.PayRefundSyncStatusEnum.FAIL; + /** * 支付退款同步结果 * @author xxm @@ -11,4 +14,19 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) public class RefundGatewaySyncResult { + + /** + * 支付网关订单状态 + * @see PayRefundSyncStatusEnum + */ + private PayRefundSyncStatusEnum syncStatus = FAIL; + + /** 同步时网关返回的对象, 序列化为json字符串 */ + private String syncInfo; + + /** 错误提示码 */ + private String errorCode; + + /** 错误提示 */ + private String errorMsg; } 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 new file mode 100644 index 00000000..a6c7a4c1 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PayRefundSyncService.java @@ -0,0 +1,108 @@ +package cn.bootx.platform.daxpay.service.core.payment.sync.service; + +import cn.bootx.platform.common.core.exception.RepetitiveOperationException; +import cn.bootx.platform.daxpay.code.PayRefundSyncStatusEnum; +import cn.bootx.platform.daxpay.exception.pay.PayFailureException; +import cn.bootx.platform.daxpay.param.pay.RefundSyncParam; +import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager; +import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder; +import cn.bootx.platform.daxpay.service.core.payment.sync.factory.RefundSyncStrategyFactory; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; +import cn.bootx.platform.daxpay.service.func.AbsRefundSyncStrategy; +import com.baomidou.lock.LockInfo; +import com.baomidou.lock.LockTemplate; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Objects; + +/** + * 支付退款同步服务类 + * @author xxm + * @since 2024/1/29 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class PayRefundSyncService { + private final PayRefundOrderManager refundOrderManager; + + private final LockTemplate lockTemplate; + + /** + * 退款同步, 开启一个新的事务, 不受外部抛出异常的影响 + */ + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void sync(RefundSyncParam param){ + // 先获取退款单 + PayRefundOrder requestOrder; + if (Objects.nonNull(param.getRefundId())){ + requestOrder = refundOrderManager.findById(param.getRefundId()) + .orElseThrow(() -> new PayFailureException("未查询到退款订单")); + } else { + requestOrder = refundOrderManager.findByRefundNo(param.getRefundNo()) + .orElseThrow(() -> new PayFailureException("未查询到退款订单")); + } + // 如果不是异步支付, 直接返回返回 + if (!requestOrder.isAsyncPay()){ + // TODO 需要限制同步的请求不进行同步 + return; + } + this.syncPayOrder(requestOrder); + + } + + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void syncPayOrder(PayRefundOrder refundOrder) { + // 加锁 + LockInfo lock = lockTemplate.lock("sync:refund:" + refundOrder.getId()); + if (Objects.isNull(lock)) { + throw new RepetitiveOperationException("退款同步处理中,请勿重复操作"); + } + + try { + // 获取支付同步策略类 + AbsRefundSyncStrategy syncPayStrategy = RefundSyncStrategyFactory.create(refundOrder.getAsyncChannel()); + syncPayStrategy.initRefundParam(refundOrder); + // 执行操作, 获取支付网关同步的结果 + RefundGatewaySyncResult syncResult = syncPayStrategy.doSyncStatus(); + + // 判断是否同步成功 + if (Objects.equals(syncResult.getSyncStatus(), PayRefundSyncStatusEnum.FAIL)) { + // 同步失败, 返回失败响应, 同时记录失败的日志 +// return new PaySyncResult().setErrorMsg(syncResult.getErrorMsg()); + log.error("同步失败"); + return; + } + + // 判断网关状态是否和支付单一致, 同时特定情况下更新网关同步状态 +// boolean statusSync = this.checkAndAdjustSyncStatus(syncResult, payOrder); +// PayRepairResult repairResult = new PayRepairResult(); +// try { +// // 状态不一致,执行支付单修复逻辑 +// if (!statusSync) { +// repairResult = this.resultHandler(syncResult, payOrder); +// } +// } catch (PayFailureException e) { +// // 同步失败, 返回失败响应, 同时记录失败的日志 +// syncResult.setSyncStatus(PaySyncStatusEnum.FAIL); +// this.saveRecord(payOrder, syncResult, false, null, e.getMessage()); +// return new PaySyncResult().setErrorMsg(e.getMessage()); +// } +// +// // 同步成功记录日志 +// this.saveRecord(payOrder, syncResult, !statusSync, repairResult.getRepairId(), null); +// return new PaySyncResult() +// .setGatewayStatus(syncResult.getSyncStatus() +// .getCode()) +// .setSuccess(true) +// .setRepair(!statusSync) +// .setRepairId(repairResult.getRepairId()); + } finally { + lockTemplate.releaseLock(lock); + } + } +} 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 8b9eff19..cf8db51c 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 @@ -79,11 +79,12 @@ public class PaySyncService { * 同步支付状态, 开启一个新的事务, 不受外部抛出异常的影响 * 1. 如果状态一致, 不进行处理 * 2. 如果状态不一致, 调用修复逻辑进行修复 + * todo 需要进行异常处理, 现在会有 Transaction rolled back because it has been marked as rollback-only 问题 */ @Transactional(propagation = Propagation.REQUIRES_NEW) public PaySyncResult syncPayOrder(PayOrder payOrder) { // 加锁 - LockInfo lock = lockTemplate.lock("payment:refund:" + payOrder.getId()); + LockInfo lock = lockTemplate.lock("sync:payment" + payOrder.getId()); if (Objects.isNull(lock)){ throw new RepetitiveOperationException("支付同步处理中,请勿重复操作"); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/AliRefundSyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/AliRefundSyncStrategy.java new file mode 100644 index 00000000..3e37829f --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/AliRefundSyncStrategy.java @@ -0,0 +1,49 @@ +package cn.bootx.platform.daxpay.service.core.payment.sync.strategy.Refund; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.code.PaySyncStatusEnum; +import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig; +import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService; +import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPaySyncService; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; +import cn.bootx.platform.daxpay.service.func.AbsRefundSyncStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 支付宝退款同步策略 + * @author xxm + * @since 2024/1/29 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class AliRefundSyncStrategy extends AbsRefundSyncStrategy { + + private final AliPayConfigService alipayConfigService; + + private final AliPaySyncService aliPaySyncService;; + + /** + * 策略标识 + */ + @Override + public PayChannelEnum getChannel() { + return PayChannelEnum.ALI; + } + + /** + * 异步支付单与支付网关进行状态比对后的结果 + * + * @see PaySyncStatusEnum + */ + @Override + public RefundGatewaySyncResult doSyncStatus() { + AliPayConfig config = alipayConfigService.getConfig(); + alipayConfigService.initConfig(config); + return aliPaySyncService.syncRefundStatus(this.getRefundOrder()); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/WeChatRefundSyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/WeChatRefundSyncStrategy.java new file mode 100644 index 00000000..ff45f03f --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/Refund/WeChatRefundSyncStrategy.java @@ -0,0 +1,38 @@ +package cn.bootx.platform.daxpay.service.core.payment.sync.strategy.Refund; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; +import cn.bootx.platform.daxpay.service.func.AbsRefundSyncStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 微信退款同步策略 + * @author xxm + * @since 2024/1/29 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class WeChatRefundSyncStrategy extends AbsRefundSyncStrategy { + + /** + * 策略标识 + */ + @Override + public PayChannelEnum getChannel() { + return PayChannelEnum.WECHAT; + } + + /** + * 异步支付单与支付网关进行状态比对后的结果 + */ + @Override + public RefundGatewaySyncResult doSyncStatus() { + return null; + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/AliPaySyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/AliPaySyncStrategy.java similarity index 99% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/AliPaySyncStrategy.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/AliPaySyncStrategy.java index c525acb4..f4be83fe 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/AliPaySyncStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/AliPaySyncStrategy.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.service.core.payment.sync.strategy; +package cn.bootx.platform.daxpay.service.core.payment.sync.strategy.pay; import cn.bootx.platform.daxpay.code.PayChannelEnum; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/WeChatPaySyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/WeChatPaySyncStrategy.java similarity index 99% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/WeChatPaySyncStrategy.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/WeChatPaySyncStrategy.java index 134cc4b2..eee5b660 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/WeChatPaySyncStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/WeChatPaySyncStrategy.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.service.core.payment.sync.strategy; +package cn.bootx.platform.daxpay.service.core.payment.sync.strategy.pay; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayExpiredTimeTask.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayExpiredTimeTask.java index 262e5caf..5b62ffb3 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayExpiredTimeTask.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayExpiredTimeTask.java @@ -1,6 +1,5 @@ package cn.bootx.platform.daxpay.service.core.timeout.task; -import cn.bootx.platform.common.core.exception.RepetitiveOperationException; import cn.bootx.platform.daxpay.param.pay.PaySyncParam; import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService; import cn.bootx.platform.daxpay.service.core.timeout.dao.PayExpiredTimeRepository; @@ -8,6 +7,7 @@ import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.time.LocalDateTime; @@ -29,14 +29,19 @@ public class PayExpiredTimeTask { private final LockTemplate lockTemplate; -// @Scheduled(cron = "*/5 * * * * ?") + /** + * 先使用定时任务实现, 五秒轮训一下 + * + */ + @Scheduled(cron = "*/5 * * * * ?") public void task(){ log.debug("执行超时取消任务...."); Set expiredKeys = repository.getExpiredKeys(LocalDateTime.now()); for (String expiredKey : expiredKeys) { LockInfo lock = lockTemplate.lock("payment:expired:" + expiredKey,10000,0); if (Objects.isNull(lock)){ - throw new RepetitiveOperationException("支付同步处理中,请勿重复操作"); + log.warn("支付同步处理中,执行下一个"); + continue; } try { // 执行同步操作, 网关同步时会对支付的进行状态的处理 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayWaitOrderSyncTask.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayWaitOrderSyncTask.java index 7790d5cf..cffd068e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayWaitOrderSyncTask.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/timeout/task/PayWaitOrderSyncTask.java @@ -14,7 +14,7 @@ import java.util.Objects; import java.util.Set; /** - * + * 待支付订单的状态同步, 先不进行启用 * @author xxm * @since 2024/1/5 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/PayRefundOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/PayRefundOrderDto.java index add6baab..536b2e25 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/PayRefundOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/PayRefundOrderDto.java @@ -1,6 +1,7 @@ package cn.bootx.platform.daxpay.service.dto.order.refund; import cn.bootx.platform.common.core.rest.dto.BaseDto; +import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -31,6 +32,16 @@ public class PayRefundOrderDto extends BaseDto { @Schema(description = "退款号") private String refundNo; + @Schema(description = "是否含有异步通道") + private boolean asyncPay; + + /** + * 异步通道 + * @see PayChannelEnum#ASYNC_TYPE_CODE + */ + @Schema(description = "异步通道") + private String asyncChannel; + @Schema(description = "支付网关订单号") private String gatewayOrderNo; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundChannelOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundChannelOrderDto.java index c2437624..5b76bafb 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundChannelOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/refund/RefundChannelOrderDto.java @@ -1,6 +1,7 @@ package cn.bootx.platform.daxpay.service.dto.order.refund; import cn.bootx.platform.common.core.rest.dto.BaseDto; +import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.table.modify.annotation.DbColumn; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -36,4 +37,11 @@ public class RefundChannelOrderDto extends BaseDto { @Schema(description = "退款金额") private Integer amount; + + /** + * 退款状态 + * @see PayRefundStatusEnum + */ + @Schema(description = "退款状态") + private String status; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsCallbackStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsCallbackStrategy.java index 6ba68c86..1b8294ba 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsCallbackStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsCallbackStrategy.java @@ -14,6 +14,7 @@ import lombok.extern.slf4j.Slf4j; import javax.annotation.Resource; import java.util.Map; +import java.util.Optional; /** * 回调处理抽象类, 处理支付回调和退款回调 @@ -32,35 +33,42 @@ public abstract class AbsCallbackStrategy implements PayStrategy { /** * 回调处理入口 + * TODO 需要处理异常情况进行保存 */ public String callback(Map params) { - // 将参数写入到上下文中 CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo(); - callbackInfo.getCallbackParam().putAll(params); - // 验证消息 - if (!this.verifyNotify()) { - callbackInfo.setCallbackStatus(PayCallbackStatusEnum.FAIL).setMsg("验证信息格式不通过"); - // 消息有问题, 保存记录并返回 - this.saveCallbackRecord(); - return null; - } - // 提前设置订单修复的来源 - PaymentContextLocal.get().getRepairInfo().setSource(PayRepairSourceEnum.CALLBACK); + try { + // 将参数写入到上下文中 + callbackInfo.getCallbackParam().putAll(params); + // 验证消息 + if (!this.verifyNotify()) { + callbackInfo.setCallbackStatus(PayCallbackStatusEnum.FAIL).setMsg("验证信息格式不通过"); + // 消息有问题, 保存记录并返回 + this.saveCallbackRecord(); + return null; + } + // 提前设置订单修复的来源 + PaymentContextLocal.get().getRepairInfo().setSource(PayRepairSourceEnum.CALLBACK); - // 判断回调类型 - PayCallbackTypeEnum callbackType = this.getCallbackType(); - if (callbackType == PayCallbackTypeEnum.PAY){ - // 解析支付数据并放处理 - this.resolvePayData(); - payCallbackService.payCallback(); - } else { - // 解析退款数据并放处理 - this.resolveRefundData(); - refundCallbackService.refundCallback(); + // 判断回调类型 + PayCallbackTypeEnum callbackType = this.getCallbackType(); + if (callbackType == PayCallbackTypeEnum.PAY){ + // 解析支付数据并放处理 + this.resolvePayData(); + payCallbackService.payCallback(); + } else { + // 解析退款数据并放处理 + this.resolveRefundData(); + refundCallbackService.refundCallback(); + } + this.saveCallbackRecord(); + return this.getReturnMsg(); + } catch (Exception e) { + log.error("回调处理失败", e); + callbackInfo.setCallbackStatus(PayCallbackStatusEnum.FAIL).setMsg("回调处理失败: "+e.getMessage()); + this.saveCallbackRecord(); + throw e; } - // 记录回调记录 - this.saveCallbackRecord(); - return this.getReturnMsg(); } /** @@ -94,12 +102,18 @@ public abstract class AbsCallbackStrategy implements PayStrategy { */ public void saveCallbackRecord() { CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo(); + + // 回调类型 + String callbackType = Optional.ofNullable(this.getCallbackType()) + .map(PayCallbackTypeEnum::getCode) + .orElse(null); + PayCallbackRecord payNotifyRecord = new PayCallbackRecord() .setPayChannel(this.getChannel().getCode()) .setNotifyInfo(JSONUtil.toJsonStr(callbackInfo.getCallbackParam())) .setOrderId(callbackInfo.getOrderId()) .setGatewayOrderNo(callbackInfo.getGatewayOrderNo()) - .setCallbackType(this.getCallbackType().getCode()) + .setCallbackType(callbackType) .setRepairOrderId(callbackInfo.getPayRepairId()) .setStatus(callbackInfo.getCallbackStatus().getCode()) .setMsg(callbackInfo.getMsg()); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundRepairStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundRepairStrategy.java index ed2c6868..35c6c15f 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundRepairStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundRepairStrategy.java @@ -4,6 +4,7 @@ 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.refund.entity.PayRefundChannelOrder; import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; import lombok.Getter; /** @@ -31,15 +32,10 @@ public abstract class AbsRefundRepairStrategy implements PayStrategy{ this.payChannelOrder = payChannelOrder; } - /** - * 修复前处理 - */ - public void doBeforeHandler(){ - - } /** - * 支付成功修复 + * 异步支付单与支付网关进行状态比对后的结果 */ + public abstract RefundGatewaySyncResult doSyncStatus(); } 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 9e532d9a..3b48079b 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 @@ -10,6 +10,8 @@ import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChanne import lombok.Getter; import lombok.Setter; +import java.time.LocalDateTime; + /** * 抽象支付退款策略基类 * @@ -59,7 +61,8 @@ public abstract class AbsRefundStrategy implements PayStrategy{ */ public void doSuccessHandler() { // 更新退款订单数据状态 - this.refundChannelOrder.setStatus(PayRefundStatusEnum.SUCCESS.getCode()); + this.refundChannelOrder.setStatus(PayRefundStatusEnum.SUCCESS.getCode()) + .setRefundTime(LocalDateTime.now()); // 支付通道订单客可退余额 int refundableBalance = this.getPayChannelOrder().getRefundableBalance() - this.refundChannelOrder.getAmount(); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundSyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundSyncStrategy.java index 91c27e3b..79ab15da 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundSyncStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsRefundSyncStrategy.java @@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.service.func; import cn.bootx.platform.daxpay.code.PaySyncStatusEnum; import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder; -import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult; +import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; import lombok.Getter; /** @@ -18,7 +18,7 @@ public abstract class AbsRefundSyncStrategy implements PayStrategy{ /** * 初始化参数 */ - public void initParam(PayRefundOrder refundOrder){ + public void initRefundParam(PayRefundOrder refundOrder){ this.refundOrder = refundOrder; } @@ -26,5 +26,5 @@ public abstract class AbsRefundSyncStrategy implements PayStrategy{ * 异步支付单与支付网关进行状态比对后的结果 * @see PaySyncStatusEnum */ - public abstract PayGatewaySyncResult doSyncStatus(); + public abstract RefundGatewaySyncResult doSyncStatus(); }