Commit 3e09da012849bd45438344fe6a65eee78415dd92

Authored by YunaiV
1 parent 5808f77a

code review:支付钱包

yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java
@@ -6,14 +6,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -6,14 +6,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 6 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
7 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 7 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;  
10 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; 9 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*;
11 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; 10 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
12 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; 11 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 12 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
14 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
  14 +import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient;
15 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 15 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
16 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 16 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
  17 +import com.google.common.collect.Maps;
17 import io.swagger.v3.oas.annotations.Operation; 18 import io.swagger.v3.oas.annotations.Operation;
18 import io.swagger.v3.oas.annotations.Parameter; 19 import io.swagger.v3.oas.annotations.Parameter;
19 import io.swagger.v3.oas.annotations.tags.Tag; 20 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -25,12 +26,17 @@ import javax.annotation.Resource; @@ -25,12 +26,17 @@ import javax.annotation.Resource;
25 import javax.servlet.http.HttpServletResponse; 26 import javax.servlet.http.HttpServletResponse;
26 import javax.validation.Valid; 27 import javax.validation.Valid;
27 import java.io.IOException; 28 import java.io.IOException;
28 -import java.util.*; 29 +import java.util.ArrayList;
  30 +import java.util.List;
  31 +import java.util.Map;
  32 +import java.util.Objects;
29 33
30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 34 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 35 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
32 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 36 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
33 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 37 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
  38 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
  39 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
34 40
35 @Tag(name = "管理后台 - 支付订单") 41 @Tag(name = "管理后台 - 支付订单")
36 @RestController 42 @RestController
@@ -70,13 +76,16 @@ public class PayOrderController { @@ -70,13 +76,16 @@ public class PayOrderController {
70 @PostMapping("/submit") 76 @PostMapping("/submit")
71 @Operation(summary = "提交支付订单") 77 @Operation(summary = "提交支付订单")
72 public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { 78 public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) {
73 - // 钱包支付需要 额外传 user_id 和 user_type 79 + // 1. 钱包支付事,需要额外传 user_id 和 user_type
74 if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) { 80 if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) {
75 - Map<String, String> channelExtras = reqVO.getChannelExtras() == null ? new HashMap<>(8) : reqVO.getChannelExtras();  
76 - channelExtras.put("user_id", String.valueOf(WebFrameworkUtils.getLoginUserId()));  
77 - channelExtras.put("user_type", String.valueOf(WebFrameworkUtils.getLoginUserType())); 81 + Map<String, String> channelExtras = reqVO.getChannelExtras() == null ?
  82 + Maps.newHashMapWithExpectedSize(2) : reqVO.getChannelExtras();
  83 + channelExtras.put(WalletPayClient.USER_ID_KEY, String.valueOf(getLoginUserId()));
  84 + channelExtras.put(WalletPayClient.USER_TYPE_KEY, String.valueOf(getLoginUserType()));
78 reqVO.setChannelExtras(channelExtras); 85 reqVO.setChannelExtras(channelExtras);
79 } 86 }
  87 +
  88 + // 2. 提交支付
80 PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); 89 PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP());
81 return success(respVO); 90 return success(respVO);
82 } 91 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java
@@ -37,7 +37,7 @@ public class AppPayWalletController { @@ -37,7 +37,7 @@ public class AppPayWalletController {
37 @Operation(summary = "获取钱包") 37 @Operation(summary = "获取钱包")
38 @PreAuthenticated 38 @PreAuthenticated
39 public CommonResult<AppPayWalletRespVO> getPayWallet() { 39 public CommonResult<AppPayWalletRespVO> getPayWallet() {
40 - PayWalletDO wallet = payWalletService.getOrCreatePayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); 40 + PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
41 return success(PayWalletConvert.INSTANCE.convert(wallet)); 41 return success(PayWalletConvert.INSTANCE.convert(wallet));
42 } 42 }
43 43
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java
@@ -37,6 +37,8 @@ public class PayWalletDO extends BaseDO { @@ -37,6 +37,8 @@ public class PayWalletDO extends BaseDO {
37 */ 37 */
38 private Integer userType; 38 private Integer userType;
39 39
  40 + // TODO @jason:三个都搞 integer?应该要统一哈
  41 +
40 /** 42 /**
41 * 余额,单位分 43 * 余额,单位分
42 */ 44 */
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java
@@ -15,6 +15,7 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; { @@ -15,6 +15,7 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
15 PayWalletDO::getUserType, userType); 15 PayWalletDO::getUserType, userType);
16 } 16 }
17 17
  18 + // TODO @jason:减少时,需要 update price -= ? where price >= ?,避免并发问题。现在基于 price 来过滤,虽然也能解决并发问题,但是冲突概率会高一点;可以看到 TradeBrokerageUserMapper 的做法;
