Quellcode durchsuchen

feat:【PAY 支付】示例转账单,改成示例提现单,理解成本更低

YunaiV vor 6 Monaten
Ursprung
Commit
7653be9d48
35 geänderte Dateien mit 449 neuen und 261 gelöschten Zeilen
  1. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java
  2. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java
  3. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  4. 0 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java
  5. 7 2
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayTransferNotifyReqDTO.java
  6. 1 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
  7. 25 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java
  8. 8 4
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
  9. 11 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/PayChannelEnum.java
  10. 42 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/demo/PayDemoWithdrawStatusEnum.java
  11. 39 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/demo/PayDemoWithdrawTypeEnum.java
  12. 11 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferStatusEnum.java
  13. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
  14. 2 2
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.http
  15. 18 17
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.java
  16. 0 35
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java
  17. 0 47
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferRespVO.java
  18. 38 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/withdraw/PayDemoWithdrawCreateReqVO.java
  19. 44 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/withdraw/PayDemoWithdrawRespVO.java
  20. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferPageItemRespVO.java
  21. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferPageReqVO.java
  22. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java
  23. 26 19
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoWithdrawDO.java
  24. 0 4
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java
  25. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java
  26. 0 17
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoTransferMapper.java
  27. 24 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoWithdrawMapper.java
  28. 3 3
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java
  29. 3 3
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
  30. 0 39
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferService.java
  31. 93 52
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
  32. 40 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawService.java
  33. 4 4
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java
  34. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
  35. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java

@@ -89,7 +89,7 @@ public class BrokerageWithdrawController {
     public CommonResult<Boolean> updateBrokerageWithdrawTransferred(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
         log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
         brokerageWithdrawService.updateBrokerageWithdrawTransferred(
-                Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId());
+                Long.parseLong(notifyReqDTO.getMerchantOrderId()), notifyReqDTO.getPayTransferId());
         return success(true);
     }
 

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

@@ -141,7 +141,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
         PayTransferCreateReqDTO payTransferCreateReqDTO = new PayTransferCreateReqDTO()
                 .setAppKey(tradeOrderProperties.getPayAppKey())
                 .setChannelCode("wx_lite") // TODO @芋艿:【转账】这里要处理下;
-                .setMerchantTransferId(withdraw.getId().toString())
+                .setMerchantOrderId(withdraw.getId().toString())
                 .setPrice(withdraw.getPrice())
                 .setSubject("佣金提现")
                 .setUserAccount(socialUser.getOpenid()).setUserIp(getClientIP());

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -280,7 +280,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         TradeOrderDO order = validateOrderExists(id);
         // 1.2 校验订单已支付
         if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayStatus()) {
-            // 特殊:如果订单已支付,且支付单号相同,直接返回,说明重复回调
+            // 特殊:支付单号相同,直接返回,说明重复回调
             if (ObjectUtil.equals(order.getPayOrderId(), payOrderId)) {
                 log.warn("[updateOrderPaid][order({}) 已支付,且支付单号相同({}),直接返回]", order, payOrderId);
                 return;

+ 0 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.pay.api.notify.dto;
 
-import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;

+ 7 - 2
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayTransferNotifyReqDTO.java

@@ -1,9 +1,12 @@
 package cn.iocoder.yudao.module.pay.api.notify.dto;
 
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
+import lombok.NoArgsConstructor;
 
 /**
  * 转账单的通知 Request DTO
@@ -11,14 +14,16 @@ import jakarta.validation.constraints.NotNull;
  * @author jason
  */
 @Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 public class PayTransferNotifyReqDTO {
 
-    // TODO 芋艿:要不要改成 orderId 待定;
     /**
      * 商户转账单号
      */
     @NotEmpty(message = "商户转账单号不能为空")
-    private String merchantTransferId;
+    private String merchantOrderId;
 
     /**
      * 转账订单编号

+ 1 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java

@@ -42,7 +42,7 @@ public class PayTransferCreateReqDTO {
      * 商户转账单编号
      */
     @NotEmpty(message = "商户转账单编号能为空")
-    private String merchantTransferId;
+    private String merchantOrderId;
 
     /**
      * 转账金额,单位:分

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

@@ -1,8 +1,11 @@
 package cn.iocoder.yudao.module.pay.api.transfer.dto;
 
+import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
 import lombok.Data;
 
+import java.time.LocalDateTime;
+
 @Data
 public class PayTransferRespDTO {
 
@@ -16,6 +19,22 @@ public class PayTransferRespDTO {
      */
     private String no;
 
+    /**
+     * 转账渠道编码
+     *
+     * 枚举 {@link PayChannelEnum}
+     */
+    private String channelCode;
+
+    // ========== 商户相关字段 ==========
+
+    /**
+     * 商户转账单编号
+     */
+    private String merchantOrderId;
+
+    // ========== 转账相关字段 ==========
+
     /**
      * 转账金额,单位:分
      */
@@ -28,4 +47,10 @@ public class PayTransferRespDTO {
      */
     private Integer status;
 
+    /**
+     * 订单转账成功时间
+     */
+    private LocalDateTime successTime;
+
+
 }

+ 8 - 4
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java

@@ -85,8 +85,12 @@ public interface ErrorCodeConstants {
     ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_900_009, "发起退款失败,退款单编号不匹配");
     ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_900_010, "发起退款失败,退款单金额不匹配");
 
-    // ========== 示例转账订单 1-007-901-001 ==========
-    ErrorCode DEMO_TRANSFER_NOT_FOUND = new ErrorCode(1_007_901_001, "示例转账单不存在");
-    ErrorCode DEMO_TRANSFER_FAIL_TRANSFER_ID_ERROR = new ErrorCode(1_007_901_002, "转账失败,转账单编号不匹配");
-    ErrorCode DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH = new ErrorCode(1_007_901_003, "转账失败,转账单金额不匹配");
+    // ========== 示例提现单 1-007-901-000 ==========
+    ErrorCode DEMO_WITHDRAW_NOT_FOUND = new ErrorCode(1_007_901_000, "示例提现单不存在");
+    ErrorCode DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_ID_ERROR = new ErrorCode(1_007_901_001, "更新示例提现单状态失败,支付转账单编号不匹配");
+    ErrorCode DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_STATUS_NOT_SUCCESS_OR_CLOSED = new ErrorCode(1_007_901_002, "更新示例提现单状态失败,支付转账单状态不是【转账成功】或【转账失败】状态");
+    ErrorCode DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1_007_901_003, "更新示例提现单状态失败,支付转账单金额不匹配");
+    ErrorCode DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_MERCHANT_EXISTS = new ErrorCode(1_007_901_004, "更新示例提现单状态失败,支付转账单商户订单号不匹配");
+    ErrorCode DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_CHANNEL_NOT_MATCH = new ErrorCode(1_007_901_005, "更新示例提现单状态失败,支付转账单渠道不匹配");
+
 }

