From 325d5e6b121cb95420bc96ccfd0b69050d7bf26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com> Date: Sat, 5 Oct 2024 21:32:36 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E3=80=91=E5=AE=8C=E6=88=90=E8=BD=AC=E8=B4=A6=E5=9B=9E=E8=B0=83?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/BrokerageRecordController.java | 2 +- .../BrokerageWithdrawController.java | 5 +- .../vo/record/BrokerageRecordRespVO.java | 2 +- .../BrokerageWithdrawRejectReqVO.java | 2 +- .../vo/withdraw/BrokerageWithdrawRespVO.java | 2 +- .../brokerage/BrokerageWithdrawMapper.java | 2 +- .../brokerage/BrokerageRecordService.java | 2 +- .../brokerage/BrokerageRecordServiceImpl.java | 2 +- .../brokerage/BrokerageWithdrawService.java | 10 +- .../BrokerageWithdrawServiceImpl.java | 41 ++++-- .../pay/api/transfer/PayTransferApi.java | 7 + .../api/transfer/dto/PayTransferRespDTO.java | 32 +++++ .../pay/api/transfer/PayTransferApiImpl.java | 9 ++ .../admin/notify/PayNotifyController.java | 24 ++++ .../convert/transfer/PayTransferConvert.java | 5 +- .../dal/mysql/transfer/PayTransferMapper.java | 7 + .../framework/pay/config/PayProperties.java | 9 ++ .../framework/pay/core/WalletPayClient.java | 5 + .../pay/service/refund/PayRefundService.java | 1 - .../service/refund/PayRefundServiceImpl.java | 2 + .../service/transfer/PayTransferService.java | 9 ++ .../transfer/PayTransferServiceImpl.java | 32 +++-- .../framework/pay/core/client/PayClient.java | 11 ++ .../WxPayTransferPartnerNotifyV3Result.java | 128 ++++++++++++++++++ .../core/client/impl/AbstractPayClient.java | 16 +++ .../impl/alipay/AbstractAlipayPayClient.java | 5 + .../impl/alipay/AlipayAppPayClient.java | 2 + .../impl/alipay/AlipayBarPayClient.java | 2 + .../client/impl/alipay/AlipayPcPayClient.java | 2 + .../core/client/impl/mock/MockPayClient.java | 5 + .../impl/weixin/AbstractWxPayClient.java | 33 ++++- .../src/main/resources/application-dev.yaml | 3 +- .../src/main/resources/application-local.yaml | 1 + 33 files changed, 378 insertions(+), 42 deletions(-) create mode 100644 yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java create mode 100644 yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageRecordController.java index bcf46d1dfe..cbb8a6b22c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageRecordController.java @@ -44,7 +44,7 @@ public class BrokerageRecordController { @Operation(summary = "获得佣金记录") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") - public CommonResult getBrokerageRecord(@RequestParam("id") Integer id) { + public CommonResult getBrokerageRecord(@RequestParam("id") Long id) { BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id); return success(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java index 8c1b60f06b..9b865ae953 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java @@ -45,7 +45,7 @@ public class BrokerageWithdrawController { @PutMapping("/approve") @Operation(summary = "通过申请") @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')") - public CommonResult approveBrokerageWithdraw(@RequestParam("id") Integer id) { + public CommonResult approveBrokerageWithdraw(@RequestParam("id") Long id) { brokerageWithdrawService.auditBrokerageWithdraw(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "", getClientIP()); return success(true); } @@ -62,7 +62,7 @@ public class BrokerageWithdrawController { @Operation(summary = "获得佣金提现") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:query')") - public CommonResult getBrokerageWithdraw(@RequestParam("id") Integer id) { + public CommonResult getBrokerageWithdraw(@RequestParam("id") Long id) { BrokerageWithdrawDO brokerageWithdraw = brokerageWithdrawService.getBrokerageWithdraw(id); return success(BrokerageWithdrawConvert.INSTANCE.convert(brokerageWithdraw)); } @@ -87,6 +87,7 @@ public class BrokerageWithdrawController { // 目前业务逻辑,不需要做任何事情 // 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警 log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO); + brokerageWithdrawService.updateTransfer(Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId()); return success(true); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordRespVO.java index 224ecf1e53..0012eb9ce7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordRespVO.java @@ -14,7 +14,7 @@ import java.time.LocalDateTime; public class BrokerageRecordRespVO extends BrokerageRecordBaseVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896") - private Integer id; + private Long id; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRejectReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRejectReqVO.java index 7de2b7d7f2..a0967f19b9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRejectReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRejectReqVO.java @@ -14,7 +14,7 @@ public class BrokerageWithdrawRejectReqVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161") @NotNull(message = "编号不能为空") - private Integer id; + private Long id; @Schema(description = "审核驳回原因", example = "不对") @NotEmpty(message = "审核驳回原因不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRespVO.java index de74bb4f6c..0abd77e69a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRespVO.java @@ -14,7 +14,7 @@ import java.time.LocalDateTime; public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161") - private Integer id; + private Long id; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageWithdrawMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageWithdrawMapper.java index 9e2cf68ad1..dc2b009160 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageWithdrawMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageWithdrawMapper.java @@ -35,7 +35,7 @@ public interface BrokerageWithdrawMapper extends BaseMapperX() .eq(BrokerageWithdrawDO::getId, id) .eq(BrokerageWithdrawDO::getStatus, status)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java index 5869889f26..bc1f3aa6bd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java @@ -32,7 +32,7 @@ public interface BrokerageRecordService { * @param id 编号 * @return 佣金记录 */ - BrokerageRecordDO getBrokerageRecord(Integer id); + BrokerageRecordDO getBrokerageRecord(Long id); /** * 获得佣金记录分页 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java index 26e18c7bd7..6406f5d7ed 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java @@ -64,7 +64,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { private ProductSkuApi productSkuApi; @Override - public BrokerageRecordDO getBrokerageRecord(Integer id) { + public BrokerageRecordDO getBrokerageRecord(Long id) { return brokerageRecordMapper.selectById(id); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawService.java index 865b4c97b1..0fc2b401ff 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawService.java @@ -28,7 +28,7 @@ public interface BrokerageWithdrawService { * @param status 审核状态 * @param auditReason 驳回原因 */ - void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp); + void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp); /** * 获得佣金提现 @@ -36,7 +36,7 @@ public interface BrokerageWithdrawService { * @param id 编号 * @return 佣金提现 */ - BrokerageWithdrawDO getBrokerageWithdraw(Integer id); + BrokerageWithdrawDO getBrokerageWithdraw(Long id); /** * 获得佣金提现分页 @@ -77,4 +77,10 @@ public interface BrokerageWithdrawService { return convertMap(getWithdrawSummaryListByUserId(userIds, status), BrokerageWithdrawSummaryRespBO::getUserId); } + /** + * + * @param merchantTransferId 提现编号 + * @param payTransferId 转账订单编号 + */ + void updateTransfer(Long merchantTransferId, Long payTransferId); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java index 7799b41fa6..ee82f4f31f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi; import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO; +import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum; import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum; import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; @@ -39,7 +41,6 @@ import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO.TRADE_ORDER_NO_PREFIX; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** @@ -76,7 +77,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @Override @Transactional(rollbackFor = Exception.class) - public void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) { + public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) { // 1.1 校验存在 BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id); @@ -105,7 +106,6 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { PayTransferCreateReqDTO payTransferCreateReqDTO = getPayTransferCreateReqDTO(userIp, withdraw, socialUser); payTransferApi.createTransfer(payTransferCreateReqDTO); } - // TODO 疯狂:调用转账接口 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) { templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT; // 3.2 驳回时需要退还用户佣金 @@ -116,13 +116,13 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { } // 4. 通知用户 - Map templateParams = MapUtil.builder() - .put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime())) - .put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice())) - .put("reason", auditReason) - .build(); - notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO() - .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams)); +// Map templateParams = MapUtil.builder() +// .put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime())) +// .put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice())) +// .put("reason", auditReason) +// .build(); +// notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO() +// .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams)); } private PayTransferCreateReqDTO getPayTransferCreateReqDTO(String userIp, BrokerageWithdrawDO withdraw, SocialUserRespDTO socialUser) { @@ -138,7 +138,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { return payTransferCreateReqDTO; } - private BrokerageWithdrawDO validateBrokerageWithdrawExists(Integer id) { + private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) { BrokerageWithdrawDO withdraw = brokerageWithdrawMapper.selectById(id); if (withdraw == null) { throw exception(BROKERAGE_WITHDRAW_NOT_EXISTS); @@ -147,7 +147,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { } @Override - public BrokerageWithdrawDO getBrokerageWithdraw(Integer id) { + public BrokerageWithdrawDO getBrokerageWithdraw(Long id) { return brokerageWithdrawMapper.selectById(id); } @@ -186,6 +186,23 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus()); } + @Override + public void updateTransfer(Long id, Long payTransferId) { + BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id); + PayTransferRespDTO transfer = payTransferApi.getTransfer(payTransferId); + if(PayTransferStatusEnum.isSuccess(transfer.getStatus())){ + withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()); + }else if(PayTransferStatusEnum.isPendingStatus(transfer.getStatus())){ + withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus()); + }else{ + withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus()); + // 3.2 驳回时需要退还用户佣金 + brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT, + String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle()); + } + brokerageWithdrawMapper.updateById(withdraw); + } + /** * 计算提现手续费 * diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java index 7f000be74d..2139f08ef0 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.api.transfer; import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO; import jakarta.validation.Valid; /** @@ -19,4 +20,10 @@ public interface PayTransferApi { */ Long createTransfer(@Valid PayTransferCreateReqDTO reqDTO); + /** + * 获取转账单详细 + * @param id 转账单编号 + * @return 转账单详细 + */ + PayTransferRespDTO getTransfer(Long id); } diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java new file mode 100644 index 0000000000..4969da6bd8 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.pay.api.transfer.dto; + +import lombok.Data; + +@Data +public class PayTransferRespDTO { + + /** + * 编号 + */ + private Long id; + + /** + * 转账单号 + * + */ + private String no; + + /** + * 转账金额,单位:分 + */ + private Integer price; + + /** + * 转账状态 + * + * 枚举 {@link PayTransferStatusRespEnum} + */ + private Integer status; + + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java index 5e6a3dcdb7..7c6cf5d758 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.pay.api.transfer; import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO; +import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -24,4 +27,10 @@ public class PayTransferApiImpl implements PayTransferApi { return payTransferService.createTransfer(reqDTO); } + @Override + public PayTransferRespDTO getTransfer(Long id) { + PayTransferDO transfer = payTransferService.getTransfer(id); + return PayTransferConvert.INSTANCE.convert3(transfer); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java index 631cd7562b..0f707f0ee8 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; @@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; +import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -49,6 +51,8 @@ public class PayNotifyController { @Resource private PayRefundService refundService; @Resource + private PayTransferService payTransferService; + @Resource private PayNotifyService notifyService; @Resource private PayAppService appService; @@ -95,6 +99,26 @@ public class PayNotifyController { return "success"; } + @PostMapping(value = "/transfer/{channelId}") + @Operation(summary = "支付渠道的统一【转账】回调") + @PermitAll + public String notifyTransfer(@PathVariable("channelId") Long channelId, + @RequestParam(required = false) Map params, + @RequestBody(required = false) String body) { + log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body); + // 1. 校验支付渠道是否存在 + PayClient payClient = channelService.getPayClient(channelId); + if (payClient == null) { + log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); + throw exception(CHANNEL_NOT_FOUND); + } + + // 2. 解析通知数据 + PayTransferRespDTO notify = payClient.parseTransferNotify(params, body); + payTransferService.notifyTransfer(channelId, notify); + return "success"; + } + @GetMapping("/get-detail") @Operation(summary = "获得回调通知的明细") @Parameter(name = "id", description = "编号", required = true, example = "1024") diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java index 4e79548d0d..73bb57a997 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.transfer; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageItemRespVO; @@ -24,7 +25,9 @@ public interface PayTransferConvert { PayTransferCreateReqDTO convert(PayDemoTransferCreateReqVO vo); - PayTransferRespVO convert(PayTransferDO bean); + PayTransferRespVO convert(PayTransferDO bean); + + PayTransferRespDTO convert3(PayTransferDO bean); PageResult convertPage(PageResult pageResult); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java index af4f6debf7..a4845e0f82 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; @@ -44,6 +45,12 @@ public interface PayTransferMapper extends BaseMapperX { default List selectListByStatus(Integer status){ return selectList(PayTransferDO::getStatus, status); } + + default PayTransferDO selectByAppIdAndNo(Long appId, String no){ + return selectOne(new LambdaQueryWrapperX() + .eq(PayTransferDO::getAppId, appId) + .eq(PayTransferDO::getNo, no)); + } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/config/PayProperties.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/config/PayProperties.java index d124bbfc51..84905a5325 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/config/PayProperties.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/config/PayProperties.java @@ -39,6 +39,15 @@ public class PayProperties { @URL(message = "支付回调地址的格式必须是 URL") private String refundNotifyUrl; + /** + * 转账回调地址 + * + * 实际上,对应的 PayNotifyController 的 notifyTransfer 方法的 URL + * + * 回调顺序:支付渠道(支付宝支付、微信支付) => yudao-module-pay 的 transferNotifyUrl 地址 => 业务的 PayAppDO.transferNotifyUrl 地址 + */ + private String transferNotifyUrl; + /** * 支付订单 no 的前缀 */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java index c7be35f1ab..63fc92ba3c 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java @@ -177,6 +177,11 @@ public class WalletPayClient extends AbstractPayClient { throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo)); } + @Override + protected PayTransferRespDTO doParseTransferNotify(Map params, String body) throws Throwable { + throw new UnsupportedOperationException("未实现"); + } + @Override public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { throw new UnsupportedOperationException("待实现"); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java index 258cea9640..7515e7747e 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java @@ -78,5 +78,4 @@ public interface PayRefundService { * @return 同步到状态的退款数量,包括退款成功、退款失败 */ int syncRefund(); - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java index 8df7f88615..b0c1c3d306 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java @@ -193,6 +193,8 @@ public class PayRefundServiceImpl implements PayRefundService { TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyRefund(channel, notify)); } + + /** * 通知并更新订单的退款结果 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java index d3bc982e44..8168050d12 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.pay.service.transfer; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO; @@ -54,4 +55,12 @@ public interface PayTransferService { * @return 同步到状态的转账数量,包括转账成功、转账失败、转账中的 */ int syncTransfer(); + + /** + * 渠道的转账通知 + * + * @param channelId 渠道编号 + * @param notify 通知 + */ + void notifyTransfer(Long channelId, PayTransferRespDTO notify); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java index 04d86d1848..f6486b1886 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper; import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum; +import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; @@ -28,6 +29,7 @@ import jakarta.annotation.Resource; import jakarta.validation.Validator; 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.List; @@ -50,6 +52,9 @@ public class PayTransferServiceImpl implements PayTransferService { private static final String TRANSFER_NO_PREFIX = "T"; + @Resource + private PayProperties payProperties; + @Resource private PayTransferMapper transferMapper; @Resource @@ -104,7 +109,7 @@ public class PayTransferServiceImpl implements PayTransferService { // 3. 调用三方渠道发起转账 PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(transfer) .setOutTransferNo(transfer.getNo()); - transferUnifiedReq.setNotifyUrl(payApp.getTransferNotifyUrl()); + transferUnifiedReq.setNotifyUrl(genChannelTransferNotifyUrl(channel)); PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq); // 4. 通知转账结果 getSelf().notifyTransfer(channel, unifiedTransferResp); @@ -118,6 +123,16 @@ public class PayTransferServiceImpl implements PayTransferService { return transfer.getId(); } + /** + * 根据支付渠道的编码,生成支付渠道的回调地址 + * + * @param channel 支付渠道 + * @return 支付渠道的回调地址 配置地址 + "/" + channel id + */ + private String genChannelTransferNotifyUrl(PayChannelDO channel) { + return payProperties.getTransferNotifyUrl() + "/" + channel.getId(); + } + private PayTransferDO validateTransferCanCreate(PayTransferCreateReqDTO dto, Long appId) { PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, dto.getMerchantTransferId()); if (transfer != null) { @@ -156,7 +171,8 @@ public class PayTransferServiceImpl implements PayTransferService { private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) { // 1.校验 - PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); + PayTransferDO transfer = transferMapper.selectByAppIdAndNo( + channel.getAppId(), notify.getOutTransferNo()); if (transfer == null) { throw exception(PAY_TRANSFER_NOT_FOUND); } @@ -174,16 +190,13 @@ public class PayTransferServiceImpl implements PayTransferService { throw exception(PAY_TRANSFER_STATUS_IS_NOT_WAITING); } log.info("[notifyTransferInProgress][transfer({}) 更新为转账进行中状态]", transfer.getId()); - - // 3. 插入转账通知记录 - notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(), - transfer.getId()); } private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) { // 1.校验 - PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); + PayTransferDO transfer = transferMapper.selectByAppIdAndNo( + channel.getAppId(), notify.getOutTransferNo()); if (transfer == null) { throw exception(PAY_TRANSFER_NOT_FOUND); } @@ -212,7 +225,8 @@ public class PayTransferServiceImpl implements PayTransferService { private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { // 1.校验 - PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); + PayTransferDO transfer = transferMapper.selectByAppIdAndNo( + channel.getAppId(), notify.getOutTransferNo()); if (transfer == null) { throw exception(PAY_TRANSFER_NOT_FOUND); } @@ -285,7 +299,7 @@ public class PayTransferServiceImpl implements PayTransferService { } } - private void notifyTransfer(Long channelId, PayTransferRespDTO notify) { + public void notifyTransfer(Long channelId, PayTransferRespDTO notify) { // 校验渠道是否有效 PayChannelDO channel = channelService.validPayChannel(channelId); // 通知转账结果给对应的业务 diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java index 86e3566b2b..413f568834 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java @@ -79,6 +79,8 @@ public interface PayClient { */ PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo); + // ============ 转账相关 ========== + /** * 调用渠道,进行转账 * @@ -95,4 +97,13 @@ public interface PayClient { * @return 转账信息 */ PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type); + + /** + * 解析 transfer 回调数据 + * + * @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数 + * @param body HTTP 回调接口的 request body + * @return 转账信息 + */ + PayTransferRespDTO parseTransferNotify(Map params, String body); } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java new file mode 100644 index 0000000000..b0431a0d77 --- /dev/null +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.framework.pay.core.client.dto.transfer; + +import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse; +import com.github.binarywang.wxpay.bean.notify.WxPayBaseNotifyV3Result; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@NoArgsConstructor +public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result { + + private static final long serialVersionUID = -1L; + + /** + * 源数据 + */ + private OriginNotifyResponse rawData; + + /** + * 解密后的数据 + */ + private TransferNotifyResult result; + + @Override + public void setRawData(OriginNotifyResponse rawData) { + this.rawData = rawData; + } + + @Override + public void setResult(TransferNotifyResult data) { + this.result = data; + } + + public TransferNotifyResult getResult() { + return result; + } + + public OriginNotifyResponse getRawData() { + return rawData; + } + + @Data + @NoArgsConstructor + public static class TransferNotifyResult implements Serializable { + private static final long serialVersionUID = 1L; + + /*********************** 公共字段 ******************** + + /** + * 商家批次单号 + */ + @SerializedName(value = "out_batch_no") + protected String outBatchNo; + + /** + * 微信批次单号 + */ + @SerializedName(value = "batch_id") + protected String batchId; + + /** + * 批次状态 + */ + @SerializedName(value = "batch_status") + protected String batchStatus; + + /** + * 批次总笔数 + */ + @SerializedName(value = "total_num") + protected Integer totalNum; + + /** + * 批次总金额 + */ + @SerializedName(value = "total_amount") + protected Integer totalAmount; + + /** + * 批次更新时间 + */ + @SerializedName(value = "update_time") + private String updateTime; + + /*********************** FINISHED ******************** + + /** + * 转账成功金额 + */ + @SerializedName(value = "success_amount") + protected Integer successAmount; + + /** + * 转账成功笔数 + */ + @SerializedName(value = "success_num") + protected Integer successNum; + + /** + * 转账失败金额 + */ + @SerializedName(value = "fail_amount") + protected Integer failAmount; + + /** + * 转账失败笔数 + */ + @SerializedName(value = "fail_num") + protected Integer failNum; + + /*********************** CLOSED ******************** + + /** + * 商户号 + */ + @SerializedName(value = "mchid") + protected String mchId; + + /** + * 批次关闭原因 + */ + @SerializedName(value = "close_reason") + protected String closeReason; + + } +} diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java index 82d68b58f6..5c47504026 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -219,6 +219,22 @@ public abstract class AbstractPayClient implemen } } + @Override + public final PayTransferRespDTO parseTransferNotify(Map params, String body) { + try { + return doParseTransferNotify(params, body); + } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可 + throw ex; + } catch (Throwable ex) { + log.error("[doParseTransferNotify][客户端({}) params({}) body({}) 解析失败]", + getId(), params, body, ex); + throw buildPayException(ex); + } + } + + protected abstract PayTransferRespDTO doParseTransferNotify(Map params, String body) + throws Throwable; + @Override public final PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type) { try { diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java index 4dcf236755..471dc7d923 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java @@ -325,6 +325,11 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient params, String body) throws Throwable { + throw new UnsupportedOperationException("未实现"); + } + // ========== 各种工具方法 ========== protected String formatAmount(Integer amount) { diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java index 4e5a37e9de..c990e7be6d 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; import com.alipay.api.AlipayApiException; @@ -56,4 +57,5 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { return PayOrderRespDTO.waitingOf(displayMode, response.getBody(), reqDTO.getOutTradeNo(), response); } + } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java index 1f90d6b58e..8bd3413576 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java @@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; import com.alipay.api.AlipayApiException; @@ -82,4 +83,5 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { return PayOrderRespDTO.waitingOf(displayMode, "", reqDTO.getOutTradeNo(), response); } + } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java index 6dbd19bef3..39cd78d540 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.Method; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; import com.alipay.api.AlipayApiException; @@ -66,4 +67,5 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { return PayOrderRespDTO.waitingOf(displayMode, response.getBody(), reqDTO.getOutTradeNo(), response); } + } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java index 1ad1ad7134..34b1d5db6f 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java @@ -57,6 +57,11 @@ public class MockPayClient extends AbstractPayClient { outRefundNo, MOCK_RESP_SUCCESS_DATA); } + @Override + protected PayTransferRespDTO doParseTransferNotify(Map params, String body) throws Throwable { + throw new UnsupportedOperationException("未实现"); + } + @Override protected PayRefundRespDTO doParseRefundNotify(Map params, String body) { throw new UnsupportedOperationException("模拟支付无退款回调"); diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index f5c753b8e3..dc2bdfa0cf 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -14,14 +14,11 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPartnerNotifyV3Result; import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum; -import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties; -import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result; +import com.github.binarywang.wxpay.bean.notify.*; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest; @@ -31,7 +28,6 @@ import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.TransferService; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; -import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; @@ -355,6 +351,29 @@ public abstract class AbstractWxPayClient extends AbstractPayClient params, String body) throws WxPayException { + switch (config.getApiVersion()) { + case API_VERSION_V3: + return parseTransferNotifyV3(body); + default: + throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); + } + } + + private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException { + WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class); + WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult(); + // 2. 构建结果 + if (Objects.equals("FINISHED", result.getBatchStatus())) { + if(result.getFailNum() <= 0){ + return PayTransferRespDTO.successOf(result.getBatchId(), parseDateV3(result.getUpdateTime()), + result.getOutBatchNo(), response); + } + } + return PayTransferRespDTO.closedOf(result.getBatchStatus(), result.getCloseReason(), result.getOutBatchNo(), response); + } + @Override protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException { try { @@ -452,7 +471,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient