Commit 081ef0502c4d90bb6fa1602a69acb8a6237f1cc1

Authored by YunaiV
1 parent 602bd5f9

【代码评审】商城:分销提现时,支持余额自动添加,以及微信提现到余额里

Showing 28 changed files with 149 additions and 139 deletions
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawTypeEnum.java
@@ -17,9 +17,9 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable { @@ -17,9 +17,9 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable {
17 17
18 WALLET(1, "钱包"), 18 WALLET(1, "钱包"),
19 BANK(2, "银行卡"), 19 BANK(2, "银行卡"),
20 - WECHAT(3, "微信"), 20 + WECHAT(3, "微信"), // 手动打款
21 ALIPAY(4, "支付宝"), 21 ALIPAY(4, "支付宝"),
22 - ALIPAY_SMALL(5, "微信零钱"), 22 + WECHAT_API(5, "微信零钱"), // 自动打款,通过微信转账 API
23 ; 23 ;
24 24
25 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawTypeEnum::getType).toArray(); 25 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawTypeEnum::getType).toArray();
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java
@@ -46,7 +46,8 @@ public class BrokerageWithdrawController { @@ -46,7 +46,8 @@ public class BrokerageWithdrawController {
46 @Operation(summary = "通过申请") 46 @Operation(summary = "通过申请")
47 @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')") 47 @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
48 public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Long id) { 48 public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Long id) {
49 - brokerageWithdrawService.auditBrokerageWithdraw(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "", getClientIP()); 49 + brokerageWithdrawService.auditBrokerageWithdraw(id,
  50 + BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "", getClientIP());
50 return success(true); 51 return success(true);
51 } 52 }
52 53
@@ -54,7 +55,8 @@ public class BrokerageWithdrawController { @@ -54,7 +55,8 @@ public class BrokerageWithdrawController {
54 @Operation(summary = "驳回申请") 55 @Operation(summary = "驳回申请")
55 @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')") 56 @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
56 public CommonResult<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawRejectReqVO reqVO) { 57 public CommonResult<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawRejectReqVO reqVO) {
57 - brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(), BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason(), getClientIP()); 58 + brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(),
  59 + BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason(), getClientIP());
58 return success(true); 60 return success(true);
59 } 61 }
60 62
@@ -80,14 +82,14 @@ public class BrokerageWithdrawController { @@ -80,14 +82,14 @@ public class BrokerageWithdrawController {
80 return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap)); 82 return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap));
81 } 83 }
82 84
  85 + // TODO @luchi:update-transferred,url 改成这个。和 update-paid 、update-refunded 保持一致
