Commit 87cee4628ac3c00659b1cd3f2c4e85e71f2b1f8c

Authored by YunaiV
1 parent 396051b4

【代码优化】商城:优化分销提现的逻辑(余额)

yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java
@@ -11,9 +11,6 @@ public interface MessageTemplateConstants { @@ -11,9 +11,6 @@ public interface MessageTemplateConstants {
11 11
12 String SMS_ORDER_DELIVERY = "order_delivery"; // 短信模版编号 12 String SMS_ORDER_DELIVERY = "order_delivery"; // 短信模版编号
13 13
14 - String SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过)  
15 - String SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过)  
16 -  
17 // ======================= 小程序订阅消息模版 ======================= 14 // ======================= 小程序订阅消息模版 =======================
18 15
19 String WXA_ORDER_DELIVERY = "订单发货通知"; 16 String WXA_ORDER_DELIVERY = "订单发货通知";
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawTypeEnum.java
@@ -38,4 +38,14 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable { @@ -38,4 +38,14 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable {
38 return ARRAYS; 38 return ARRAYS;
39 } 39 }
40 40
  41 + /**
  42 + * 是否通过支付平台的 API 打款
  43 + *
  44 + * @param type 类型
  45 + * @return 是否
  46 + */
  47 + public static boolean isApi(Integer type) {
  48 + return WECHAT_API.getType().equals(type);
  49 + }
  50 +
41 } 51 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java
@@ -9,8 +9,7 @@ import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi; @@ -9,8 +9,7 @@ import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
9 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 9 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
10 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO; 10 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
11 import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi; 11 import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi;
12 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;  
13 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO; 12 +import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
14 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum; 13 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
15 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum; 14 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
16 import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum; 15 import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
@@ -24,7 +23,6 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert; @@ -24,7 +23,6 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
24 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO; 23 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
25 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; 24 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
26 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper; 25 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
27 -import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants;  
28 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; 26 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
29 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; 27 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
30 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum; 28 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
@@ -33,6 +31,7 @@ import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSumma @@ -33,6 +31,7 @@ import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSumma
33 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; 31 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
34 import jakarta.annotation.Resource; 32 import jakarta.annotation.Resource;
35 import jakarta.validation.Validator; 33 import jakarta.validation.Validator;
  34 +import lombok.extern.slf4j.Slf4j;
36 import org.springframework.stereotype.Service; 35 import org.springframework.stereotype.Service;
37 import org.springframework.transaction.annotation.Transactional; 36 import org.springframework.transaction.annotation.Transactional;
38 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
@@ -43,6 +42,7 @@ import java.util.Collections; @@ -43,6 +42,7 @@ import java.util.Collections;
43 import java.util.List; 42 import java.util.List;
44 43
45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 44 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  45 +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
46 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; 46 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
47 47
48 /** 48 /**
@@ -52,6 +52,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; @@ -52,6 +52,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
52 */ 52 */
53 @Service 53 @Service
54 @Validated 54 @Validated
  55 +@Slf4j
