Commit 89e847c8cd044ccc4187c40043d4ced04a32b985

Authored by jason
1 parent db0fbf05

钱包,转账 review 修改

Showing 32 changed files with 205 additions and 82 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-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,6 +65,7 @@ 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 70 PayTransferTypeEnum transferTypeEnum = typeOf(transferType);
70 71 switch (transferTypeEnum) {
... ...
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);
... ...
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 }
... ...