83 @PostMapping("/update-transfer") 86 @PostMapping("/update-transfer")
84 @Operation(summary = "更新转账订单为转账成功") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob 87 @Operation(summary = "更新转账订单为转账成功") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
85 @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 88 @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
86 - public CommonResult<Boolean> updateAfterRefund(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {  
87 - // 目前业务逻辑,不需要做任何事情  
88 - // 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警 89 + public CommonResult<Boolean> updateBrokerageWithdrawTransferred(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
89 log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO); 90 log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
90 - brokerageWithdrawService.updateTransfer(Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId()); 91 + brokerageWithdrawService.updateBrokerageWithdrawTransferred(
  92 + Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId());
91 return success(true); 93 return success(true);
92 } 94 }
93 95
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/order/TradeOrderAutoCommentJob.java
@@ -21,7 +21,7 @@ public class TradeOrderAutoCommentJob implements JobHandler { @@ -21,7 +21,7 @@ public class TradeOrderAutoCommentJob implements JobHandler {
21 @Override 21 @Override
22 @TenantJob 22 @TenantJob
23 public String execute(String param) { 23 public String execute(String param) {
24 - int count = tradeOrderUpdateService.createOrderItemCommentBySystem(); 24 + int count = tradeOrderUpdateService.createOrderItemCommentBySystem();
25 return String.format("评论订单 %s 个", count); 25 return String.format("评论订单 %s 个", count);
26 } 26 }
27 27
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawService.java
@@ -27,6 +27,7 @@ public interface BrokerageWithdrawService { @@ -27,6 +27,7 @@ public interface BrokerageWithdrawService {
27 * @param id 佣金编号 27 * @param id 佣金编号
28 * @param status 审核状态 28 * @param status 审核状态
29 * @param auditReason 驳回原因 29 * @param auditReason 驳回原因
  30 + * @param userIp 操作 IP
30 */ 31 */
31 void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp); 32 void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp);
32 33
@@ -56,6 +57,16 @@ public interface BrokerageWithdrawService { @@ -56,6 +57,16 @@ public interface BrokerageWithdrawService {
56 Long createBrokerageWithdraw(Long userId, AppBrokerageWithdrawCreateReqVO createReqVO); 57 Long createBrokerageWithdraw(Long userId, AppBrokerageWithdrawCreateReqVO createReqVO);
57 58
58 /** 59 /**
  60 + * 【API】更新佣金提现的转账结果
  61 + *
  62 + * 目前用于支付回调,标记提现转账结果
  63 + *
  64 + * @param id 提现编号
  65 + * @param payTransferId 转账订单编号
  66 + */
  67 + void updateBrokerageWithdrawTransferred(Long id, Long payTransferId);
  68 +
  69 + /**
59 * 按照 userId,汇总每个用户的提现 70 * 按照 userId,汇总每个用户的提现
60 * 71 *
61 * @param userIds 用户编号 72 * @param userIds 用户编号
@@ -77,10 +88,4 @@ public interface BrokerageWithdrawService { @@ -77,10 +88,4 @@ public interface BrokerageWithdrawService {
77 return convertMap(getWithdrawSummaryListByUserId(userIds, status), BrokerageWithdrawSummaryRespBO::getUserId); 88 return convertMap(getWithdrawSummaryListByUserId(userIds, status), BrokerageWithdrawSummaryRespBO::getUserId);
78 } 89 }
79 90
80 - /**  
81 - *  
82 - * @param merchantTransferId 提现编号  
83 - * @param payTransferId 转账订单编号  
84 - */  
85 - void updateTransfer(Long merchantTransferId, Long payTransferId);  
86 } 91 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java
1 package cn.iocoder.yudao.module.trade.service.brokerage; 1 package cn.iocoder.yudao.module.trade.service.brokerage;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.date.LocalDateTimeUtil;  
5 -import cn.hutool.core.map.MapUtil;  
6 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
7 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
8 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -17,7 +15,6 @@ import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum; @@ -17,7 +15,6 @@ import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
17 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum; 15 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
18 import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum; 16 import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
19 import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; 17 import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
20 -import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;  
21 import cn.iocoder.yudao.module.system.api.social.SocialUserApi; 18 import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
22 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; 19 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
23 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 20 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
@@ -27,7 +24,6 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert; @@ -27,7 +24,6 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
27 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO; 24 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
28 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; 25 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
29 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper; 26 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
30 -import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO;  
31 import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants; 27 import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants;
32 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; 28 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
33 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; 29 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
@@ -35,14 +31,16 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum; @@ -35,14 +31,16 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
35 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 31 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
36 import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO; 32 import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
37 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; 33 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
  34 +import jakarta.annotation.Resource;
  35 +import jakarta.validation.Validator;
38 import org.springframework.stereotype.Service; 36 import org.springframework.stereotype.Service;
39 import org.springframework.transaction.annotation.Transactional; 37 import org.springframework.transaction.annotation.Transactional;
40 import org.springframework.validation.annotation.Validated; 38 import org.springframework.validation.annotation.Validated;
41 39
42 -import jakarta.annotation.Resource;  
43 -import jakarta.validation.Validator;  
44 import java.time.LocalDateTime; 40 import java.time.LocalDateTime;
45 -import java.util.*; 41 +import java.util.Collection;
  42 +import java.util.Collections;
  43 +import java.util.List;
46 44
47 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
48 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; 46 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
@@ -58,8 +56,6 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -58,8 +56,6 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
58 56
59 @Resource 57 @Resource
60 private BrokerageWithdrawMapper brokerageWithdrawMapper; 58 private BrokerageWithdrawMapper brokerageWithdrawMapper;
61 - @Resource  
62 - private TradeNoRedisDAO tradeNoRedisDAO;  
63 59
64 @Resource 60 @Resource
65 private BrokerageRecordService brokerageRecordService; 61 private BrokerageRecordService brokerageRecordService;
@@ -104,6 +100,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -104,6 +100,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
104 templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE; 100 templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE;
105 // 3.1 通过时佣金转余额 101 // 3.1 通过时佣金转余额
106 if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) { 102 if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
  103 + // TODO 改成直接调用 addWallet 增加余额,不用查询 wallet
107 PayWalletRespDTO wallet = payWalletApi.getWalletByUserId(withdraw.getUserId()); 104 PayWalletRespDTO wallet = payWalletApi.getWalletByUserId(withdraw.getUserId());
108 payWalletApi.addWallet(new PayWalletCreateReqDto() 105 payWalletApi.addWallet(new PayWalletCreateReqDto()
109 .setWalletId(wallet.getId()) 106 .setWalletId(wallet.getId())
@@ -116,12 +113,9 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -116,12 +113,9 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
116 if (rows == 0) { 113 if (rows == 0) {
117 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING); 114 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
118 } 115 }
119 - }else if (BrokerageWithdrawTypeEnum.ALIPAY_SMALL.getType().equals(withdraw.getType())){  
120 - //获取openid  
121 - SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType());  
122 - // 微信提现  
123 - PayTransferCreateReqDTO payTransferCreateReqDTO = getPayTransferCreateReqDTO(userIp, withdraw, socialUser);  
124 - payTransferApi.createTransfer(payTransferCreateReqDTO); 116 + } else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(withdraw.getType())) {
  117 + // TODO @luchi:这里,要加个转账单号的记录;另外,调用 API 转账,是立马成功,还是有延迟的哈?
  118 + Long payTransferId = createPayTransfer(userIp, withdraw);
125 } 119 }
126 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) { 120 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
127 templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT; 121 templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT;
@@ -132,6 +126,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -132,6 +126,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
132 throw new IllegalArgumentException("不支持的提现状态:" + status); 126 throw new IllegalArgumentException("不支持的提现状态:" + status);
133 } 127 }
134 128
  129 + // TODO @luchi:这个通知,还是要的呀~~~