55 public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { 56 public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
56 57
57 @Resource 58 @Resource
@@ -82,62 +83,55 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -82,62 +83,55 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
82 public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) { 83 public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) {
83 // 1.1 校验存在 84 // 1.1 校验存在
84 BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id); 85 BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
85 -  
86 // 1.2 校验状态为审核中 86 // 1.2 校验状态为审核中
87 if (ObjectUtil.notEqual(BrokerageWithdrawStatusEnum.AUDITING.getStatus(), withdraw.getStatus())) { 87 if (ObjectUtil.notEqual(BrokerageWithdrawStatusEnum.AUDITING.getStatus(), withdraw.getStatus())) {
88 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING); 88 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
89 } 89 }
90 90
91 - // 2. 更新 91 + // 2. 更新状态
92 int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(), 92 int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(),
93 new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now())); 93 new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
94 if (rows == 0) { 94 if (rows == 0) {
95 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING); 95 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
96 } 96 }
97 97
98 - String templateCode; 98 + // 3.1 审批通过的后续处理
99 if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) { 99 if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) {
100 - templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE;  
101 - // 3.1 通过时佣金转余额  
102 - if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {  
103 - // TODO 改成直接调用 addWallet 增加余额,不用查询 wallet  
104 - PayWalletRespDTO wallet = payWalletApi.getWalletByUserId(withdraw.getUserId());  
105 - payWalletApi.addWallet(new PayWalletCreateReqDto()  
106 - .setWalletId(wallet.getId())  
107 - .setBizType(PayWalletBizTypeEnum.WITHDRAW)  
108 - .setBizId(withdraw.getId().toString())  
109 - .setPrice(withdraw.getPrice())  
110 - .setTitle("分佣提现"));  
111 - rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus(),  
112 - new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));  
113 - if (rows == 0) {  
114 - throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);  
115 - }  
116 - } else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(withdraw.getType())) {  
117 - // TODO @luchi:这里,要加个转账单号的记录;另外,调用 API 转账,是立马成功,还是有延迟的哈?  
118 - Long payTransferId = createPayTransfer(userIp, withdraw);  
119 - } 100 + auditBrokerageWithdrawSuccess(withdraw);
  101 + // 3.2 审批不通过的后续处理
120 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) { 102 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
121 - templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT;  
122 - // 3.2 驳回时需要退还用户佣金  
123 brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT, 103 brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
124 String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle()); 104 String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
125 } else { 105 } else {
126 throw new IllegalArgumentException("不支持的提现状态:" + status); 106 throw new IllegalArgumentException("不支持的提现状态:" + status);
127 } 107 }
  108 + }
128 109
129 - // TODO @luchi:这个通知,还是要的呀~~~  
130 - // 4. 通知用户  
131 -// Map<String, Object> templateParams = MapUtil.<String, Object>builder()  
132 -// .put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime()))  
133 -// .put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice()))  
134 -// .put("reason", auditReason)  
135 -// .build();  
136 -// notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO()  
137 -// .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams)); 110 + private void auditBrokerageWithdrawSuccess(BrokerageWithdrawDO withdraw) {
  111 + // 1.1 钱包
  112 + if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
  113 + payWalletApi.addWalletBalance(new PayWalletAddBalanceReqDTO()
  114 + .setUserId(withdraw.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue())
  115 + .setBizType(PayWalletBizTypeEnum.BROKERAGE_WITHDRAW.getType()).setBizId(withdraw.getId().toString())
  116 + .setPrice(withdraw.getPrice()));
  117 + // 1.2 微信 API
  118 + } else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(withdraw.getType())) {
  119 + // TODO @luchi:这里,要加个转账单号的记录;另外,调用 API 转账,是立马成功,还是有延迟的哈?
  120 + Long payTransferId = createPayTransfer(withdraw);
  121 + // 1.3 剩余类型,都是手动打款,所以不处理
  122 + } else {
  123 + // TODO 可优化:未来可以考虑,接入支付宝、银联等 API 转账,实现自动打款
  124 + log.info("[auditBrokerageWithdrawSuccess][withdraw({}) 类型({}) 手动打款,无需处理]", withdraw.getId(), withdraw.getType());
  125 + }
  126 +
  127 + // 2. 非支付 API,则直接体现成功
  128 + if (!BrokerageWithdrawTypeEnum.isApi(withdraw.getType())) {
  129 + brokerageWithdrawMapper.updateByIdAndStatus(withdraw.getId(), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus(),
  130 + new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()));
  131 + }
