Переглянути джерело

feat:【MALL 商城】商城分佣提现,初步对接成功微信支付

YunaiV 6 місяців тому
батько
коміт
4d25e810e3
22 змінених файлів з 162 додано та 225 видалено
  1. 3 0
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/DictTypeConstants.java
  2. 0 1
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawStatusEnum.java
  3. 6 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java
  4. 41 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java
  5. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java
  6. 3 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java
  7. 8 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java
  8. 9 9
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawPageReqVO.java
  9. 17 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java
  10. 0 6
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java
  11. 0 19
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageWithdrawConvert.java
  12. 0 7
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageWithdrawDO.java
  13. 4 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java
  14. 7 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java
  15. 14 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java
  16. 0 7
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoWithdrawDO.java
  17. 1 2
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
  18. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
  19. 8 1
      yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
  20. 0 129
      yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java
  21. 6 1
      yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
  22. 32 29
      yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java

+ 3 - 0
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/DictTypeConstants.java

@@ -7,6 +7,9 @@ package cn.iocoder.yudao.module.trade.enums;
  */
 public interface DictTypeConstants {
 
+    String BROKERAGE_RECORD_STATUS = "brokerage_record_status"; // 佣金记录状态
+
+    String BROKERAGE_WITHDRAW_TYPE = "brokerage_withdraw_type"; // 佣金提现类型
     String BROKERAGE_WITHDRAW_STATUS = "brokerage_withdraw_status"; // 佣金提现状态
 
 }

+ 0 - 1
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawStatusEnum.java

@@ -6,7 +6,6 @@ import lombok.Getter;
 
 import java.util.Arrays;
 