18 /** 19 /**
19 * 当余额减少时候更新 20 * 当余额减少时候更新
20 * 21 *
@@ -27,6 +28,7 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; { @@ -27,6 +28,7 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
27 */ 28 */
28 default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, 29 default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge,
29 Long totalExpense, Integer price, Long id) { 30 Long totalExpense, Integer price, Long id) {
  31 + // TODO @jason:这种偏判断的,最红放在 service 层;mapper 可以写多个方法;
30 PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price); 32 PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price);
31 if(bizType == PayWalletBizTypeEnum.PAYMENT){ 33 if(bizType == PayWalletBizTypeEnum.PAYMENT){
32 updateDO.setTotalExpense(totalExpense + price); 34 updateDO.setTotalExpense(totalExpense + price);
@@ -40,6 +42,7 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; { @@ -40,6 +42,7 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
40 .ge(PayWalletDO::getBalance, price)); 42 .ge(PayWalletDO::getBalance, price));
41 } 43 }
42 44
  45 + // TODO @jason:类似上面的修改建议哈;
43 /** 46 /**
44 * 当余额增加时候更新 47 * 当余额增加时候更新
45 * 48 *
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java
@@ -37,13 +37,13 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FO @@ -37,13 +37,13 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FO
37 @Slf4j 37 @Slf4j
38 public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { 38 public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> {
39 39
40 - private PayWalletService wallService; 40 + public static final String USER_ID_KEY = "user_id";
  41 + public static final String USER_TYPE_KEY = "user_type";
41 42
  43 + private PayWalletService wallService;
42 private PayWalletTransactionService walletTransactionService; 44 private PayWalletTransactionService walletTransactionService;
43 -  
44 - private PayOrderService payOrderService;  
45 -  
46 - private PayRefundService payRefundService; 45 + private PayOrderService orderService;
  46 + private PayRefundService refundService;
47 47
48 public WalletPayClient(Long channelId, NonePayClientConfig config) { 48 public WalletPayClient(Long channelId, NonePayClientConfig config) {
49 super(channelId, PayChannelEnum.WALLET.getCode(), config); 49 super(channelId, PayChannelEnum.WALLET.getCode(), config);
@@ -62,8 +62,9 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -62,8 +62,9 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
62 @Override 62 @Override
63 protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { 63 protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
64 try { 64 try {
65 - String userId = MapUtil.getStr(reqDTO.getChannelExtras(), "user_id");  
66 - String userType = MapUtil.getStr(reqDTO.getChannelExtras(), "user_type"); 65 + // TODO @jason:直接 getLong 和 getInt 会不会更简洁哈
  66 + String userId = MapUtil.getStr(reqDTO.getChannelExtras(), USER_ID_KEY);
  67 + String userType = MapUtil.getStr(reqDTO.getChannelExtras(), USER_TYPE_KEY);
67 Assert.notEmpty(userId, "用户 id 不能为空"); 68 Assert.notEmpty(userId, "用户 id 不能为空");
68 Assert.notEmpty(userType, "用户类型不能为空"); 69 Assert.notEmpty(userType, "用户类型不能为空");
69 PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType), 70 PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType),
@@ -92,10 +93,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -92,10 +93,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
92 93
93 @Override 94 @Override
94 protected PayOrderRespDTO doGetOrder(String outTradeNo) { 95 protected PayOrderRespDTO doGetOrder(String outTradeNo) {
95 - if (payOrderService == null) {  
96 - payOrderService = SpringUtil.getBean(PayOrderService.class); 96 + if (orderService == null) {
  97 + orderService = SpringUtil.getBean(PayOrderService.class);
97 } 98 }
98 - PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); 99 + PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo);
99 // 支付交易拓展单不存在, 返回关闭状态 100 // 支付交易拓展单不存在, 返回关闭状态
100 if (orderExtension == null) { 101 if (orderExtension == null) {
101 return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()), 102 return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()),
@@ -147,10 +148,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -147,10 +148,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
147 148
148 @Override 149 @Override
149 protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { 150 protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
150 - if (payRefundService == null) {  
151 - payRefundService = SpringUtil.getBean(PayRefundService.class); 151 + if (refundService == null) {
  152 + refundService = SpringUtil.getBean(PayRefundService.class);
152 } 153 }
153 - PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); 154 + PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo);
154 // 支付退款单不存在, 返回退款失败状态 155 // 支付退款单不存在, 返回退款失败状态
155 if (payRefund == null) { 156 if (payRefund == null) {
156 return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(), 157 return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(),
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
@@ -12,12 +12,14 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; @@ -12,12 +12,14 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
12 public interface PayWalletService { 12 public interface PayWalletService {
13 13
14 /** 14 /**
15 - * 获取钱包信息,如果不存在创建钱包。由于用户注册时候不会创建钱包 15 + * 获取钱包信息
  16 + *
  17 + * 如果不存在,则创建钱包。由于用户注册时候不会创建钱包
16 * 18 *
17 * @param userId 用户编号 19 * @param userId 用户编号
18 * @param userType 用户类型 20 * @param userType 用户类型
19 */ 21 */
20 - PayWalletDO getOrCreatePayWallet(Long userId, Integer userType); 22 + PayWalletDO getOrCreateWallet(Long userId, Integer userType);
21 23
22 /** 24 /**
23 * 钱包订单支付 25 * 钱包订单支付
@@ -29,6 +31,14 @@ public interface PayWalletService { @@ -29,6 +31,14 @@ public interface PayWalletService {
29 */ 31 */
30 PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price); 32 PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price);
31 33
  34 + /**
  35 + * 钱包订单支付退款
  36 + *
  37 + * @param outRefundNo 外部退款号
  38 + * @param refundPrice 退款金额
  39 + * @param reason 退款原因
  40 + */
  41 + PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason);
