Commit cc4c924717b862a85765f918a8205cdcfcc80f41
1 parent
91b03e7c
钱包 review DO 类修改
Showing
9 changed files
with
74 additions
and
79 deletions
sql/mysql/pay_wallet.sql
| 1 | 1 | -- ---------------------------- |
| 2 | --- 支付-钱包表 | |
| 2 | +-- 会员钱包表 | |
| 3 | 3 | -- ---------------------------- |
| 4 | 4 | DROP TABLE IF EXISTS `pay_wallet`; |
| 5 | 5 | CREATE TABLE `pay_wallet` |
| ... | ... | @@ -17,28 +17,27 @@ CREATE TABLE `pay_wallet` |
| 17 | 17 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 18 | 18 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 19 | 19 | PRIMARY KEY (`id`) USING BTREE |
| 20 | -) ENGINE=InnoDB COMMENT='支付钱包表'; | |
| 20 | +) ENGINE=InnoDB COMMENT='会员钱包表'; | |
| 21 | 21 | |
| 22 | 22 | -- ---------------------------- |
| 23 | --- 支付- 钱包余额明细表 | |
| 23 | +-- 会员钱包流水表 | |
| 24 | 24 | -- ---------------------------- |
| 25 | 25 | DROP TABLE IF EXISTS `pay_wallet_transaction`; |
| 26 | 26 | CREATE TABLE `pay_wallet_transaction` |
| 27 | 27 | ( |
| 28 | - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | |
| 29 | - `wallet_id` bigint NOT NULL COMMENT '会员钱包 id', | |
| 30 | - `biz_type` tinyint NOT NULL COMMENT '关联类型', | |
| 31 | - `biz_id` bigint NOT NULL COMMENT '关联业务编号', | |
| 32 | - `no` varchar(64) NOT NULL COMMENT '流水号', | |
| 33 | - `description` varchar(255) COMMENT '操作说明', | |
| 34 | - `amount` int NOT NULL COMMENT '交易金额, 单位分', | |
| 35 | - `balance` int NOT NULL COMMENT '余额, 单位分', | |
| 36 | - `transaction_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '交易时间', | |
| 37 | - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | |
| 38 | - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | |
| 39 | - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | |
| 40 | - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | |
| 41 | - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | |
| 42 | - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | |
| 28 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | |
| 29 | + `wallet_id` bigint NOT NULL COMMENT '会员钱包 id', | |
| 30 | + `biz_type` tinyint NOT NULL COMMENT '关联类型', | |
| 31 | + `biz_id` varchar(64) NOT NULL COMMENT '关联业务编号', | |
| 32 | + `no` varchar(64) NOT NULL COMMENT '流水号', | |
| 33 | + `title` varchar(128) NOT NULL COMMENT '流水标题', | |
| 34 | + `price` int NOT NULL COMMENT '交易金额, 单位分', | |
| 35 | + `balance` int NOT NULL COMMENT '余额, 单位分', | |
| 36 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | |
| 37 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | |
| 38 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | |
| 39 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | |
| 40 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | |
| 41 | + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | |
| 43 | 42 | PRIMARY KEY (`id`) USING BTREE |
| 44 | -) ENGINE=InnoDB COMMENT='支付钱包余额明细表'; | |
| 43 | +) ENGINE=InnoDB COMMENT='会员钱包流水表'; | ... | ... |
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 | 37 | @Operation(summary = "获取钱包") |
| 38 | 38 | @PreAuthenticated |
| 39 | 39 | public CommonResult<AppPayWalletRespVO> getPayWallet() { |
| 40 | - PayWalletDO wallet = payWalletService.getPayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); | |
| 40 | + PayWalletDO wallet = payWalletService.getOrCreatePayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); | |
| 41 | 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/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java
| ... | ... | @@ -15,9 +15,6 @@ public class AppPayWalletTransactionRespVO { |
| 15 | 15 | @Schema(description = "业务分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 16 | 16 | private Integer bizType; |
| 17 | 17 | |
| 18 | - @Schema(description = "交易时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | |
| 19 | - private LocalDateTime transactionTime; | |
| 20 | - | |
| 21 | 18 | @Schema(description = "交易金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 22 | 19 | private Long price; |
| 23 | 20 | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java
| ... | ... | @@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableId; |
| 7 | 7 | import com.baomidou.mybatisplus.annotation.TableName; |
| 8 | 8 | import lombok.Data; |
| 9 | 9 | |
| 10 | -import java.time.LocalDateTime; | |
| 11 | - | |
| 12 | 10 | /** |
| 13 | 11 | * 会员钱包流水 DO |
| 14 | 12 | * |
| ... | ... | @@ -24,6 +22,7 @@ public class PayWalletTransactionDO extends BaseDO { |
| 24 | 22 | */ |
| 25 | 23 | @TableId |
| 26 | 24 | private Long id; |
| 25 | + | |
| 27 | 26 | /** |
| 28 | 27 | * 流水号 |
| 29 | 28 | */ |
| ... | ... | @@ -42,34 +41,26 @@ public class PayWalletTransactionDO extends BaseDO { |
| 42 | 41 | * 枚举 {@link PayWalletBizTypeEnum#getType()} |
| 43 | 42 | */ |
| 44 | 43 | private Integer bizType; |
| 45 | - // TODO @jason:使用 string;因为可能有业务是 string 接入哈。 | |
| 44 | + | |
| 46 | 45 | /** |
| 47 | 46 | * 关联业务编号 |
| 48 | 47 | */ |
| 49 | - private Long bizId; | |
| 48 | + private String bizId; | |
| 50 | 49 | |
| 51 | - // TODO @jason:想了下,改成 title;流水标题;因为账户明细那,会看到这个; | |
| 52 | 50 | /** |
| 53 | - * 附加说明 | |
| 51 | + * 流水说明 | |
| 54 | 52 | */ |
| 55 | - private String description; | |
| 53 | + private String title; | |
| 56 | 54 | |
| 57 | - // TODO @jason:使用 price 哈。项目里,金额都是用这个为主; | |
| 58 | 55 | /** |
| 59 | 56 | * 交易金额,单位分 |
| 60 | 57 | * |
| 61 | 58 | * 正值表示余额增加,负值表示余额减少 |
| 62 | 59 | */ |
| 63 | - private Integer amount; | |
| 60 | + private Integer price; | |
| 61 | + | |
| 64 | 62 | /** |
| 65 | 63 | * 交易后余额,单位分 |
| 66 | 64 | */ |
| 67 | 65 | private Integer balance; |
| 68 | - | |
| 69 | - // TODO @jason:使用 createTime 就够啦 | |
| 70 | - /** | |
| 71 | - * 交易时间 | |
| 72 | - */ | |
| 73 | - private LocalDateTime transactionTime; | |
| 74 | - | |
| 75 | 66 | } | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java
| ... | ... | @@ -18,9 +18,9 @@ public interface PayWalletTransactionMapper extends BaseMapperX<PayWalletTransac |
| 18 | 18 | LambdaQueryWrapperX<PayWalletTransactionDO> query = new LambdaQueryWrapperX<PayWalletTransactionDO>() |
| 19 | 19 | .eq(PayWalletTransactionDO::getWalletId, walletId); |
| 20 | 20 | if (Objects.equals(pageReqVO.getType(), AppPayWalletTransactionPageReqVO.TYPE_INCOME)) { |
| 21 | - query.gt(PayWalletTransactionDO::getAmount, 0); | |
| 21 | + query.gt(PayWalletTransactionDO::getPrice, 0); | |
| 22 | 22 | } else if (Objects.equals(pageReqVO.getType(), AppPayWalletTransactionPageReqVO.TYPE_EXPENSE)) { |
| 23 | - query.lt(PayWalletTransactionDO::getAmount, 0); | |
| 23 | + query.lt(PayWalletTransactionDO::getPrice, 0); | |
| 24 | 24 | } |
| 25 | 25 | query.orderByDesc(PayWalletTransactionDO::getId); |
| 26 | 26 | return selectPage(pageReqVO, query); | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java
| ... | ... | @@ -50,7 +50,7 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { |
| 50 | 50 | PayWalletTransactionDO transaction = wallService.pay(Long.valueOf(userId), Integer.valueOf(userType), |
| 51 | 51 | reqDTO.getOutTradeNo(), reqDTO.getPrice()); |
| 52 | 52 | return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), |
| 53 | - transaction.getTransactionTime(), | |
| 53 | + transaction.getCreateTime(), | |
| 54 | 54 | reqDTO.getOutTradeNo(), transaction); |
| 55 | 55 | } catch (Throwable ex) { |
| 56 | 56 | log.error("[doUnifiedOrder] 失败", ex); |
| ... | ... | @@ -81,7 +81,7 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { |
| 81 | 81 | try { |
| 82 | 82 | PayWalletTransactionDO payWalletTransaction = wallService.refund(reqDTO.getOutRefundNo(), |
| 83 | 83 | reqDTO.getRefundPrice(), reqDTO.getReason()); |
| 84 | - return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getTransactionTime(), | |
| 84 | + return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getCreateTime(), | |
| 85 | 85 | reqDTO.getOutRefundNo(), payWalletTransaction); |
| 86 | 86 | } catch (Throwable ex) { |
| 87 | 87 | log.error("[doUnifiedRefund] 失败", ex); | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
| ... | ... | @@ -11,18 +11,19 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; |
| 11 | 11 | */ |
| 12 | 12 | public interface PayWalletService { |
| 13 | 13 | |
| 14 | - // TODO @jason:改成 getOrCreateWallet;因为目前解耦,用户注册时,不会创建钱包;需要这里兜底处理; | |
| 15 | 14 | /** |
| 16 | - * 获取钱包信息 | |
| 15 | + * 获取钱包信息,如果不存在创建钱包。由于用户注册时候不会创建钱包 | |
| 17 | 16 | * |
| 18 | 17 | * @param userId 用户编号 |
| 19 | 18 | * @param userType 用户类型 |
| 20 | 19 | */ |
| 21 | - PayWalletDO getPayWallet(Long userId, Integer userType); | |
| 20 | + PayWalletDO getOrCreatePayWallet(Long userId, Integer userType); | |
| 22 | 21 | |
| 23 | 22 | /** |
| 24 | 23 | * 钱包订单支付 |
| 25 | 24 | * |
| 25 | + * @param userId 用户 id | |
| 26 | + * @param userType 用户类型 | |
| 26 | 27 | * @param outTradeNo 外部订单号 |
| 27 | 28 | * @param price 金额 |
| 28 | 29 | */ | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
| ... | ... | @@ -57,8 +57,19 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 57 | 57 | private PayRefundService payRefundService; |
| 58 | 58 | |
| 59 | 59 | @Override |
| 60 | - public PayWalletDO getPayWallet(Long userId, Integer userType) { | |
| 61 | - return payWalletMapper.selectByUserIdAndType(userId, userType); | |
| 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); | |
| 71 | + } | |
| 72 | + return payWalletDO; | |
| 62 | 73 | } |
| 63 | 74 | |
| 64 | 75 | |
| ... | ... | @@ -76,8 +87,8 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 76 | 87 | @Override |
| 77 | 88 | public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, |
| 78 | 89 | Long bizId, PayWalletBizTypeEnum bizType, Integer price) { |
| 79 | - // 1.1 判断钱包是否有效 | |
| 80 | - PayWalletDO payWallet = validatePayWallet(userId, userType); | |
| 90 | + // 1.1 获取钱包 | |
| 91 | + PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); | |
| 81 | 92 | // 1.2 判断余额是否足够 |
| 82 | 93 | int afterBalance = payWallet.getBalance() - price; |
| 83 | 94 | if (afterBalance < 0) { |
| ... | ... | @@ -90,12 +101,11 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 90 | 101 | if (number == 0) { |
| 91 | 102 | throw exception(TOO_MANY_REQUESTS); |
| 92 | 103 | } |
| 93 | - | |
| 94 | - // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO | |
| 95 | - String walletNo = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); | |
| 104 | + // 2.2 生成钱包流水 | |
| 105 | + String walletNo = generateWalletNo(bizType); | |
| 96 | 106 | PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) |
| 97 | - .setNo(walletNo).setAmount(-price).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) | |
| 98 | - .setBizId(bizId).setBizType(bizType.getType()).setDescription(bizType.getDescription()); | |
| 107 | + .setNo(walletNo).setPrice(-price).setBalance(afterBalance) | |
| 108 | + .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription()); | |
| 99 | 109 | payWalletTransactionService.createWalletTransaction(walletTransaction); |
| 100 | 110 | return walletTransaction; |
| 101 | 111 | } |
| ... | ... | @@ -103,8 +113,8 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 103 | 113 | @Override |
| 104 | 114 | public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId, |
| 105 | 115 | PayWalletBizTypeEnum bizType, Integer price) { |
| 106 | - // 1.1 判断钱包是否有效 | |
| 107 | - PayWalletDO payWallet = validatePayWallet(userId, userType); | |
| 116 | + // 1.1 获取钱包 | |
| 117 | + PayWalletDO payWallet = getOrCreatePayWallet(userId, userType); | |
| 108 | 118 | |
| 109 | 119 | // 2.1 增加余额 |
| 110 | 120 | int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), |
| ... | ... | @@ -113,27 +123,31 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 113 | 123 | throw exception(TOO_MANY_REQUESTS); |
| 114 | 124 | } |
| 115 | 125 | |
| 116 | - // 2.2 生成钱包流水 TODO 根据 bizType 生成 NO | |
| 117 | - String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); | |
| 126 | + // 2.2 生成钱包流水 | |
| 127 | + String walletNo = generateWalletNo(bizType); | |
| 118 | 128 | 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()); | |
| 129 | + .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price) | |
| 130 | + .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()) | |
| 131 | + .setTitle(bizType.getDescription()); | |
| 122 | 132 | payWalletTransactionService.createWalletTransaction(newWalletTransaction); |
| 123 | 133 | return newWalletTransaction; |
| 124 | 134 | } |
| 125 | 135 | |
| 126 | - | |
| 127 | - private PayWalletDO validatePayWallet(Long userId, Integer userType) { | |
| 128 | - PayWalletDO payWallet = getPayWallet(userId, userType); | |
| 129 | - if (payWallet == null) { | |
| 130 | - log.error("[validatePayWallet] 用户 {} 钱包不存在", userId); | |
| 131 | - throw exception(WALLET_NOT_FOUND); | |
| 136 | + private String generateWalletNo(PayWalletBizTypeEnum bizType) { | |
| 137 | + String no = ""; | |
| 138 | + switch(bizType){ | |
| 139 | + case PAYMENT : | |
| 140 | + no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); | |
| 141 | + break; | |
| 142 | + case PAYMENT_REFUND : | |
| 143 | + no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); | |
| 144 | + break; | |
| 145 | + default : | |
| 146 | + // TODO 待增加 | |
| 132 | 147 | } |
| 133 | - return payWallet; | |
| 148 | + return no; | |
| 134 | 149 | } |
| 135 | 150 | |
| 136 | - | |
| 137 | 151 | @Override |
| 138 | 152 | @Transactional(rollbackFor = Exception.class) |
| 139 | 153 | public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { |
| ... | ... | @@ -163,7 +177,7 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 163 | 177 | throw exception(WALLET_TRANSACTION_NOT_FOUND); |
| 164 | 178 | } |
| 165 | 179 | // 原来的支付金额 |
| 166 | - int amount = - payWalletTransaction.getAmount(); | |
| 180 | + int amount = - payWalletTransaction.getPrice(); | |
| 167 | 181 | if (refundPrice != amount) { |
| 168 | 182 | throw exception(WALLET_REFUND_AMOUNT_ERROR); |
| 169 | 183 | } | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java
| ... | ... | @@ -11,9 +11,6 @@ import org.springframework.stereotype.Service; |
| 11 | 11 | |
| 12 | 12 | import javax.annotation.Resource; |
| 13 | 13 | |
| 14 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 15 | -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.WALLET_NOT_FOUND; | |
| 16 | - | |
| 17 | 14 | /** |
| 18 | 15 | * 钱包流水 Service 实现类 |
| 19 | 16 | * |
| ... | ... | @@ -32,11 +29,7 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ |
| 32 | 29 | @Override |
| 33 | 30 | public PageResult<PayWalletTransactionDO> getWalletTransactionPage(Long userId, Integer userType, |
| 34 | 31 | AppPayWalletTransactionPageReqVO pageVO) { |
| 35 | - PayWalletDO wallet = payWalletService.getPayWallet(userId, userType); | |
| 36 | - if (wallet == null) { | |
| 37 | - log.error("[getWalletTransactionPage][用户({}/{}) 钱包不存在", userId, userType); | |
| 38 | - throw exception(WALLET_NOT_FOUND); | |
| 39 | - } | |
| 32 | + PayWalletDO wallet = payWalletService.getOrCreatePayWallet(userId, userType); | |
| 40 | 33 | return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO); |
| 41 | 34 | } |
| 42 | 35 | ... | ... |