-// TODO 芋艿:提现的打通,在纠结下;
 /**
  * 佣金提现状态枚举
  *

+ 6 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java

@@ -3,11 +3,13 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
-import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
+import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
 import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -36,8 +38,9 @@ public class AppBrokerageRecordController {
     @Operation(summary = "获得分销记录分页")
     public CommonResult<PageResult<AppBrokerageRecordRespVO>> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) {
         PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(
-                BrokerageRecordConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
-        return success(BeanUtils.toBean(pageResult, AppBrokerageRecordRespVO.class));
+                BeanUtils.toBean(pageReqVO, BrokerageRecordPageReqVO.class).setUserId(getLoginUserId()));
+        return success(BeanUtils.toBean(pageResult, AppBrokerageRecordRespVO.class, recordVO ->
+                recordVO.setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_RECORD_STATUS, recordVO.getStatus()))));
     }
 
     @GetMapping("/get-product-brokerage-price")

+ 41 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java

@@ -1,14 +1,23 @@
 package cn.iocoder.yudao.module.trade.controller.app.brokerage;
 
+import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
+import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
+import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
-import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
+import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
 import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
@@ -16,6 +25,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Objects;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
 
@@ -29,12 +40,39 @@ public class AppBrokerageWithdrawController {
     @Resource
     private BrokerageWithdrawService brokerageWithdrawService;
 
+    @Resource
+    private PayTransferApi payTransferApi;
+
     @GetMapping("/page")
     @Operation(summary = "获得分销提现分页")
     public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
         PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
-                BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
-        return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
+                BeanUtils.toBean(pageReqVO, BrokerageWithdrawPageReqVO.class).setUserId(getLoginUserId()));
+        return success(BeanUtils.toBean(pageResult, AppBrokerageWithdrawRespVO.class, withdrawVO ->
+                withdrawVO.setTypeName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_TYPE, withdrawVO.getType()))
+                        .setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_STATUS, withdrawVO.getStatus()))));
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得佣金提现")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    public CommonResult<AppBrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Long id) {
+        BrokerageWithdrawDO withdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
+        if (withdraw == null || ObjUtil.notEqual(withdraw.getUserId(), getLoginUserId())) {
+            return success(null);
+        }
+        // 审核中(转账中),并且是微信转账,需要返回 mchId 用于确认收款
+        AppBrokerageWithdrawRespVO withdrawVO = BeanUtils.toBean(withdraw, AppBrokerageWithdrawRespVO.class);
+        if (Objects.equals(withdraw.getStatus(), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus())
+                && Objects.equals(withdraw.getType(), BrokerageWithdrawTypeEnum.WECHAT_API.getType())
+                && withdraw.getPayTransferId() != null) {
+            PayTransferRespDTO transfer = payTransferApi.getTransfer(withdraw.getPayTransferId());
+            if (transfer != null) {
+                withdrawVO.setTransferChannelPackageInfo(transfer.getChannelPackageInfo())
+                        .setTransferChannelMchId(transfer.getChannelMchId());
+            }
+        }
+        return success(withdrawVO);
     }
 
     @PostMapping("/create")

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java

@@ -20,11 +20,11 @@ public class AppBrokerageRecordPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
-    @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "业务类型", example = "1")
     @InEnum(value = BrokerageRecordBizTypeEnum.class, message = "业务类型必须是 {value}")
     private Integer bizType;
 
-    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态", example = "1")
     @InEnum(value = BrokerageRecordStatusEnum.class, message = "状态必须是 {value}")
     private Integer status;
 

+ 3 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java

@@ -24,6 +24,9 @@ public class AppBrokerageRecordRespVO {
     @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
+    @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "待结算")
+    private String statusName;
+
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 

+ 8 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java

@@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw;
 
 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Min;
 import lombok.Data;
 import org.hibernate.validator.constraints.URL;
 
@@ -22,6 +24,7 @@ public class AppBrokerageWithdrawCreateReqVO {
 
     @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
     @PositiveOrZero(message = "提现金额不能小于 0")
+    @Min(value = 30, message = "微信提现金额不能小于 0.3", groups = {WechatApi.class})
     @NotNull(message = "提现金额不能为空")
     private Integer price;
 
@@ -43,6 +46,11 @@ public class AppBrokerageWithdrawCreateReqVO {
     @Schema(description = "开户地址", example = "海淀支行")
     private String bankAddress;
 
+    @Schema(description = "转账渠道", example = "wx_lite")
+    @NotNull(message = "转账渠道不能为空", groups = {WechatApi.class})
+    @InEnum(PayChannelEnum.class)
+    private String transferChannelCode;
+
     public interface Wallet {
     }
 

+ 9 - 9
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawPageReqVO.java

@@ -1,22 +1,22 @@
 package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
-import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
 @Schema(description = "应用 App - 分销提现分页 Request VO")
 @Data
 public class AppBrokerageWithdrawPageReqVO extends PageParam {
 
-    @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "类型必须是 {value}")
-    private Integer type;
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
 
-    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @InEnum(value = BrokerageWithdrawStatusEnum.class, message = "状态必须是 {value}")
-    private Integer status;
 
 }

+ 17 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java

@@ -12,6 +12,12 @@ public class AppBrokerageWithdrawRespVO {
     @Schema(description = "提现编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     private Long id;
 
+    @Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer type;
+
+    @Schema(description = "提现类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "微信")
+    private String typeName;
+
     @Schema(description = "提现状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     private Integer status;
 
@@ -24,4 +30,15 @@ public class AppBrokerageWithdrawRespVO {
     @Schema(description = "提现时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
+    // ========== 微信转账专属 ==========
+
+    @Schema(description = "转账单编号", example = "1024")
+    private Long payTransferId;
+
+    @Schema(description = "渠道 package 信息")
+    private String transferChannelPackageInfo;
+
+    @Schema(description = "渠道商户号")
+    private String transferChannelMchId;
+
 }

+ 0 - 6
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java

@@ -1,15 +1,11 @@
 package cn.iocoder.yudao.module.trade.convert.brokerage;
 
-import cn.hutool.core.math.Money;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
-import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordRespVO;
-import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
@@ -68,8 +64,6 @@ public interface BrokerageRecordConvert {
         return result;
     }
 
-    BrokerageRecordPageReqVO convert(AppBrokerageRecordPageReqVO pageReqVO, Long userId);
-
     default PageResult<AppBrokerageUserRankByPriceRespVO> convertPage03(PageResult<AppBrokerageUserRankByPriceRespVO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
         for (AppBrokerageUserRankByPriceRespVO vo : pageResult.getList()) {
             copyTo(userMap.get(vo.getId()), vo);

+ 0 - 19
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageWithdrawConvert.java

@@ -1,15 +1,9 @@
 package cn.iocoder.yudao.module.trade.convert.brokerage;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
-import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
-import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
-import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
@@ -27,8 +21,6 @@ public interface BrokerageWithdrawConvert {
 
     BrokerageWithdrawConvert INSTANCE = Mappers.getMapper(BrokerageWithdrawConvert.class);
 
-    BrokerageWithdrawDO convert(AppBrokerageWithdrawCreateReqVO createReqVO, Long userId, Integer feePrice);
-
     BrokerageWithdrawRespVO convert(BrokerageWithdrawDO bean);
 
     List<BrokerageWithdrawRespVO> convertList(List<BrokerageWithdrawDO> list);
@@ -43,15 +35,4 @@ public interface BrokerageWithdrawConvert {
         return result;
     }
 
-    PageResult<AppBrokerageWithdrawRespVO> convertPage02(PageResult<BrokerageWithdrawDO> pageResult);
-
-    default PageResult<AppBrokerageWithdrawRespVO> convertPage03(PageResult<BrokerageWithdrawDO> pageResult) {
-        PageResult<AppBrokerageWithdrawRespVO> result = convertPage02(pageResult);
-        for (AppBrokerageWithdrawRespVO vo : result.getList()) {
-            vo.setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_STATUS, vo.getStatus()));
-        }
-        return result;
-    }
-
-    BrokerageWithdrawPageReqVO convert(AppBrokerageWithdrawPageReqVO pageReqVO, Long userId);
 }

+ 0 - 7
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageWithdrawDO.java

@@ -126,12 +126,5 @@ public class BrokerageWithdrawDO extends BaseDO {
      * 转账错误提示
      */
     private String transferErrorMsg;