32 42
33 /** 43 /**
34 * 扣减钱包余额 44 * 扣减钱包余额
@@ -43,7 +53,6 @@ public interface PayWalletService { @@ -43,7 +53,6 @@ public interface PayWalletService {
43 PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, 53 PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType,
44 Long bizId, PayWalletBizTypeEnum bizType, Integer price); 54 Long bizId, PayWalletBizTypeEnum bizType, Integer price);
45 55
46 -  
47 /** 56 /**
48 * 增加钱包余额 57 * 增加钱包余额
49 * 58 *
@@ -57,13 +66,4 @@ public interface PayWalletService { @@ -57,13 +66,4 @@ public interface PayWalletService {
57 PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, 66 PayWalletTransactionDO addWalletBalance(Long userId, Integer userType,
58 Long bizId, PayWalletBizTypeEnum bizType, Integer price); 67 Long bizId, PayWalletBizTypeEnum bizType, Integer price);
59 68
60 - /**  
61 - * 钱包订单支付退款  
62 - *  
63 - * @param outRefundNo 外部退款号  
64 - * @param refundPrice 退款金额  
65 - * @param reason 退款原因  
66 - */  
67 - PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason);  
68 -  
69 } 69 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
@@ -43,81 +43,124 @@ public class PayWalletServiceImpl implements PayWalletService { @@ -43,81 +43,124 @@ public class PayWalletServiceImpl implements PayWalletService {
43 private static final String WALLET_REFUND_NO_PREFIX = "WR"; 43 private static final String WALLET_REFUND_NO_PREFIX = "WR";
44 44
45 @Resource 45 @Resource
46 - private PayWalletMapper payWalletMapper; 46 + private PayWalletMapper walletMapper;
47 @Resource 47 @Resource
48 private PayNoRedisDAO noRedisDAO; 48 private PayNoRedisDAO noRedisDAO;
49 49
50 @Resource 50 @Resource
51 - private PayWalletTransactionService payWalletTransactionService; 51 + private PayWalletTransactionService walletTransactionService;
52 @Resource 52 @Resource
53 @Lazy 53 @Lazy
54 - private PayOrderService payOrderService; 54 + private PayOrderService orderService;
55 @Resource 55 @Resource
56 @Lazy 56 @Lazy
57 - private PayRefundService payRefundService; 57 + private PayRefundService refundService;
58 58
59 @Override 59 @Override
60 - public PayWalletDO getOrCreatePayWallet(Long userId, Integer userType) {  
61 - PayWalletDO payWalletDO = payWalletMapper.selectByUserIdAndType(userId, userType);  
62 - if (payWalletDO == null) {  
63 - payWalletDO = new PayWalletDO();  
64 - payWalletDO.setUserId(userId);  
65 - payWalletDO.setUserType(userType);  
66 - payWalletDO.setBalance(0);  
67 - payWalletDO.setTotalExpense(0L);  
68 - payWalletDO.setTotalRecharge(0L);  
69 - payWalletDO.setCreateTime(LocalDateTime.now());  
70 - payWalletMapper.insert(payWalletDO); 60 + public PayWalletDO getOrCreateWallet(Long userId, Integer userType) {
  61 + PayWalletDO wallet = walletMapper.selectByUserIdAndType(userId, userType);
  62 + if (wallet == null) {
  63 + wallet = new PayWalletDO().setUserId(userId).setUserType(userType)
  64 + .setBalance(0).setTotalExpense(0L).setTotalRecharge(0L);
  65 + wallet.setCreateTime(LocalDateTime.now());
  66 + walletMapper.insert(wallet);
71 } 67 }
72 - return payWalletDO; 68 + return wallet;
73 } 69 }
74 70
75 -  
76 @Override 71 @Override
77 @Transactional(rollbackFor = Exception.class) 72 @Transactional(rollbackFor = Exception.class)
78 public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) { 73 public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) {
79 - // 判断支付交易拓展单是否存  
80 - PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); 74 + // 1. 判断支付交易拓展单是否存
  75 + PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo);