138 } 132 }
139 133
140 - private Long createPayTransfer(String userIp, BrokerageWithdrawDO withdraw) { 134 + private Long createPayTransfer(BrokerageWithdrawDO withdraw) {
141 // 1.1 获取微信 openid 135 // 1.1 获取微信 openid
142 SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId( 136 SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(
143 UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType()); 137 UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType());
@@ -149,7 +143,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -149,7 +143,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
149 .setMerchantTransferId(withdraw.getId().toString()) 143 .setMerchantTransferId(withdraw.getId().toString())
150 .setPrice(withdraw.getPrice()) 144 .setPrice(withdraw.getPrice())
151 .setSubject("佣金提现") 145 .setSubject("佣金提现")
152 - .setOpenid(socialUser.getOpenid()).setUserIp(userIp); 146 + .setOpenid(socialUser.getOpenid()).setUserIp(getClientIP());
153 // 2. 发起请求 147 // 2. 发起请求
154 return payTransferApi.createTransfer(payTransferCreateReqDTO); 148 return payTransferApi.createTransfer(payTransferCreateReqDTO);
155 } 149 }
@@ -230,6 +224,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { @@ -230,6 +224,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
230 // TODO @luchi:建议参考支付那,即使成功的情况下,也要各种校验;金额是否匹配、转账单号是否匹配、是否重复调用; 224 // TODO @luchi:建议参考支付那,即使成功的情况下,也要各种校验;金额是否匹配、转账单号是否匹配、是否重复调用;
231 if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) { 225 if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) {
232 withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()); 226 withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());
  227 + // TODO @luchi:发送站内信