-    /**
-     * 渠道 package 信息
-     *
-     * 特殊:目前只有微信转账有这个东西!!!
-     * @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
-     */
-    private String transferChannelPackageInfo;
 
 }

+ 4 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
@@ -18,7 +19,6 @@ import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
-import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
@@ -157,8 +157,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
 
         // 2. 更新提现记录
         brokerageWithdrawMapper.updateById(new BrokerageWithdrawDO().setId(withdraw.getId())
-                .setPayTransferId(transferRespDTO.getId()).setTransferChannelCode(channelCode)
-                .setTransferChannelPackageInfo(transferRespDTO.getChannelPackageInfo()));
+                .setPayTransferId(transferRespDTO.getId()).setTransferChannelCode(channelCode));
     }
 
     private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) {
@@ -190,7 +189,8 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
         // 2.1 计算手续费
         Integer feePrice = calculateFeePrice(createReqVO.getPrice(), tradeConfig.getBrokerageWithdrawFeePercent());
         // 2.2 创建佣金提现记录
-        BrokerageWithdrawDO withdraw = BrokerageWithdrawConvert.INSTANCE.convert(createReqVO, userId, feePrice);
+        BrokerageWithdrawDO withdraw = BeanUtils.toBean(createReqVO, BrokerageWithdrawDO.class)
+                .setUserId(userId).setFeePrice(feePrice);
         brokerageWithdrawMapper.insert(withdraw);
 
         // 3. 创建用户佣金记录

+ 7 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java

@@ -70,5 +70,12 @@ public class PayTransferRespDTO {
      * @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
      */
     private String channelPackageInfo;
+    /**
+     * 渠道商户号
+     *
+     * 特殊:目前只有微信转账有这个东西!!!
+     * @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
+     */
+    private String channelMchId;
 
 }

+ 14 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java

@@ -1,10 +1,13 @@
 package cn.iocoder.yudao.module.pay.api.transfer;
 
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateRespDTO;
 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
+import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
+import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
 import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
@@ -21,6 +24,8 @@ public class PayTransferApiImpl implements PayTransferApi {
 
     @Resource
     private PayTransferService payTransferService;
+    @Resource
+    private PayChannelService payChannelService;
 
     @Override
     public PayTransferCreateRespDTO createTransfer(PayTransferCreateReqDTO reqDTO) {
@@ -30,7 +35,15 @@ public class PayTransferApiImpl implements PayTransferApi {
     @Override
     public PayTransferRespDTO getTransfer(Long id) {
         PayTransferDO transfer = payTransferService.getTransfer(id);
-        return BeanUtils.toBean(transfer, PayTransferRespDTO.class);
+        if (transfer == null) {
+            return null;
+        }
+        PayChannelDO channel = payChannelService.getChannel(transfer.getChannelId());
+        String mchId = null;
+        if (channel != null && channel.getConfig() instanceof WxPayClientConfig) {
+            mchId = ((WxPayClientConfig) channel.getConfig()).getMchId();
+        }
+        return BeanUtils.toBean(transfer, PayTransferRespDTO.class).setChannelMchId(mchId);
     }
 
 }

+ 0 - 7
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoWithdrawDO.java

@@ -80,12 +80,5 @@ public class PayDemoWithdrawDO extends BaseDO {
      * 转账错误提示
      */
     private String transferErrorMsg;
-    /**
-     * 渠道 package 信息
-     *
-     * 特殊:目前只有微信转账有这个东西!!!
-     * @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
-     */
-    private String transferChannelPackageInfo;
 
 }

+ 1 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java

@@ -88,8 +88,7 @@ public class PayDemoTransferServiceImpl implements PayDemoWithdrawService {
 
         // 2.2 更新转账单到 demo 示例提现单,并将状态更新为转账中
         demoTransferMapper.updateByIdAndStatus(withdraw.getId(), withdraw.getStatus(),
-                new PayDemoWithdrawDO().setPayTransferId(transferRespDTO.getId())
-                        .setTransferChannelPackageInfo(transferRespDTO.getChannelPackageInfo()));
+                new PayDemoWithdrawDO().setPayTransferId(transferRespDTO.getId()));
         return transferRespDTO.getId();
     }
 

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java

@@ -174,7 +174,7 @@ public class PayTransferServiceImpl implements PayTransferService {
         int updateCounts = transferMapper.updateByIdAndStatus(transfer.getId(),
                 PayTransferStatusEnum.WAITING.getStatus(),
                 new PayTransferDO().setStatus(PayTransferStatusEnum.PROCESSING.getStatus())
-                        .setChannelPackageInfo(transfer.getChannelPackageInfo()));
+                        .setChannelPackageInfo(notify.getChannelPackageInfo()));
         if (updateCounts == 0) {
             throw exception(PAY_TRANSFER_NOTIFY_FAIL_STATUS_IS_NOT_WAITING);
         }

+ 8 - 1
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java

@@ -14,7 +14,7 @@ import java.util.Map;
  *
  * @author 芋道源码
  */
-public interface PayClient {
+public interface PayClient<Config> {
 
     /**
      * 获得渠道编号
@@ -23,6 +23,13 @@ public interface PayClient {
      */
     Long getId();
 
+    /**
+     * 获得渠道配置
+     *
+     * @return 渠道配置
+     */
+    Config getConfig();
+
     // ============ 支付相关 ==========
 
     /**

+ 0 - 129
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java

@@ -1,129 +0,0 @@
-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;
-
-// TODO @luchi:这个可以复用 wxjava 里的类么?
-@NoArgsConstructor
-public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferPartnerNotifyV3Result.TransferNotifyResult> {
-
-    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;
-
-    }
-}

+ 6 - 1
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java

@@ -23,7 +23,7 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString
  * @author 芋道源码
  */
 @Slf4j
-public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient {
+public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient<Config> {
 
     /**
      * 渠道编号
@@ -74,6 +74,11 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
         return channelId;
     }
 
+    @Override
+    public Config getConfig() {
+        return config;
+    }
+
     // ============ 支付相关 ==========
 
     @Override

+ 32 - 29
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java

@@ -15,13 +15,13 @@ 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 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.TransferBillsGetResult;
+import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsRequest;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
 import com.github.binarywang.wxpay.config.WxPayConfig;
@@ -354,34 +354,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
         return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
     }
 
-    @Override
-    public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
-        switch (config.getApiVersion()) {
-            case API_VERSION_V3:
-                return parseTransferNotifyV3(body, headers);
-            case API_VERSION_V2:
-                throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
-            default:
-                throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
-        }
-    }
-
-    private PayTransferRespDTO parseTransferNotifyV3(String body, Map<String, String> headers) throws WxPayException {
-        // 1. 解析回调
-        SignatureHeader signatureHeader = getRequestHeader(headers);
-        // TODO @luchi:这个可以复用 wxjava 里的类么?
-        WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, signatureHeader, 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 {
@@ -522,6 +494,37 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
                 response.getOutBillNo(), response);
     }
 
+    @Override
+    public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
+        switch (config.getApiVersion()) {
+            case API_VERSION_V3:
+                return parseTransferNotifyV3(body, headers);
+            case API_VERSION_V2:
+                throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
+            default:
+                throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
+        }
+    }
+
+    private PayTransferRespDTO parseTransferNotifyV3(String body, Map<String, String> headers) throws WxPayException {
+        // 1. 解析回调
+        SignatureHeader signatureHeader = getRequestHeader(headers);
+        TransferBillsNotifyResult response = client.getTransferService().parseTransferBillsNotifyResult(body, signatureHeader);
+        TransferBillsNotifyResult.DecryptNotifyResult result = response.getResult();
+
+        // 2. 创建返回结果
+        String state = result.getState();
+        if (ObjectUtils.equalsAny(state, "ACCEPTED", "PROCESSING", "WAIT_USER_CONFIRM", "TRANSFERING")) {
+            return PayTransferRespDTO.processingOf(result.getTransferBillNo(), result.getOutBillNo(), response);
+        }
+        if (Objects.equals("SUCCESS", state)) {
+            return PayTransferRespDTO.successOf(result.getTransferBillNo(), parseDateV3(result.getUpdateTime()),
+                    result.getOutBillNo(), response);
+        }
+        return PayTransferRespDTO.closedOf(state, result.getFailReason(),
+                result.getOutBillNo(), response);
+    }
+
     // ========== 各种工具方法 ==========
 
     /**