81 if (orderExtension == null) { 76 if (orderExtension == null) {
82 throw exception(ORDER_EXTENSION_NOT_FOUND); 77 throw exception(ORDER_EXTENSION_NOT_FOUND);
83 } 78 }
  79 + // 2. 扣减余额
84 return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price); 80 return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price);
85 } 81 }
86 82
87 @Override 83 @Override
  84 + @Transactional(rollbackFor = Exception.class)
  85 + public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) {
  86 + // 1.1 判断退款单是否存在
  87 + PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo);
  88 + if (payRefund == null) {
  89 + throw exception(REFUND_NOT_FOUND);
  90 + }
  91 + // 1.2 校验是否可以退款
  92 + Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice);
  93 + PayWalletDO wallet = walletMapper.selectById(walletId);
  94 + Assert.notNull(wallet, "钱包 {} 不存在", walletId);
  95 + // 2. 增加余额
  96 + return addWalletBalance(wallet.getUserId(), wallet.getUserType(), payRefund.getId(), PAYMENT_REFUND, refundPrice);
  97 + }
  98 +
  99 + /**
  100 + * 校验是否能退款
  101 + *
  102 + * @param refundId 支付退款单 id
  103 + * @param walletPayNo 钱包支付 no
  104 + */
  105 + private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) {
  106 + // 1. 校验钱包支付交易存在
  107 + PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransactionByNo(walletPayNo);
  108 + if (walletTransaction == null) {
  109 + throw exception(WALLET_TRANSACTION_NOT_FOUND);
  110 + }
  111 + // 原来的支付金额
  112 + // TODO @jason:应该允许多次退款哈;
  113 + int amount = - walletTransaction.getPrice();
  114 + if (refundPrice != amount) {
  115 + throw exception(WALLET_REFUND_AMOUNT_ERROR);
  116 + }
  117 + PayWalletTransactionDO refundTransaction = walletTransactionService.getWalletTransaction(
  118 + String.valueOf(refundId), PAYMENT_REFUND);
  119 + if (refundTransaction != null) {
  120 + throw exception(WALLET_REFUND_EXIST);
  121 + }
  122 + return walletTransaction.getWalletId();
  123 + }
  124 +
  125 + @Override