135 // 4. 通知用户 130 // 4. 通知用户
136 // Map<String, Object> templateParams = MapUtil.<String, Object>builder() 131 // Map<String, Object> templateParams = MapUtil.<String, Object>builder()
137 // .put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime())) 132 // .put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime()))
@@ -142,17 +137,21 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -142,17 +137,21 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
142 // .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams)); 137 // .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams));
143 } 138 }
144 139
145 - private PayTransferCreateReqDTO getPayTransferCreateReqDTO(String userIp, BrokerageWithdrawDO withdraw, SocialUserRespDTO socialUser) {  
146 - PayTransferCreateReqDTO payTransferCreateReqDTO = new PayTransferCreateReqDTO();  
147 - payTransferCreateReqDTO.setAppKey(tradeOrderProperties.getPayAppKey());  
148 - payTransferCreateReqDTO.setChannelCode("wx_lite");  
149 - payTransferCreateReqDTO.setUserIp(userIp);  
150 - payTransferCreateReqDTO.setType(PayTransferTypeEnum.WX_BALANCE.getType());  
151 - payTransferCreateReqDTO.setMerchantTransferId(withdraw.getId().toString());  
152 - payTransferCreateReqDTO.setPrice(withdraw.getPrice());  
153 - payTransferCreateReqDTO.setSubject("佣金提现");  
154 - payTransferCreateReqDTO.setOpenid(socialUser.getOpenid());  
155 - return payTransferCreateReqDTO; 140 + private Long createPayTransfer(String userIp, BrokerageWithdrawDO withdraw) {
  141 + // 1.1 获取微信 openid
  142 + SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(
  143 + UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType());
  144 + // TODO @luchi:这里,需要校验非空。如果空的话,要有业务异常哈;
  145 + // 1.2 构建请求
  146 + PayTransferCreateReqDTO payTransferCreateReqDTO = new PayTransferCreateReqDTO()
  147 + .setAppKey(tradeOrderProperties.getPayAppKey())
  148 + .setChannelCode("wx_lite").setType(PayTransferTypeEnum.WX_BALANCE.getType())
  149 + .setMerchantTransferId(withdraw.getId().toString())
  150 + .setPrice(withdraw.getPrice())
  151 + .setSubject("佣金提现")
  152 + .setOpenid(socialUser.getOpenid()).setUserIp(userIp);
  153 + // 2. 发起请求
  154 + return payTransferApi.createTransfer(payTransferCreateReqDTO);
156 } 155 }
157 156
158 private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) { 157 private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) {
@@ -194,32 +193,6 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -194,32 +193,6 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
194 return withdraw.getId(); 193 return withdraw.getId();
195 } 194 }
196 195
197 - @Override  
198 - public List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,  
199 - BrokerageWithdrawStatusEnum status) {  
200 - if (CollUtil.isEmpty(userIds)) {  
201 - return Collections.emptyList();  
202 - }  
203 - return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus());  
204 - }  
205 -  
206 - @Override  
207 - public void updateTransfer(Long id, Long payTransferId) {  
208 - BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);  
209 - PayTransferRespDTO transfer = payTransferApi.getTransfer(payTransferId);  
210 - if(PayTransferStatusEnum.isSuccess(transfer.getStatus())){  
211 - withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());  
212 - }else if(PayTransferStatusEnum.isPendingStatus(transfer.getStatus())){  
213 - withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus());  
214 - }else{  
215 - withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus());  
216 - // 3.2 驳回时需要退还用户佣金  
217 - brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,  
218 - String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());  
219 - }  
220 - brokerageWithdrawMapper.updateById(withdraw);  
221 - }  
222 -  
223 /** 196 /**
224 * 计算提现手续费 197 * 计算提现手续费
225 * 198 *
@@ -227,7 +200,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -227,7 +200,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
227 * @param percent 手续费百分比 200 * @param percent 手续费百分比
228 * @return 提现手续费 201 * @return 提现手续费
229 */ 202 */
230 - Integer calculateFeePrice(Integer withdrawPrice, Integer percent) { 203 + private Integer calculateFeePrice(Integer withdrawPrice, Integer percent) {
231 Integer feePrice = 0; 204 Integer feePrice = 0;
232 if (percent != null && percent > 0) { 205 if (percent != null && percent > 0) {
233 feePrice = MoneyUtils.calculateRatePrice(withdrawPrice, Double.valueOf(percent)); 206 feePrice = MoneyUtils.calculateRatePrice(withdrawPrice, Double.valueOf(percent));
@@ -241,11 +214,41 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -241,11 +214,41 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
241 * @param withdrawPrice 提现金额 214 * @param withdrawPrice 提现金额
242 * @return 分销配置 215 * @return 分销配置
243 */ 216 */
244 - TradeConfigDO validateWithdrawPrice(Integer withdrawPrice) { 217 + private TradeConfigDO validateWithdrawPrice(Integer withdrawPrice) {
245 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); 218 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
246 if (tradeConfig.getBrokerageWithdrawMinPrice() != null && withdrawPrice < tradeConfig.getBrokerageWithdrawMinPrice()) { 219 if (tradeConfig.getBrokerageWithdrawMinPrice() != null && withdrawPrice < tradeConfig.getBrokerageWithdrawMinPrice()) {
247 throw exception(BROKERAGE_WITHDRAW_MIN_PRICE, MoneyUtils.fenToYuanStr(tradeConfig.getBrokerageWithdrawMinPrice())); 220 throw exception(BROKERAGE_WITHDRAW_MIN_PRICE, MoneyUtils.fenToYuanStr(tradeConfig.getBrokerageWithdrawMinPrice()));
248 } 221 }
249 return tradeConfig; 222 return tradeConfig;
250 } 223 }
  224 +
  225 + @Override
  226 + @Transactional(rollbackFor = Exception.class)
  227 + public void updateBrokerageWithdrawTransferred(Long id, Long payTransferId) {
  228 + BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
  229 + PayTransferRespDTO transfer = payTransferApi.getTransfer(payTransferId);
  230 + // TODO @luchi:建议参考支付那,即使成功的情况下,也要各种校验;金额是否匹配、转账单号是否匹配、是否重复调用;
  231 + if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) {
  232 + withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());
  233 + } else if (PayTransferStatusEnum.isPendingStatus(transfer.getStatus())) {
  234 + // TODO @luchi:这里,是不是不用更新哈?
  235 + withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus());
  236 + } else {
  237 + withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus());
  238 + // 3.2 驳回时需要退还用户佣金
  239 + brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
  240 + String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
  241 + }
  242 + brokerageWithdrawMapper.updateById(withdraw);
  243 + }
  244 +
  245 + @Override
  246 + public List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,
  247 + BrokerageWithdrawStatusEnum status) {
  248 + if (CollUtil.isEmpty(userIds)) {
  249 + return Collections.emptyList();
  250 + }
  251 + return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus());
  252 + }
  253 +