+ 11 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/PayChannelEnum.java

@@ -1,8 +1,11 @@
 package cn.iocoder.yudao.module.pay.enums;
 
+import cn.iocoder.yudao.framework.common.core.ArrayValuable;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
+import java.util.Arrays;
+
 /**
  * 支付渠道的编码的枚举
  *
@@ -10,7 +13,7 @@ import lombok.Getter;
  */
 @Getter
 @AllArgsConstructor
-public enum PayChannelEnum {
+public enum PayChannelEnum implements ArrayValuable<String> {
 
     WX_PUB("wx_pub", "微信 JSAPI 支付"), // 公众号网页
     WX_LITE("wx_lite", "微信小程序支付"),
@@ -28,6 +31,8 @@ public enum PayChannelEnum {
 
     WALLET("wallet", "钱包支付");
 
+    public static final String[] ARRAYS = Arrays.stream(values()).map(PayChannelEnum::getCode).toArray(String[]::new);
+
     /**
      * 编码
      *
@@ -39,4 +44,9 @@ public enum PayChannelEnum {
      */
     private final String name;
 
+    @Override
+    public String[] array() {
+        return ARRAYS;
+    }
+
 }

+ 42 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/demo/PayDemoWithdrawStatusEnum.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.pay.enums.demo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Objects;
+
+/**
+ * 示例提现单的状态枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum PayDemoWithdrawStatusEnum {
+
+    WAITING(0, "等待提现"),
+    SUCCESS(10, "提现成功"),
+    CLOSED(20, "提现关闭");
+
+    /**
+     * 状态
+     */
+    private final Integer status;
+    /**
+     * 状态名
+     */
+    private final String name;
+
+    public static boolean isSuccess(Integer status) {
+        return Objects.equals(status, SUCCESS.getStatus());
+    }
+
+    public static boolean isClosed(Integer status) {
+        return Objects.equals(status, CLOSED.getStatus());
+    }
+
+    public static boolean isWaiting(Integer status) {
+        return Objects.equals(status, WAITING.getStatus());
+    }
+
+}

+ 39 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/demo/PayDemoWithdrawTypeEnum.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.pay.enums.demo;
+
+import cn.iocoder.yudao.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 示例提现单的类型枚举
+ *
+ * @author owen
+ */
+@AllArgsConstructor
+@Getter
+public enum PayDemoWithdrawTypeEnum implements ArrayValuable<Integer> {
+
+    WECHAT(2, "微信"),
+    ALIPAY(1, "支付宝"),
+    WALLET(3, "钱包"),
+    ;
+
+    public static final Integer[] ARRAYS = Arrays.stream(values()).map(PayDemoWithdrawTypeEnum::getType).toArray(Integer[]::new);
+
+    /**
+     * 类型
+     */
+    private final Integer type;
+    /**
+     * 名字
+     */
+    private final String name;
+
+    @Override
+    public Integer[] array() {
+        return ARRAYS;
+    }
+
+}

+ 11 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferStatusEnum.java

@@ -48,9 +48,20 @@ public enum PayTransferStatusEnum {
      * 是否处于待转账或者转账中的状态
      *
      * @param status 状态
+     * @return 是否
      */
     public static boolean isWaitingOrProcessing(Integer status) {
         return isWaiting(status) || isProgressing(status);
     }
 
+    /**
+     * 是否处于成功或者关闭中的状态
+     *
+     * @param status 状态
+     * @return 是否
+     */
+    public static boolean isSuccessOrClosed(Integer status) {
+        return isSuccess(status) || isClosed(status);
+    }
+
 }

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java

@@ -23,7 +23,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
-@Tag(name = "管理后台 - 示例订单")
+@Tag(name = "管理后台 - 示例订单") // 目的:演示支付、退款功能
 @RestController
 @RequestMapping("/pay/demo-order")
 @Validated

+ 2 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoTransferController.http → yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.http

@@ -1,11 +1,11 @@
 ### 请求 /pay/pay/demo-order 接口 => 成功
-POST {{baseUrl}}/pay/demo-transfer/create
+POST {{baseUrl}}/pay/demo-withdraw/create
 Authorization: Bearer {{token}}
 Content-Type: application/json
 tenant-id: {{adminTenantId}}
 
 {
-  "channelCode": "alipay_pc",
+  "type": 1,
   "subject": "测试转账",
   "price": 10,
   "userAccount": "oespxk7368@sandbox.com",

+ 18 - 17
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoTransferController.java → yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.java

@@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
-import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
-import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferRespVO;
-import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
-import cn.iocoder.yudao.module.pay.service.demo.PayDemoTransferService;
+import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.withdraw.PayDemoWithdrawCreateReqVO;
+import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.withdraw.PayDemoWithdrawRespVO;
+import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoWithdrawDO;
+import cn.iocoder.yudao.module.pay.service.demo.PayDemoWithdrawService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
@@ -19,33 +19,34 @@ import org.springframework.web.bind.annotation.*;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
-@Tag(name = "管理后台 - 示例转账单")
+@Tag(name = "管理后台 - 示例提现订单") // 目的:演示转账功能
 @RestController
-@RequestMapping("/pay/demo-transfer")
+@RequestMapping("/pay/demo-withdraw")
 @Validated
-public class PayDemoTransferController {
+public class PayDemoWithdrawController {
+
     @Resource
-    private PayDemoTransferService demoTransferService;
+    private PayDemoWithdrawService demoWithdrawService;
 
     @PostMapping("/create")
-    @Operation(summary = "创建示例转账订单")
-    public CommonResult<Long> createDemoTransfer(@Valid @RequestBody PayDemoTransferCreateReqVO createReqVO) {
-        Long id = demoTransferService.createDemoTransfer(createReqVO);
+    @Operation(summary = "创建示例提现单")
+    public CommonResult<Long> createDemoTransfer(@Valid @RequestBody PayDemoWithdrawCreateReqVO createReqVO) {
+        Long id = demoWithdrawService.createDemoWithdraw(createReqVO);
         return success(id);
     }
 
     @GetMapping("/page")
-    @Operation(summary = "获得示例转账订单分页")
-    public CommonResult<PageResult<PayDemoTransferRespVO>> getDemoTransferPage(@Valid PageParam pageVO) {
-        PageResult<PayDemoTransferDO> pageResult = demoTransferService.getDemoTransferPage(pageVO);
-        return success(BeanUtils.toBean(pageResult, PayDemoTransferRespVO.class));
+    @Operation(summary = "获得示例提现单分页")
+    public CommonResult<PageResult<PayDemoWithdrawRespVO>> getDemoTransferPage(@Valid PageParam pageVO) {
+        PageResult<PayDemoWithdrawDO> pageResult = demoWithdrawService.getDemoWithdrawPage(pageVO);
+        return success(BeanUtils.toBean(pageResult, PayDemoWithdrawRespVO.class));
     }
 
     @PostMapping("/update-status")
-    @Operation(summary = "更新示例转账订单的转账状态") // 由 pay-module 转账服务,进行回调
+    @Operation(summary = "更新示例提现单的转账状态") // 由 pay-module 转账服务,进行回调
     @PermitAll // 无需登录,安全由 PayDemoTransferService 内部校验实现
     public CommonResult<Boolean> updateDemoTransferStatus(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
-        demoTransferService.updateDemoTransferStatus(Long.valueOf(notifyReqDTO.getMerchantTransferId()),
+        demoWithdrawService.updateDemoWithdrawStatus(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
                 notifyReqDTO.getPayTransferId());
         return success(true);
     }

+ 0 - 35
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java

@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-
-@Schema(description = "管理后台 - 示例转账单创建 Request VO")
-@Data
-public class PayDemoTransferCreateReqVO {
-
-    @Schema(description = "转账渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx_lite")
-    @NotEmpty(message = "转账渠道不能为空")
-    private String channelCode;
-
-    @Schema(description = "转账标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿是一种菜")
-    @NotEmpty(message = "转账标题不能为空")
-    private String subject;
-
-    @Schema(description = "转账金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
-    @NotNull(message = "转账金额不能为空")
-    @Min(value = 1, message = "转账金额必须大于零")
-    private Integer price;
-
-    @Schema(description = "收款人账号", requiredMode= Schema.RequiredMode.REQUIRED, example = "test1")
-    @NotBlank(message = "收款人账号不能为空")
-    private String userAccount;
-
-    @Schema(description = "收款人姓名", example = "test1")
-    @NotBlank(message = "收款人姓名不能为空")
-    private String userName;
-
-}

+ 0 - 47
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferRespVO.java

@@ -1,47 +0,0 @@
-package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * 示例业务转账订单 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
-@Data
-public class PayDemoTransferRespVO {
-
-    @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long id;
-
-    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Long appId;
-
-    @Schema(description = "转账金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22338")
-    private Integer price;
-
-    @Schema(description = "转账类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer type;
-
-    @Schema(description = "收款人姓名",  example = "test")
-    private String userName;
-
-    @Schema(description = "支付宝登录号", example = "32167")
-    private String alipayLogonId;
-
-    @Schema(description = "微信 openId", example = "31139")
-    private String openid;
-
-    @Schema(description = "转账状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
-    private Integer transferStatus;
-
-    @Schema(description = "转账订单编号", example = "23695")
-    private Long payTransferId;
-
-    @Schema(description = "转账支付成功渠道")
-    private String payChannelCode;
-
-    @Schema(description = "转账支付时间")
-    private LocalDateTime transferTime;
-}

+ 38 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/withdraw/PayDemoWithdrawCreateReqVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.withdraw;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.pay.enums.demo.PayDemoWithdrawTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 示例提现单创建 Request VO")
+@Data
+public class PayDemoWithdrawCreateReqVO {
+
+    @Schema(description = "提现标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿是一种菜")
+    @NotEmpty(message = "提现标题不能为空")
+    private String subject;
+
+    @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    @NotNull(message = "提现金额不能为空")
+    @Min(value = 1, message = "提现金额必须大于零")
+    private Integer price;
+
+    @Schema(description = "收款人账号", requiredMode= Schema.RequiredMode.REQUIRED, example = "test1")
+    @NotBlank(message = "收款人账号不能为空")
+    private String userAccount;
+
+    @Schema(description = "收款人姓名", example = "test1")
+    @NotBlank(message = "收款人姓名不能为空")
+    private String userName;
+
+    @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "提现方式不能为空")
+    @InEnum(PayDemoWithdrawTypeEnum.class)
+    private Integer type;
+
+}

+ 44 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/withdraw/PayDemoWithdrawRespVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.withdraw;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 示例转账单创建 Request VO")
+@Data
+public class PayDemoWithdrawRespVO {
+
+    @Schema(description = "转账单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Long id;
+
+    @Schema(description = "提现标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "吃饭报销")
+    private String subject;
+
+    @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22338")
+    private Integer price;
+
+    @Schema(description = "收款人姓名",  example = "test")
+    private String userName;
+
+    @Schema(description = "收款人账号", example = "32167")
+    private String userAccount;
+
+    @Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer type;
+
+    @Schema(description = "提现状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Integer status;
+
+    // ========== 转账相关字段 ==========
+
+    @Schema(description = "转账单编号", example = "23695")
+    private Long payTransferId;
+
+    @Schema(description = "转账渠道")
+    private String transferChannelCode;
+
+    @Schema(description = "转账成功时间")
+    private LocalDateTime transferTime;
+
+}

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferPageItemRespVO.java

@@ -28,7 +28,7 @@ public class PayTransferPageItemRespVO {
     private String channelCode;
 
     @Schema(description = "商户转账单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17481")
-    private String merchantTransferId;
+    private String merchantOrderId;
 
     @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private Integer type;

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferPageReqVO.java

@@ -24,7 +24,7 @@ public class PayTransferPageReqVO extends PageParam {
     private String channelCode;
 
     @Schema(description = "商户转账单编号", example = "17481")
-    private String merchantTransferId;
+    private String merchantOrderId;
 
     @Schema(description = "转账状态", example = "2")
     private Integer status;

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java

@@ -25,7 +25,7 @@ public class PayTransferRespVO {
     private String channelCode;
 
     @Schema(description = "商户转账单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17481")
-    private String merchantTransferId;
+    private String merchantOrderId;
 
     @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private Integer type;

+ 26 - 19
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoTransferDO.java → yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoWithdrawDO.java

@@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.pay.dal.dataobject.demo;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
-import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
+import cn.iocoder.yudao.module.pay.enums.demo.PayDemoWithdrawStatusEnum;
+import cn.iocoder.yudao.module.pay.enums.demo.PayDemoWithdrawTypeEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -11,35 +12,27 @@ import lombok.Data;
 import java.time.LocalDateTime;
 
 /**
- * 示例转账订单
+ * 示例提现订单
  *
  * 演示业务系统的转账业务
  */
-@TableName(value ="pay_demo_transfer", autoResultMap = true)
-@KeySequence("pay_demo_transfer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@TableName(value ="pay_demo_withdraw", autoResultMap = true)
+@KeySequence("pay_demo_withdraw_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
-public class PayDemoTransferDO extends BaseDO {
+public class PayDemoWithdrawDO extends BaseDO {
 
     /**
-     * 编号,自增
+     * 提现单编号,自增
      */
     @TableId
     private Long id;
 
     /**
-     * 转账渠道
-     *
-     * 枚举 {@link cn.iocoder.yudao.module.pay.enums.PayChannelEnum}
-     */
-    private String channelCode;
-
-    /**
-     * 转账标题
+     * 提现标题
      */
     private String subject;
-
     /**
-     * 转账金额,单位:分
+     * 提现金额,单位:分
      */
     private Integer price;
 
@@ -53,11 +46,19 @@ public class PayDemoTransferDO extends BaseDO {
     private String userName;
 
     /**
-     * 转账状态
+     * 提现方式
+     *
+     * 枚举 {@link PayDemoWithdrawTypeEnum}
+     */
+    private Integer type;
+    /**
+     * 提现状态
      *
-     * 枚举 {@link PayTransferStatusEnum}
+     * 枚举 {@link PayDemoWithdrawStatusEnum}
      */
-    private Integer transferStatus;
+    private Integer status;
+
+    // ========== 转账相关字段 ==========
 
     /**
      * 转账单编号
@@ -65,6 +66,12 @@ public class PayDemoTransferDO extends BaseDO {
      * 关联 {@link PayTransferDO#getId()}
      */
     private Long payTransferId;
+    /**
+     * 转账渠道
+     *
+     * 枚举 {@link cn.iocoder.yudao.module.pay.enums.PayChannelEnum}
+     */
+    private String transferChannelCode;
     /**
      * 转账成功时间
      */

+ 0 - 4
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java

@@ -66,10 +66,6 @@ public class PayNotifyTaskDO extends TenantBaseDO {
      * 商户订单编号
      */
     private String merchantOrderId;
-    /**
-     * 商户转账单编号
-     */
-    private String merchantTransferId;
     /**
      * 通知状态
      *

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java

@@ -63,7 +63,7 @@ public class PayTransferDO extends BaseDO {
      *
      * 例如说,内部系统 A 的订单号,需要保证每个 PayAppDO 唯一
      */
-    private String merchantTransferId;
+    private String merchantOrderId;
 
     // ========== 转账相关字段 ==========
 

+ 0 - 17
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoTransferMapper.java

@@ -1,17 +0,0 @@
-package cn.iocoder.yudao.module.pay.dal.mysql.demo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-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.dal.dataobject.demo.PayDemoTransferDO;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface PayDemoTransferMapper extends BaseMapperX<PayDemoTransferDO> {
-
-    default  PageResult<PayDemoTransferDO> selectPage(PageParam pageParam){
-        return selectPage(pageParam, new LambdaQueryWrapperX<PayDemoTransferDO>()
-                .orderByDesc(PayDemoTransferDO::getId));
-    }
-}

+ 24 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoWithdrawMapper.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.pay.dal.mysql.demo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+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.dal.dataobject.demo.PayDemoWithdrawDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface PayDemoWithdrawMapper extends BaseMapperX<PayDemoWithdrawDO> {
+
+    default  PageResult<PayDemoWithdrawDO> selectPage(PageParam pageParam){
+        return selectPage(pageParam, new LambdaQueryWrapperX<PayDemoWithdrawDO>()
+                .orderByDesc(PayDemoWithdrawDO::getId));
+    }
+
+    default int updateByIdAndStatus(Long id, Integer status, PayDemoWithdrawDO updateObj) {
+        return update(updateObj, new LambdaQueryWrapperX<PayDemoWithdrawDO>()
+                .eq(PayDemoWithdrawDO::getId, id)
+                .eq(PayDemoWithdrawDO::getStatus, status));
+    }
+
+}

+ 3 - 3
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java

@@ -26,9 +26,9 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
                 .eq(PayTransferDO::getStatus, whereStatus));
     }
 
-    default PayTransferDO selectByAppIdAndMerchantTransferId(Long appId, String merchantTransferId){
+    default PayTransferDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) {
         return selectOne(PayTransferDO::getAppId, appId,
-                    PayTransferDO::getMerchantTransferId, merchantTransferId);
+                    PayTransferDO::getMerchantOrderId, merchantOrderId);
     }
 
     default PageResult<PayTransferDO> selectPage(PayTransferPageReqVO reqVO) {
@@ -36,7 +36,7 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
                 .eqIfPresent(PayTransferDO::getNo, reqVO.getNo())
                 .eqIfPresent(PayTransferDO::getAppId, reqVO.getAppId())
                 .eqIfPresent(PayTransferDO::getChannelCode, reqVO.getChannelCode())
-                .eqIfPresent(PayTransferDO::getMerchantTransferId, reqVO.getMerchantTransferId())
+                .eqIfPresent(PayTransferDO::getMerchantOrderId, reqVO.getMerchantOrderId())
                 .eqIfPresent(PayTransferDO::getStatus, reqVO.getStatus())
                 .likeIfPresent(PayTransferDO::getUserName, reqVO.getUserName())
                 .eqIfPresent(PayTransferDO::getChannelTransferNo, reqVO.getChannelTransferNo())

+ 3 - 3
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java

@@ -119,14 +119,14 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
         }
         // 1.2 校验订单已支付
         if (order.getPayStatus()) {
-            // 特殊:如果订单已支付,且支付单号相同,直接返回,说明重复回调
+            // 特殊:支付单号相同,直接返回,说明重复回调
             if (ObjectUtil.equals(order.getPayOrderId(), payOrderId)) {
                 log.warn("[updateDemoOrderPaid][order({}) 已支付,且支付单号相同({}),直接返回]", order, payOrderId);
                 return;
             }
             // 异常:支付单号不同,说明支付单号错误
-            log.error("[updateDemoOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
-                    order, payOrderId, toJsonString(order));
+            log.error("[updateDemoOrderPaid][order({}) 支付单不匹配({}),请进行处理!]",
+                    order, payOrderId);
             throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
         }
 

+ 0 - 39
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferService.java

@@ -1,39 +0,0 @@
-package cn.iocoder.yudao.module.pay.service.demo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
-import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
-
-import jakarta.validation.Valid;
-
-/**
- * 示例转账业务 Service 接口
- *
- * @author jason
- */
-public interface PayDemoTransferService {
-
-    /**
-     * 创建转账业务示例订单
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Long createDemoTransfer(@Valid PayDemoTransferCreateReqVO createReqVO);
-
-    /**
-     * 获得转账业务示例订单分页
-     *
-     * @param pageVO 分页查询参数
-     */
-    PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO);
-
-    /**
-     * 更新转账业务示例订单的转账状态
-     *
-     * @param id 编号
-     * @param payTransferId 转账单编号
-     */
-    void updateDemoTransferStatus(Long id, Long payTransferId);
-}

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

@@ -3,22 +3,24 @@ package cn.iocoder.yudao.module.pay.service.demo;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 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.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
-import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
-import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
-import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
+import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
+import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.withdraw.PayDemoWithdrawCreateReqVO;
+import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoWithdrawDO;
+import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoWithdrawMapper;
+import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
+import cn.iocoder.yudao.module.pay.enums.demo.PayDemoWithdrawStatusEnum;
+import cn.iocoder.yudao.module.pay.enums.demo.PayDemoWithdrawTypeEnum;
 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
-import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
 import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
-import java.util.Objects;
-
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
@@ -30,7 +32,8 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
  */
 @Service
 @Validated
-public class PayDemoTransferServiceImpl implements PayDemoTransferService {
+@Slf4j
+public class PayDemoTransferServiceImpl implements PayDemoWithdrawService {
 
     /**
      * 接入的支付应用标识
@@ -40,75 +43,113 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
     private static final String PAY_APP_KEY = "demo";
 
     @Resource
-    private PayDemoTransferMapper demoTransferMapper;
-
-    @Resource
-    private PayTransferService payTransferService;
+    private PayDemoWithdrawMapper demoTransferMapper;
 
     @Resource
     private PayTransferApi payTransferApi;
 
     @Override
-    public Long createDemoTransfer(@Valid PayDemoTransferCreateReqVO reqVO) {
-        // 1. 保存示例转账业务表
-        PayDemoTransferDO demoTransfer = BeanUtils.toBean(reqVO, PayDemoTransferDO.class)
-                .setTransferStatus(PayTransferStatusEnum.WAITING.getStatus());
-        demoTransferMapper.insert(demoTransfer);
+    public Long createDemoWithdraw(@Valid PayDemoWithdrawCreateReqVO reqVO) {
+        // 1. 保存示例提现单
+        PayDemoWithdrawDO withdraw = BeanUtils.toBean(reqVO, PayDemoWithdrawDO.class)
+                .setTransferChannelCode(getTransferChannelCode(reqVO.getType()))
+                .setStatus(PayTransferStatusEnum.WAITING.getStatus());
+        demoTransferMapper.insert(withdraw);
 
         // 2.1 创建支付单
         Long payTransferId = payTransferApi.createTransfer(new PayTransferCreateReqDTO()
-                .setChannelCode(reqVO.getChannelCode())
-                .setAppKey(PAY_APP_KEY).setUserIp(getClientIP()) // 支付应用
-                .setMerchantTransferId(String.valueOf(demoTransfer.getId())) // 业务的订单编号
-                .setSubject(reqVO.getSubject()).setPrice(demoTransfer.getPrice()) // 价格信息
+                .setAppKey(PAY_APP_KEY).setChannelCode(withdraw.getTransferChannelCode()).setUserIp(getClientIP()) // 支付应用
+                .setMerchantOrderId(String.valueOf(withdraw.getId())) // 业务的订单编号
+                .setSubject(reqVO.getSubject()).setPrice(withdraw.getPrice()) // 价格信息
                 .setUserAccount(reqVO.getUserAccount()).setUserName(reqVO.getUserName())); // 收款信息
-        // 2.2 更新转账单到 demo 示例转账业务表
-        demoTransferMapper.updateById(new PayDemoTransferDO().setId(demoTransfer.getId())
+        // 2.2 更新转账单到 demo 示例提现单
+        demoTransferMapper.updateById(new PayDemoWithdrawDO().setId(withdraw.getId())
                .setPayTransferId(payTransferId));
-        return demoTransfer.getId();
+        return withdraw.getId();
+    }
+
+    private String getTransferChannelCode(Integer type) {
+        if (ObjectUtil.equal(type, PayDemoWithdrawTypeEnum.ALIPAY.getType())) {
+            return PayChannelEnum.ALIPAY_PC.getCode();
+        }
+        if (ObjectUtil.equal(type, PayDemoWithdrawTypeEnum.WECHAT.getType())) {
+            return PayChannelEnum.WX_LITE.getCode();
+        }
+        if (ObjectUtil.equal(type, PayDemoWithdrawTypeEnum.WALLET.getType())) {
+            return PayChannelEnum.WALLET.getCode();
+        }
+        throw new IllegalArgumentException("未知提现方式:" + type);
     }
 
     @Override
-    public PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO) {
+    public PageResult<PayDemoWithdrawDO> getDemoWithdrawPage(PageParam pageVO) {
         return demoTransferMapper.selectPage(pageVO);
     }
 
     @Override
-    public void updateDemoTransferStatus(Long id, Long payTransferId) {
-        PayTransferDO payTransfer = validateDemoTransferStatusCanUpdate(id, payTransferId);
-        // TODO @芋艿:这块,需要在优化下;
-        // 更新示例订单状态
-        if (payTransfer != null) {
-            demoTransferMapper.updateById(new PayDemoTransferDO().setId(id)
-                    .setPayTransferId(payTransferId)
-                    .setTransferStatus(payTransfer.getStatus())
-                    .setTransferTime(payTransfer.getSuccessTime()));
+    public void updateDemoWithdrawStatus(Long id, Long payTransferId) {
+        // 1.1 校验转账单是否存在
+        PayDemoWithdrawDO withdraw = demoTransferMapper.selectById(id);
+        if (withdraw == null) {
+            log.error("[updateDemoWithdrawStatus][withdraw({}) payOrder({}) 不存在提现单,请进行处理!]", id, payTransferId);
+            throw exception(DEMO_WITHDRAW_NOT_FOUND);
+        }
+        // 1.2 校验转账单已成结束(成功或失败)
+        if (PayDemoWithdrawStatusEnum.isSuccess(withdraw.getStatus())
+            || PayDemoWithdrawStatusEnum.isClosed(withdraw.getStatus())) {
+            // 特殊:转账单编号相同,直接返回,说明重复回调
+            if (ObjectUtil.equal(withdraw.getPayTransferId(), payTransferId)) {
+                log.warn("[updateDemoWithdrawStatus][withdraw({}) 已结束,且转账单编号相同({}),直接返回]", withdraw, payTransferId);
+                return;
+            }
+            // 异常:转账单编号不同,说明转账单编号错误
+            log.error("[updateDemoWithdrawStatus][withdraw({}) 转账单不匹配({}),请进行处理!]", withdraw, payTransferId);
+            throw exception(DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_ID_ERROR);
         }
+
+        // 2. 校验提现单的合法性
+        PayTransferRespDTO payTransfer = validateDemoTransferStatusCanUpdate(withdraw, payTransferId);
+
+        // 3. 更新示例订单状态
+        demoTransferMapper.updateById(new PayDemoWithdrawDO().setId(id)
+                .setPayTransferId(payTransferId)
+                .setStatus(payTransfer.getStatus())
+                .setTransferTime(payTransfer.getSuccessTime()));
     }
 
-    private PayTransferDO validateDemoTransferStatusCanUpdate(Long id, Long payTransferId) {
-        PayDemoTransferDO demoTransfer = demoTransferMapper.selectById(id);
-        if (demoTransfer == null) {
-            throw exception(DEMO_TRANSFER_NOT_FOUND);
+    private PayTransferRespDTO validateDemoTransferStatusCanUpdate(PayDemoWithdrawDO withdraw, Long payTransferId) {
+        // 1. 校验转账单是否存在
+        PayTransferRespDTO payTransfer = payTransferApi.getTransfer(payTransferId);
+        if (payTransfer == null) {
+            log.error("[validateDemoTransferStatusCanUpdate][withdraw({}) payTransfer({}) 不存在,请进行处理!]", withdraw.getId(), payTransferId);
+            throw exception(PAY_TRANSFER_NOT_FOUND);
         }
-        // TODO @芋艿:这里也要更新下;
-        // 无需更新返回 null
-        if (PayTransferStatusEnum.isSuccess(demoTransfer.getTransferStatus())
-                || PayTransferStatusEnum.isClosed(demoTransfer.getTransferStatus())) {
-            return null;
+
+        // 2.1 校验转账单已成功
+        if (!PayTransferStatusEnum.isSuccessOrClosed(payTransfer.getStatus())) {
+            log.error("[validateDemoTransferStatusCanUpdate][withdraw({}) payTransfer({}) 未结束,请进行处理!payTransfer 数据是:{}]",
+                    withdraw.getId(), payTransferId, JsonUtils.toJsonString(payTransfer));
+            throw exception(DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_STATUS_NOT_SUCCESS_OR_CLOSED);
         }
-        PayTransferDO transfer = payTransferService.getTransfer(payTransferId);
-        if (transfer == null) {
-            throw exception(PAY_TRANSFER_NOT_FOUND);
+        // 2.2 校验转账金额一致
+        if (ObjectUtil.notEqual(payTransfer.getPrice(), withdraw.getPrice())) {
+            log.error("[validateDemoTransferStatusCanUpdate][withdraw({}) payTransfer({}) 转账金额不匹配,请进行处理!withdraw 数据是:{},payTransfer 数据是:{}]",
+                    withdraw.getId(), payTransferId, JsonUtils.toJsonString(withdraw), JsonUtils.toJsonString(payTransfer));
+            throw exception(DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_PRICE_NOT_MATCH);
         }
-        if (!Objects.equals(demoTransfer.getPrice(), transfer.getPrice())) {
-            throw exception(DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH);
+        // 2.3 校验转账订单匹配(二次)
+        if (ObjectUtil.notEqual(payTransfer.getMerchantOrderId(), withdraw.getId().toString())) {
+            log.error("[validateDemoTransferStatusCanUpdate][withdraw({}) 转账单不匹配({}),请进行处理!payTransfer 数据是:{}]",
+                    withdraw.getId(), payTransferId, JsonUtils.toJsonString(payTransfer));
+            throw exception(DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_MERCHANT_EXISTS);
         }
-        if (ObjectUtil.notEqual(transfer.getMerchantTransferId(), id.toString())) {
-            throw exception(DEMO_TRANSFER_FAIL_TRANSFER_ID_ERROR);
+        // 2.4 校验转账渠道一致
+        if (ObjectUtil.notEqual(payTransfer.getChannelCode(), withdraw.getTransferChannelCode())) {
+            log.error("[validateDemoTransferStatusCanUpdate][withdraw({}) payTransfer({}) 转账渠道不匹配,请进行处理!withdraw 数据是:{},payTransfer 数据是:{}]",
+                    withdraw.getId(), payTransferId, JsonUtils.toJsonString(withdraw), JsonUtils.toJsonString(payTransfer));
+            throw exception(DEMO_WITHDRAW_UPDATE_STATUS_FAIL_PAY_CHANNEL_NOT_MATCH);
         }
-        // TODO 校验账号
-        return transfer;
+        return payTransfer;
     }
 
 }

+ 40 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawService.java

@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.pay.service.demo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.withdraw.PayDemoWithdrawCreateReqVO;
+import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoWithdrawDO;
+
+import jakarta.validation.Valid;
+
+/**
+ * 示例提现单 Service 接口
+ *
+ * @author jason
+ */
+public interface PayDemoWithdrawService {
+
+    /**
+     * 创建示例提现单
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createDemoWithdraw(@Valid PayDemoWithdrawCreateReqVO createReqVO);
+
+    /**
+     * 获得示例提现单分页
+     *
+     * @param pageVO 分页查询参数
+     */
+    PageResult<PayDemoWithdrawDO> getDemoWithdrawPage(PageParam pageVO);
+
+    /**
+     * 更新示例提现单的状态
+     *
+     * @param id 编号
+     * @param payTransferId 转账单编号
+     */
+    void updateDemoWithdrawStatus(Long id, Long payTransferId);
+
+}

+ 4 - 4
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java

@@ -108,8 +108,8 @@ public class PayNotifyServiceImpl implements PayNotifyService {
                     .setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl());
         } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.TRANSFER.getType())) {
             PayTransferDO transfer = transferService.getTransfer(task.getDataId());
-            task.setAppId(transfer.getAppId()).setMerchantTransferId(transfer.getMerchantTransferId())
-                    .setNotifyUrl(transfer.getNotifyUrl());
+            task.setAppId(transfer.getAppId())
+                    .setMerchantOrderId(transfer.getMerchantOrderId()).setNotifyUrl(transfer.getNotifyUrl());
         }
 
         // 执行插入
@@ -225,8 +225,8 @@ public class PayNotifyServiceImpl implements PayNotifyService {
             request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId())
                     .payRefundId(task.getDataId()).build();
         } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.TRANSFER.getType())) {
-            request = new PayTransferNotifyReqDTO().setMerchantTransferId(task.getMerchantTransferId())
-                    .setPayTransferId(task.getDataId());
+            request = PayTransferNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId())
+                    .payTransferId(task.getDataId()).build();
         } else {
             throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task));
         }

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

@@ -112,7 +112,7 @@ public class PayTransferServiceImpl implements PayTransferService {
     }
 
     private PayTransferDO validateTransferCanCreate(PayTransferCreateReqDTO reqDTO, Long appId) {
-        PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, reqDTO.getMerchantTransferId());
+        PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantOrderId(appId, reqDTO.getMerchantOrderId());
         if (transfer != null) {
             // 已经存在,并且状态不为等待状态:说明已经调用渠道转账并返回结果
             if (!PayTransferStatusEnum.isWaiting(transfer.getStatus())) {

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java

@@ -122,7 +122,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
         }
         // 1.2 校验钱包充值是否可以支付
         if (recharge.getPayStatus()) {
-            // 特殊:如果订单已支付,且支付单号相同,直接返回,说明重复回调
+            // 特殊:支付单号相同,直接返回,说明重复回调
             if (ObjectUtil.equals(recharge.getPayOrderId(), payOrderId)) {
                 log.warn("[updateWalletRechargerPaid][recharge({}) 已支付,且支付单号相同({}),直接返回]", recharge, payOrderId);
                 return;