88 public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, 126 public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType,
89 Long bizId, PayWalletBizTypeEnum bizType, Integer price) { 127 Long bizId, PayWalletBizTypeEnum bizType, Integer price) {
90 // 1.1 获取钱包 128 // 1.1 获取钱包
91 - PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); 129 + PayWalletDO payWallet = getOrCreateWallet(userId, userType);
92 // 1.2 判断余额是否足够 130 // 1.2 判断余额是否足够
93 int afterBalance = payWallet.getBalance() - price; 131 int afterBalance = payWallet.getBalance() - price;
94 if (afterBalance < 0) { 132 if (afterBalance < 0) {
95 throw exception(WALLET_BALANCE_NOT_ENOUGH); 133 throw exception(WALLET_BALANCE_NOT_ENOUGH);
96 } 134 }
97 135
  136 + // TODO jason:建议基于 where price >= 来做哈;然后抛出 WALLET_BALANCE_NOT_ENOUGH
98 // 2.1 扣除余额 137 // 2.1 扣除余额
99 - int number = payWalletMapper.updateWhenDecBalance(bizType,payWallet.getBalance(), payWallet.getTotalRecharge(),  
100 - payWallet.getTotalExpense(), price, payWallet.getId()); 138 + int number = walletMapper.updateWhenDecBalance(bizType, payWallet.getBalance(),
  139 + payWallet.getTotalRecharge(), payWallet.getTotalExpense(), price, payWallet.getId());
101 if (number == 0) { 140 if (number == 0) {
102 throw exception(TOO_MANY_REQUESTS); 141 throw exception(TOO_MANY_REQUESTS);
103 } 142 }
  143 +
104 // 2.2 生成钱包流水 144 // 2.2 生成钱包流水
  145 + // TODO @jason:walletNo 交给 payWalletTransactionService 自己生成哈;
105 String walletNo = generateWalletNo(bizType); 146 String walletNo = generateWalletNo(bizType);
106 PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) 147 PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId())
107 .setNo(walletNo).setPrice(-price).setBalance(afterBalance) 148 .setNo(walletNo).setPrice(-price).setBalance(afterBalance)
108 .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription()); 149 .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription());
109 - payWalletTransactionService.createWalletTransaction(walletTransaction); 150 + // TODO @jason:是不是可以 createWalletTransaction 搞个 bo 参数,然后 PayWalletTransactionDO 交回给 walletTransactionService 更好;然后把参数简化下
  151 + walletTransactionService.createWalletTransaction(walletTransaction);
110 return walletTransaction; 152 return walletTransaction;
111 } 153 }
112 154
113 @Override 155 @Override
114 - public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId,  
115 - PayWalletBizTypeEnum bizType, Integer price) { 156 + public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType,
  157 + Long bizId, PayWalletBizTypeEnum bizType, Integer price) {
116 // 1.1 获取钱包 158 // 1.1 获取钱包
117 - PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); 159 + PayWalletDO payWallet = getOrCreateWallet(userId, userType);
118 160
119 // 2.1 增加余额 161 // 2.1 增加余额
120 - int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), 162 + // TODO @jason:类似上面的思路哈;
  163 + int number = walletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(),