251 } 254 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayTransferNotifyReqDTO.java
@@ -13,6 +13,7 @@ import jakarta.validation.constraints.NotNull; @@ -13,6 +13,7 @@ import jakarta.validation.constraints.NotNull;
13 @Data 13 @Data
14 public class PayTransferNotifyReqDTO { 14 public class PayTransferNotifyReqDTO {
15 15
  16 + // TODO 芋艿:要不要改成 orderId 待定;
16 /** 17 /**
17 * 商户转账单号 18 * 商户转账单号
18 */ 19 */
@@ -24,4 +25,5 @@ public class PayTransferNotifyReqDTO { @@ -24,4 +25,5 @@ public class PayTransferNotifyReqDTO {
24 */ 25 */
25 @NotNull(message = "转账订单编号不能为空") 26 @NotNull(message = "转账订单编号不能为空")
26 private Long payTransferId; 27 private Long payTransferId;
  28 +
27 } 29 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java
@@ -21,9 +21,11 @@ public interface PayTransferApi { @@ -21,9 +21,11 @@ public interface PayTransferApi {
21 Long createTransfer(@Valid PayTransferCreateReqDTO reqDTO); 21 Long createTransfer(@Valid PayTransferCreateReqDTO reqDTO);
22 22
23 /** 23 /**
24 - * 获取转账单详细 24 + * 获得转账单
  25 + *
25 * @param id 转账单编号 26 * @param id 转账单编号
26 - * @return 转账单详细 27 + * @return 转账单
27 */ 28 */
28 PayTransferRespDTO getTransfer(Long id); 29 PayTransferRespDTO getTransfer(Long id);
  30 +
29 } 31 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java
1 package cn.iocoder.yudao.module.pay.api.transfer.dto; 1 package cn.iocoder.yudao.module.pay.api.transfer.dto;
2 2
  3 +import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
3 import lombok.Data; 4 import lombok.Data;
4 5
5 @Data 6 @Data
@@ -12,7 +13,6 @@ public class PayTransferRespDTO { @@ -12,7 +13,6 @@ public class PayTransferRespDTO {
12 13
13 /** 14 /**
14 * 转账单号 15 * 转账单号
15 - *  
16 */ 16 */
17 private String no; 17 private String no;
18 18
@@ -24,9 +24,8 @@ public class PayTransferRespDTO { @@ -24,9 +24,8 @@ public class PayTransferRespDTO {
24 /** 24 /**
25 * 转账状态 25 * 转账状态
26 * 26 *
27 - * 枚举 {@link PayTransferStatusRespEnum} 27 + * 枚举 {@link PayTransferStatusEnum}
28 */ 28 */
29 private Integer status; 29 private Integer status;
30 30
31 -  
32 } 31 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApi.java
@@ -10,16 +10,21 @@ import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO; @@ -10,16 +10,21 @@ import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
10 */ 10 */
11 public interface PayWalletApi { 11 public interface PayWalletApi {
12 12
  13 + // TODO @luchi:1)改成 addWalletBalance;2)PayWalletCreateReqDto 搞成 userId、userType;3)bizType 使用 integer,不然后续挪到 cloud 不好弄,因为枚举不好序列化
13 /** 14 /**
14 * 添加钱包 15 * 添加钱包
  16 + *
15 * @param reqDTO 创建请求 17 * @param reqDTO 创建请求
16 */ 18 */
17 void addWallet(PayWalletCreateReqDto reqDTO); 19 void addWallet(PayWalletCreateReqDto reqDTO);
18 20
  21 + // TODO @luchi:不用去 getWalletByUserId 钱包,直接添加余额就好。里面内部去创建。如果删除掉的化,PayWalletRespDTO 也删除哈。
19 /** 22 /**
20 - * 根据用户id获取钱包信息 23 + * 根据用户编号,获取钱包信息
  24 + *
21 * @param userId 用户id 25 * @param userId 用户id
22 * @return 钱包信息 26 * @return 钱包信息
23 */ 27 */
24 PayWalletRespDTO getWalletByUserId(Long userId); 28 PayWalletRespDTO getWalletByUserId(Long userId);
  29 +
25 } 30 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java
1 package cn.iocoder.yudao.module.pay.api.transfer; 1 package cn.iocoder.yudao.module.pay.api.transfer;
2 2
  3 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
3 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 4 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
4 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO; 5 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
5 -import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert;  
6 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
7 import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService; 7 import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
  8 +import jakarta.annotation.Resource;
8 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
9 import org.springframework.validation.annotation.Validated; 10 import org.springframework.validation.annotation.Validated;
10 11
11 -import jakarta.annotation.Resource;  
12 -  
13 /** 12 /**
14 * 转账单 API 实现类 13 * 转账单 API 实现类
15 * 14 *
@@ -30,7 +29,7 @@ public class PayTransferApiImpl implements PayTransferApi { @@ -30,7 +29,7 @@ public class PayTransferApiImpl implements PayTransferApi {
30 @Override 29 @Override
31 public PayTransferRespDTO getTransfer(Long id) { 30 public PayTransferRespDTO getTransfer(Long id) {
32 PayTransferDO transfer = payTransferService.getTransfer(id); 31 PayTransferDO transfer = payTransferService.getTransfer(id);
33 - return PayTransferConvert.INSTANCE.convert3(transfer); 32 + return BeanUtils.toBean(transfer, PayTransferRespDTO.class);
34 } 33 }
35 34
36 } 35 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApiImpl.java
1 package cn.iocoder.yudao.module.pay.api.wallet; 1 package cn.iocoder.yudao.module.pay.api.wallet;
2 2
3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto; 5 import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;
5 import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO; 6 import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
6 -import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletConvert;  
7 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
8 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; 8 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
9 import jakarta.annotation.Resource; 9 import jakarta.annotation.Resource;
@@ -22,13 +22,12 @@ public class PayWalletApiImpl implements PayWalletApi { @@ -22,13 +22,12 @@ public class PayWalletApiImpl implements PayWalletApi {
22 22
23 @Override 23 @Override
24 public void addWallet(PayWalletCreateReqDto reqDTO) { 24 public void addWallet(PayWalletCreateReqDto reqDTO) {
25 - //添加钱包金额  
26 payWalletService.addWalletBalance(reqDTO.getWalletId(), reqDTO.getBizId(), reqDTO.getBizType(), reqDTO.getPrice()); 25 payWalletService.addWalletBalance(reqDTO.getWalletId(), reqDTO.getBizId(), reqDTO.getBizType(), reqDTO.getPrice());
27 } 26 }
28 27
29 @Override 28 @Override
30 public PayWalletRespDTO getWalletByUserId(Long userId) { 29 public PayWalletRespDTO getWalletByUserId(Long userId) {
31 PayWalletDO orCreateWallet = payWalletService.getOrCreateWallet(userId, UserTypeEnum.MEMBER.getValue()); 30 PayWalletDO orCreateWallet = payWalletService.getOrCreateWallet(userId, UserTypeEnum.MEMBER.getValue());
32 - return PayWalletConvert.INSTANCE.convert03(orCreateWallet); 31 + return BeanUtils.toBean(orCreateWallet, PayWalletRespDTO.class);
33 } 32 }
34 } 33 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppBaseVO.java
@@ -40,8 +40,7 @@ public class PayAppBaseVO { @@ -40,8 +40,7 @@ public class PayAppBaseVO {
40 @URL(message = "退款结果的回调地址必须为 URL 格式") 40 @URL(message = "退款结果的回调地址必须为 URL 格式")
41 private String refundNotifyUrl; 41 private String refundNotifyUrl;
42 42
43 - @Schema(description = "转账结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/refund-callback")  
44 - @NotNull(message = "转账结果的回调地址不能为空") 43 + @Schema(description = "转账结果的回调地址", example = "http://127.0.0.1:48080/transfer-callback")
45 @URL(message = "转账结果的回调地址必须为 URL 格式") 44 @URL(message = "转账结果的回调地址必须为 URL 格式")
46 private String transferNotifyUrl; 45 private String transferNotifyUrl;
47 46
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
@@ -69,7 +69,7 @@ public class PayNotifyController { @@ -69,7 +69,7 @@ public class PayNotifyController {
69 // 1. 校验支付渠道是否存在 69 // 1. 校验支付渠道是否存在
70 PayClient payClient = channelService.getPayClient(channelId); 70 PayClient payClient = channelService.getPayClient(channelId);
71 if (payClient == null) { 71 if (payClient == null) {
72 - log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 72 + log.error("[notifyOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
73 throw exception(CHANNEL_NOT_FOUND); 73 throw exception(CHANNEL_NOT_FOUND);
74 } 74 }
75 75
@@ -83,13 +83,13 @@ public class PayNotifyController { @@ -83,13 +83,13 @@ public class PayNotifyController {
83 @Operation(summary = "支付渠道的统一【退款】回调") 83 @Operation(summary = "支付渠道的统一【退款】回调")
84 @PermitAll 84 @PermitAll
85 public String notifyRefund(@PathVariable("channelId") Long channelId, 85 public String notifyRefund(@PathVariable("channelId") Long channelId,
86 - @RequestParam(required = false) Map<String, String> params,  
87 - @RequestBody(required = false) String body) { 86 + @RequestParam(required = false) Map<String, String> params,
  87 + @RequestBody(required = false) String body) {
88 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body); 88 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
89 // 1. 校验支付渠道是否存在 89 // 1. 校验支付渠道是否存在
90 PayClient payClient = channelService.getPayClient(channelId); 90 PayClient payClient = channelService.getPayClient(channelId);
91 if (payClient == null) { 91 if (payClient == null) {
92 - log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 92 + log.error("[notifyRefund][渠道编号({}) 找不到对应的支付客户端]", channelId);
93 throw exception(CHANNEL_NOT_FOUND); 93 throw exception(CHANNEL_NOT_FOUND);
94 } 94 }
95 95
@@ -103,13 +103,13 @@ public class PayNotifyController { @@ -103,13 +103,13 @@ public class PayNotifyController {
103 @Operation(summary = "支付渠道的统一【转账】回调") 103 @Operation(summary = "支付渠道的统一【转账】回调")
104 @PermitAll 104 @PermitAll
105 public String notifyTransfer(@PathVariable("channelId") Long channelId, 105 public String notifyTransfer(@PathVariable("channelId") Long channelId,
106 - @RequestParam(required = false) Map<String, String> params,  
107 - @RequestBody(required = false) String body) {  
108 - log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body); 106 + @RequestParam(required = false) Map<String, String> params,
  107 + @RequestBody(required = false) String body) {
  108 + log.info("[notifyTransfer][channelId({}) 回调数据({}/{})]", channelId, params, body);
109 // 1. 校验支付渠道是否存在 109 // 1. 校验支付渠道是否存在
110 PayClient payClient = channelService.getPayClient(channelId); 110 PayClient payClient = channelService.getPayClient(channelId);
111 if (payClient == null) { 111 if (payClient == null) {
112 - log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 112 + log.error("[notifyTransfer][渠道编号({}) 找不到对应的支付客户端]", channelId);
113 throw exception(CHANNEL_NOT_FOUND); 113 throw exception(CHANNEL_NOT_FOUND);
114 } 114 }
115 115
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.convert.transfer; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.convert.transfer;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; 4 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
5 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 5 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
6 -import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;  
7 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
8 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; 7 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
9 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageItemRespVO; 8 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageItemRespVO;
@@ -27,7 +26,6 @@ public interface PayTransferConvert { @@ -27,7 +26,6 @@ public interface PayTransferConvert {
27 26
28 PayTransferRespVO convert(PayTransferDO bean); 27 PayTransferRespVO convert(PayTransferDO bean);
29 28
30 - PayTransferRespDTO convert3(PayTransferDO bean);  
31 -  
32 PageResult<PayTransferPageItemRespVO> convertPage(PageResult<PayTransferDO> pageResult); 29 PageResult<PayTransferPageItemRespVO> convertPage(PageResult<PayTransferDO> pageResult);
  30 +
33 } 31 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java
1 package cn.iocoder.yudao.module.pay.convert.wallet; 1 package cn.iocoder.yudao.module.pay.convert.wallet;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;  
5 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;  
6 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletRespVO; 4 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletRespVO;
7 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO; 5 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO;
8 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
@@ -20,6 +18,4 @@ public interface PayWalletConvert { @@ -20,6 +18,4 @@ public interface PayWalletConvert {
20 18
21 PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page); 19 PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page);
22 20
23 - PayWalletRespDTO convert03(PayWalletDO orCreateWallet);  
24 -  
25 } 21 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
7 -import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;  
8 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
9 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 8 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
10 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
@@ -24,10 +23,6 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; { @@ -24,10 +23,6 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; {
24 PayTransferDO::getMerchantTransferId, merchantTransferId); 23 PayTransferDO::getMerchantTransferId, merchantTransferId);
25 } 24 }
26 25
27 - default PayTransferDO selectByNo(String no){  
28 - return selectOne(PayTransferDO::getNo, no);  
29 - }  
30 -  
31 default PageResult<PayTransferDO> selectPage(PayTransferPageReqVO reqVO) { 26 default PageResult<PayTransferDO> selectPage(PayTransferPageReqVO reqVO) {
32 return selectPage(reqVO, new LambdaQueryWrapperX<PayTransferDO>() 27 return selectPage(reqVO, new LambdaQueryWrapperX<PayTransferDO>()
33 .eqIfPresent(PayTransferDO::getNo, reqVO.getNo()) 28 .eqIfPresent(PayTransferDO::getNo, reqVO.getNo())
@@ -42,15 +37,15 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; { @@ -42,15 +37,15 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; {
42 .orderByDesc(PayTransferDO::getId)); 37 .orderByDesc(PayTransferDO::getId));
43 } 38 }
44 39
45 - default List<PayTransferDO> selectListByStatus(Integer status){ 40 + default List<PayTransferDO> selectListByStatus(Integer status) {
46 return selectList(PayTransferDO::getStatus, status); 41 return selectList(PayTransferDO::getStatus, status);
47 } 42 }
48 43
49 - default PayTransferDO selectByAppIdAndNo(Long appId, String no){  
50 - return selectOne(new LambdaQueryWrapperX<PayTransferDO>()  
51 - .eq(PayTransferDO::getAppId, appId)  
52 - .eq(PayTransferDO::getNo, no)); 44 + default PayTransferDO selectByAppIdAndNo(Long appId, String no) {
  45 + return selectOne(PayTransferDO::getAppId, appId,
  46 + PayTransferDO::getNo, no);
53 } 47 }
  48 +
54 } 49 }
55 50
56 51
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java
@@ -114,7 +114,6 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; { @@ -114,7 +114,6 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
114 return update(null, lambdaUpdateWrapper); 114 return update(null, lambdaUpdateWrapper);
115 } 115 }
116 116
117 -  
118 } 117 }
119 118
120 119
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java
@@ -78,4 +78,5 @@ public interface PayRefundService { @@ -78,4 +78,5 @@ public interface PayRefundService {
78 * @return 同步到状态的退款数量,包括退款成功、退款失败 78 * @return 同步到状态的退款数量,包括退款成功、退款失败
79 */ 79 */
80 int syncRefund(); 80 int syncRefund();
  81 +
81 } 82 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
@@ -193,8 +193,6 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -193,8 +193,6 @@ public class PayRefundServiceImpl implements PayRefundService {
193 TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyRefund(channel, notify)); 193 TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyRefund(channel, notify));
194 } 194 }
195 195
196 -  
197 -  
198 /** 196 /**
199 * 通知并更新订单的退款结果 197 * 通知并更新订单的退款结果
200 * 198 *
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java
@@ -63,4 +63,5 @@ public interface PayTransferService { @@ -63,4 +63,5 @@ public interface PayTransferService {
63 * @param notify 通知 63 * @param notify 通知
64 */ 64 */
65 void notifyTransfer(Long channelId, PayTransferRespDTO notify); 65 void notifyTransfer(Long channelId, PayTransferRespDTO notify);
  66 +
66 } 67 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
@@ -29,7 +29,6 @@ import jakarta.annotation.Resource; @@ -29,7 +29,6 @@ import jakarta.annotation.Resource;
29 import jakarta.validation.Validator; 29 import jakarta.validation.Validator;
30 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
31 import org.springframework.stereotype.Service; 31 import org.springframework.stereotype.Service;
32 -import org.springframework.transaction.annotation.Propagation;  
33 import org.springframework.transaction.annotation.Transactional; 32 import org.springframework.transaction.annotation.Transactional;
34 33
35 import java.util.List; 34 import java.util.List;
@@ -171,8 +170,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -171,8 +170,7 @@ public class PayTransferServiceImpl implements PayTransferService {
171 170
172 private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) { 171 private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) {
173 // 1.校验 172 // 1.校验
174 - PayTransferDO transfer = transferMapper.selectByAppIdAndNo(  
175 - channel.getAppId(), notify.getOutTransferNo()); 173 + PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
176 if (transfer == null) { 174 if (transfer == null) {
177 throw exception(PAY_TRANSFER_NOT_FOUND); 175 throw exception(PAY_TRANSFER_NOT_FOUND);
178 } 176 }
@@ -195,8 +193,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -195,8 +193,7 @@ public class PayTransferServiceImpl implements PayTransferService {
195 193
196 private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) { 194 private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
197 // 1.校验 195 // 1.校验
198 - PayTransferDO transfer = transferMapper.selectByAppIdAndNo(  
199 - channel.getAppId(), notify.getOutTransferNo()); 196 + PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
200 if (transfer == null) { 197 if (transfer == null) {
201 throw exception(PAY_TRANSFER_NOT_FOUND); 198 throw exception(PAY_TRANSFER_NOT_FOUND);
202 } 199 }
@@ -225,8 +222,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -225,8 +222,7 @@ public class PayTransferServiceImpl implements PayTransferService {
225 222
226 private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { 223 private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
227 // 1.校验 224 // 1.校验
228 - PayTransferDO transfer = transferMapper.selectByAppIdAndNo(  
229 - channel.getAppId(), notify.getOutTransferNo()); 225 + PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
230 if (transfer == null) { 226 if (transfer == null) {
231 throw exception(PAY_TRANSFER_NOT_FOUND); 227 throw exception(PAY_TRANSFER_NOT_FOUND);
232 } 228 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
@@ -200,6 +200,7 @@ public class PayWalletServiceImpl implements PayWalletService { @@ -200,6 +200,7 @@ public class PayWalletServiceImpl implements PayWalletService {
200 case UPDATE_BALANCE: // 更新余额 200 case UPDATE_BALANCE: // 更新余额
201 walletMapper.updateWhenRecharge(payWallet.getId(), price); 201 walletMapper.updateWhenRecharge(payWallet.getId(), price);
202 break; 202 break;
  203 + // TODO @luchi:1)不能使用 updateWhenRecharge,它是充值哈。应该增加余额就 ok 了。。ps:顺便帮我把 UPDATE_BALANCE 也改改哈;2)其实不用 WITHDRAW 枚举,复用 UPDATE_BALANCE 就好了。
203 case WITHDRAW: 204 case WITHDRAW:
204 walletMapper.updateWhenRecharge(payWallet.getId(), price); 205 walletMapper.updateWhenRecharge(payWallet.getId(), price);
205 break; 206 break;
yudao-module-pay/yudao-spring-boot-starter-biz-pay/pom.xml
@@ -64,10 +64,6 @@ @@ -64,10 +64,6 @@
64 <groupId>com.github.binarywang</groupId> 64 <groupId>com.github.binarywang</groupId>
65 <artifactId>weixin-java-pay</artifactId> 65 <artifactId>weixin-java-pay</artifactId>
66 </dependency> 66 </dependency>
67 - <dependency>  
68 - <groupId>com.github.binarywang</groupId>  
69 - <artifactId>wx-java-miniapp-spring-boot-starter</artifactId>  
70 - </dependency>  
71 67
72 <!-- Test 测试相关 --> 68 <!-- Test 测试相关 -->
73 <dependency> 69 <dependency>
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
@@ -106,4 +106,5 @@ public interface PayClient { @@ -106,4 +106,5 @@ public interface PayClient {
106 * @return 转账信息 106 * @return 转账信息
107 */ 107 */
108 PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body); 108 PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body);
  109 +
109 } 110 }
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java
@@ -84,4 +84,5 @@ public class PayTransferUnifiedReqDTO { @@ -84,4 +84,5 @@ public class PayTransferUnifiedReqDTO {
84 @NotEmpty(message = "转账结果的回调地址不能为空") 84 @NotEmpty(message = "转账结果的回调地址不能为空")
85 @URL(message = "转账结果的 notify 回调地址必须是 URL 格式") 85 @URL(message = "转账结果的 notify 回调地址必须是 URL 格式")
86 private String notifyUrl; 86 private String notifyUrl;
  87 +
87 } 88 }
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/WxPayTransferPartnerNotifyV3Result.java
@@ -8,6 +8,7 @@ import lombok.NoArgsConstructor; @@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
8 8
9 import java.io.Serializable; 9 import java.io.Serializable;
10 10
  11 +// TODO @luchi:这个可以复用 wxjava 里的类么?
11 @NoArgsConstructor 12 @NoArgsConstructor
12 public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferPartnerNotifyV3Result.TransferNotifyResult> { 13 public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferPartnerNotifyV3Result.TransferNotifyResult> {
13 14
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,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -325,6 +325,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
325 } 325 }
326 } 326 }
327 327
  328 + // TODO @chihuo:这里是不是也要实现,支付宝的。
328 @Override 329 @Override
329 protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable { 330 protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
330 throw new UnsupportedOperationException("未实现"); 331 throw new UnsupportedOperationException("未实现");
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
@@ -18,21 +18,23 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPart @@ -18,21 +18,23 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPart
18 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; 18 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
19 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; 19 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
20 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum; 20 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
21 -import com.github.binarywang.wxpay.bean.notify.*; 21 +import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
  22 +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
  23 +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
  24 +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
22 import com.github.binarywang.wxpay.bean.request.*; 25 import com.github.binarywang.wxpay.bean.request.*;
23 import com.github.binarywang.wxpay.bean.result.*; 26 import com.github.binarywang.wxpay.bean.result.*;
24 import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest; 27 import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
25 import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult; 28 import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
26 import com.github.binarywang.wxpay.config.WxPayConfig; 29 import com.github.binarywang.wxpay.config.WxPayConfig;
27 import com.github.binarywang.wxpay.exception.WxPayException; 30 import com.github.binarywang.wxpay.exception.WxPayException;
28 -import com.github.binarywang.wxpay.service.TransferService;  
29 import com.github.binarywang.wxpay.service.WxPayService; 31 import com.github.binarywang.wxpay.service.WxPayService;
30 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; 32 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
31 import lombok.extern.slf4j.Slf4j; 33 import lombok.extern.slf4j.Slf4j;
32 34
33 import java.time.LocalDateTime; 35 import java.time.LocalDateTime;
34 import java.time.ZoneId; 36 import java.time.ZoneId;
35 -import java.util.ArrayList; 37 +import java.util.Collections;
36 import java.util.List; 38 import java.util.List;
37 import java.util.Map; 39 import java.util.Map;
38 import java.util.Objects; 40 import java.util.Objects;
@@ -356,17 +358,21 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC @@ -356,17 +358,21 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
356 switch (config.getApiVersion()) { 358 switch (config.getApiVersion()) {
357 case API_VERSION_V3: 359 case API_VERSION_V3:
358 return parseTransferNotifyV3(body); 360 return parseTransferNotifyV3(body);
  361 + case API_VERSION_V2:
  362 + throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
359 default: 363 default:
360 throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); 364 throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
361 } 365 }
362 } 366 }
363 367
364 private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException { 368 private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException {
  369 + // 1. 解析回调
  370 + // TODO @luchi:这个可以复用 wxjava 里的类么?
365 WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class); 371 WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class);
366 WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult(); 372 WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult();
367 // 2. 构建结果 373 // 2. 构建结果
368 if (Objects.equals("FINISHED", result.getBatchStatus())) { 374 if (Objects.equals("FINISHED", result.getBatchStatus())) {
369 - if(result.getFailNum() <= 0){ 375 + if (result.getFailNum() <= 0) {
370 return PayTransferRespDTO.successOf(result.getBatchId(), parseDateV3(result.getUpdateTime()), 376 return PayTransferRespDTO.successOf(result.getBatchId(), parseDateV3(result.getUpdateTime()),
371 result.getOutBatchNo(), response); 377 result.getOutBatchNo(), response);
372 } 378 }
@@ -453,29 +459,33 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC @@ -453,29 +459,33 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
453 459
454 @Override 460 @Override
455 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws WxPayException { 461 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws WxPayException {
456 - TransferService transferService = client.getTransferService();  
457 - List<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();  
458 - transferDetailList.add(TransferBatchesRequest.TransferDetail.newBuilder()  
459 - .outDetailNo(reqDTO.getOutTransferNo())  
460 - .transferAmount(reqDTO.getPrice())  
461 - .transferRemark(reqDTO.getSubject())  
462 - .openid(reqDTO.getOpenid())  
463 - .build()); 462 + // 1. 构建 TransferBatchesRequest 请求
  463 + List<TransferBatchesRequest.TransferDetail> transferDetailList = Collections.singletonList(
  464 + TransferBatchesRequest.TransferDetail.newBuilder()
  465 + .outDetailNo(reqDTO.getOutTransferNo())
  466 + .transferAmount(reqDTO.getPrice())
  467 + .transferRemark(reqDTO.getSubject())
  468 + .openid(reqDTO.getOpenid())
  469 + .build());
  470 + // TODO @luchi:能不能我们搞个 TransferBatchesRequestX extends TransferBatchesRequest,这样更简洁一点。
464 TransferBatchesRequest transferBatches = TransferBatchesRequest.newBuilder() 471 TransferBatchesRequest transferBatches = TransferBatchesRequest.newBuilder()
465 .appid(this.config.getAppId()) 472 .appid(this.config.getAppId())
466 .outBatchNo(reqDTO.getOutTransferNo()) 473 .outBatchNo(reqDTO.getOutTransferNo())
467 .batchName(reqDTO.getSubject()) 474 .batchName(reqDTO.getSubject())
468 .batchRemark(reqDTO.getSubject()) 475 .batchRemark(reqDTO.getSubject())
469 .totalAmount(reqDTO.getPrice()) 476 .totalAmount(reqDTO.getPrice())
470 - .totalNum(1)  
471 - .transferDetailList(transferDetailList).build();  
472 - transferBatches.setNotifyUrl(reqDTO.getNotifyUrl());  
473 - TransferBatchesResult transferBatchesResult = transferService.transferBatches(transferBatches); 477 + .totalNum(transferDetailList.size())
  478 + .transferDetailList(transferDetailList).build()
  479 + .setNotifyUrl(reqDTO.getNotifyUrl());
  480 + // 2.1 执行请求
  481 + TransferBatchesResult transferBatchesResult = client.getTransferService().transferBatches(transferBatches);
  482 + // 2.2 创建返回结果
474 return PayTransferRespDTO.dealingOf(transferBatchesResult.getBatchId(), reqDTO.getOutTransferNo(), transferBatchesResult); 483 return PayTransferRespDTO.dealingOf(transferBatchesResult.getBatchId(), reqDTO.getOutTransferNo(), transferBatchesResult);
475 } 484 }
476 485
477 @Override 486 @Override
478 protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) { 487 protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) {
  488 + // TODO luchi:这个最好实现下。因为可能要主动轮询转账结果
479 throw new UnsupportedOperationException("待实现"); 489 throw new UnsupportedOperationException("待实现");
480 } 490 }
481 491