Commit 0e754a9924aff002dde438bf725ea84c3a7f5c35

Authored by puhui999
2 parents f363c598 89e847c8

Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product

Showing 42 changed files with 323 additions and 245 deletions
sql/mysql/pay_wallet.sql
... ... @@ -9,7 +9,7 @@ CREATE TABLE `pay_transfer`
9 9 `app_id` bigint NOT NULL COMMENT '应用编号',
10 10 `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号',
11 11 `price` int NOT NULL COMMENT '转账金额,单位:分',
12   - `title` varchar(512) NOT NULL COMMENT '转账标题',
  12 + `subject` varchar(512) NOT NULL COMMENT '转账标题',
13 13 `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同',
14 14 `status` tinyint NOT NULL COMMENT '转账状态',
15 15 `success_time` datetime NULL COMMENT '转账成功时间',
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java
... ... @@ -50,8 +50,6 @@ public class PayClientFactoryImpl implements PayClientFactory {
50 50 clientClass.put(ALIPAY_APP, AlipayAppPayClient.class);
51 51 clientClass.put(ALIPAY_PC, AlipayPcPayClient.class);
52 52 clientClass.put(ALIPAY_BAR, AlipayBarPayClient.class);
53   - // 支付包转账客户端
54   - clientClass.put(ALIPAY_TRANSFER, AlipayTransferClient.class);
55 53 // Mock 支付客户端
56 54 clientClass.put(MOCK, MockPayClient.class);
57 55 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
... ... @@ -6,24 +6,28 @@ import cn.hutool.core.lang.Assert;
6 6 import cn.hutool.core.map.MapUtil;
7 7 import cn.hutool.core.util.StrUtil;
8 8 import cn.hutool.http.HttpUtil;
  9 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 10 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
10 11 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
11 12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
12 13 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
13 14 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  15 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  16 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
14 17 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
15 18 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
  19 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
16 20 import com.alipay.api.AlipayApiException;
17 21 import com.alipay.api.AlipayConfig;
18 22 import com.alipay.api.AlipayResponse;
19 23 import com.alipay.api.DefaultAlipayClient;
20   -import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
21   -import com.alipay.api.domain.AlipayTradeQueryModel;
22   -import com.alipay.api.domain.AlipayTradeRefundModel;
  24 +import com.alipay.api.domain.*;
23 25 import com.alipay.api.internal.util.AlipaySignature;
  26 +import com.alipay.api.request.AlipayFundTransUniTransferRequest;
24 27 import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
25 28 import com.alipay.api.request.AlipayTradeQueryRequest;
26 29 import com.alipay.api.request.AlipayTradeRefundRequest;
  30 +import com.alipay.api.response.AlipayFundTransUniTransferResponse;
27 31 import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
28 32 import com.alipay.api.response.AlipayTradeQueryResponse;
29 33 import com.alipay.api.response.AlipayTradeRefundResponse;
... ... @@ -39,6 +43,9 @@ import java.util.Objects;
39 43 import java.util.function.Supplier;
40 44  
41 45 import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
  46 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
  47 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
  48 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
42 49  
43 50 /**
44 51 * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款)
... ... @@ -105,16 +112,20 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
105 112 // 1.2 构建 AlipayTradeQueryRequest 请求
106 113 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
107 114 request.setBizModel(model);
108   -
109   - // 2.1 执行请求
110   - AlipayTradeQueryResponse response = client.execute(request);
  115 + AlipayTradeQueryResponse response;
  116 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  117 + // 证书模式
  118 + response = client.certificateExecute(request);
  119 + } else {
  120 + response = client.execute(request);
  121 + }
111 122 if (!response.isSuccess()) { // 不成功,例如说订单不存在
112 123 return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
113 124 outTradeNo, response);
114 125 }
115 126 // 2.2 解析订单的状态
116 127 Integer status = parseStatus(response.getTradeStatus());
117   - Assert.notNull(status, (Supplier<Throwable>) () -> {
  128 + Assert.notNull(status, () -> {
118 129 throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody()));
119 130 });
120 131 return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()),
... ... @@ -148,7 +159,13 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
148 159 request.setBizModel(model);
149 160  
150 161 // 2.1 执行请求
151   - AlipayTradeRefundResponse response = client.execute(request);
  162 + AlipayTradeRefundResponse response;
  163 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  164 + // 证书模式
  165 + response = client.certificateExecute(request);
  166 + } else {
  167 + response = client.execute(request);
  168 + }
152 169 if (!response.isSuccess()) {
153 170 // 当出现 ACQ.SYSTEM_ERROR, 退款可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
154 171 if (ObjectUtils.equalsAny(response.getSubCode(), "ACQ.SYSTEM_ERROR", "SYSTEM_ERROR")) {
... ... @@ -185,7 +202,13 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
185 202 request.setBizModel(model);
186 203  
187 204 // 2.1 执行请求
188   - AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
  205 + AlipayTradeFastpayRefundQueryResponse response;
  206 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  207 + // 证书模式
  208 + response = client.certificateExecute(request);
  209 + } else {
  210 + response = client.execute(request);
  211 + }
189 212 if (!response.isSuccess()) {
190 213 // 明确不存在的情况,应该就是失败,可进行关闭
191 214 if (ObjectUtils.equalsAny(response.getSubCode(), "TRADE_NOT_EXIST", "ACQ.TRADE_NOT_EXIST")) {
... ... @@ -202,7 +225,69 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
202 225 return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
203 226 }
204 227  
  228 + @Override
  229 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
  230 + // 1.1 校验公钥类型 必须使用公钥证书模式
  231 + if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  232 + throw new IllegalStateException("支付宝单笔转账必须使用公钥证书模式");
  233 + }
205 234  
  235 + // 1.2 构建 AlipayFundTransUniTransferModel
  236 + AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
  237 + // ① 通用的参数
  238 + model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额
  239 + model.setOrderTitle(reqDTO.getTitle()); // 转账业务的标题,用于在支付宝用户的账单里显示。
  240 + model.setOutBizNo(reqDTO.getOutTransferNo());
  241 + model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
  242 + model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER
  243 + model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
  244 + PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(reqDTO.getType());
  245 + switch (transferType) {
  246 + // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦?
  247 + // @芋艿。 是不是还要考虑转账到银行卡。所以传 transferType 但是转账到银行卡不知道要如何测试??
  248 + case ALIPAY_BALANCE: {
  249 + // ② 个性化的参数
  250 + Participant payeeInfo = new Participant();
  251 + payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
  252 + String logonId = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_LOGON_ID");
  253 + if (StrUtil.isEmpty(logonId)) {
  254 + throw exception0(BAD_REQUEST.getCode(), "支付包登录 ID 不能为空");
  255 + }
  256 + String accountName = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_ACCOUNT_NAME");
  257 + if (StrUtil.isEmpty(accountName)) {
  258 + throw exception0(BAD_REQUEST.getCode(), "支付包账户名称不能为空");
  259 + }
  260 + payeeInfo.setIdentity(logonId); // 支付宝登录号
  261 + payeeInfo.setName(accountName); // 支付宝账号姓名
  262 + model.setPayeeInfo(payeeInfo);
  263 + // 1.3 构建 AlipayFundTransUniTransferRequest
  264 + AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
  265 + request.setBizModel(model);
  266 + // 执行请求
  267 + AlipayFundTransUniTransferResponse response = client.certificateExecute(request);
  268 + // 处理结果
  269 + if (!response.isSuccess()) {
  270 + // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
  271 + if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
  272 + return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
  273 + }
  274 + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
  275 + reqDTO.getOutTransferNo(), response);
  276 + }
  277 + return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
  278 + response.getOutBizNo(), response);
  279 + }
  280 + case BANK_CARD: {
  281 + Participant payeeInfo = new Participant();
  282 + payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
  283 + // TODO 待实现
  284 + throw new UnsupportedOperationException("待实现");
  285 + }
  286 + default: {
  287 + throw new IllegalStateException("不正确的转账类型: " + transferType);
  288 + }
  289 + }
  290 + }
206 291  
207 292 // ========== 各种工具方法 ==========
208 293  
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java
... ... @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3 3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
5   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
6   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 5 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
8 6 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
9 7 import com.alipay.api.AlipayApiException;
... ... @@ -58,9 +56,4 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
58 56 return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
59 57 reqDTO.getOutTradeNo(), response);
60 58 }
61   -
62   - @Override
63   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
64   - throw new UnsupportedOperationException("支付宝【App 支付】不支持转账操作");
65   - }
66 59 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java
... ... @@ -5,8 +5,6 @@ import cn.hutool.core.map.MapUtil;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
7 7 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
9   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
10 8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
11 9 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
12 10 import com.alipay.api.AlipayApiException;
... ... @@ -16,9 +14,11 @@ import com.alipay.api.response.AlipayTradePayResponse;
16 14 import lombok.extern.slf4j.Slf4j;
17 15  
18 16 import java.time.LocalDateTime;
  17 +import java.util.Objects;
19 18  
20 19 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
21 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
  21 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
22 22  
23 23 /**
24 24 * 支付宝【条码支付】的 PayClient 实现类
... ... @@ -61,7 +61,13 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
61 61 request.setReturnUrl(reqDTO.getReturnUrl());
62 62  
63 63 // 2.1 执行请求
64   - AlipayTradePayResponse response = client.execute(request);
  64 + AlipayTradePayResponse response;
  65 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  66 + // 证书模式
  67 + response = client.certificateExecute(request);
  68 + } else {
  69 + response = client.execute(request);
  70 + }
65 71 // 2.2 处理结果
66 72 if (!response.isSuccess()) {
67 73 return buildClosedPayOrderRespDTO(reqDTO, response);
... ... @@ -76,9 +82,4 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
76 82 return PayOrderRespDTO.waitingOf(displayMode, "",
77 83 reqDTO.getOutTradeNo(), response);
78 84 }
79   -
80   - @Override
81   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
82   - throw new UnsupportedOperationException("支付宝【条码支付】不支持转账操作");
83   - }
84 85 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
... ... @@ -4,8 +4,6 @@ import cn.hutool.core.util.ObjectUtil;
4 4 import cn.hutool.http.Method;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
7   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
9 7 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
10 8 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
11 9 import com.alipay.api.AlipayApiException;
... ... @@ -68,9 +66,4 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
68 66 return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
69 67 reqDTO.getOutTradeNo(), response);
70 68 }
71   -
72   - @Override
73   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
74   - throw new UnsupportedOperationException("支付宝【PC 网站】不支持转账操作");
75   - }
76 69 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
... ... @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3 3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
5   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
6   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 5 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
8 6 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
9 7 import com.alipay.api.AlipayApiException;
... ... @@ -12,6 +10,10 @@ import com.alipay.api.request.AlipayTradePrecreateRequest;
12 10 import com.alipay.api.response.AlipayTradePrecreateResponse;
13 11 import lombok.extern.slf4j.Slf4j;
14 12  
  13 +import java.util.Objects;
  14 +
  15 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
  16 +
15 17 /**
16 18 * 支付宝【扫码支付】的 PayClient 实现类
17 19 *
... ... @@ -47,7 +49,13 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient {
47 49 request.setReturnUrl(reqDTO.getReturnUrl());
48 50  
49 51 // 2.1 执行请求
50   - AlipayTradePrecreateResponse response = client.execute(request);
  52 + AlipayTradePrecreateResponse response;
  53 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  54 + // 证书模式
  55 + response = client.certificateExecute(request);
  56 + } else {
  57 + response = client.execute(request);
  58 + }
51 59 // 2.2 处理结果
52 60 if (!response.isSuccess()) {
53 61 return buildClosedPayOrderRespDTO(reqDTO, response);
... ... @@ -55,9 +63,4 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient {
55 63 return PayOrderRespDTO.waitingOf(displayMode, response.getQrCode(),
56 64 reqDTO.getOutTradeNo(), response);
57 65 }
58   -
59   - @Override
60   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
61   - throw new UnsupportedOperationException("支付宝【扫码支付】不支持转账操作");
62   - }
63 66 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayTransferClient.java deleted
1   -package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2   -
3   -import cn.hutool.core.map.MapUtil;
4   -import cn.hutool.core.util.StrUtil;
5   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6   -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
7   -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
9   -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
10   -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
11   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
12   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
13   -import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
14   -import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
15   -import com.alipay.api.AlipayApiException;
16   -import com.alipay.api.domain.AlipayFundTransUniTransferModel;
17   -import com.alipay.api.domain.Participant;
18   -import com.alipay.api.request.AlipayFundTransUniTransferRequest;
19   -import com.alipay.api.response.AlipayFundTransUniTransferResponse;
20   -import lombok.extern.slf4j.Slf4j;
21   -
22   -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
23   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
24   -
25   -// TODO @jason:看看能不能融合到 AbstractAlipayPayClient 中。
26   -/**
27   - * 支付宝转账的 PayClient 实现类
28   - *
29   - * @author jason
30   - */
31   -@Slf4j
32   -public class AlipayTransferClient extends AbstractAlipayPayClient {
33   - // TODO @jason:方法之间,要有空格噢
34   - public AlipayTransferClient(Long channelId, AlipayPayClientConfig config) {
35   - super(channelId, PayChannelEnum.ALIPAY_TRANSFER.getCode(), config);
36   - }
37   - @Override
38   - protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
39   - throw new UnsupportedOperationException("支付宝转账不支持统一下单请求");
40   - }
41   - @Override
42   - protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
43   - throw new UnsupportedOperationException("支付宝转账不支持统一退款请求");
44   - }
45   - @Override
46   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
47   - // 1.1 构建 AlipayFundTransUniTransferModel
48   - AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
49   - // ① 通用的参数
50   - model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额
51   - model.setOrderTitle(reqDTO.getTitle()); // 转账业务的标题,用于在支付宝用户的账单里显示。
52   - model.setOutBizNo(reqDTO.getOutTransferNo());
53   - model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
54   - model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER
55   - model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
56   - PayTransferTypeEnum transferType = PayTransferTypeEnum.ofType(reqDTO.getType());
57   - switch(transferType) {
58   - case WX_BALANCE:
59   - case WALLET_BALANCE: {
60   - log.error("[doUnifiedTransfer],支付宝转账不支持的转账类型{}", transferType);
61   - throw new UnsupportedOperationException(String.format("支付宝转账不支持转账类型: %s",transferType.getName()));
62   - }
63   - // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦?
64   - case ALIPAY_BALANCE: {
65   - // ② 个性化的参数
66   - Participant payeeInfo = new Participant();
67   - payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
68   - String logonId = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_LOGON_ID");
69   - if (StrUtil.isEmpty(logonId)) {
70   - throw exception0(BAD_REQUEST.getCode(), "支付包登录 ID 不能为空");
71   - }
72   - String accountName = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_ACCOUNT_NAME");
73   - if (StrUtil.isEmpty(accountName)) {
74   - throw exception0(BAD_REQUEST.getCode(), "支付包账户名称不能为空");
75   - }
76   - payeeInfo.setIdentity(logonId); // 支付宝登录号
77   - payeeInfo.setName(accountName); // 支付宝账号姓名
78   - model.setPayeeInfo(payeeInfo);
79   - // 1.2 构建 AlipayFundTransUniTransferRequest
80   - AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
81   - request.setBizModel(model);
82   - // 执行请求
83   - AlipayFundTransUniTransferResponse response = client.certificateExecute(request);
84   - // 处理结果
85   - if (!response.isSuccess()) {
86   - // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
87   - if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
88   - return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
89   - }
90   - return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
91   - reqDTO.getOutTransferNo(), response);
92   - }
93   - return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
94   - response.getOutBizNo(), response);
95   - }
96   - case BANK_CARD: {
97   - Participant payeeInfo = new Participant();
98   - payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
99   - throw new UnsupportedOperationException("待实现");
100   - }
101   - default: {
102   - throw new IllegalStateException("不正确的转账类型: " + transferType);
103   - }
104   - }
105   - }
106   -
107   -}
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
... ... @@ -3,8 +3,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
3 3 import cn.hutool.http.Method;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
6   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
7   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
8 6 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 7 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
10 8 import com.alipay.api.AlipayApiException;
... ... @@ -57,9 +55,4 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient {
57 55 return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
58 56 reqDTO.getOutTradeNo(), response);
59 57 }
60   -
61   - @Override
62   - public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
63   - throw new UnsupportedOperationException("支付宝【Wap 网站】不支持转账操作");
64   - }
65 58 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java
... ... @@ -28,9 +28,6 @@ public enum PayChannelEnum {
28 28 ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class),
29 29 ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class),
30 30 ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class),
31   - // TODO @jason:是不是按照微信聊的,合并回 ALIPAY_PC;因为支付宝、微信都是多种支付方式,选择其中的一种即可;
32   - ALIPAY_TRANSFER("alipay_transfer", "支付宝转账", AlipayPayClientConfig.class),
33   -
34 31 MOCK("mock", "模拟支付", NonePayClientConfig.class),
35 32  
36 33 WALLET("wallet", "钱包支付", NonePayClientConfig.class);
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferTypeEnum.java
... ... @@ -34,8 +34,7 @@ public enum PayTransferTypeEnum implements IntArrayValuable {
34 34 return ARRAYS;
35 35 }
36 36  
37   - // TODO @jason:是不是 typeOf 更符合预期哈?
38   - public static PayTransferTypeEnum ofType(Integer type) {
  37 + public static PayTransferTypeEnum typeOf(Integer type) {
39 38 return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
40 39 }
41 40  
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
1 1 package cn.iocoder.yudao.module.pay.api.transfer.dto;
2 2  
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
3 5 import lombok.Data;
4 6  
5 7 import javax.validation.constraints.Min;
... ... @@ -23,7 +25,7 @@ public class PayTransferCreateReqDTO {
23 25 * 类型
24 26 */
25 27 @NotNull(message = "转账类型不能为空")
26   - // TODO @jason:枚举的校验
  28 + @InEnum(PayTransferTypeEnum.class)
27 29 private Integer type;
28 30  
29 31 /**
... ... @@ -35,14 +37,14 @@ public class PayTransferCreateReqDTO {
35 37 /**
36 38 * 转账金额,单位:分
37 39 */
38   - // TODO @jason:这个金额是不是非空哈
39 40 @Min(value = 1, message = "转账金额必须大于零")
  41 + @NotNull(message = "转账金额不能为空")
40 42 private Integer price;
41 43  
42   - // TODO @jason:这个标题,是不是不允许空呀
43 44 /**
44 45 * 转账标题
45 46 */
  47 + @NotEmpty(message = "转账标题不能为空")
46 48 private String title;
47 49  
48 50 @NotEmpty(message = "收款方信息不能为空")
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
... ... @@ -62,6 +62,7 @@ public interface ErrorCodeConstants {
62 62 ErrorCode WALLET_RECHARGE_PACKAGE_AND_PRICE_IS_EMPTY = new ErrorCode(1_007_008_011, "充值金额和充钱套餐不能同时为空");
63 63 ErrorCode WALLET_RECHARGE_PACKAGE_NOT_FOUND = new ErrorCode(1_007_008_012, "钱包充值套餐不存在");
64 64 ErrorCode WALLET_RECHARGE_PACKAGE_IS_DISABLE = new ErrorCode(1_007_008_013, "钱包充值套餐已禁用");
  65 + ErrorCode WALLET_RECHARGE_PACKAGE_NAME_EXISTS = new ErrorCode(1_007_008_014, "钱包充值套餐名称已存在");
65 66  
66 67 // ========== 转账模块 1-007-009-000 ==========
67 68 ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}");
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java
1 1 package cn.iocoder.yudao.module.pay.enums.member;
2 2  
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
3 4 import lombok.AllArgsConstructor;
4 5 import lombok.Getter;
5 6  
  7 +import java.util.Arrays;
  8 +
6 9 /**
7 10 * 钱包交易业务分类
8 11 *
... ... @@ -10,7 +13,7 @@ import lombok.Getter;
10 13 */
11 14 @AllArgsConstructor
12 15 @Getter
13   -public enum PayWalletBizTypeEnum {
  16 +public enum PayWalletBizTypeEnum implements IntArrayValuable {
14 17  
15 18 RECHARGE(1, "充值"),
16 19 RECHARGE_REFUND(2, "充值退款"),
... ... @@ -28,4 +31,10 @@ public enum PayWalletBizTypeEnum {
28 31 */
29 32 private final String description;
30 33  
  34 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PayWalletBizTypeEnum::getType).toArray();
  35 +
  36 + @Override
  37 + public int[] array() {
  38 + return ARRAYS;
  39 + }
31 40 }
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.enums.transfer;
  2 +
  3 +import cn.hutool.core.util.ArrayUtil;
  4 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Getter;
  7 +
  8 +import java.util.Arrays;
  9 +
  10 +/**
  11 + * 转账类型枚举
  12 + *
  13 + * @author jason
  14 + */
  15 +@AllArgsConstructor
  16 +@Getter
  17 +public enum PayTransferTypeEnum implements IntArrayValuable {
  18 +
  19 + ALIPAY_BALANCE(1, "支付宝余额"),
  20 + WX_BALANCE(2, "微信余额"),
  21 + BANK_CARD(3, "银行卡"),
  22 + WALLET_BALANCE(4, "钱包余额");
  23 +
  24 + public static final String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID";
  25 + public static final String ALIPAY_ACCOUNT_NAME = "ALIPAY_ACCOUNT_NAME";
  26 +
  27 + private final Integer type;
  28 + private final String name;
  29 +
  30 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PayTransferTypeEnum::getType).toArray();
  31 +
  32 + @Override
  33 + public int[] array() {
  34 + return ARRAYS;
  35 + }
  36 +
  37 + public static PayTransferTypeEnum typeOf(Integer type) {
  38 + return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
  39 + }
  40 +
  41 +}
... ...
yudao-module-pay/yudao-module-pay-biz/pom.xml
... ... @@ -24,6 +24,11 @@
24 24 <version>${revision}</version>
25 25 </dependency>
26 26  
  27 + <dependency>
  28 + <groupId>cn.iocoder.boot</groupId>
  29 + <artifactId>yudao-module-member-api</artifactId>
  30 + <version>${revision}</version>
  31 + </dependency>
27 32 <!-- 业务组件 -->
28 33 <dependency>
29 34 <groupId>cn.iocoder.boot</groupId>
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java
1 1 package cn.iocoder.yudao.module.pay.api.transfer;
2 2  
3 3 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
  4 +import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
4 5 import org.springframework.stereotype.Service;
5 6 import org.springframework.validation.annotation.Validated;
6 7  
  8 +import javax.annotation.Resource;
  9 +
7 10 /**
8 11 * 转账单 API 实现类
9 12 *
... ... @@ -12,11 +15,11 @@ import org.springframework.validation.annotation.Validated;
12 15 @Service
13 16 @Validated
14 17 public class PayTransferApiImpl implements PayTransferApi {
  18 + @Resource
  19 + private PayTransferService payTransferService;
15 20  
16 21 @Override
17 22 public Long createTransfer(PayTransferCreateReqDTO reqDTO) {
18   - // TODO @jason:貌似没实现噢
19   - return null;
  23 + return payTransferService.createTransfer(reqDTO);
20 24 }
21   -
22 25 }
23 26 \ No newline at end of file
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java
... ... @@ -17,11 +17,10 @@ import java.util.Map;
17 17 @Data
18 18 public class PayDemoTransferCreateReqVO {
19 19  
20   - // TODO @jason:这个字段,是不是叫 type 就好了。
21 20 @Schema(description = "转账类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 21 @NotNull(message = "转账类型不能为空")
23 22 @InEnum(PayTransferTypeEnum.class)
24   - private Integer transferType;
  23 + private Integer type;
25 24  
26 25 @NotNull(message = "转账金额不能为空")
27 26 @Min(value = 1, message = "转账金额必须大于零")
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/PayTransferController.java
... ... @@ -29,7 +29,7 @@ public class PayTransferController {
29 29  
30 30 @PostMapping("/submit")
31 31 @Operation(summary = "提交转账订单")
32   - // TODO @jason:权限的设置
  32 + // TODO @jason:权限的设置, 管理后台页面加的时候加一下
33 33 public CommonResult<PayTransferSubmitRespVO> submitPayTransfer(@Valid @RequestBody PayTransferSubmitReqVO reqVO) {
34 34 PayTransferSubmitRespVO respVO = payTransferService.submitTransfer(reqVO, getClientIP());
35 35 return success(respVO);
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletController.java
1 1 package cn.iocoder.yudao.module.pay.controller.admin.wallet;
2 2  
  3 +import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.hutool.core.util.StrUtil;
3 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  8 +import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
  9 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
5 10 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO;
6 11 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletRespVO;
7 12 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletUserReqVO;
... ... @@ -19,8 +24,14 @@ import org.springframework.web.bind.annotation.RestController;
19 24  
20 25 import javax.annotation.Resource;
21 26 import javax.validation.Valid;
  27 +import java.util.List;
  28 +import java.util.Map;
  29 +import java.util.Set;
22 30  
  31 +import static cn.iocoder.yudao.framework.common.enums.UserTypeEnum.MEMBER;
23 32 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  34 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
24 35  
25 36 @Tag(name = "管理后台 - 用户钱包")
26 37 @RestController
... ... @@ -31,21 +42,37 @@ public class PayWalletController {
31 42  
32 43 @Resource
33 44 private PayWalletService payWalletService;
  45 + @Resource
  46 + private MemberUserApi memberUserApi;
34 47  
35 48 @GetMapping("/get")
36 49 @PreAuthorize("@ss.hasPermission('pay:wallet:query')")
37 50 @Operation(summary = "获得用户钱包明细")
38 51 public CommonResult<PayWalletRespVO> getWallet(PayWalletUserReqVO reqVO) {
39   - PayWalletDO wallet = payWalletService.getOrCreateWallet(reqVO.getUserId(), reqVO.getUserType());
40   - return success(PayWalletConvert.INSTANCE.convert02(wallet));
  52 + PayWalletDO wallet = payWalletService.getOrCreateWallet(reqVO.getUserId(), MEMBER.getValue());
  53 + MemberUserRespDTO memberUser = memberUserApi.getUser(reqVO.getUserId());
  54 + String nickname = memberUser == null ? "" : memberUser.getNickname();
  55 + String avatar = memberUser == null ? "" : memberUser.getAvatar();
  56 + return success(PayWalletConvert.INSTANCE.convert02(nickname, avatar, wallet));
41 57 }
42 58  
43 59 @GetMapping("/page")
44 60 @Operation(summary = "获得会员钱包分页")
45 61 @PreAuthorize("@ss.hasPermission('pay:wallet:query')")
46 62 public CommonResult<PageResult<PayWalletRespVO>> getWalletPage(@Valid PayWalletPageReqVO pageVO) {
47   - PageResult<PayWalletDO> pageResult = payWalletService.getWalletPage(pageVO);
48   - return success(PayWalletConvert.INSTANCE.convertPage(pageResult));
  63 + if (StrUtil.isNotEmpty(pageVO.getNickname())) {
  64 + Set<Long> userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageVO.getNickname()),
  65 + MemberUserRespDTO::getId);
  66 + pageVO.setUserIds(userIds);
  67 + }
  68 + // 暂时支持查询 userType 会员类型。管理员类型还不知道使用场景
  69 + PageResult<PayWalletDO> pageResult = payWalletService.getWalletPage(MEMBER.getValue(),pageVO);
  70 + if (CollectionUtil.isEmpty(pageResult.getList())) {
  71 + return success(new PageResult<>(pageResult.getTotal()));
  72 + }
  73 + List<Long> userIds = convertList(pageResult.getList(), PayWalletDO::getUserId);
  74 + Map<Long, MemberUserRespDTO> userMap = convertMap(memberUserApi.getUserList(userIds),MemberUserRespDTO::getId);
  75 + return success(PayWalletConvert.INSTANCE.convertPage(pageResult, userMap));
49 76 }
50 77  
51 78 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletTransactionController.java
... ... @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.pay.service.wallet.PayWalletTransactionService;
10 10 import io.swagger.v3.oas.annotations.Operation;
11 11 import io.swagger.v3.oas.annotations.tags.Tag;
12 12 import lombok.extern.slf4j.Slf4j;
  13 +import org.springframework.security.access.prepost.PreAuthorize;
13 14 import org.springframework.validation.annotation.Validated;
14 15 import org.springframework.web.bind.annotation.GetMapping;
15 16 import org.springframework.web.bind.annotation.RequestMapping;
... ... @@ -32,7 +33,7 @@ public class PayWalletTransactionController {
32 33  
33 34 @GetMapping("/page")
34 35 @Operation(summary = "获得钱包流水分页")
35   - // TODO @jason:权限校验,缺一个
  36 + @PreAuthorize("@ss.hasPermission('pay:wallet:query')")
36 37 public CommonResult<PageResult<PayWalletTransactionRespVO>> getWalletTransactionPage(
37 38 @Valid PayWalletTransactionPageReqVO pageReqVO) {
38 39 PageResult<PayWalletTransactionDO> result = payWalletTransactionService.getWalletTransactionPage(pageReqVO);
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/rechargepackage/WalletRechargePackagePageReqVO.java
... ... @@ -20,14 +20,6 @@ public class WalletRechargePackagePageReqVO extends PageParam {
20 20 @Schema(description = "套餐名", example = "李四")
21 21 private String name;
22 22  
23   - // TODO @jason:payPrice 和 bonusPrice 可以去掉。。。一般太少检索啦;
24   -
25   - @Schema(description = "支付金额", example = "16454")
26   - private Integer payPrice;
27   -
28   - @Schema(description = "赠送金额", example = "20887")
29   - private Integer bonusPrice;
30   -
31 23 @Schema(description = "状态", example = "2")
32 24 private Integer status;
33 25  
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/wallet/PayWalletPageReqVO.java
1 1 package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4   -import cn.iocoder.yudao.framework.common.validation.InEnum;
5   -import lombok.*;
6   -import io.swagger.v3.oas.annotations.media.Schema;
7 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
8 8 import org.springframework.format.annotation.DateTimeFormat;
  9 +
9 10 import java.time.LocalDateTime;
  11 +import java.util.Collection;
10 12  
11 13 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
12 14  
... ... @@ -16,12 +18,11 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
16 18 @ToString(callSuper = true)
17 19 public class PayWalletPageReqVO extends PageParam {
18 20  
19   - @Schema(description = "用户编号", example = "14138")
20   - private Long userId;
  21 + @Schema(description = "用户昵称", example = "李四")
  22 + private String nickname;
21 23  
22   - @Schema(description = "用户类型", example = "1")
23   - @InEnum(UserTypeEnum.class)
24   - private Integer userType;
  24 + @Schema(description = "用户编号", example = "[1,2]")
  25 + private Collection<Long> userIds;
25 26  
26 27 @Schema(description = "创建时间")
27 28 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/wallet/PayWalletRespVO.java
... ... @@ -19,6 +19,10 @@ public class PayWalletRespVO extends PayWalletBaseVO {
19 19 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
20 20 private LocalDateTime createTime;
21 21  
22   - // TODO @jason:要不把用户昵称 + avatar 也读取下?
  22 + @Schema(description = "用户昵称")
  23 + private String nickname;
  24 +
  25 + @Schema(description = "用户头像")
  26 + private String avatar;
23 27  
24 28 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/wallet/PayWalletUserReqVO.java
1 1 package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4   -import cn.iocoder.yudao.framework.common.validation.InEnum;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
7 5  
... ... @@ -14,10 +12,4 @@ public class PayWalletUserReqVO {
14 12 @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
15 13 @NotNull(message = "用户编号不能为空")
16 14 private Long userId;
17   -
18   - @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19   - @NotNull(message = "用户类型不能为空")
20   - @InEnum(value = UserTypeEnum.class, message = "用户类型必须是 {value}")
21   - private Integer userType;
22   -
23 15 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletRechargeController.java
... ... @@ -19,6 +19,7 @@ import javax.annotation.Resource;
19 19 import javax.validation.Valid;
20 20  
21 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
22 23 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
23 24 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
24 25  
... ... @@ -35,9 +36,9 @@ public class AppPayWalletRechargeController {
35 36 @PostMapping("/create")
36 37 @Operation(summary = "创建钱包充值记录(发起充值)")
37 38 public CommonResult<AppPayWalletRechargeCreateRespVO> createWalletRecharge(
38   - @Valid @RequestBody AppPayWalletRechargeCreateReqVO reqVO) {
  39 + @Valid @RequestBody AppPayWalletRechargeCreateReqVO reqVO) {
39 40 PayWalletRechargeDO walletRecharge = walletRechargeService.createWalletRecharge(
40   - getLoginUserId(), getLoginUserType(), reqVO);
  41 + getLoginUserId(), getLoginUserType(), getClientIP(), reqVO);
41 42 return success(PayWalletRechargeConvert.INSTANCE.convert(walletRecharge));
42 43 }
43 44  
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java
... ... @@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge;
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
5 5  
  6 +import javax.validation.constraints.AssertTrue;
6 7 import javax.validation.constraints.Min;
  8 +import java.util.Objects;
7 9  
8 10 @Schema(description = "用户 APP - 创建钱包充值 Request VO")
9 11 @Data
... ... @@ -16,6 +18,8 @@ public class AppPayWalletRechargeCreateReqVO {
16 18 @Schema(description = "充值套餐编号", example = "1024")
17 19 private Long packageId;
18 20  
19   - // TODO @jaosn:写个 AssertTrue 的校验方法,payPrice 和 packageId 必须二选一
20   -
  21 + @AssertTrue(message = "充值金额和充钱套餐不能同时为空")
  22 + public boolean validatePayPriceAndPackageId() {
  23 + return Objects.nonNull(payPrice) || Objects.nonNull(packageId);
  24 + }
21 25 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java
... ... @@ -11,9 +11,9 @@ import org.mapstruct.factory.Mappers;
11 11 public interface PayTransferConvert {
12 12  
13 13 PayTransferConvert INSTANCE = Mappers.getMapper(PayTransferConvert.class);
14   -
  14 + @Mapping(source = "title", target = "subject")
15 15 PayTransferDO convert(PayTransferCreateReqDTO dto);
16   - @Mapping(source = "transferType", target = "type")
  16 +
17 17 PayTransferCreateReqDTO convert(PayDemoTransferCreateReqVO vo);
18 18  
19 19 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java
1 1 package cn.iocoder.yudao.module.pay.convert.wallet;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  5 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
4 6 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletRespVO;
5 7 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO;
6 8 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
7 9 import org.mapstruct.Mapper;
8 10 import org.mapstruct.factory.Mappers;
9 11  
  12 +import java.util.Map;
  13 +
10 14 @Mapper
11 15 public interface PayWalletConvert {
12 16  
... ... @@ -14,8 +18,18 @@ public interface PayWalletConvert {
14 18  
15 19 AppPayWalletRespVO convert(PayWalletDO bean);
16 20  
17   - PayWalletRespVO convert02(PayWalletDO bean);
  21 + PayWalletRespVO convert02(String nickname,String avatar, PayWalletDO bean);
18 22  
19 23 PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page);
20 24  
  25 + default PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page, Map<Long, MemberUserRespDTO> userMap){
  26 + PageResult<PayWalletRespVO> pageResult = convertPage(page);
  27 + pageResult.getList().forEach( wallet -> MapUtils.findAndThen(userMap, wallet.getUserId(),
  28 + user -> {
  29 + wallet.setNickname(user.getNickname());
  30 + wallet.setAvatar(user.getAvatar());
  31 + }));
  32 + return pageResult;
  33 + }
  34 +
21 35 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java
... ... @@ -64,11 +64,11 @@ public class PayTransferDO extends BaseDO {
64 64 * 例如说,内部系统 A 的订单号,需要保证每个 PayAppDO 唯一
65 65 */
66 66 private String merchantOrderId;
67   - // TODO @jason:这个字段,要不要改成 subject。。。和 payorderdo 保持一致;哈哈哈,我也忘记为啥当时选了这个名字了。。。
  67 +
68 68 /**
69 69 * 转账标题
70 70 */
71   - private String title;
  71 + private String subject;
72 72  
73 73 // ========== 转账相关字段 ==========
74 74 /**
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferExtensionDO.java
... ... @@ -11,6 +11,7 @@ import lombok.Data;
11 11 import java.util.Map;
12 12  
13 13 // TODO @jason:转账是不是类似 refund,不用拓展单呀?支付做拓展单的原因,是因为它存在不确定性,可以切换多种;转账和退款,都是明确方式的;
  14 +// @芋艿 转账是不是也存在多种方式。 例如转账到银行卡。 可以使用微信,也可以使用支付宝。 支付宝账号余额不够,可以切换到微信
14 15 /**
15 16 * 转账拓展单 DO
16 17 *
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java
... ... @@ -17,10 +17,10 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
17 17 PayWalletDO::getUserType, userType);
18 18 }
19 19  
20   - default PageResult<PayWalletDO> selectPage(PayWalletPageReqVO reqVO) {
  20 + default PageResult<PayWalletDO> selectPage(Integer userType, PayWalletPageReqVO reqVO) {
21 21 return selectPage(reqVO, new LambdaQueryWrapperX<PayWalletDO>()
22   - .eqIfPresent(PayWalletDO::getUserId, reqVO.getUserId())
23   - .eqIfPresent(PayWalletDO::getUserType, reqVO.getUserType())
  22 + .inIfPresent(PayWalletDO::getUserId, reqVO.getUserIds())
  23 + .eqIfPresent(PayWalletDO::getUserType, userType)
24 24 .betweenIfPresent(PayWalletDO::getCreateTime, reqVO.getCreateTime())
25 25 .orderByDesc(PayWalletDO::getId));
26 26 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletRechargePackageMapper.java
... ... @@ -12,14 +12,14 @@ import org.apache.ibatis.annotations.Mapper;
12 12 public interface PayWalletRechargePackageMapper extends BaseMapperX<PayWalletRechargePackageDO> {
13 13  
14 14 default PageResult<PayWalletRechargePackageDO> selectPage(WalletRechargePackagePageReqVO reqVO) {
15   - // TODO @jason:排序按照充值金额
16 15 return selectPage(reqVO, new LambdaQueryWrapperX<PayWalletRechargePackageDO>()
17 16 .likeIfPresent(PayWalletRechargePackageDO::getName, reqVO.getName())
18   - .eqIfPresent(PayWalletRechargePackageDO::getPayPrice, reqVO.getPayPrice())
19   - .eqIfPresent(PayWalletRechargePackageDO::getBonusPrice, reqVO.getBonusPrice())
20 17 .eqIfPresent(PayWalletRechargePackageDO::getStatus, reqVO.getStatus())
21 18 .betweenIfPresent(PayWalletRechargePackageDO::getCreateTime, reqVO.getCreateTime())
22   - .orderByDesc(PayWalletRechargePackageDO::getId));
  19 + .orderByDesc(PayWalletRechargePackageDO::getPayPrice));
23 20 }
24 21  
  22 + default PayWalletRechargePackageDO selectByName(String name){
  23 + return selectOne(PayWalletRechargePackageDO::getName, name);
  24 + }
25 25 }
26 26 \ No newline at end of file
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
... ... @@ -46,10 +46,10 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
46 46 @Transactional(rollbackFor = Exception.class)
47 47 public Long createDemoTransfer(Long userId, @Valid PayDemoTransferCreateReqVO vo) {
48 48 // 1 校验收款账号
49   - validatePayeeInfo(vo.getTransferType(), vo.getPayeeInfo());
  49 + validatePayeeInfo(vo.getType(), vo.getPayeeInfo());
50 50  
51 51 // 2 保存示例转账业务表
52   - PayDemoTransferDO demoTransfer = new PayDemoTransferDO().setUserId(userId).setType(vo.getTransferType())
  52 + PayDemoTransferDO demoTransfer = new PayDemoTransferDO().setUserId(userId).setType(vo.getType())
53 53 .setPrice(vo.getPrice()).setPayeeInfo(vo.getPayeeInfo())
54 54 .setTransferStatus(WAITING.getStatus());
55 55 demoTransferMapper.insert(demoTransfer);
... ... @@ -65,8 +65,9 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
65 65 }
66 66  
67 67 // TODO @jason:可以参考 AppBrokerageWithdrawCreateReqVO 搞下字段哈,进行校验
  68 + // @jason payeeinfo 字段确定改一下
68 69 private void validatePayeeInfo(Integer transferType, Map<String, String> payeeInfo) {
69   - PayTransferTypeEnum transferTypeEnum = ofType(transferType);
  70 + PayTransferTypeEnum transferTypeEnum = typeOf(transferType);
70 71 switch (transferTypeEnum) {
71 72 case ALIPAY_BALANCE: {
72 73 if (StrUtil.isEmpty(MapUtil.getStr(payeeInfo, ALIPAY_LOGON_ID))) {
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
... ... @@ -79,7 +79,7 @@ public class PayTransferServiceImpl implements PayTransferService {
79 79 // 3. 调用三方渠道发起转账
80 80 PayTransferUnifiedReqDTO transferUnifiedReq = new PayTransferUnifiedReqDTO()
81 81 .setOutTransferNo(transferExtension.getNo()).setPrice(transfer.getPrice())
82   - .setType(transfer.getType()).setTitle(transfer.getTitle())
  82 + .setType(transfer.getType()).setTitle(transfer.getSubject())
83 83 .setPayeeInfo(transfer.getPayeeInfo()).setUserIp(userIp)
84 84 .setChannelExtras(reqVO.getChannelExtras());
85 85 PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
... ... @@ -214,11 +214,11 @@ public class PayTransferServiceImpl implements PayTransferService {
214 214 }
215 215  
216 216 private void validateChannelCodeAndTypeMatch(String channelCode, Integer type) {
217   - PayTransferTypeEnum transferType = PayTransferTypeEnum.ofType(type);
  217 + PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);
218 218 PayChannelEnum payChannel = PayChannelEnum.getByCode(channelCode);
219 219 switch (transferType) {
220 220 case ALIPAY_BALANCE: {
221   - if (payChannel != PayChannelEnum.ALIPAY_TRANSFER) {
  221 + if (!payChannel.getCode().startsWith("alipay")) {
222 222 throw exception(PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH);
223 223 }
224 224 break;
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargePackageServiceImpl.java
1 1 package cn.iocoder.yudao.module.pay.service.wallet;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.collection.ListUtil;
  3 +import cn.hutool.core.util.StrUtil;
5 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 6 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.rechargepackage.WalletRechargePackageCreateReqVO;
... ... @@ -14,9 +13,6 @@ import org.springframework.stereotype.Service;
14 13  
15 14 import javax.annotation.Resource;
16 15  
17   -import java.util.Collection;
18   -import java.util.List;
19   -
20 16 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 17 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
22 18  
... ... @@ -50,6 +46,8 @@ public class PayWalletRechargePackageServiceImpl implements PayWalletRechargePac
50 46  
51 47 @Override
52 48 public Long createWalletRechargePackage(WalletRechargePackageCreateReqVO createReqVO) {
  49 + // 校验套餐名是否唯一
  50 + validateRechargePackageNameUnique(null, createReqVO.getName());
53 51 // 插入
54 52 PayWalletRechargePackageDO walletRechargePackage = WalletRechargePackageConvert.INSTANCE.convert(createReqVO);
55 53 walletRechargePackageMapper.insert(walletRechargePackage);
... ... @@ -57,16 +55,33 @@ public class PayWalletRechargePackageServiceImpl implements PayWalletRechargePac
57 55 return walletRechargePackage.getId();
58 56 }
59 57  
60   - // TODO @jason:校验下,套餐名唯一
61 58 @Override
62 59 public void updateWalletRechargePackage(WalletRechargePackageUpdateReqVO updateReqVO) {
63 60 // 校验存在
64 61 validateWalletRechargePackageExists(updateReqVO.getId());
  62 + // 校验套餐名是否唯一
  63 + validateRechargePackageNameUnique(updateReqVO.getId(), updateReqVO.getName());
65 64 // 更新
66 65 PayWalletRechargePackageDO updateObj = WalletRechargePackageConvert.INSTANCE.convert(updateReqVO);
67 66 walletRechargePackageMapper.updateById(updateObj);
68 67 }
69 68  
  69 + private void validateRechargePackageNameUnique(Long id, String name) {
  70 + if (StrUtil.isBlank(name)) {
  71 + return;
  72 + }
  73 + PayWalletRechargePackageDO rechargePackage = walletRechargePackageMapper.selectByName(name);
  74 + if (rechargePackage == null) {
  75 + return ;
  76 + }
  77 + if (id == null) {
  78 + throw exception(WALLET_RECHARGE_PACKAGE_NAME_EXISTS);
  79 + }
  80 + if (!id.equals(rechargePackage.getId())) {
  81 + throw exception(WALLET_RECHARGE_PACKAGE_NAME_EXISTS);
  82 + }
  83 + }
  84 +
70 85 @Override
71 86 public void deleteWalletRechargePackage(Long id) {
72 87 // 校验存在
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java
... ... @@ -16,9 +16,10 @@ public interface PayWalletRechargeService {
16 16 * @param userId 用户 id
17 17 * @param userType 用户类型
18 18 * @param createReqVO 钱包充值请求 VO
  19 + * @param userIp 用户Ip
19 20 * @return 钱包充值记录
20 21 */
21   - PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType,
  22 + PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, String userIp,
22 23 AppPayWalletRechargeCreateReqVO createReqVO);
23 24  
24 25 /**
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
... ... @@ -29,7 +29,6 @@ import static cn.hutool.core.util.ObjectUtil.notEqual;
29 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
30 30 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
31 31 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
32   -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
33 32 import static cn.iocoder.yudao.module.pay.convert.wallet.PayWalletRechargeConvert.INSTANCE;
34 33 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
35 34 import static cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum.*;
... ... @@ -63,13 +62,13 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
63 62  
64 63 @Override
65 64 @Transactional(rollbackFor = Exception.class)
66   - public PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType,
  65 + public PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, String userIp,
67 66 AppPayWalletRechargeCreateReqVO reqVO) {
68   - // 1.1 校验参数 TODO @jason:AppPayWalletRechargeCreateReqVO 看下校验;
  67 +
69 68 if (Objects.isNull(reqVO.getPayPrice()) && Objects.isNull(reqVO.getPackageId())) {
  69 + // TODO @jason @AssertTrue 貌似没有效果。需要查下原因
70 70 throw exception(WALLET_RECHARGE_PACKAGE_AND_PRICE_IS_EMPTY);
71 71 }
72   -
73 72 // 1.1 计算充值金额
74 73 int payPrice;
75 74 int bonusPrice = 0;
... ... @@ -87,7 +86,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
87 86  
88 87 // 2.1 创建支付单
89 88 Long payOrderId = payOrderService.createOrder(new PayOrderCreateReqDTO()
90   - .setAppId(WALLET_PAY_APP_ID).setUserIp(getClientIP()) // TODO @jason:clientIp 从 controller 传递进来噢
  89 + .setAppId(WALLET_PAY_APP_ID).setUserIp(userIp)
91 90 .setMerchantOrderId(recharge.getId().toString()) // 业务的订单编号
92 91 .setSubject(WALLET_RECHARGE_ORDER_SUBJECT).setBody("")
93 92 .setPrice(recharge.getPayPrice())
... ... @@ -181,7 +180,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
181 180 // 退款失败
182 181 if (PayRefundStatusRespEnum.isFailure(payRefund.getStatus())) {
183 182 // 2.2 解冻余额
184   - payWalletService.unFreezePrice(walletRecharge.getWalletId(), walletRecharge.getTotalPrice());
  183 + payWalletService.unfreezePrice(walletRecharge.getWalletId(), walletRecharge.getTotalPrice());
185 184  
186 185 updateObj.setRefundStatus(FAILURE.getStatus());
187 186 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
... ... @@ -37,7 +37,7 @@ public interface PayWalletService {
37 37 * @param pageReqVO 分页查询
38 38 * @return 会员钱包分页
39 39 */
40   - PageResult<PayWalletDO> getWalletPage(PayWalletPageReqVO pageReqVO);
  40 + PageResult<PayWalletDO> getWalletPage(Integer userType, PayWalletPageReqVO pageReqVO);
41 41  
42 42 /**
43 43 * 钱包订单支付
... ... @@ -90,13 +90,12 @@ public interface PayWalletService {
90 90 */
91 91 void freezePrice(Long id, Integer price);
92 92  
93   - // TODO @jason:unfreeze 是单词哈,f 不用大写
94 93 /**
95 94 * 解冻钱包余额
96 95 *
97 96 * @param id 钱包编号
98 97 * @param price 解冻金额
99 98 */
100   - void unFreezePrice(Long id, Integer price);
  99 + void unfreezePrice(Long id, Integer price);
101 100  
102 101 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
... ... @@ -63,8 +63,8 @@ public class PayWalletServiceImpl implements PayWalletService {
63 63 }
64 64  
65 65 @Override
66   - public PageResult<PayWalletDO> getWalletPage(PayWalletPageReqVO pageReqVO) {
67   - return walletMapper.selectPage(pageReqVO);
  66 + public PageResult<PayWalletDO> getWalletPage(Integer userType,PayWalletPageReqVO pageReqVO) {
  67 + return walletMapper.selectPage(userType, pageReqVO);
68 68 }
69 69  
70 70 @Override
... ... @@ -196,7 +196,7 @@ public class PayWalletServiceImpl implements PayWalletService {
196 196 }
197 197  
198 198 @Override
199   - public void unFreezePrice(Long id, Integer price) {
  199 + public void unfreezePrice(Long id, Integer price) {
200 200 int updateCounts = walletMapper.unFreezePrice(id, price);
201 201 if (updateCounts == 0) {
202 202 throw exception(WALLET_FREEZE_PRICE_NOT_ENOUGH);
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java
... ... @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
12 12 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO;
13 13 import lombok.extern.slf4j.Slf4j;
14 14 import org.springframework.stereotype.Service;
  15 +import org.springframework.validation.annotation.Validated;
15 16  
16 17 import javax.annotation.Resource;
17 18  
... ... @@ -22,6 +23,7 @@ import javax.annotation.Resource;
22 23 */
23 24 @Service
24 25 @Slf4j
  26 +@Validated
25 27 public class PayWalletTransactionServiceImpl implements PayWalletTransactionService {
26 28  
27 29 /**
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/WalletTransactionCreateReqBO.java
1 1 package cn.iocoder.yudao.module.pay.service.wallet.bo;
2 2  
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
3 4 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
4 5 import lombok.Data;
5 6  
  7 +import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +
6 10 /**
7 11 * 创建钱包流水 BO
8 12 *
... ... @@ -11,12 +15,11 @@ import lombok.Data;
11 15 @Data
12 16 public class WalletTransactionCreateReqBO {
13 17  
14   - // TODO @jason:bo 的话,最好加个参数校验哈;
15   -
16 18 /**
17 19 * 钱包编号
18 20 *
19 21 */
  22 + @NotNull(message = "钱包编号不能为空")
20 23 private Long walletId;
21 24  
22 25 /**
... ... @@ -24,11 +27,13 @@ public class WalletTransactionCreateReqBO {
24 27 *
25 28 * 正值表示余额增加,负值表示余额减少
26 29 */
  30 + @NotNull(message = "交易金额不能为空")
27 31 private Integer price;
28 32  
29 33 /**
30 34 * 交易后余额,单位分
31 35 */
  36 + @NotNull(message = "交易后余额不能为空")
32 37 private Integer balance;
33 38  
34 39 /**
... ... @@ -36,15 +41,19 @@ public class WalletTransactionCreateReqBO {
36 41 *
37 42 * 枚举 {@link PayWalletBizTypeEnum#getType()}
38 43 */
  44 + @NotNull(message = "关联业务分类不能为空")
  45 + @InEnum(PayWalletBizTypeEnum.class)
39 46 private Integer bizType;
40 47  
41 48 /**
42 49 * 关联业务编号
43 50 */
  51 + @NotEmpty(message = "关联业务编号不能为空")
44 52 private String bizId;
45 53  
46 54 /**
47 55 * 流水说明
48 56 */
  57 + @NotEmpty(message = "流水说明不能为空")
49 58 private String title;
50 59 }
... ...