121 payWallet.getTotalExpense(), price, payWallet.getId()); 164 payWallet.getTotalExpense(), price, payWallet.getId());
122 if (number == 0) { 165 if (number == 0) {
123 throw exception(TOO_MANY_REQUESTS); 166 throw exception(TOO_MANY_REQUESTS);
@@ -129,63 +172,23 @@ public class PayWalletServiceImpl implements PayWalletService { @@ -129,63 +172,23 @@ public class PayWalletServiceImpl implements PayWalletService {
129 .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price) 172 .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price)
130 .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()) 173 .setBizId(String.valueOf(bizId)).setBizType(bizType.getType())
131 .setTitle(bizType.getDescription()); 174 .setTitle(bizType.getDescription());
132 - payWalletTransactionService.createWalletTransaction(newWalletTransaction); 175 + walletTransactionService.createWalletTransaction(newWalletTransaction);
133 return newWalletTransaction; 176 return newWalletTransaction;
134 } 177 }
135 178
136 private String generateWalletNo(PayWalletBizTypeEnum bizType) { 179 private String generateWalletNo(PayWalletBizTypeEnum bizType) {
  180 + // TODO @jason:对于余额来说,是不是直接 W+序号就行了,它其实不关注业务;;;不然就耦合啦
137 String no = ""; 181 String no = "";
138 switch(bizType){ 182 switch(bizType){
139 - case PAYMENT : 183 + case PAYMENT:
140 no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); 184 no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX);
141 break; 185 break;
142 - case PAYMENT_REFUND : 186 + case PAYMENT_REFUND:
143 no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); 187 no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX);
144 break; 188 break;
145 default : 189 default :
146 - // TODO 待增加  
147 } 190 }
148 return no; 191 return no;
149 } 192 }
150 193
151 - @Override  
152 - @Transactional(rollbackFor = Exception.class)  
153 - public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) {  
154 - // 1.1 判断退款单是否存在  
155 - PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo);  
156 - if (payRefund == null) {  
157 - throw exception(REFUND_NOT_FOUND);  
158 - }  
159 - // 1.2 校验是否可以退款  
160 - Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice);  
161 -  
162 - PayWalletDO payWallet = payWalletMapper.selectById(walletId);  
163 - Assert.notNull(payWallet, "钱包 {} 不存在", walletId);  
164 - return addWalletBalance(payWallet.getUserId(), payWallet.getUserType(),payRefund.getId(), PAYMENT_REFUND, refundPrice);  
165 - }  
166 -  
167 - /**  
168 - * 校验是否能退款  
169 - *  
170 - * @param refundId 支付退款单 id  
171 - * @param walletPayNo 钱包支付 no  
172 - */  
173 - private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) {  
174 - // 查询钱包支付交易  
175 - PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo);  
176 - if (payWalletTransaction == null) {  
177 - throw exception(WALLET_TRANSACTION_NOT_FOUND);  
178 - }  
179 - // 原来的支付金额  
180 - int amount = - payWalletTransaction.getPrice();  
181 - if (refundPrice != amount) {  
182 - throw exception(WALLET_REFUND_AMOUNT_ERROR);  
183 - }  
184 - PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction(  
185 - String.valueOf(refundId), PAYMENT_REFUND);  
186 - if (refundTransaction != null) {  
187 - throw exception(WALLET_REFUND_EXIST);  
188 - }  
189 - return payWalletTransaction.getWalletId();  
190 - }  
191 } 194 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java
@@ -28,7 +28,7 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ @@ -28,7 +28,7 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ
28 @Override 28 @Override
29 public PageResult<PayWalletTransactionDO> getWalletTransactionPage(Long userId, Integer userType, 29 public PageResult<PayWalletTransactionDO> getWalletTransactionPage(Long userId, Integer userType,
30 AppPayWalletTransactionPageReqVO pageVO) { 30 AppPayWalletTransactionPageReqVO pageVO) {
31 - PayWalletDO wallet = payWalletService.getOrCreatePayWallet(userId, userType); 31 + PayWalletDO wallet = payWalletService.getOrCreateWallet(userId, userType);
32 return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO); 32 return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO);
33 } 33 }
34 34