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 11  
12 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 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 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 9 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
10 10 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
11 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 13 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
15 14 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
16 15 import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
... ... @@ -24,7 +23,6 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
24 23 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
25 24 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
26 25 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
27   -import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants;
28 26 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
29 27 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
30 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 31 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
34 32 import jakarta.annotation.Resource;
35 33 import jakarta.validation.Validator;
  34 +import lombok.extern.slf4j.Slf4j;
36 35 import org.springframework.stereotype.Service;
37 36 import org.springframework.transaction.annotation.Transactional;
38 37 import org.springframework.validation.annotation.Validated;
... ... @@ -43,6 +42,7 @@ import java.util.Collections;
43 42 import java.util.List;
44 43  
45 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 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 52 */
53 53 @Service
54 54 @Validated
  55 +@Slf4j
55 56 public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
56 57  
57 58 @Resource
... ... @@ -82,62 +83,55 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
82 83 public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) {
83 84 // 1.1 校验存在
84 85 BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
85   -
86 86 // 1.2 校验状态为审核中
87 87 if (ObjectUtil.notEqual(BrokerageWithdrawStatusEnum.AUDITING.getStatus(), withdraw.getStatus())) {
88 88 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
89 89 }
90 90  
91   - // 2. 更新
  91 + // 2. 更新状态
92 92 int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(),
93 93 new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
94 94 if (rows == 0) {
95 95 throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
96 96 }
97 97  
98   - String templateCode;
  98 + // 3.1 审批通过的后续处理
99 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 102 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
121   - templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT;
122   - // 3.2 驳回时需要退还用户佣金
123 103 brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
124 104 String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
125 105 } else {
126 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 135 // 1.1 获取微信 openid
142 136 SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(
143 137 UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType());
... ... @@ -149,7 +143,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
149 143 .setMerchantTransferId(withdraw.getId().toString())
150 144 .setPrice(withdraw.getPrice())
151 145 .setSubject("佣金提现")
152   - .setOpenid(socialUser.getOpenid()).setUserIp(userIp);
  146 + .setOpenid(socialUser.getOpenid()).setUserIp(getClientIP());
153 147 // 2. 发起请求
154 148 return payTransferApi.createTransfer(payTransferCreateReqDTO);
155 149 }
... ... @@ -230,6 +224,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
230 224 // TODO @luchi:建议参考支付那,即使成功的情况下,也要各种校验;金额是否匹配、转账单号是否匹配、是否重复调用;
231 225 if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) {
232 226 withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());
  227 + // TODO @luchi:发送站内信
233 228 } else if (PayTransferStatusEnum.isPendingStatus(transfer.getStatus())) {
234 229 // TODO @luchi:这里,是不是不用更新哈?
235 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 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 6 * 钱包 API 接口
... ... @@ -10,21 +9,11 @@ import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
10 9 */
11 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 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 4 import jakarta.validation.constraints.NotNull;
5 5 import lombok.Data;
6 6  
  7 +/**
  8 + * 钱包余额增加 Request DTO
  9 + *
  10 + * @author 芋道源码
  11 + */
7 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 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 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 20 PAYMENT(3, "支付"),
21 21 PAYMENT_REFUND(4, "支付退款"),
22 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 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 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 5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
  6 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
8 7 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
9 8 import jakarta.annotation.Resource;
10 9 import org.springframework.stereotype.Service;
... ... @@ -21,13 +20,14 @@ public class PayWalletApiImpl implements PayWalletApi {
21 20 private PayWalletService payWalletService;
22 21  
23 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 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 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 187  
188 188 // 2. 加锁,更新钱包余额(目的:避免钱包流水的并发更新时,余额变化不连贯)
189 189 return lockRedisDAO.lock(walletId, UPDATE_TIMEOUT_MILLIS, () -> {
190   - // 2. 更新钱包金额
  190 + // 3. 更新钱包金额
191 191 switch (bizType) {
192 192 case PAYMENT_REFUND: { // 退款更新
193 193 walletMapper.updateWhenConsumptionRefund(payWallet.getId(), price);
... ... @@ -198,19 +198,15 @@ public class PayWalletServiceImpl implements PayWalletService {
198 198 break;
199 199 }
200 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 203 break;
207 204 default: {
208   - // TODO 其它类型待实现
209   - throw new UnsupportedOperationException("待实现");
  205 + throw new UnsupportedOperationException("待实现:" + bizType);
210 206 }
211 207 }
212 208  
213   - // 3. 生成钱包流水
  209 + // 4. 生成钱包流水
214 210 WalletTransactionCreateReqBO transactionCreateReqBO = new WalletTransactionCreateReqBO()
215 211 .setWalletId(payWallet.getId()).setPrice(price).setBalance(payWallet.getBalance() + price)
216 212 .setBizId(bizId).setBizType(bizType.getType()).setTitle(bizType.getDescription());
... ...