233 } else if (PayTransferStatusEnum.isPendingStatus(transfer.getStatus())) { 228 } else if (PayTransferStatusEnum.isPendingStatus(transfer.getStatus())) {
234 // TODO @luchi:这里,是不是不用更新哈? 229 // TODO @luchi:这里,是不是不用更新哈?
235 withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus()); 230 withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus());
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApi.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.module.pay.api.wallet.dto.PayWalletCreateReqDto;  
4 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO; 3 +import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
5 4
6 /** 5 /**
7 * 钱包 API 接口 6 * 钱包 API 接口
@@ -10,21 +9,11 @@ import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO; @@ -10,21 +9,11 @@ import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
10 */ 9 */
11 public interface PayWalletApi { 10 public interface PayWalletApi {
12 11
13 - // TODO @luchi:1)改成 addWalletBalance;2)PayWalletCreateReqDto 搞成 userId、userType;3)bizType 使用 integer,不然后续挪到 cloud 不好弄,因为枚举不好序列化  
14 /** 12 /**
15 - * 添加钱包 13 + * 添加钱包余额
16 * 14 *
17 - * @param reqDTO 创建请求 15 + * @param reqDTO 增加余额请求
18 */ 16 */
19 - void addWallet(PayWalletCreateReqDto reqDTO);  
20 -  
21 - // TODO @luchi:不用去 getWalletByUserId 钱包,直接添加余额就好。里面内部去创建。如果删除掉的化,PayWalletRespDTO 也删除哈。  
22 - /**  
23 - * 根据用户编号,获取钱包信息  
24 - *  
25 - * @param userId 用户id  
26 - * @return 钱包信息  
27 - */  
28 - PayWalletRespDTO getWalletByUserId(Long userId); 17 + void addWalletBalance(PayWalletAddBalanceReqDTO reqDTO);
29 18
30 } 19 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/dto/PayWalletCreateReqDto.java renamed to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/dto/PayWalletAddBalanceReqDTO.java
1 package cn.iocoder.yudao.module.pay.api.wallet.dto; 1 package cn.iocoder.yudao.module.pay.api.wallet.dto;
2 2
3 -import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum; 3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4 import jakarta.validation.constraints.NotNull; 4 import jakarta.validation.constraints.NotNull;
5 import lombok.Data; 5 import lombok.Data;
6 6
  7 +/**
  8 + * 钱包余额增加 Request DTO
  9 + *
  10 + * @author 芋道源码
  11 + */
7 @Data 12 @Data
8 -public class PayWalletCreateReqDto { 13 +public class PayWalletAddBalanceReqDTO {
9 14
10 /** 15 /**
11 - * 钱包编号 16 + * 用户编号
  17 + *
  18 + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
  19 + */
  20 + @NotNull(message = "用户编号不能为空")
  21 + private Long userId;
  22 + /**
  23 + * 用户类型
  24 + *
  25 + * 关联 {@link UserTypeEnum}
12 */ 26 */
13 - @NotNull(message = "钱包编号不能为空")  
14 - private Long walletId; 27 + @NotNull(message = "用户类型不能为空")
  28 + private Integer userType;
15 29
16 /** 30 /**
17 * 关联业务分类 31 * 关联业务分类
18 */ 32 */
19 @NotNull(message = "关联业务分类不能为空") 33 @NotNull(message = "关联业务分类不能为空")
20 - private PayWalletBizTypeEnum bizType;  
21 - 34 + private Integer bizType;
22 /** 35 /**
23 * 关联业务编号 36 * 关联业务编号
24 */ 37 */
@@ -26,12 +39,6 @@ public class PayWalletCreateReqDto { @@ -26,12 +39,6 @@ public class PayWalletCreateReqDto {
26 private String bizId; 39 private String bizId;
27 40
28 /** 41 /**
29 - * 流水说明  
30 - */  
31 - @NotNull(message = "流水说明不能为空")  
32 - private String title;  
33 -  
34 - /**  
35 * 交易金额,单位分 42 * 交易金额,单位分
36 * 43 *
37 * 正值表示余额增加,负值表示余额减少 44 * 正值表示余额增加,负值表示余额减少
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/dto/PayWalletRespDTO.java deleted
1 -package cn.iocoder.yudao.module.pay.api.wallet.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -@Data  
6 -public class PayWalletRespDTO {  
7 -  
8 - /**  
9 - * 编号  
10 - */  
11 - private Long id;  
12 -  
13 - /**  
14 - * 余额,单位分  
15 - */  
16 - private Integer balance;  
17 -  
18 -}  
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/wallet/PayWalletBizTypeEnum.java
@@ -20,7 +20,7 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable { @@ -20,7 +20,7 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
20 PAYMENT(3, "支付"), 20 PAYMENT(3, "支付"),
21 PAYMENT_REFUND(4, "支付退款"), 21 PAYMENT_REFUND(4, "支付退款"),
22 UPDATE_BALANCE(5, "更新余额"), 22 UPDATE_BALANCE(5, "更新余额"),
23 - WITHDRAW(6, "分佣提现"); 23 + BROKERAGE_WITHDRAW(6, "分佣提现");
24 24
25 /** 25 /**
26 * 业务分类 26 * 业务分类
@@ -38,4 +38,8 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable { @@ -38,4 +38,8 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
38 return ARRAYS; 38 return ARRAYS;
39 } 39 }
40 40
  41 + public static PayWalletBizTypeEnum valueOf(Integer type) {
  42 + return Arrays.stream(values()).filter(item -> item.getType().equals(type)).findFirst().orElse(null);
  43 + }
  44 +
41 } 45 }
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;  
4 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
5 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;  
6 -import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO; 3 +import cn.hutool.core.lang.Assert;
  4 +import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
7 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
  6 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
8 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; 7 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
9 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
10 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
@@ -21,13 +20,14 @@ public class PayWalletApiImpl implements PayWalletApi { @@ -21,13 +20,14 @@ public class PayWalletApiImpl implements PayWalletApi {
21 private PayWalletService payWalletService; 20 private PayWalletService payWalletService;
22 21
23 @Override 22 @Override
24 - public void addWallet(PayWalletCreateReqDto reqDTO) {  
25 - payWalletService.addWalletBalance(reqDTO.getWalletId(), reqDTO.getBizId(), reqDTO.getBizType(), reqDTO.getPrice());  
26 - } 23 + public void addWalletBalance(PayWalletAddBalanceReqDTO reqDTO) {
  24 + // 创建或获取钱包
  25 + PayWalletDO wallet = payWalletService.getOrCreateWallet(reqDTO.getUserId(), reqDTO.getUserType());
  26 + Assert.notNull(wallet, "钱包({}/{})不存在", reqDTO.getUserId(), reqDTO.getUserType());
27 27
28 - @Override  
29 - public PayWalletRespDTO getWalletByUserId(Long userId) {  
30 - PayWalletDO orCreateWallet = payWalletService.getOrCreateWallet(userId, UserTypeEnum.MEMBER.getValue());  
31 - return BeanUtils.toBean(orCreateWallet, PayWalletRespDTO.class); 28 + // 增加余额
  29 + PayWalletBizTypeEnum bizType = PayWalletBizTypeEnum.valueOf(reqDTO.getBizType());
  30 + payWalletService.addWalletBalance(wallet.getId(), reqDTO.getBizId(), bizType, reqDTO.getPrice());
32 } 31 }
  32 +
33 } 33 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java
@@ -69,6 +69,19 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; { @@ -69,6 +69,19 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
69 } 69 }
70 70
71 /** 71 /**
  72 + * 增加余额的时候,更新钱包
  73 + *
  74 + * @param id 钱包 id
  75 + * @param price 钱包金额
  76 + */
  77 + default void updateWhenAdd(Long id, Integer price) {
  78 + LambdaUpdateWrapper<PayWalletDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<PayWalletDO>()
  79 + .setSql(" balance = balance + " + price)
  80 + .eq(PayWalletDO::getId, id);
  81 + update(null, lambdaUpdateWrapper);
  82 + }
  83 +
  84 + /**
72 * 冻结钱包部分余额 85 * 冻结钱包部分余额
73 * 86 *
74 * @param id 钱包 id 87 * @param id 钱包 id
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
@@ -187,7 +187,7 @@ public class PayWalletServiceImpl implements PayWalletService { @@ -187,7 +187,7 @@ public class PayWalletServiceImpl implements PayWalletService {
187 187
188 // 2. 加锁,更新钱包余额(目的:避免钱包流水的并发更新时,余额变化不连贯) 188 // 2. 加锁,更新钱包余额(目的:避免钱包流水的并发更新时,余额变化不连贯)
189 return lockRedisDAO.lock(walletId, UPDATE_TIMEOUT_MILLIS, () -> { 189 return lockRedisDAO.lock(walletId, UPDATE_TIMEOUT_MILLIS, () -> {
190 - // 2. 更新钱包金额 190 + // 3. 更新钱包金额
191 switch (bizType) { 191 switch (bizType) {
192 case PAYMENT_REFUND: { // 退款更新 192 case PAYMENT_REFUND: { // 退款更新
193 walletMapper.updateWhenConsumptionRefund(payWallet.getId(), price); 193 walletMapper.updateWhenConsumptionRefund(payWallet.getId(), price);
@@ -198,19 +198,15 @@ public class PayWalletServiceImpl implements PayWalletService { @@ -198,19 +198,15 @@ public class PayWalletServiceImpl implements PayWalletService {
198 break; 198 break;
199 } 199 }
200 case UPDATE_BALANCE: // 更新余额 200 case UPDATE_BALANCE: // 更新余额
201 - walletMapper.updateWhenRecharge(payWallet.getId(), price);  
202 - break;  
203 - // TODO @luchi:1)不能使用 updateWhenRecharge,它是充值哈。应该增加余额就 ok 了。。ps:顺便帮我把 UPDATE_BALANCE 也改改哈;2)其实不用 WITHDRAW 枚举,复用 UPDATE_BALANCE 就好了。  
204 - case WITHDRAW:  
205 - walletMapper.updateWhenRecharge(payWallet.getId(), price); 201 + case BROKERAGE_WITHDRAW: // 分佣提现
  202 + walletMapper.updateWhenAdd(payWallet.getId(), price);
206 break; 203 break;
207 default: { 204 default: {
208 - // TODO 其它类型待实现  
209 - throw new UnsupportedOperationException("待实现"); 205 + throw new UnsupportedOperationException("待实现:" + bizType);
210 } 206 }
211 } 207 }
212 208
213 - // 3. 生成钱包流水 209 + // 4. 生成钱包流水
214 WalletTransactionCreateReqBO transactionCreateReqBO = new WalletTransactionCreateReqBO() 210 WalletTransactionCreateReqBO transactionCreateReqBO = new WalletTransactionCreateReqBO()
215 .setWalletId(payWallet.getId()).setPrice(price).setBalance(payWallet.getBalance() + price) 211 .setWalletId(payWallet.getId()).setPrice(price).setBalance(payWallet.getBalance() + price)
216 .setBizId(bizId).setBizType(bizType.getType()).setTitle(bizType.getDescription()); 212 .setBizId(bizId).setBizType(bizType.getType()).setTitle(bizType.getDescription());