Commit 91b03e7c93c9f027a3bb4b5b5984b98243c77d6e
1 parent
6a819da0
钱包 review 修改
Showing
5 changed files
with
157 additions
and
48 deletions
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java
| @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | 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; | ||
| 9 | +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||
| 8 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; | 10 | import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; |
| 9 | import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; | 11 | import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; |
| 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; | 12 | import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; |
| @@ -23,9 +25,7 @@ import javax.annotation.Resource; | @@ -23,9 +25,7 @@ import javax.annotation.Resource; | ||
| 23 | import javax.servlet.http.HttpServletResponse; | 25 | import javax.servlet.http.HttpServletResponse; |
| 24 | import javax.validation.Valid; | 26 | import javax.validation.Valid; |
| 25 | import java.io.IOException; | 27 | import java.io.IOException; |
| 26 | -import java.util.ArrayList; | ||
| 27 | -import java.util.List; | ||
| 28 | -import java.util.Map; | 28 | +import java.util.*; |
| 29 | 29 | ||
| 30 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 30 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 31 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 31 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| @@ -70,6 +70,12 @@ public class PayOrderController { | @@ -70,6 +70,12 @@ public class PayOrderController { | ||
| 70 | @PostMapping("/submit") | 70 | @PostMapping("/submit") |
| 71 | @Operation(summary = "提交支付订单") | 71 | @Operation(summary = "提交支付订单") |
| 72 | public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { | 72 | public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { |
| 73 | + if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) { | ||
| 74 | + Map<String, String> channelExtras = reqVO.getChannelExtras() == null ? new HashMap<>(8) : reqVO.getChannelExtras(); | ||
| 75 | + channelExtras.put("user_id", String.valueOf(WebFrameworkUtils.getLoginUserId())); | ||
| 76 | + channelExtras.put("user_type", String.valueOf(WebFrameworkUtils.getLoginUserType())); | ||
| 77 | + reqVO.setChannelExtras(channelExtras); | ||
| 78 | + } | ||
| 73 | PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); | 79 | PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); |
| 74 | return success(respVO); | 80 | return success(respVO); |
| 75 | } | 81 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java
| @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet; | @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet; | ||
| 3 | 3 | ||
| 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.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.member.PayWalletBizTypeEnum; | ||
| 7 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||
| 6 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 7 | 9 | ||
| 8 | @Mapper | 10 | @Mapper |
| @@ -12,6 +14,55 @@ public interface PayWalletMapper extends BaseMapperX<PayWalletDO> { | @@ -12,6 +14,55 @@ public interface PayWalletMapper extends BaseMapperX<PayWalletDO> { | ||
| 12 | return selectOne(PayWalletDO::getUserId, userId, | 14 | return selectOne(PayWalletDO::getUserId, userId, |
| 13 | PayWalletDO::getUserType, userType); | 15 | PayWalletDO::getUserType, userType); |
| 14 | } | 16 | } |
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 当余额减少时候更新 | ||
| 20 | + * | ||
| 21 | + * @param bizType 业务类型 | ||
| 22 | + * @param balance 当前余额 | ||
| 23 | + * @param totalRecharge 当前累计充值 | ||
| 24 | + * @param totalExpense 当前累计支出 | ||
| 25 | + * @param price 支出的金额 | ||
| 26 | + * @param id 钱包 id | ||
| 27 | + */ | ||
| 28 | + default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, | ||
| 29 | + Long totalExpense, Integer price, Long id) { | ||
| 30 | + PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price); | ||
| 31 | + if(bizType == PayWalletBizTypeEnum.PAYMENT){ | ||
| 32 | + updateDO.setTotalExpense(totalExpense + price); | ||
| 33 | + } | ||
| 34 | + if (bizType == PayWalletBizTypeEnum.RECHARGE_REFUND) { | ||
| 35 | + updateDO.setTotalRecharge(totalRecharge - price); | ||
| 36 | + } | ||
| 37 | + return update(updateDO, | ||
| 38 | + new LambdaQueryWrapper<PayWalletDO>().eq(PayWalletDO::getId, id) | ||
| 39 | + .eq(PayWalletDO::getBalance, balance) | ||
| 40 | + .ge(PayWalletDO::getBalance, price)); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 当余额增加时候更新 | ||
| 45 | + * | ||
| 46 | + * @param bizType 业务类型 | ||
| 47 | + * @param balance 当前余额 | ||
| 48 | + * @param totalRecharge 当前累计充值 | ||
| 49 | + * @param totalExpense 当前累计支出 | ||
| 50 | + * @param price 金额 | ||
| 51 | + * @param id 钱包 id | ||
| 52 | + */ | ||
| 53 | + default int updateWhenIncBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, | ||
| 54 | + Long totalExpense, Integer price, Long id) { | ||
| 55 | + PayWalletDO updateDO = new PayWalletDO().setBalance(balance + price); | ||
| 56 | + if (bizType == PayWalletBizTypeEnum.PAYMENT_REFUND) { | ||
| 57 | + updateDO.setTotalExpense(totalExpense - price); | ||
| 58 | + } | ||
| 59 | + if (bizType == PayWalletBizTypeEnum.RECHARGE) { | ||
| 60 | + updateDO.setTotalExpense(totalRecharge + price); | ||
| 61 | + } | ||
| 62 | + return update(updateDO, | ||
| 63 | + new LambdaQueryWrapper<PayWalletDO>().eq(PayWalletDO::getId, id) | ||
| 64 | + .eq(PayWalletDO::getBalance, balance)); | ||
| 65 | + } | ||
| 15 | } | 66 | } |
| 16 | 67 | ||
| 17 | 68 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java
| 1 | package cn.iocoder.yudao.module.pay.framework.pay.wallet; | 1 | package cn.iocoder.yudao.module.pay.framework.pay.wallet; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.lang.Assert; | ||
| 4 | +import cn.hutool.core.map.MapUtil; | ||
| 3 | import cn.hutool.extra.spring.SpringUtil; | 5 | import cn.hutool.extra.spring.SpringUtil; |
| 4 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 6 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 7 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| @@ -41,7 +43,12 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { | @@ -41,7 +43,12 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { | ||
| 41 | @Override | 43 | @Override |
| 42 | protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { | 44 | protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 43 | try { | 45 | try { |
| 44 | - PayWalletTransactionDO transaction = wallService.pay(reqDTO.getOutTradeNo(), reqDTO.getPrice()); | 46 | + String userId = MapUtil.getStr(reqDTO.getChannelExtras(), "user_id"); |
| 47 | + String userType = MapUtil.getStr(reqDTO.getChannelExtras(), "user_type"); | ||
| 48 | + Assert.notEmpty(userId, "用户 id 不能为空"); | ||
| 49 | + Assert.notEmpty(userType, "用户类型不能为空"); | ||
| 50 | + PayWalletTransactionDO transaction = wallService.pay(Long.valueOf(userId), Integer.valueOf(userType), | ||
| 51 | + reqDTO.getOutTradeNo(), reqDTO.getPrice()); | ||
| 45 | return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), | 52 | return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), |
| 46 | transaction.getTransactionTime(), | 53 | transaction.getTransactionTime(), |
| 47 | reqDTO.getOutTradeNo(), transaction); | 54 | reqDTO.getOutTradeNo(), transaction); |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.wallet; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.wallet; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; | 3 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
| 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; | 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 5 | +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | ||
| 5 | 6 | ||
| 6 | /** | 7 | /** |
| 7 | * 钱包 Service 接口 | 8 | * 钱包 Service 接口 |
| @@ -20,15 +21,43 @@ public interface PayWalletService { | @@ -20,15 +21,43 @@ public interface PayWalletService { | ||
| 20 | PayWalletDO getPayWallet(Long userId, Integer userType); | 21 | PayWalletDO getPayWallet(Long userId, Integer userType); |
| 21 | 22 | ||
| 22 | /** | 23 | /** |
| 23 | - * 钱包支付 | 24 | + * 钱包订单支付 |
| 24 | * | 25 | * |
| 25 | * @param outTradeNo 外部订单号 | 26 | * @param outTradeNo 外部订单号 |
| 26 | * @param price 金额 | 27 | * @param price 金额 |
| 27 | */ | 28 | */ |
| 28 | - PayWalletTransactionDO pay(String outTradeNo, Integer price); | 29 | + PayWalletTransactionDO pay(Long userId, Integer userType, String outTradeNo, Integer price); |
| 30 | + | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 扣减钱包余额 | ||
| 34 | + * | ||
| 35 | + * @param userId 用户 id | ||
| 36 | + * @param userType 用户类型 | ||
| 37 | + * @param bizId 业务关联 id | ||
| 38 | + * @param bizType 业务关联分类 | ||
| 39 | + * @param price 扣减金额 | ||
| 40 | + * @return 钱包流水 | ||
| 41 | + */ | ||
| 42 | + PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, | ||
| 43 | + Long bizId, PayWalletBizTypeEnum bizType, Integer price); | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 增加钱包余额 | ||
| 48 | + * | ||
| 49 | + * @param userId 用户 id | ||
| 50 | + * @param userType 用户类型 | ||
| 51 | + * @param bizId 业务关联 id | ||
| 52 | + * @param bizType 业务关联分类 | ||
| 53 | + * @param price 增加金额 | ||
| 54 | + * @return 钱包流水 | ||
| 55 | + */ | ||
| 56 | + PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, | ||
| 57 | + Long bizId, PayWalletBizTypeEnum bizType, Integer price); | ||
| 29 | 58 | ||
| 30 | /** | 59 | /** |
| 31 | - * 钱包支付退款 | 60 | + * 钱包订单支付退款 |
| 32 | * | 61 | * |
| 33 | * @param outRefundNo 外部退款号 | 62 | * @param outRefundNo 外部退款号 |
| 34 | * @param refundPrice 退款金额 | 63 | * @param refundPrice 退款金额 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
| 1 | package cn.iocoder.yudao.module.pay.service.wallet; | 1 | package cn.iocoder.yudao.module.pay.service.wallet; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; |
| 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
| 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 7 | import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; | 8 | import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; |
| 8 | import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | 9 | import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; |
| 10 | +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | ||
| 9 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | 11 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 10 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | 12 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 11 | import lombok.extern.slf4j.Slf4j; | 13 | import lombok.extern.slf4j.Slf4j; |
| @@ -16,9 +18,8 @@ import org.springframework.transaction.annotation.Transactional; | @@ -16,9 +18,8 @@ import org.springframework.transaction.annotation.Transactional; | ||
| 16 | import javax.annotation.Resource; | 18 | import javax.annotation.Resource; |
| 17 | import java.time.LocalDateTime; | 19 | import java.time.LocalDateTime; |
| 18 | 20 | ||
| 21 | +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.TOO_MANY_REQUESTS; | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 22 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 20 | -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; | ||
| 21 | -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType; | ||
| 22 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; | 23 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; |
| 23 | import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; | 24 | import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; |
| 24 | import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT_REFUND; | 25 | import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT_REFUND; |
| @@ -60,42 +61,70 @@ public class PayWalletServiceImpl implements PayWalletService { | @@ -60,42 +61,70 @@ public class PayWalletServiceImpl implements PayWalletService { | ||
| 60 | return payWalletMapper.selectByUserIdAndType(userId, userType); | 61 | return payWalletMapper.selectByUserIdAndType(userId, userType); |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | - // TODO @jason:可以做的更抽象一点;pay(bizType, bizId, price);reduceWalletBalance; | ||
| 64 | - // TODO @jason:最好是,明确传入哪个 userId 或者 walletId; | 64 | + |
| 65 | @Override | 65 | @Override |
| 66 | @Transactional(rollbackFor = Exception.class) | 66 | @Transactional(rollbackFor = Exception.class) |
| 67 | - public PayWalletTransactionDO pay(String outTradeNo, Integer price) { | ||
| 68 | - // 1.1 判断支付交易拓展单是否存 | 67 | + public PayWalletTransactionDO pay(Long userId, Integer userType, String outTradeNo, Integer price) { |
| 68 | + // 判断支付交易拓展单是否存 | ||
| 69 | PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); | 69 | PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); |
| 70 | if (orderExtension == null) { | 70 | if (orderExtension == null) { |
| 71 | throw exception(ORDER_EXTENSION_NOT_FOUND); | 71 | throw exception(ORDER_EXTENSION_NOT_FOUND); |
| 72 | } | 72 | } |
| 73 | + return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 77 | + public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, | ||
| 78 | + Long bizId, PayWalletBizTypeEnum bizType, Integer price) { | ||
| 79 | + // 1.1 判断钱包是否有效 | ||
| 80 | + PayWalletDO payWallet = validatePayWallet(userId, userType); | ||
| 73 | // 1.2 判断余额是否足够 | 81 | // 1.2 判断余额是否足够 |
| 74 | - PayWalletDO payWallet = validatePayWallet(); | ||
| 75 | int afterBalance = payWallet.getBalance() - price; | 82 | int afterBalance = payWallet.getBalance() - price; |
| 76 | if (afterBalance < 0) { | 83 | if (afterBalance < 0) { |
| 77 | throw exception(WALLET_BALANCE_NOT_ENOUGH); | 84 | throw exception(WALLET_BALANCE_NOT_ENOUGH); |
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | // 2.1 扣除余额 | 87 | // 2.1 扣除余额 |
| 81 | - // TODO @jason:不要直接整个更新;而是 new 一个出来更新;然后要考虑并发,要 where 余额 > price,以及 - price | ||
| 82 | - payWallet.setBalance(afterBalance); | ||
| 83 | - payWallet.setTotalExpense(payWallet.getTotalExpense() + price); | ||
| 84 | - payWalletMapper.updateById(payWallet); | 88 | + int number = payWalletMapper.updateWhenDecBalance(bizType,payWallet.getBalance(), payWallet.getTotalRecharge(), |
| 89 | + payWallet.getTotalExpense(), price, payWallet.getId()); | ||
| 90 | + if (number == 0) { | ||
| 91 | + throw exception(TOO_MANY_REQUESTS); | ||
| 92 | + } | ||
| 85 | 93 | ||
| 86 | - // 2.2 生成钱包流水 | 94 | + // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO |
| 87 | String walletNo = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); | 95 | String walletNo = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); |
| 88 | PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) | 96 | PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) |
| 89 | - .setNo(walletNo).setAmount(price * -1).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) | ||
| 90 | - .setBizId(orderExtension.getOrderId()).setBizType(PAYMENT.getType()); | 97 | + .setNo(walletNo).setAmount(-price).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) |
| 98 | + .setBizId(bizId).setBizType(bizType.getType()).setDescription(bizType.getDescription()); | ||
| 91 | payWalletTransactionService.createWalletTransaction(walletTransaction); | 99 | payWalletTransactionService.createWalletTransaction(walletTransaction); |
| 92 | return walletTransaction; | 100 | return walletTransaction; |
| 93 | } | 101 | } |
| 94 | 102 | ||
| 95 | - // TODO @jason:不要在 service 里去使用用户上下文,这样和 request 就耦合了。 | ||
| 96 | - private PayWalletDO validatePayWallet() { | ||
| 97 | - Long userId = getLoginUserId(); | ||
| 98 | - Integer userType = getLoginUserType(); | 103 | + @Override |
| 104 | + public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, | ||
| 105 | + PayWalletBizTypeEnum bizType, Integer price) { | ||
| 106 | + // 1.1 判断钱包是否有效 | ||
| 107 | + PayWalletDO payWallet = validatePayWallet(userId, userType); | ||
| 108 | + | ||
| 109 | + // 2.1 增加余额 | ||
| 110 | + int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), | ||
| 111 | + payWallet.getTotalExpense(), price, payWallet.getId()); | ||
| 112 | + if (number == 0) { | ||
| 113 | + throw exception(TOO_MANY_REQUESTS); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO | ||
| 117 | + String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); | ||
| 118 | + PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) | ||
| 119 | + .setNo(walletNo).setAmount(price).setBalance(payWallet.getBalance()+price).setTransactionTime(LocalDateTime.now()) | ||
| 120 | + .setBizId(bizId).setBizType(bizType.getType()) | ||
| 121 | + .setDescription(bizType.getDescription()); | ||
| 122 | + payWalletTransactionService.createWalletTransaction(newWalletTransaction); | ||
| 123 | + return newWalletTransaction; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + | ||
| 127 | + private PayWalletDO validatePayWallet(Long userId, Integer userType) { | ||
| 99 | PayWalletDO payWallet = getPayWallet(userId, userType); | 128 | PayWalletDO payWallet = getPayWallet(userId, userType); |
| 100 | if (payWallet == null) { | 129 | if (payWallet == null) { |
| 101 | log.error("[validatePayWallet] 用户 {} 钱包不存在", userId); | 130 | log.error("[validatePayWallet] 用户 {} 钱包不存在", userId); |
| @@ -104,7 +133,7 @@ public class PayWalletServiceImpl implements PayWalletService { | @@ -104,7 +133,7 @@ public class PayWalletServiceImpl implements PayWalletService { | ||
| 104 | return payWallet; | 133 | return payWallet; |
| 105 | } | 134 | } |
| 106 | 135 | ||
| 107 | - // TODO @jason:可以做的更抽象一点;pay(bizType, bizId, price);addWalletBalance;这样,如果后续充值,应该也是能复用这个方法的; | 136 | + |
| 108 | @Override | 137 | @Override |
| 109 | @Transactional(rollbackFor = Exception.class) | 138 | @Transactional(rollbackFor = Exception.class) |
| 110 | public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { | 139 | public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { |
| @@ -114,23 +143,11 @@ public class PayWalletServiceImpl implements PayWalletService { | @@ -114,23 +143,11 @@ public class PayWalletServiceImpl implements PayWalletService { | ||
| 114 | throw exception(REFUND_NOT_FOUND); | 143 | throw exception(REFUND_NOT_FOUND); |
| 115 | } | 144 | } |
| 116 | // 1.2 校验是否可以退款 | 145 | // 1.2 校验是否可以退款 |
| 117 | - PayWalletDO payWallet = validatePayWallet(); | ||
| 118 | - validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), payWallet.getId(), refundPrice); | ||
| 119 | - | ||
| 120 | - // TODO @jason:不要直接整个更新;而是 new 一个出来更新;然后要考虑并发,要 where 余额 + 金额 | ||
| 121 | - Integer afterBalance = payWallet.getBalance() + refundPrice; | ||
| 122 | - payWallet.setBalance(afterBalance); | ||
| 123 | - payWallet.setTotalExpense(payWallet.getTotalExpense() + refundPrice * -1L); | ||
| 124 | - payWalletMapper.updateById(payWallet); | 146 | + Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice); |
| 125 | 147 | ||
| 126 | - // 2.2 生成钱包流水 | ||
| 127 | - String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); | ||
| 128 | - PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) | ||
| 129 | - .setNo(walletNo).setAmount(refundPrice).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) | ||
| 130 | - .setBizId(payRefund.getId()).setBizType(PAYMENT_REFUND.getType()) | ||
| 131 | - .setDescription(reason); | ||
| 132 | - payWalletTransactionService.createWalletTransaction(newWalletTransaction); | ||
| 133 | - return newWalletTransaction; | 148 | + PayWalletDO payWallet = payWalletMapper.selectById(walletId); |
| 149 | + Assert.notNull(payWallet, "钱包 {} 不存在", walletId); | ||
| 150 | + return addWalletBalance(payWallet.getUserId(), payWallet.getUserType(),payRefund.getId(), PAYMENT_REFUND, refundPrice); | ||
| 134 | } | 151 | } |
| 135 | 152 | ||
| 136 | /** | 153 | /** |
| @@ -138,24 +155,23 @@ public class PayWalletServiceImpl implements PayWalletService { | @@ -138,24 +155,23 @@ public class PayWalletServiceImpl implements PayWalletService { | ||
| 138 | * | 155 | * |
| 139 | * @param refundId 支付退款单 id | 156 | * @param refundId 支付退款单 id |
| 140 | * @param walletPayNo 钱包支付 no | 157 | * @param walletPayNo 钱包支付 no |
| 141 | - * @param walletId 钱包 id | ||
| 142 | */ | 158 | */ |
| 143 | - // TODO @jason:不要使用基本类型; | ||
| 144 | - private void validateWalletCanRefund(long refundId, String walletPayNo, long walletId, int refundPrice) { | 159 | + private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) { |
| 145 | // 查询钱包支付交易 | 160 | // 查询钱包支付交易 |
| 146 | PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo); | 161 | PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo); |
| 147 | if (payWalletTransaction == null) { | 162 | if (payWalletTransaction == null) { |
| 148 | throw exception(WALLET_TRANSACTION_NOT_FOUND); | 163 | throw exception(WALLET_TRANSACTION_NOT_FOUND); |
| 149 | } | 164 | } |
| 150 | // 原来的支付金额 | 165 | // 原来的支付金额 |
| 151 | - int amount = payWalletTransaction.getAmount() * -1; // TODO @jason:直接 - payWalletTransaction.getAmount() 即可; | 166 | + int amount = - payWalletTransaction.getAmount(); |
| 152 | if (refundPrice != amount) { | 167 | if (refundPrice != amount) { |
| 153 | throw exception(WALLET_REFUND_AMOUNT_ERROR); | 168 | throw exception(WALLET_REFUND_AMOUNT_ERROR); |
| 154 | } | 169 | } |
| 155 | - PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction(walletId, refundId, PAYMENT_REFUND); | 170 | + PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction( |
| 171 | + payWalletTransaction.getWalletId(), refundId, PAYMENT_REFUND); | ||
| 156 | if (refundTransaction != null) { | 172 | if (refundTransaction != null) { |
| 157 | throw exception(WALLET_REFUND_EXIST); | 173 | throw exception(WALLET_REFUND_EXIST); |
| 158 | } | 174 | } |
| 175 | + return payWalletTransaction.getWalletId(); | ||
| 159 | } | 176 | } |
| 160 | - | ||
| 161 | } | 177 | } |