Commit cddeb37289ec192fc7d912e697ddaf06b448522e

Authored by owen
2 parents 4eedf6ad 40e1a879

Merge remote-tracking branch 'origin/feature/mall_product' into brokerate

# Conflicts:
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java
Showing 84 changed files with 1006 additions and 580 deletions
sql/mysql/pay_wallet.sql
@@ -8,8 +8,8 @@ CREATE TABLE `pay_wallet` @@ -8,8 +8,8 @@ CREATE TABLE `pay_wallet`
8 `user_id` bigint NOT NULL COMMENT '用户编号', 8 `user_id` bigint NOT NULL COMMENT '用户编号',
9 `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', 9 `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型',
10 `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分', 10 `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分',
11 - `total_expense` bigint NOT NULL DEFAULT 0 COMMENT '累计支出,单位分',  
12 - `total_recharge` bigint NOT NULL DEFAULT 0 COMMENT '累计充值,单位分', 11 + `total_expense` int NOT NULL DEFAULT 0 COMMENT '累计支出,单位分',
  12 + `total_recharge` int NOT NULL DEFAULT 0 COMMENT '累计充值,单位分',
13 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', 13 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
14 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 14 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
15 `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', 15 `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
@@ -41,7 +41,7 @@ public class CommonResult<T> implements Serializable { @@ -41,7 +41,7 @@ public class CommonResult<T> implements Serializable {
41 * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。 41 * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。
42 * 42 *
43 * @param result 传入的 result 对象 43 * @param result 传入的 result 对象
44 - * @param <T> 返回的泛型 44 + * @param <T> 返回的泛型
45 * @return 新的 CommonResult 对象 45 * @return 新的 CommonResult 对象
46 */ 46 */
47 public static <T> CommonResult<T> error(CommonResult<?> result) { 47 public static <T> CommonResult<T> error(CommonResult<?> result) {
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.bargain;
  2 +
  3 +/**
  4 + * 砍价活动 Api 接口
  5 + *
  6 + * @author HUIHUI
  7 + */
  8 +public interface BargainActivityApi {
  9 +
  10 + /**
  11 + * 更新砍价活动库存
  12 + *
  13 + * @param activityId 砍价活动编号
  14 + * @param count 购买数量
  15 + */
  16 + void updateBargainActivityStock(Long activityId, Integer count);
  17 +
  18 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/dto/BargainRecordCreateReqDTO.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.bargain.dto; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.bargain.dto;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
5 -import javax.validation.constraints.NotEmpty;  
6 import javax.validation.constraints.NotNull; 5 import javax.validation.constraints.NotNull;
7 6
8 // TODO @芋艿:这块要在看看 7 // TODO @芋艿:这块要在看看
@@ -40,17 +39,7 @@ public class BargainRecordCreateReqDTO { @@ -40,17 +39,7 @@ public class BargainRecordCreateReqDTO {
40 */ 39 */
41 @NotNull(message = "订单编号不能为空") 40 @NotNull(message = "订单编号不能为空")
42 private Long orderId; 41 private Long orderId;
43 - // TODO @puhui999:spuName、picUrl、 之类字段不用传递;  
44 - /**  
45 - * 商品名字  
46 - */  
47 - @NotEmpty(message = "商品名字不能为空")  
48 - private String spuName;  
49 - /**  
50 - * 商品图片  
51 - */  
52 - @NotEmpty(message = "商品图片不能为空")  
53 - private String picUrl; 42 +
54 /** 43 /**
55 * 砍价商品单价 44 * 砍价商品单价
56 */ 45 */
@@ -61,17 +50,7 @@ public class BargainRecordCreateReqDTO { @@ -61,17 +50,7 @@ public class BargainRecordCreateReqDTO {
61 */ 50 */
62 @NotNull(message = "商品原价不能为空") 51 @NotNull(message = "商品原价不能为空")
63 private Integer price; 52 private Integer price;
64 - // TODO @puhui999:nickname、avatar 不用传递,去查询;  
65 - /**  
66 - * 用户昵称  
67 - */  
68 - @NotEmpty(message = "用户昵称不能为空")  
69 - private String nickname;  
70 - /**  
71 - * 用户头像  
72 - */  
73 - @NotEmpty(message = "用户头像不能为空")  
74 - private String avatar; 53 +
75 /** 54 /**
76 * 开团状态:进行中 砍价成功 砍价失败 55 * 开团状态:进行中 砍价成功 砍价失败
77 */ 56 */
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
@@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.promotion.api.combination; @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; 3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
4 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; 4 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
5 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;  
6 5
7 import javax.validation.Valid; 6 import javax.validation.Valid;
  7 +import java.time.LocalDateTime;
8 import java.util.List; 8 import java.util.List;
9 9
10 // TODO @芋艿:后面也再撸撸这几个接口 10 // TODO @芋艿:后面也再撸撸这几个接口
@@ -51,13 +51,29 @@ public interface CombinationRecordApi { @@ -51,13 +51,29 @@ public interface CombinationRecordApi {
51 */ 51 */
52 void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount); 52 void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount);
53 53
54 - // TODO @puhui999:是不是搞成具体的方法,拼团成功,拼团失败,这种方法; 54 + /**
  55 + * 更新拼团状态为成功
  56 + *
  57 + * @param userId 用户编号
  58 + * @param orderId 订单编号
  59 + */
  60 + void updateRecordStatusToSuccess(Long userId, Long orderId);
55 61
56 /** 62 /**
57 - * 更新开团记录状态 63 + * 更新拼团状态为失败
58 * 64 *
59 - * @param reqDTO 请求 DTO 65 + * @param userId 用户编号
  66 + * @param orderId 订单编号
  67 + */
  68 + void updateRecordStatusToFailed(Long userId, Long orderId);
  69 +
  70 + /**
  71 + * 更新拼团状态为 进行中
  72 + *
  73 + * @param userId 用户编号
  74 + * @param orderId 订单编号
  75 + * @param startTime 开始时间
60 */ 76 */
61 - void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO); 77 + void updateRecordStatusToInProgress(Long userId, Long orderId, LocalDateTime startTime);
62 78
63 } 79 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordUpdateStatusReqDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.combination.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import javax.validation.constraints.NotNull;  
6 -import java.time.LocalDateTime;  
7 -  
8 -/**  
9 - * 拼团记录的更新状态 Request DTO  
10 - *  
11 - * @author HUIHUI  
12 - */  
13 -@Data  
14 -public class CombinationRecordUpdateStatusReqDTO {  
15 -  
16 - /**  
17 - * 用户编号  
18 - */  
19 - @NotNull(message = "用户编号不能为空")  
20 - private Long userId;  
21 -  
22 - /**  
23 - * 订单编号  
24 - */  
25 - @NotNull(message = "订单编号不能为空")  
26 - private Long orderId;  
27 -  
28 - /**  
29 - * 开团状态:正在开团 拼团成功 拼团失败  
30 - */  
31 - @NotNull(message = "开团状态不能为空")  
32 - private Integer status;  
33 -  
34 - /**  
35 - * 团开始时间  
36 - */  
37 - private LocalDateTime startTime;  
38 -  
39 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.seckill;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
  4 +
  5 +/**
  6 + * 秒杀活动 API 接口
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +public interface SeckillActivityApi {
  11 +
  12 + /**
  13 + * 更新秒杀库存
  14 + *
  15 + * @param updateStockReqDTO 请求
  16 + */
  17 + void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO);
  18 +
  19 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.seckill.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * 更新秒杀库存 request DTO
  9 + *
  10 + * @author HUIHUI
  11 + */
  12 +@Data
  13 +public class SeckillActivityUpdateStockReqDTO {
  14 +
  15 + // TODO @puhui999:参数校验
  16 +
  17 + // TODO @puhui999:秒杀的话,一次只能购买一种商品哈;不能多个哈;
  18 +
  19 + /**
  20 + * 活动编号
  21 + */
  22 + private Long activityId;
  23 + /**
  24 + * 总购买数量
  25 + */
  26 + private Integer count;
  27 + /**
  28 + * 活动商品
  29 + */
  30 + private List<Item> items;
  31 +
  32 + @Data
  33 + public static class Item {
  34 +
  35 + /**
  36 + * SPU 编号
  37 + */
  38 + private Long spuId;
  39 + /**
  40 + * SKU 编号
  41 + */
  42 + private Long skuId;
  43 + /**
  44 + * 购买数量
  45 + */
  46 + private Integer count;
  47 +
  48 + }
  49 +
  50 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -51,10 +51,11 @@ public interface ErrorCodeConstants { @@ -51,10 +51,11 @@ public interface ErrorCodeConstants {
51 51
52 // ========== 秒杀活动 1013008000 ========== 52 // ========== 秒杀活动 1013008000 ==========
53 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在"); 53 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
54 - ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动"); 54 + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
55 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); 55 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
56 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); 56 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
57 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); 57 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
  58 + ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "更新秒杀活动库存失败,原因秒杀库存不足");
58 59
59 // ========== 秒杀时段 1013009000 ========== 60 // ========== 秒杀时段 1013009000 ==========
60 ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); 61 ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.bargain;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO;
  4 +import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
  5 +import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
  6 +import org.springframework.stereotype.Service;
  7 +
  8 +import javax.annotation.Resource;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  11 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.BARGAIN_ACTIVITY_NOT_EXISTS;
  12 +
  13 +/**
  14 + * 砍价活动 Api 接口实现类
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@Service
  19 +public class BargainActivityApiImpl implements BargainActivityApi {
  20 +
  21 + @Resource
  22 + private BargainActivityService bargainActivityService;
  23 +
  24 + @Override
  25 + public void updateBargainActivityStock(Long activityId, Integer count) {
  26 + // TODO @puhui999:可以整个实现到 bargainActivityService 中
  27 + // 查询砍价活动
  28 + BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId);
  29 + if (activity == null) {
  30 + throw exception(BARGAIN_ACTIVITY_NOT_EXISTS);
  31 + }
  32 +
  33 + // 更新砍价库存
  34 + // TODO @puhui999:考虑下并发更新问题
  35 + BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO();
  36 + reqVO.setId(activityId);
  37 + reqVO.setStock(activity.getStock() - count);
  38 + bargainActivityService.updateBargainActivity(reqVO);
  39 + }
  40 +
  41 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
@@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.promotion.api.combination; @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; 3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
4 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; 4 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
5 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;  
6 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 5 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
7 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 6 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
8 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; 7 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
9 import org.springframework.stereotype.Service; 8 import org.springframework.stereotype.Service;
10 9
11 import javax.annotation.Resource; 10 import javax.annotation.Resource;
  11 +import java.time.LocalDateTime;
12 import java.util.List; 12 import java.util.List;
13 13
14 /** 14 /**
@@ -43,12 +43,19 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @@ -43,12 +43,19 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
43 } 43 }
44 44
45 @Override 45 @Override
46 - public void updateCombinationRecordStatus(CombinationRecordUpdateStatusReqDTO reqDTO) {  
47 - if (null == reqDTO.getStartTime()) {  
48 - recordService.updateCombinationRecordStatusByUserIdAndOrderId(reqDTO);  
49 - } else {  
50 - recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(reqDTO);  
51 - } 46 + public void updateRecordStatusToSuccess(Long userId, Long orderId) {
  47 + recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.SUCCESS.getStatus(), userId, orderId);
  48 + }
  49 +
  50 + @Override
  51 + public void updateRecordStatusToFailed(Long userId, Long orderId) {
  52 + recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.FAILED.getStatus(), userId, orderId);
  53 + }
  54 +
  55 + @Override
  56 + public void updateRecordStatusToInProgress(Long userId, Long orderId, LocalDateTime startTime) {
  57 + recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordStatusEnum.IN_PROGRESS.getStatus(),
  58 + userId, orderId, startTime);
52 } 59 }
53 60
54 } 61 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.seckill;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  4 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
  5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
  6 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
  7 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +import javax.annotation.Resource;
  11 +import java.util.ArrayList;
  12 +import java.util.HashMap;
  13 +import java.util.List;
  14 +import java.util.Map;
  15 +
  16 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  17 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_UPDATE_STOCK_FAIL;
  18 +
  19 +/**
  20 + * 秒杀活动接口 Api 接口实现类
  21 + *
  22 + * @author HUIHUI
  23 + */
  24 +@Service
  25 +public class SeckillActivityApiImpl implements SeckillActivityApi {
  26 +
  27 + @Resource
  28 + private SeckillActivityService activityService;
  29 +
  30 + // TODO @puhui:建议这块弄到 activityService 实现哈;
  31 + // TODO @puhui:这个方法,要考虑事务性
  32 + @Override
  33 + public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) {
  34 + // TODO @puhui999:长方法,最好有 1.1 1.2 2.1 这种步骤哈;
  35 + SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId());
  36 + if (seckillActivity.getStock() < updateStockReqDTO.getCount()) {
  37 + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
  38 + }
  39 + // 获取活动商品
  40 + // TODO @puhui999:在一个方法里,dos 和 dolist 最好保持一致,要么用 s,要么用 list 哈;
  41 + List<SeckillProductDO> productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId());
  42 + // TODO @puhui999:这个是不是搞成 CollectionUtils.convertMultiMap()
  43 + List<SeckillActivityUpdateStockReqDTO.Item> items = updateStockReqDTO.getItems();
  44 + Map<Long, List<Long>> map = new HashMap<>();
  45 + items.forEach(item -> {
  46 + if (map.containsKey(item.getSpuId())) {
  47 + List<Long> skuIds = map.get(item.getSpuId());
  48 + skuIds.add(item.getSkuId());
  49 + map.put(item.getSpuId(), skuIds);
  50 + } else {
  51 + List<Long> list = new ArrayList<>();
  52 + list.add(item.getSkuId());
  53 + map.put(item.getSpuId(), list);
  54 + }
  55 + });
  56 + // 过滤出购买的商品
  57 + // TODO @puhui999:productDOList 可以简化成 productList;一般来说,do 之类不用带着哈,在变量里;
  58 + List<SeckillProductDO> productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId()));
  59 + Map<Long, SeckillActivityUpdateStockReqDTO.Item> productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p);
  60 + // 检查活动商品库存是否充足
  61 + // TODO @puhui999:避免 b 这种无业务含义的变量;
  62 + boolean b = CollectionUtils.anyMatch(productDOList, item -> {
  63 + SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId());
  64 + return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0;
  65 + });
  66 + if (b) {
  67 + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
  68 + }
  69 + // TODO @puhui999:类似 doList,应该和下面的 update 逻辑粘的更紧密一点;so 在空行的时候,应该挪到 74 之后里去;甚至更合理,应该是 79 之后;说白了,逻辑要分块,每个模块涉及的代码要紧密在一起;
  70 + List<SeckillProductDO> doList = CollectionUtils.convertList(productDOList, item -> {
  71 + item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount());
  72 + return item;
  73 + });
  74 +
  75 + // 更新活动库存
  76 + // TODO @puhui999:考虑下并发更新
  77 + seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount());
  78 + seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount());
  79 + activityService.updateSeckillActivity(seckillActivity);
  80 + // 更新活动商品库存
  81 + activityService.updateSeckillActivityProductList(doList);
  82 + }
  83 +
  84 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java
@@ -9,6 +9,7 @@ import lombok.*; @@ -9,6 +9,7 @@ import lombok.*;
9 9
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
11 11
  12 +// TODO 芋艿:把字段的顺序,和 do 顺序对齐下
12 /** 13 /**
13 * 拼团记录 DO 14 * 拼团记录 DO
14 * 15 *
@@ -27,34 +28,28 @@ import java.time.LocalDateTime; @@ -27,34 +28,28 @@ import java.time.LocalDateTime;
27 @AllArgsConstructor 28 @AllArgsConstructor
28 public class CombinationRecordDO extends BaseDO { 29 public class CombinationRecordDO extends BaseDO {
29 30
  31 + /**
  32 + * 编号,主键自增
  33 + */
30 @TableId 34 @TableId
31 private Long id; 35 private Long id;
  36 +
32 /** 37 /**
33 * 拼团活动编号 38 * 拼团活动编号
  39 + *
  40 + * 关联 {@link CombinationActivityDO#getId()}
34 */ 41 */
35 private Long activityId; 42 private Long activityId;
36 /** 43 /**
37 - * SPU 编号  
38 - */  
39 - private Long spuId;  
40 - /**  
41 - * SKU 编号  
42 - */  
43 - private Long skuId;  
44 - /**  
45 - * 用户编号  
46 - */  
47 - private Long userId;  
48 - /**  
49 - * 订单编号 44 + * 拼团商品单价
  45 + *
  46 + * 冗余 {@link CombinationProductDO#getCombinationPrice()}
50 */ 47 */
51 - private Long orderId; 48 + private Integer combinationPrice;
52 /** 49 /**
53 - * 团长编号  
54 - *  
55 - * 关联 {@link CombinationRecordDO#getId()} 50 + * SPU 编号
56 */ 51 */
57 - private Long headId; 52 + private Long spuId;
58 /** 53 /**
59 * 商品名字 54 * 商品名字
60 */ 55 */
@@ -64,9 +59,14 @@ public class CombinationRecordDO extends BaseDO { @@ -64,9 +59,14 @@ public class CombinationRecordDO extends BaseDO {
64 */ 59 */
65 private String picUrl; 60 private String picUrl;
66 /** 61 /**
67 - * 拼团商品单价 62 + * SKU 编号
68 */ 63 */
69 - private Integer combinationPrice; 64 + private Long skuId;
  65 +
  66 + /**
  67 + * 用户编号
  68 + */
  69 + private Long userId;
70 /** 70 /**
71 * 用户昵称 71 * 用户昵称
72 */ 72 */
@@ -75,6 +75,13 @@ public class CombinationRecordDO extends BaseDO { @@ -75,6 +75,13 @@ public class CombinationRecordDO extends BaseDO {
75 * 用户头像 75 * 用户头像
76 */ 76 */
77 private String avatar; 77 private String avatar;
  78 +
  79 + /**
  80 + * 团长编号
  81 + *
  82 + * 关联 {@link CombinationRecordDO#getId()}
  83 + */
  84 + private Long headId;
78 /** 85 /**
79 * 开团状态 86 * 开团状态
80 * 87 *
@@ -82,15 +89,30 @@ public class CombinationRecordDO extends BaseDO { @@ -82,15 +89,30 @@ public class CombinationRecordDO extends BaseDO {
82 */ 89 */
83 private Integer status; 90 private Integer status;
84 /** 91 /**
  92 + * 订单编号
  93 + */
  94 + private Long orderId;
  95 + /**
  96 + * 开团需要人数
  97 + *
  98 + * 关联 {@link CombinationActivityDO#getUserSize()}
  99 + */
  100 + private Integer userSize;
  101 + /**
  102 + * 已加入拼团人数
  103 + */
  104 + private Integer userCount;
  105 + /**
85 * 是否虚拟成团 106 * 是否虚拟成团
86 */ 107 */
87 private Boolean virtualGroup; 108 private Boolean virtualGroup;
  109 +
88 /** 110 /**
89 - * 过期时间,单位:小时 111 + * 过期时间
90 * 112 *
91 - * 关联 {@link CombinationActivityDO#getLimitDuration()} 113 + * 基于 {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算
92 */ 114 */
93 - private Integer expireTime; 115 + private LocalDateTime expireTime;
94 /** 116 /**
95 * 开始时间 (订单付款后开始的时间) 117 * 开始时间 (订单付款后开始的时间)
96 */ 118 */
@@ -99,15 +121,5 @@ public class CombinationRecordDO extends BaseDO { @@ -99,15 +121,5 @@ public class CombinationRecordDO extends BaseDO {
99 * 结束时间(成团时间/失败时间) 121 * 结束时间(成团时间/失败时间)
100 */ 122 */
101 private LocalDateTime endTime; 123 private LocalDateTime endTime;
102 - /**  
103 - * 开团需要人数  
104 - *  
105 - * 关联 {@link CombinationActivityDO#getUserSize()}  
106 - */  
107 - private Integer userSize;  
108 - /**  
109 - * 已加入拼团人数  
110 - */  
111 - private Integer userCount;  
112 124
113 } 125 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
1 package cn.iocoder.yudao.module.promotion.service.combination; 1 package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; 3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
4 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;  
5 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; 4 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
6 5
  6 +import java.time.LocalDateTime;
7 import java.util.List; 7 import java.util.List;
8 8
9 /** 9 /**
@@ -16,9 +16,11 @@ public interface CombinationRecordService { @@ -16,9 +16,11 @@ public interface CombinationRecordService {
16 /** 16 /**
17 * 更新拼团状态 17 * 更新拼团状态
18 * 18 *
19 - * @param reqDTO 请求 DTO 19 + * @param status 状态
  20 + * @param userId 用户编号
  21 + * @param orderId 订单编号
20 */ 22 */
21 - void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO); 23 + void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId);
22 24
23 /** 25 /**
24 * 创建拼团记录 26 * 创建拼团记录
@@ -30,9 +32,12 @@ public interface CombinationRecordService { @@ -30,9 +32,12 @@ public interface CombinationRecordService {
30 /** 32 /**
31 * 更新拼团状态和开始时间 33 * 更新拼团状态和开始时间
32 * 34 *
33 - * @param reqDTO 请求 DTO 35 + * @param status 状态
  36 + * @param userId 用户编号
  37 + * @param orderId 订单编号
  38 + * @param startTime 开始时间
34 */ 39 */
35 - void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO); 40 + void updateRecordStatusAndStartTimeByUserIdAndOrderId(Integer status, Long userId, Long orderId, LocalDateTime startTime);
36 41
37 /** 42 /**
38 * 获得拼团状态 43 * 获得拼团状态
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.combination; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.combination;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; 5 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
6 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;  
7 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 6 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
8 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
9 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
@@ -21,6 +20,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU @@ -21,6 +20,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
21 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 20 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
22 21
23 // TODO 芋艿:等拼团记录做完,完整 review 下 22 // TODO 芋艿:等拼团记录做完,完整 review 下
  23 +
24 /** 24 /**
25 * 拼团记录 Service 实现类 25 * 拼团记录 Service 实现类
26 * 26 *
@@ -38,27 +38,27 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -38,27 +38,27 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
38 38
39 @Override 39 @Override
40 @Transactional(rollbackFor = Exception.class) 40 @Transactional(rollbackFor = Exception.class)
41 - public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { 41 + public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) {
42 // 校验拼团是否存在 42 // 校验拼团是否存在
43 - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); 43 + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
44 44
45 // 更新状态 45 // 更新状态
46 - recordDO.setStatus(reqDTO.getStatus()); 46 + recordDO.setStatus(status);
47 recordMapper.updateById(recordDO); 47 recordMapper.updateById(recordDO);
48 } 48 }
49 49
50 @Override 50 @Override
51 @Transactional(rollbackFor = Exception.class) 51 @Transactional(rollbackFor = Exception.class)
52 - public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {  
53 - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); 52 + public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Integer status, Long userId, Long orderId, LocalDateTime startTime) {
  53 + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
54 // 更新状态 54 // 更新状态
55 - recordDO.setStatus(reqDTO.getStatus()); 55 + recordDO.setStatus(status);
56 // 更新开始时间 56 // 更新开始时间
57 - recordDO.setStartTime(reqDTO.getStartTime()); 57 + recordDO.setStartTime(startTime);
58 recordMapper.updateById(recordDO); 58 recordMapper.updateById(recordDO);
59 59
60 // 更新拼团参入人数 60 // 更新拼团参入人数
61 - List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus()); 61 + List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), status);
62 if (CollUtil.isNotEmpty(recordDOs)) { 62 if (CollUtil.isNotEmpty(recordDOs)) {
63 recordDOs.forEach(item -> { 63 recordDOs.forEach(item -> {
64 item.setUserCount(recordDOs.size()); 64 item.setUserCount(recordDOs.size());
@@ -115,8 +115,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -115,8 +115,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
115 // 2. 创建拼团记录 115 // 2. 创建拼团记录
116 CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); 116 CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
117 record.setVirtualGroup(false); 117 record.setVirtualGroup(false);
118 - // TODO @puhui999:过期时间,应该是 Date 哈;  
119 - record.setExpireTime(activity.getLimitDuration()); 118 + record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration()));
120 record.setUserSize(activity.getUserSize()); 119 record.setUserSize(activity.getUserSize());
121 recordMapper.insert(record); 120 recordMapper.insert(record);
122 } 121 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
@@ -34,6 +34,20 @@ public interface SeckillActivityService { @@ -34,6 +34,20 @@ public interface SeckillActivityService {
34 void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); 34 void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO);
35 35
36 /** 36 /**
  37 + * 更新秒杀活动
  38 + *
  39 + * @param activityDO 秒杀活动
  40 + */
  41 + void updateSeckillActivity(SeckillActivityDO activityDO);
  42 +
  43 + /**
  44 + * 更新秒杀活动商品
  45 + *
  46 + * @param productList 活动商品列表
  47 + */
  48 + void updateSeckillActivityProductList(List<SeckillProductDO> productList);
  49 +
  50 + /**
37 * 关闭秒杀活动 51 * 关闭秒杀活动
38 * 52 *
39 * @param id 编号 53 * @param id 编号
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
@@ -79,8 +79,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -79,8 +79,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
79 * 1. 校验秒杀时段是否存在 79 * 1. 校验秒杀时段是否存在
80 * 2. 秒杀商品是否参加其它活动 80 * 2. 秒杀商品是否参加其它活动
81 * 81 *
82 - * @param configIds 秒杀时段数组  
83 - * @param spuId 商品 SPU 编号 82 + * @param configIds 秒杀时段数组
  83 + * @param spuId 商品 SPU 编号
84 * @param activityId 秒杀活动编号 84 * @param activityId 秒杀活动编号
85 */ 85 */
86 private void validateProductConflict(List<Long> configIds, Long spuId, Long activityId) { 86 private void validateProductConflict(List<Long> configIds, Long spuId, Long activityId) {
@@ -92,15 +92,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -92,15 +92,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
92 if (activityId != null) { // 排除自己 92 if (activityId != null) { // 排除自己
93 activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); 93 activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
94 } 94 }
95 - // TODO @puhui999:一个 spu,参与两个活动应该没关系,关键是活动时间不充能重叠;  
96 - // 2.2 过滤出所有 spuId 有交集的活动,判断是否存在重叠  
97 - List<SeckillActivityDO> activityDOs1 = filterList(activityList, s -> ObjectUtil.equal(s.getSpuId(), spuId));  
98 - if (isNotEmpty(activityDOs1)) {  
99 - throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);  
100 - }  
101 - // 2.3 过滤出所有 configIds 有交集的活动,判断是否存在重叠  
102 - List<SeckillActivityDO> activityDOs2 = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds));  
103 - if (isNotEmpty(activityDOs2)) { 95 + // 2.2 过滤出所有 configIds 有交集的活动,判断是否存在重叠
  96 + List<SeckillActivityDO> conflictActivityList = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds));
  97 + if (isNotEmpty(conflictActivityList)) {
104 throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); 98 throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
105 } 99 }
106 } 100 }
@@ -108,7 +102,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -108,7 +102,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
108 /** 102 /**
109 * 校验秒杀商品是否都存在 103 * 校验秒杀商品是否都存在
110 * 104 *
111 - * @param spuId 商品 SPU 编号 105 + * @param spuId 商品 SPU 编号
112 * @param products 秒杀商品 106 * @param products 秒杀商品
113 */ 107 */
114 private void validateProductExists(Long spuId, List<SeckillProductBaseVO> products) { 108 private void validateProductExists(Long spuId, List<SeckillProductBaseVO> products) {
@@ -150,11 +144,21 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -150,11 +144,21 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
150 updateSeckillProduct(updateObj, updateReqVO.getProducts()); 144 updateSeckillProduct(updateObj, updateReqVO.getProducts());
151 } 145 }
152 146
  147 + @Override
  148 + public void updateSeckillActivity(SeckillActivityDO activityDO) {
  149 + seckillActivityMapper.updateById(activityDO);
  150 + }
  151 +
  152 + @Override
  153 + public void updateSeckillActivityProductList(List<SeckillProductDO> productList) {
  154 + seckillProductMapper.updateBatch(productList);
  155 + }
  156 +
153 /** 157 /**
154 * 更新秒杀商品 158 * 更新秒杀商品
155 * 159 *
156 * @param activity 秒杀活动 160 * @param activity 秒杀活动
157 - * @param products 该活动的最新商品配置 161 + * @param products 该活动的最新商品配置
158 */ 162 */
159 private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductBaseVO> products) { 163 private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductBaseVO> products) {
160 // 第一步,对比新老数据,获得添加、修改、删除的列表 164 // 第一步,对比新老数据,获得添加、修改、删除的列表
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
1 package cn.iocoder.yudao.module.promotion.util; 1 package cn.iocoder.yudao.module.promotion.util;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
5 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 4 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
6 -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;  
7 5
8 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
9 -import java.util.List;  
10 -import java.util.Set;  
11 -import java.util.function.Function;  
12 -  
13 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
14 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;  
15 -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;  
16 7
17 /** 8 /**
18 * 活动工具类 9 * 活动工具类
@@ -31,21 +22,4 @@ public class PromotionUtils { @@ -31,21 +22,4 @@ public class PromotionUtils {
31 return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); 22 return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus();
32 } 23 }
33 24
34 - /**  
35 - * 校验商品 sku 是否都存在  
36 - *  
37 - * @param skus 数据库中的商品 skus  
38 - * @param products 需要校验的商品  
39 - * @param func 获取需要校验的商品的 skuId  
40 - */  
41 - public static <T> void validateProductSkuAllExists(List<ProductSkuRespDTO> skus, List<T> products, Function<T, Long> func) {  
42 - // 校验 sku 个数是否一致  
43 - Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);  
44 - Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);  
45 - // 校验 skuId 是否存在  
46 - if (anyMatch(skuIdsSet, s -> !skuIdsSet1.contains(s))) {  
47 - throw exception(SKU_NOT_EXISTS);  
48 - }  
49 - }  
50 -  
51 } 25 }
yudao-module-mall/yudao-module-trade-biz/pom.xml
@@ -86,6 +86,11 @@ @@ -86,6 +86,11 @@
86 <artifactId>yudao-spring-boot-starter-mybatis</artifactId> 86 <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
87 </dependency> 87 </dependency>
88 88
  89 + <dependency>
  90 + <groupId>cn.iocoder.boot</groupId>
  91 + <artifactId>yudao-spring-boot-starter-redis</artifactId>
  92 + </dependency>
  93 +
89 <!-- Test 测试相关 --> 94 <!-- Test 测试相关 -->
90 <dependency> 95 <dependency>
91 <groupId>cn.iocoder.boot</groupId> 96 <groupId>cn.iocoder.boot</groupId>
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java
@@ -20,13 +20,14 @@ public class BrokerageApiImpl implements BrokerageApi { @@ -20,13 +20,14 @@ public class BrokerageApiImpl implements BrokerageApi {
20 @Resource 20 @Resource
21 private BrokerageUserService brokerageUserService; 21 private BrokerageUserService brokerageUserService;
22 22
  23 + @Override
23 public BrokerageUserDTO getBrokerageUser(Long userId) { 24 public BrokerageUserDTO getBrokerageUser(Long userId) {
24 return BrokerageUserConvert.INSTANCE.convertDTO(brokerageUserService.getBrokerageUser(userId)); 25 return BrokerageUserConvert.INSTANCE.convertDTO(brokerageUserService.getBrokerageUser(userId));
25 } 26 }
26 27
27 @Override 28 @Override
28 public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { 29 public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) {
29 - return brokerageUserService.bindUser(userId, bindUserId, isNewUser); 30 + return brokerageUserService.bindBrokerageUser(userId, bindUserId, isNewUser);
30 } 31 }
31 32
32 } 33 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
@@ -76,6 +76,11 @@ public class TradeAfterSaleController { @@ -76,6 +76,11 @@ public class TradeAfterSaleController {
76 public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) { 76 public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
77 // 查询订单 77 // 查询订单
78 TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); 78 TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id);
  79 + // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理;
  80 +// if (afterSale == null) {
  81 +// return success(null, AFTER_SALE_NOT_FOUND.getMsg());
  82 +// }
  83 +
79 // 查询订单 84 // 查询订单
80 TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); 85 TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId());
81 // 查询订单项 86 // 查询订单项
@@ -92,7 +97,11 @@ public class TradeAfterSaleController { @@ -92,7 +97,11 @@ public class TradeAfterSaleController {
92 TradeAfterSaleLogRespDTO respVO = new TradeAfterSaleLogRespDTO(); 97 TradeAfterSaleLogRespDTO respVO = new TradeAfterSaleLogRespDTO();
93 respVO.setId((long) i); 98 respVO.setId((long) i);
94 respVO.setUserId((long) i); 99 respVO.setUserId((long) i);
95 - respVO.setUserType(1); 100 + respVO.setUserType(i % 2 == 0 ? 2 : 1);
  101 + // 模拟系统操作
  102 + if (i == 2) {
  103 + respVO.setUserType(3);
  104 + }
96 respVO.setAfterSaleId(id); 105 respVO.setAfterSaleId(id);
97 respVO.setOrderId((long) i); 106 respVO.setOrderId((long) i);
98 respVO.setOrderItemId((long) i); 107 respVO.setOrderItemId((long) i);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java
@@ -35,7 +35,7 @@ public class TradeAfterSaleDetailRespVO extends TradeAfterSaleBaseVO { @@ -35,7 +35,7 @@ public class TradeAfterSaleDetailRespVO extends TradeAfterSaleBaseVO {
35 /** 35 /**
36 * 售后日志 36 * 售后日志
37 */ 37 */
38 - private List<TradeAfterSaleLogRespVO> afterSaleLog; 38 + private List<TradeAfterSaleLogRespVO> logs;
39 39
40 @Schema(description = "管理后台 - 交易订单的详情的订单项目") 40 @Schema(description = "管理后台 - 交易订单的详情的订单项目")
41 @Data 41 @Data
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java
@@ -62,7 +62,7 @@ public class BrokerageUserController { @@ -62,7 +62,7 @@ public class BrokerageUserController {
62 @Operation(summary = "修改推广资格") 62 @Operation(summary = "修改推广资格")
63 @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") 63 @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')")
64 public CommonResult<Boolean> updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { 64 public CommonResult<Boolean> updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) {
65 - brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getEnabled()); 65 + brokerageUserService.updateBrokerageUserEnabled(updateReqVO.getId(), updateReqVO.getEnabled());
66 return success(true); 66 return success(true);
67 } 67 }
68 68
@@ -90,12 +90,12 @@ public class BrokerageUserController { @@ -90,12 +90,12 @@ public class BrokerageUserController {
90 // 合计分佣订单 90 // 合计分佣订单
91 Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap = convertMap(userIds, 91 Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap = convertMap(userIds,
92 userId -> userId, 92 userId -> userId,
93 - userId -> brokerageRecordService.summaryByUserIdAndBizTypeAndStatus(userId, 93 + userId -> brokerageRecordService.getUserBrokerageSummaryByUserId(userId,
94 BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus())); 94 BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus()));
95 // 合计推广用户数量 95 // 合计推广用户数量
96 Map<Long, Long> brokerageUserCountMap = convertMap(userIds, 96 Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
97 userId -> userId, 97 userId -> userId,
98 - userId -> brokerageUserService.getCountByBindUserId(userId)); 98 + userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId));
99 99
100 // todo 合计提现 100 // todo 合计提现
101 101
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java
@@ -19,7 +19,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @@ -19,7 +19,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO {
19 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 19 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
20 private LocalDateTime createTime; 20 private LocalDateTime createTime;
21 21
22 -  
23 // ========== 用户信息 ========== 22 // ========== 用户信息 ==========
24 23
25 @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") 24 @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
@@ -27,7 +26,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @@ -27,7 +26,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO {
27 @Schema(description = "用户昵称", example = "李四") 26 @Schema(description = "用户昵称", example = "李四")
28 private String nickname; 27 private String nickname;
29 28
30 -  
31 // ========== 推广信息 ========== 29 // ========== 推广信息 ==========
32 30
33 @Schema(description = "推广用户数量(一级)", example = "20019") 31 @Schema(description = "推广用户数量(一级)", example = "20019")
@@ -37,7 +35,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @@ -37,7 +35,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO {
37 @Schema(description = "推广订单金额", example = "20019") 35 @Schema(description = "推广订单金额", example = "20019")
38 private Integer brokerageOrderPrice; 36 private Integer brokerageOrderPrice;
39 37
40 -  
41 // ========== 提现信息 ========== 38 // ========== 提现信息 ==========
42 39
43 @Schema(description = "已提现金额", example = "20019") 40 @Schema(description = "已提现金额", example = "20019")
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java
@@ -67,6 +67,11 @@ public class TradeOrderController { @@ -67,6 +67,11 @@ public class TradeOrderController {
67 public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) { 67 public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
68 // 查询订单 68 // 查询订单
69 TradeOrderDO order = tradeOrderQueryService.getOrder(id); 69 TradeOrderDO order = tradeOrderQueryService.getOrder(id);
  70 + // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理;
  71 +// if (order == null) {
  72 +// return success(null, ORDER_NOT_FOUND.getMsg());
  73 +// }
  74 +
70 // 查询订单项 75 // 查询订单项
71 List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); 76 List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
72 // orderLog 77 // orderLog
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java
@@ -26,24 +26,23 @@ public class TradeOrderDetailRespVO extends TradeOrderBaseVO { @@ -26,24 +26,23 @@ public class TradeOrderDetailRespVO extends TradeOrderBaseVO {
26 private MemberUserRespVO user; 26 private MemberUserRespVO user;
27 27
28 /** 28 /**
29 - * TODO 订单操作日志, 先模拟一波;返回 logs,简洁,然后复数哈 29 + * TODO 订单操作日志, 先模拟一波
30 */ 30 */
31 - private List<OrderLog> orderLog; 31 + private List<OrderLog> logs;
32 32
33 - // TODO @puhui999:swagger 注解 33 + @Schema(description = "管理后台 - 交易订单的操作日志")
34 @Data 34 @Data
35 public static class OrderLog { 35 public static class OrderLog {
36 36
37 - /**  
38 - * 内容  
39 - */ 37 + @Schema(description = "操作详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单发货")
40 private String content; 38 private String content;
41 39
42 - /**  
43 - * 创建时间  
44 - */ 40 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-01 10:50:20")
45 private LocalDateTime createTime; 41 private LocalDateTime createTime;
46 42
  43 + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  44 + private Integer userType;
  45 +
47 } 46 }
48 47
49 @Schema(description = "管理后台 - 交易订单的详情的订单项目") 48 @Schema(description = "管理后台 - 交易订单的详情的订单项目")
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  6 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; 7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; 8 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
8 import io.swagger.v3.oas.annotations.Operation; 9 import io.swagger.v3.oas.annotations.Operation;
@@ -11,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; @@ -11,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
11 import org.springframework.validation.annotation.Validated; 12 import org.springframework.validation.annotation.Validated;
12 import org.springframework.web.bind.annotation.GetMapping; 13 import org.springframework.web.bind.annotation.GetMapping;
13 import org.springframework.web.bind.annotation.RequestMapping; 14 import org.springframework.web.bind.annotation.RequestMapping;
  15 +import org.springframework.web.bind.annotation.RequestParam;
14 import org.springframework.web.bind.annotation.RestController; 16 import org.springframework.web.bind.annotation.RestController;
15 17
16 import javax.validation.Valid; 18 import javax.validation.Valid;
@@ -40,4 +42,14 @@ public class AppBrokerageRecordController { @@ -40,4 +42,14 @@ public class AppBrokerageRecordController {
40 return success(new PageResult<>(asList(vo1, vo2), 10L)); 42 return success(new PageResult<>(asList(vo1, vo2), 10L));
41 } 43 }
42 44
  45 + @GetMapping("/get-product-brokerage-price")
  46 + @Operation(summary = "获得商品的分销金额")
  47 + public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
  48 + AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO();
  49 + respVO.setEnabled(true); // TODO @疯狂:需要开启分销 + 人允许分销
  50 + respVO.setBrokerageMinPrice(1);
  51 + respVO.setBrokerageMaxPrice(2);
  52 + return success(respVO);
  53 + }
  54 +
43 } 55 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java
@@ -37,11 +37,19 @@ public class AppBrokerageUserController { @@ -37,11 +37,19 @@ public class AppBrokerageUserController {
37 @PreAuthenticated 37 @PreAuthenticated
38 public CommonResult<AppBrokerageUserRespVO> getBrokerageUser() { 38 public CommonResult<AppBrokerageUserRespVO> getBrokerageUser() {
39 AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() 39 AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO()
  40 + .setBrokerageEnabled(true)
40 .setPrice(2000) 41 .setPrice(2000)
41 .setFrozenPrice(3000); 42 .setFrozenPrice(3000);
42 return success(respVO); 43 return success(respVO);
43 } 44 }
44 45
  46 + @PutMapping("/bind")
  47 + @Operation(summary = "绑定推广员")
  48 + @PreAuthenticated
  49 + public CommonResult<Boolean> bindBrokerageUser(@Valid @RequestBody AppBrokerageUserBindReqVO reqVO) {
  50 + return success(brokerageUserService.bindBrokerageUser(getLoginUserId(), reqVO.getBindUserId(), false));
  51 + }
  52 +
45 // TODO 芋艿:临时 mock => 53 // TODO 芋艿:临时 mock =>
46 @GetMapping("/get-summary") 54 @GetMapping("/get-summary")
47 @Operation(summary = "获得个人分销统计") 55 @Operation(summary = "获得个人分销统计")
@@ -49,7 +57,7 @@ public class AppBrokerageUserController { @@ -49,7 +57,7 @@ public class AppBrokerageUserController {
49 public CommonResult<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() { 57 public CommonResult<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() {
50 AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO() 58 AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO()
51 .setYesterdayPrice(1) 59 .setYesterdayPrice(1)
52 - .setPrice(2) 60 + .setBrokeragePrice(2)
53 .setFrozenPrice(3) 61 .setFrozenPrice(3)
54 .setWithdrawPrice(4) 62 .setWithdrawPrice(4)
55 .setFirstBrokerageUserCount(166) 63 .setFirstBrokerageUserCount(166)
@@ -84,16 +92,16 @@ public class AppBrokerageUserController { @@ -84,16 +92,16 @@ public class AppBrokerageUserController {
84 public CommonResult<PageResult<AppBrokerageUserRankByPriceRespVO>> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { 92 public CommonResult<PageResult<AppBrokerageUserRankByPriceRespVO>> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) {
85 AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() 93 AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO()
86 .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") 94 .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
87 - .setPrice(10); 95 + .setBrokeragePrice(10);
88 AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() 96 AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO()
89 .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") 97 .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
90 - .setPrice(6); 98 + .setBrokeragePrice(6);
91 AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() 99 AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO()
92 .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") 100 .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
93 - .setPrice(4); 101 + .setBrokeragePrice(4);
94 AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() 102 AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO()
95 .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") 103 .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
96 - .setPrice(4); 104 + .setBrokeragePrice(4);
97 return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); 105 return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L));
98 } 106 }
99 107
@@ -105,11 +113,11 @@ public class AppBrokerageUserController { @@ -105,11 +113,11 @@ public class AppBrokerageUserController {
105 AppBrokerageUserChildSummaryPageReqVO pageReqVO) { 113 AppBrokerageUserChildSummaryPageReqVO pageReqVO) {
106 AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO() 114 AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO()
107 .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") 115 .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
108 - .setPrice(10).setPrice(20).setBrokerageOrderCount(30) 116 + .setBrokeragePrice(10).setBrokeragePrice(20).setBrokerageOrderCount(30)
109 .setBrokerageTime(LocalDateTime.now()); 117 .setBrokerageTime(LocalDateTime.now());
110 AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO() 118 AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO()
111 .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") 119 .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
112 - .setPrice(20).setPrice(30).setBrokerageOrderCount(40) 120 + .setBrokeragePrice(20).setBrokeragePrice(30).setBrokerageOrderCount(40)
113 .setBrokerageTime(LocalDateTime.now()); 121 .setBrokerageTime(LocalDateTime.now());
114 return success(new PageResult<>(asList(vo1, vo2), 10L)); 122 return success(new PageResult<>(asList(vo1, vo2), 10L));
115 } 123 }
@@ -118,15 +126,9 @@ public class AppBrokerageUserController { @@ -118,15 +126,9 @@ public class AppBrokerageUserController {
118 @GetMapping("/get-rank-by-price") 126 @GetMapping("/get-rank-by-price")
119 @Operation(summary = "获得分销用户排行(基于佣金)") 127 @Operation(summary = "获得分销用户排行(基于佣金)")
120 @Parameter(name = "times", description = "时间段", required = true) 128 @Parameter(name = "times", description = "时间段", required = true)
121 - public CommonResult<Integer> getBrokerageUserRankByPrice( 129 + public CommonResult<Integer> bindBrokerageUser(
122 @RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) { 130 @RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) {
123 return success(1); 131 return success(1);
124 } 132 }
125 133
126 - @PutMapping("/bind-user")  
127 - @Operation(summary = "绑定推广员")  
128 - public CommonResult<Boolean> getBrokerageUserRankByPrice(@Valid AppBrokerageUserBindReqVO reqVO) {  
129 - return success(brokerageUserService.bindUser(getLoginUserId(), reqVO.getBindUserId(), false));  
130 - }  
131 -  
132 } 134 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageProductPriceRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "用户 App - 商品的分销金额 Response VO")
  7 +@Data
  8 +public class AppBrokerageProductPriceRespVO {
  9 +
  10 + @Schema(description = "是否开启", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  11 + private Boolean enabled;
  12 +
  13 + @Schema(description = "分销最小金额,单位:分", example = "100")
  14 + private Integer brokerageMinPrice;
  15 +
  16 + @Schema(description = "分销最大金额,单位:分", example = "100")
  17 + private Integer brokerageMaxPrice;
  18 +
  19 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java
@@ -19,7 +19,7 @@ public class AppBrokerageUserChildSummaryRespVO { @@ -19,7 +19,7 @@ public class AppBrokerageUserChildSummaryRespVO {
19 private String avatar; 19 private String avatar;
20 20
21 @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 21 @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
22 - private Integer price; 22 + private Integer brokeragePrice;
23 23
24 @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") 24 @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
25 private Integer brokerageOrderCount; 25 private Integer brokerageOrderCount;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java
@@ -14,7 +14,7 @@ public class AppBrokerageUserMySummaryRespVO { @@ -14,7 +14,7 @@ public class AppBrokerageUserMySummaryRespVO {
14 private Integer withdrawPrice; 14 private Integer withdrawPrice;
15 15
16 @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") 16 @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408")
17 - private Integer price; 17 + private Integer brokeragePrice;
18 18
19 @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") 19 @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
20 private Integer frozenPrice; 20 private Integer frozenPrice;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java
@@ -17,6 +17,6 @@ public class AppBrokerageUserRankByPriceRespVO { @@ -17,6 +17,6 @@ public class AppBrokerageUserRankByPriceRespVO {
17 private String avatar; 17 private String avatar;
18 18
19 @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 19 @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
20 - private Integer price; 20 + private Integer brokeragePrice;
21 21
22 } 22 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java
@@ -7,6 +7,9 @@ import lombok.Data; @@ -7,6 +7,9 @@ import lombok.Data;
7 @Data 7 @Data
8 public class AppBrokerageUserRespVO { 8 public class AppBrokerageUserRespVO {
9 9
  10 + @Schema(description = "是否有分销资格", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  11 + private Boolean brokerageEnabled;
  12 +
10 @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") 13 @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408")
11 private Integer price; 14 private Integer price;
12 15
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java
@@ -23,21 +23,18 @@ public class AppBrokerageWithdrawCreateReqVO { @@ -23,21 +23,18 @@ public class AppBrokerageWithdrawCreateReqVO {
23 @Min(value = 1, message = "提现金额不能小于 1") 23 @Min(value = 1, message = "提现金额不能小于 1")
24 private Integer price; 24 private Integer price;
25 25
26 -  
27 // ========== 银行卡、微信、支付宝 提现相关字段 ========== 26 // ========== 银行卡、微信、支付宝 提现相关字段 ==========
28 27
29 @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") 28 @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789")
30 @NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class}) 29 @NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class})
31 private String accountNo; 30 private String accountNo;
32 31
33 -  
34 // ========== 微信、支付宝 提现相关字段 ========== 32 // ========== 微信、支付宝 提现相关字段 ==========
35 33
36 @Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png") 34 @Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png")
37 @URL(message = "收款码的图片,必须是一个 URL") 35 @URL(message = "收款码的图片,必须是一个 URL")
38 private String accountQrCodeUrl; 36 private String accountQrCodeUrl;
39 37
40 -  
41 // ========== 银行卡 提现相关字段 ========== 38 // ========== 银行卡 提现相关字段 ==========
42 39
43 @Schema(description = "持卡人姓名", example = "张三") 40 @Schema(description = "持卡人姓名", example = "张三")
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
6 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; 6 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
7 -import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;  
8 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; 7 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; 8 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
10 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; 9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
@@ -82,9 +81,10 @@ public class AppTradeOrderController { @@ -82,9 +81,10 @@ public class AppTradeOrderController {
82 public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) { 81 public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) {
83 // 查询订单 82 // 查询订单
84 TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); 83 TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id);
85 - if (order == null) {  
86 - return success(null);  
87 - } 84 + // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理;
  85 +// if (order == null) {
  86 +// return success(null, ORDER_NOT_FOUND.getMsg());
  87 +// }
88 88
89 // 查询订单项 89 // 查询订单项
90 List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); 90 List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
@@ -50,12 +50,18 @@ public class AppTradeOrderSettlementReqVO { @@ -50,12 +50,18 @@ public class AppTradeOrderSettlementReqVO {
50 private Long seckillActivityId; 50 private Long seckillActivityId;
51 51
52 // ========== 拼团活动相关字段 ========== 52 // ========== 拼团活动相关字段 ==========
  53 + // TODO @puhui999:是不是拼团记录的编号哈?
53 @Schema(description = "拼团活动编号", example = "1024") 54 @Schema(description = "拼团活动编号", example = "1024")
54 private Long combinationActivityId; 55 private Long combinationActivityId;
55 56
56 @Schema(description = "拼团团长编号", example = "2048") 57 @Schema(description = "拼团团长编号", example = "2048")
57 private Long combinationHeadId; 58 private Long combinationHeadId;
58 59
  60 + // ========== 砍价活动相关字段 ==========
  61 + // TODO @puhui999:是不是砍价记录的编号哈?
  62 + @Schema(description = "砍价活动编号", example = "123")
  63 + private Long bargainActivityId;
  64 +
59 @Data 65 @Data
60 @Schema(description = "用户 App - 商品项") 66 @Schema(description = "用户 App - 商品项")
61 @Valid 67 @Valid
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java
@@ -78,7 +78,7 @@ public interface TradeAfterSaleConvert { @@ -78,7 +78,7 @@ public interface TradeAfterSaleConvert {
78 // 处理订单信息 78 // 处理订单信息
79 respVO.setOrder(convert(order)); 79 respVO.setOrder(convert(order));
80 // 处理售后日志 80 // 处理售后日志
81 - respVO.setAfterSaleLog(convertList1(logs)); 81 + respVO.setLogs(convertList1(logs));
82 return respVO; 82 return respVO;
83 } 83 }
84 List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespDTO> list); 84 List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespDTO> list);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java
@@ -33,27 +33,22 @@ public interface BrokerageRecordConvert { @@ -33,27 +33,22 @@ public interface BrokerageRecordConvert {
33 33
34 PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> page); 34 PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> page);
35 35
  36 + // TODO @疯狂:可能 title 不是很固化,会存在类似:沐晴成功购买《XXX JVM 实战》
36 default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, 37 default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId,
37 - Integer brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime, 38 + Integer brokerageFrozenDays, int brokeragePrice, LocalDateTime unfreezeTime,
38 String title, Long sourceUserId, Integer sourceUserType) { 39 String title, Long sourceUserId, Integer sourceUserType) {
39 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); 40 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0);
40 // 不冻结时,佣金直接就是结算状态 41 // 不冻结时,佣金直接就是结算状态
41 Integer status = brokerageFrozenDays > 0 42 Integer status = brokerageFrozenDays > 0
42 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() 43 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus()
43 : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); 44 : BrokerageRecordStatusEnum.SETTLEMENT.getStatus();
44 - return new BrokerageRecordDO()  
45 - .setUserId(user.getId())  
46 - .setBizType(bizType.getType())  
47 - .setBizId(bizId)  
48 - .setPrice(brokerage)  
49 - .setTotalPrice(user.getPrice()) 45 + return new BrokerageRecordDO().setUserId(user.getId())
  46 + .setBizType(bizType.getType()).setBizId(bizId)
  47 + .setPrice(brokeragePrice).setTotalPrice(user.getBrokeragePrice())
50 .setTitle(title) 48 .setTitle(title)
51 - .setDescription(StrUtil.format(bizType.getDescription(), String.format("¥%.2f", brokerage / 100d)))  
52 - .setStatus(status)  
53 - .setFrozenDays(brokerageFrozenDays)  
54 - .setUnfreezeTime(unfreezeTime)  
55 - .setSourceUserType(sourceUserType)  
56 - .setSourceUserId(sourceUserId); 49 + .setDescription(StrUtil.format(bizType.getDescription(), String.format("¥%.2f", brokeragePrice / 100d)))
  50 + .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime)
  51 + .setSourceUserType(sourceUserType).setSourceUserId(sourceUserId);
57 } 52 }
58 53
59 default PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> pageResult, Map<Long, MemberUserRespDTO> userMap) { 54 default PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java
@@ -41,25 +41,19 @@ public interface BrokerageUserConvert { @@ -41,25 +41,19 @@ public interface BrokerageUserConvert {
41 41
42 // 推广用户数量(一级) 42 // 推广用户数量(一级)
43 vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); 43 vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0));
44 - 44 + // 推广订单数量、推广订单金额
45 Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); 45 Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId()));
46 - // 推广订单数量  
47 - vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0));  
48 - // 推广订单金额  
49 - vo.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0));  
50 -  
51 - // todo 已提现次数  
52 - vo.setWithdrawCount(0);  
53 - // todo 已提现金额  
54 - vo.setWithdrawPrice(0); 46 + vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0))
  47 + .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0));
  48 + // todo 已提现次数、已提现金额
  49 + vo.setWithdrawCount(0).setWithdrawPrice(0);
55 } 50 }
56 return result; 51 return result;
57 } 52 }
58 53
59 default BrokerageUserRespVO copyTo(MemberUserRespDTO source, BrokerageUserRespVO target) { 54 default BrokerageUserRespVO copyTo(MemberUserRespDTO source, BrokerageUserRespVO target) {
60 - Optional.ofNullable(source)  
61 - .ifPresent(user -> target.setNickname(user.getNickname())  
62 - .setAvatar(user.getAvatar())); 55 + Optional.ofNullable(source).ifPresent(
  56 + user -> target.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
63 return target; 57 return target;
64 } 58 }
65 59
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -95,6 +95,7 @@ public interface TradeOrderConvert { @@ -95,6 +95,7 @@ public interface TradeOrderConvert {
95 items.forEach(item -> item.setIncrCount(-item.getIncrCount())); 95 items.forEach(item -> item.setIncrCount(-item.getIncrCount()));
96 return new ProductSkuUpdateStockReqDTO(items); 96 return new ProductSkuUpdateStockReqDTO(items);
97 } 97 }
  98 +
98 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); 99 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
99 100
100 @Mappings({ 101 @Mappings({
@@ -153,9 +154,10 @@ public interface TradeOrderConvert { @@ -153,9 +154,10 @@ public interface TradeOrderConvert {
153 TradeOrderDetailRespVO.OrderLog orderLog = new TradeOrderDetailRespVO.OrderLog(); 154 TradeOrderDetailRespVO.OrderLog orderLog = new TradeOrderDetailRespVO.OrderLog();
154 orderLog.setContent("订单操作" + i); 155 orderLog.setContent("订单操作" + i);
155 orderLog.setCreateTime(LocalDateTime.now()); 156 orderLog.setCreateTime(LocalDateTime.now());
  157 + orderLog.setUserType(i % 2 == 0 ? 2 : 1);
156 orderLogs.add(orderLog); 158 orderLogs.add(orderLog);
157 } 159 }
158 - orderVO.setOrderLog(orderLogs); 160 + orderVO.setLogs(orderLogs);
159 return orderVO; 161 return orderVO;
160 } 162 }
161 163
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java
@@ -43,7 +43,7 @@ public class BrokerageUserDO extends BaseDO { @@ -43,7 +43,7 @@ public class BrokerageUserDO extends BaseDO {
43 private LocalDateTime bindUserTime; 43 private LocalDateTime bindUserTime;
44 44
45 /** 45 /**
46 - * 推广资格 46 + * 是否有分销资格
47 */ 47 */
48 private Boolean brokerageEnabled; 48 private Boolean brokerageEnabled;
49 /** 49 /**
@@ -54,7 +54,7 @@ public class BrokerageUserDO extends BaseDO { @@ -54,7 +54,7 @@ public class BrokerageUserDO extends BaseDO {
54 /** 54 /**
55 * 可用佣金 55 * 可用佣金
56 */ 56 */
57 - private Integer price; 57 + private Integer brokeragePrice;
58 /** 58 /**
59 * 冻结佣金 59 * 冻结佣金
60 */ 60 */
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java
@@ -53,6 +53,7 @@ public interface BrokerageRecordMapper extends BaseMapperX&lt;BrokerageRecordDO&gt; { @@ -53,6 +53,7 @@ public interface BrokerageRecordMapper extends BaseMapperX&lt;BrokerageRecordDO&gt; {
53 BrokerageRecordDO::getBizId, bizId); 53 BrokerageRecordDO::getBizId, bizId);
54 } 54 }
55 55
  56 + // TODO @疯狂:mysql 关键字,大写哈;这样看起来清晰点;例如说 SELECT COUNT(1)
56 @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}") 57 @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}")
57 UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, 58 UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId,
58 @Param("bizType") Integer bizType, 59 @Param("bizType") Integer bizType,
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java
@@ -134,4 +134,5 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; { @@ -134,4 +134,5 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; {
134 .eq(BrokerageUserDO::getId, id) 134 .eq(BrokerageUserDO::getId, id)
135 .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); 135 .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null));
136 } 136 }
  137 +
137 } 138 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.dal.redis.no;
  2 +
  3 +import cn.hutool.core.date.DatePattern;
  4 +import cn.hutool.core.date.DateUtil;
  5 +import org.springframework.data.redis.core.StringRedisTemplate;
  6 +import org.springframework.stereotype.Repository;
  7 +
  8 +import javax.annotation.Resource;
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 订单序号的 Redis DAO
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@Repository
  17 +public class TradeOrderNoRedisDAO {
  18 +
  19 + public static final String TRADE_ORDER_NO_PREFIX = "O";
  20 +
  21 + @Resource
  22 + private StringRedisTemplate stringRedisTemplate;
  23 +
  24 + /**
  25 + * 生成序号
  26 + *
  27 + * @param prefix 前缀
  28 + * @return 序号
  29 + */
  30 + public String generate(String prefix) {
  31 + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN);
  32 + Long no = stringRedisTemplate.opsForValue().increment(noPrefix);
  33 + return noPrefix + no;
  34 + }
  35 +
  36 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
@@ -90,12 +90,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa @@ -90,12 +90,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
90 90
91 @Override 91 @Override
92 public TradeAfterSaleDO getAfterSale(Long id) { 92 public TradeAfterSaleDO getAfterSale(Long id) {
93 - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);  
94 - // TODO @puhui999;读不到,不要这里报错哈;交给前端报错;一般是读取信息不到,message 提示,然后 close tab;  
95 - if (afterSale == null) {  
96 - throw exception(AFTER_SALE_NOT_FOUND);  
97 - }  
98 - return afterSale; 93 + return tradeAfterSaleMapper.selectById(id);
99 } 94 }
100 95
101 // TODO 芋艿:拼团失败,要不要发起售后的方式退款?还是走取消逻辑? 96 // TODO 芋艿:拼团失败,要不要发起售后的方式退款?还是走取消逻辑?
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java
@@ -5,6 +5,7 @@ import lombok.Data; @@ -5,6 +5,7 @@ import lombok.Data;
5 import lombok.NoArgsConstructor; 5 import lombok.NoArgsConstructor;
6 6
7 import javax.validation.constraints.NotBlank; 7 import javax.validation.constraints.NotBlank;
  8 +import javax.validation.constraints.NotNull;
8 9
9 /** 10 /**
10 * 佣金 增加 Request BO 11 * 佣金 增加 Request BO
@@ -24,6 +25,7 @@ public class BrokerageAddReqBO { @@ -24,6 +25,7 @@ public class BrokerageAddReqBO {
24 /** 25 /**
25 * 佣金基数 26 * 佣金基数
26 */ 27 */
  28 + @NotNull(message = "佣金基数不能为空")
27 private Integer basePrice; 29 private Integer basePrice;
28 /** 30 /**
29 * 一级佣金(固定) 31 * 一级佣金(固定)
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java
@@ -13,6 +13,7 @@ import lombok.NoArgsConstructor; @@ -13,6 +13,7 @@ import lombok.NoArgsConstructor;
13 @NoArgsConstructor 13 @NoArgsConstructor
14 @AllArgsConstructor 14 @AllArgsConstructor
15 public class UserBrokerageSummaryBO { 15 public class UserBrokerageSummaryBO {
  16 +
16 /** 17 /**
17 * 佣金数量 18 * 佣金数量
18 */ 19 */
@@ -21,4 +22,5 @@ public class UserBrokerageSummaryBO { @@ -21,4 +22,5 @@ public class UserBrokerageSummaryBO {
21 * 佣金总额 22 * 佣金总额
22 */ 23 */
23 private Integer price; 24 private Integer price;
  25 +
24 } 26 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java
@@ -66,5 +66,5 @@ public interface BrokerageRecordService { @@ -66,5 +66,5 @@ public interface BrokerageRecordService {
66 * @param status 佣金状态 66 * @param status 佣金状态
67 * @return 用户佣金汇总 67 * @return 用户佣金汇总
68 */ 68 */
69 - UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status); 69 + UserBrokerageSummaryBO getUserBrokerageSummaryByUserId(Long userId, Integer bizType, Integer status);
70 } 70 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java
@@ -91,6 +91,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -91,6 +91,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
91 @Override 91 @Override
92 @Transactional(rollbackFor = Exception.class) 92 @Transactional(rollbackFor = Exception.class)
93 public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) { 93 public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) {
  94 + // TODO @疯狂:userId 加进去查询,会不会更好一点?万一穿错参数;
94 BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId); 95 BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId);
95 if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { 96 if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) {
96 log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); 97 log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId);
@@ -209,9 +210,9 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -209,9 +210,9 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
209 } 210 }
210 211
211 @Override 212 @Override
212 - public UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status) { 213 + public UserBrokerageSummaryBO getUserBrokerageSummaryByUserId(Long userId, Integer bizType, Integer status) {
213 UserBrokerageSummaryBO summaryBO = brokerageRecordMapper.selectCountAndSumPriceByUserIdAndBizTypeAndStatus(userId, bizType, status); 214 UserBrokerageSummaryBO summaryBO = brokerageRecordMapper.selectCountAndSumPriceByUserIdAndBizTypeAndStatus(userId, bizType, status);
214 - return summaryBO == null ? new UserBrokerageSummaryBO(0, 0) : summaryBO; 215 + return summaryBO != null ? summaryBO : new UserBrokerageSummaryBO(0, 0);
215 } 216 }
216 217
217 @Transactional(rollbackFor = Exception.class) 218 @Transactional(rollbackFor = Exception.class)
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java
@@ -52,7 +52,7 @@ public interface BrokerageUserService { @@ -52,7 +52,7 @@ public interface BrokerageUserService {
52 * @param id 用户编号 52 * @param id 用户编号
53 * @param enabled 推广资格 53 * @param enabled 推广资格
54 */ 54 */
55 - void updateBrokerageEnabled(Long id, Boolean enabled); 55 + void updateBrokerageUserEnabled(Long id, Boolean enabled);
56 56
57 /** 57 /**
58 * 获得用户的推广人 58 * 获得用户的推广人
@@ -79,20 +79,21 @@ public interface BrokerageUserService { @@ -79,20 +79,21 @@ public interface BrokerageUserService {
79 void updateUserFrozenPrice(Long id, Integer frozenPrice); 79 void updateUserFrozenPrice(Long id, Integer frozenPrice);
80 80
81 /** 81 /**
82 - * 更新用户冻结佣金(减少), 更新用户佣金(增加) 82 + * 更新用户冻结佣金(减少),更新用户佣金(增加)
83 * 83 *
84 * @param id 用户编号 84 * @param id 用户编号
85 * @param frozenPrice 减少冻结佣金(负数) 85 * @param frozenPrice 减少冻结佣金(负数)
86 */ 86 */
87 void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice); 87 void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice);
88 88
  89 + // TODO @疯狂:这个后面可能要支持下,二级
89 /** 90 /**
90 * 获得推广用户数量(一级) 91 * 获得推广用户数量(一级)
91 * 92 *
92 * @param bindUserId 绑定的推广员编号 93 * @param bindUserId 绑定的推广员编号
93 * @return 推广用户数量 94 * @return 推广用户数量
94 */ 95 */
95 - Long getCountByBindUserId(Long bindUserId); 96 + Long getBrokerageUserCountByBindUserId(Long bindUserId);
96 97
97 /** 98 /**
98 * 【会员】绑定推广员 99 * 【会员】绑定推广员
@@ -102,5 +103,6 @@ public interface BrokerageUserService { @@ -102,5 +103,6 @@ public interface BrokerageUserService {
102 * @param isNewUser 是否为新用户 103 * @param isNewUser 是否为新用户
103 * @return 是否绑定 104 * @return 是否绑定
104 */ 105 */
105 - boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); 106 + boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser);
  107 +
106 } 108 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java
@@ -55,23 +55,24 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -55,23 +55,24 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
55 55
56 @Override 56 @Override
57 public void updateBrokerageUserId(Long id, Long bindUserId) { 57 public void updateBrokerageUserId(Long id, Long bindUserId) {
58 - // 0. 校验存在 58 + // 校验存在
59 BrokerageUserDO brokerageUser = validateBrokerageUserExists(id); 59 BrokerageUserDO brokerageUser = validateBrokerageUserExists(id);
  60 +
  61 + // 情况一:清除推广员
60 if (bindUserId == null) { 62 if (bindUserId == null) {
61 - // 1. 清除推广员 63 + // 清除推广员
62 brokerageUserMapper.updateBindUserIdAndBindUserTimeToNull(id); 64 brokerageUserMapper.updateBindUserIdAndBindUserTimeToNull(id);
63 return; 65 return;
64 } 66 }
65 67
66 - // 2.1 校验能否绑定 68 + // 情况二:修改推广员
67 validateCanBindUser(brokerageUser, bindUserId); 69 validateCanBindUser(brokerageUser, bindUserId);
68 - // 2.2 修改推广员  
69 brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) 70 brokerageUserMapper.updateById(new BrokerageUserDO().setId(id)
70 .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); 71 .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()));
71 } 72 }
72 73
73 @Override 74 @Override
74 - public void updateBrokerageEnabled(Long id, Boolean enabled) { 75 + public void updateBrokerageUserEnabled(Long id, Boolean enabled) {
75 // 校验存在 76 // 校验存在
76 validateBrokerageUserExists(id); 77 validateBrokerageUserExists(id);
77 if (BooleanUtil.isTrue(enabled)) { 78 if (BooleanUtil.isTrue(enabled)) {
@@ -130,39 +131,42 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -130,39 +131,42 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
130 } 131 }
131 132
132 @Override 133 @Override
133 - public Long getCountByBindUserId(Long bindUserId) { 134 + public Long getBrokerageUserCountByBindUserId(Long bindUserId) {
  135 + // TODO @疯狂:mapper 封装下哈;不直接在 service 调用这种基础 mapper 的基础方法
134 return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId); 136 return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId);
135 } 137 }
136 138
  139 + // TODO @疯狂:因为现在 user 会存在使用验证码直接注册,所以 isNewUser 不太好传递;我们是不是可以约定绑定的时间,createTime 在 30 秒内,就认为新用户;
137 @Override 140 @Override
138 - public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { 141 + public boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser) {
  142 + // TODO @疯狂:userId 为空,搞到参数校验里哇;
139 if (userId == null) { 143 if (userId == null) {
140 throw exception(0); 144 throw exception(0);
141 } 145 }
142 146
143 - boolean isInsert = false; 147 + // 1. 获得分销用户
  148 + boolean isNewBrokerageUser = false;
144 BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); 149 BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId);
145 - // 分销用户不存在的情况:1.新注册 2.旧数据 3.分销功能关闭后又打开  
146 - if (brokerageUser == null) {  
147 - isInsert = true;  
148 - brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0); 150 + if (brokerageUser == null) { // 分销用户不存在的情况:1. 新注册;2. 旧数据;3. 分销功能关闭后又打开
  151 + isNewBrokerageUser = true;
  152 + brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setBrokeragePrice(0).setFrozenPrice(0);
149 } 153 }
150 154
151 - // 校验分配配置  
152 - boolean validated = validateTradeConfig(brokerageUser, bindUserId, isNewUser); 155 + // 2.1 校验是否能绑定用户
  156 + boolean validated = isUserCanBind(brokerageUser, bindUserId, isNewUser);
153 if (!validated) { 157 if (!validated) {
154 return false; 158 return false;
155 } 159 }
156 -  
157 - // 校验能否绑定 160 + // 2.3 校验能否绑定
158 validateCanBindUser(brokerageUser, bindUserId); 161 validateCanBindUser(brokerageUser, bindUserId);
159 -  
160 - if (isInsert) { 162 + // 2.3 绑定用户
  163 + if (isNewBrokerageUser) {
161 Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition(); 164 Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition();
162 - if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) {  
163 - // 人人分销:用户默认就有分销资格 165 + if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { // 人人分销:用户默认就有分销资格
  166 + // TODO @疯狂:应该设置下 brokerageTime,而不是 bindUserTime
164 brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now()); 167 brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now());
165 } 168 }
  169 + // TODO @疯狂:这里是不是要设置 bindUserId、bindUserTime 字段哈;
166 brokerageUserMapper.insert(brokerageUser); 170 brokerageUserMapper.insert(brokerageUser);
167 } else { 171 } else {
168 brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId) 172 brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId)
@@ -171,7 +175,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -171,7 +175,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
171 return true; 175 return true;
172 } 176 }
173 177
174 - private boolean validateTradeConfig(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) { 178 + private boolean isUserCanBind(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) {
175 // 校验分销功能是否启用 179 // 校验分销功能是否启用
176 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); 180 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
177 if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) { 181 if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) {
@@ -194,7 +198,6 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -194,7 +198,6 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
194 } 198 }
195 } 199 }
196 200
197 - validateCanBindUser(user, bindUserId);  
198 return true; 201 return true;
199 } 202 }
200 203
@@ -210,6 +213,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -210,6 +213,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
210 throw exception(BROKERAGE_BIND_SELF); 213 throw exception(BROKERAGE_BIND_SELF);
211 } 214 }
212 215
  216 + // TODO @疯狂:这块是不是一直查询到根节点,中间不允许出现自己;就是不能形成环。虽然目前是 2 级,但是未来可能会改多级; = = 环的话,就会存在问题哈
213 // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!! 217 // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!!
214 if (Objects.equals(user.getId(), bindUser.getBindUserId())) { 218 if (Objects.equals(user.getId(), bindUser.getBindUserId())) {
215 throw exception(BROKERAGE_BIND_LOOP); 219 throw exception(BROKERAGE_BIND_LOOP);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.order; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.order;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 -import cn.hutool.core.util.IdUtil;  
6 import cn.hutool.core.util.ObjectUtil; 5 import cn.hutool.core.util.ObjectUtil;
7 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
8 import cn.hutool.extra.spring.SpringUtil; 7 import cn.hutool.extra.spring.SpringUtil;
@@ -25,12 +24,14 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; @@ -25,12 +24,14 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
25 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; 24 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
26 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 25 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
27 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 26 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  27 +import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
28 import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; 28 import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
29 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; 29 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
30 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; 30 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
31 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;  
32 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; 31 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
33 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; 32 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
  33 +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
  34 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
34 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 35 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
35 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; 36 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
36 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; 37 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
@@ -46,6 +47,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; @@ -46,6 +47,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
46 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 47 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
47 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; 48 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
48 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; 49 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
  50 +import cn.iocoder.yudao.module.trade.dal.redis.no.TradeOrderNoRedisDAO;
49 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; 51 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
50 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; 52 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
51 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; 53 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
@@ -74,7 +76,7 @@ import java.util.Set; @@ -74,7 +76,7 @@ import java.util.Set;
74 76
75 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 77 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
76 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 78 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
77 -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; 79 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_EQUAL;
78 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_PAID; 80 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_PAID;
79 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; 81 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
80 82
@@ -92,6 +94,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -92,6 +94,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
92 private TradeOrderMapper tradeOrderMapper; 94 private TradeOrderMapper tradeOrderMapper;
93 @Resource 95 @Resource
94 private TradeOrderItemMapper tradeOrderItemMapper; 96 private TradeOrderItemMapper tradeOrderItemMapper;
  97 + @Resource
  98 + private TradeOrderNoRedisDAO orderNoRedisDAO;
95 99
96 @Resource 100 @Resource
97 private CartService cartService; 101 private CartService cartService;
@@ -115,6 +119,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -115,6 +119,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
115 @Resource 119 @Resource
116 private BargainRecordApi bargainRecordApi; 120 private BargainRecordApi bargainRecordApi;
117 @Resource 121 @Resource
  122 + private SeckillActivityApi seckillActivityApi;
  123 + @Resource
  124 + private BargainActivityApi bargainActivityApi;
  125 + @Resource
118 private MemberUserApi memberUserApi; 126 private MemberUserApi memberUserApi;
119 @Resource 127 @Resource
120 private MemberLevelApi memberLevelApi; 128 private MemberLevelApi memberLevelApi;
@@ -195,22 +203,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -195,22 +203,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
195 // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去 203 // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去
196 // 拼团 204 // 拼团
197 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { 205 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
198 - MemberUserRespDTO user = memberUserApi.getUser(userId);  
199 - List<CombinationRecordRespDTO> recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId());  
200 - // TODO 拼团一次应该只能选择一种规格的商品  
201 - TradeOrderItemDO orderItemDO = orderItems.get(0);  
202 - if (CollUtil.isNotEmpty(recordRespDTOS)) {  
203 - List<Long> skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));  
204 - List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS,  
205 - CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);  
206 - combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(),  
207 - CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount());  
208 - }  
209 -  
210 - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); 206 + createCombinationRecord(userId, createReqVO, orderItems, order);
211 } 207 }
212 // 3.2 秒杀的特殊逻辑 208 // 3.2 秒杀的特殊逻辑
213 - // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除  
214 if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { 209 if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) {
215 210
216 } 211 }
@@ -220,6 +215,22 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -220,6 +215,22 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
220 return order; 215 return order;
221 } 216 }
222 217
  218 + private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List<TradeOrderItemDO> orderItems, TradeOrderDO order) {
  219 + MemberUserRespDTO user = memberUserApi.getUser(userId);
  220 + List<CombinationRecordRespDTO> recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId());
  221 + // TODO 拼团一次应该只能选择一种规格的商品
  222 + TradeOrderItemDO orderItemDO = orderItems.get(0);
  223 + if (CollUtil.isNotEmpty(recordRespDTOS)) {
  224 + List<Long> skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
  225 + List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS,
  226 + CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
  227 + combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(),
  228 + CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount());
  229 + }
  230 +
  231 + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user));
  232 + }
  233 +
223 // TODO @puhui999:订单超时,自动取消; 234 // TODO @puhui999:订单超时,自动取消;
224 235
225 /** 236 /**
@@ -246,8 +257,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -246,8 +257,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
246 address = validateAddress(userId, createReqVO.getAddressId()); 257 address = validateAddress(userId, createReqVO.getAddressId());
247 } 258 }
248 TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address); 259 TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address);
  260 + String no = orderNoRedisDAO.generate(TradeOrderNoRedisDAO.TRADE_ORDER_NO_PREFIX);
249 order.setType(validateActivity(createReqVO)); 261 order.setType(validateActivity(createReqVO));
250 - order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @puhui999: 参考支付订单,的 no 生成哈; 262 + order.setNo(no);
251 order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); 263 order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
252 order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); 264 order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
253 order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); 265 order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum));
@@ -299,19 +311,23 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -299,19 +311,23 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
299 private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, 311 private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
300 TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems, 312 TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
301 TradePriceCalculateRespBO calculateRespBO) { 313 TradePriceCalculateRespBO calculateRespBO) {
302 - // 下单时扣减商品库存  
303 - // TODO @puhui999:扣库存,需要前置; 314 + Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum);
304 // 1)如果是秒杀商品:额外扣减秒杀的库存; 315 // 1)如果是秒杀商品:额外扣减秒杀的库存;
305 - // 2)如果是拼团活动:额外扣减拼团的库存;  
306 - // 3)如果是砍价活动:额外扣减砍价的库存;  
307 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));  
308 -  
309 - // 删除购物车商品  
310 - Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);  
311 - if (CollUtil.isNotEmpty(cartIds)) {  
312 - cartService.deleteCart(userId, cartIds);  
313 - }  
314 - 316 + if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) {
  317 + SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO();
  318 + updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId());
  319 + updateStockReqDTO.setCount(count);
  320 + updateStockReqDTO.setItems(CollectionUtils.convertList(orderItems, item -> {
  321 + SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item();
  322 + item1.setSpuId(item.getSpuId());
  323 + item1.setSkuId(item.getSkuId());
  324 + item1.setCount(item.getCount());
  325 + return item1;
  326 + }));
  327 + seckillActivityApi.updateSeckillStock(updateStockReqDTO);
  328 + }
  329 + // 2)如果是砍价活动:额外扣减砍价的库存;
  330 + bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count);
315 // 扣减积分 TODO 芋艿:待实现,需要前置; 331 // 扣减积分 TODO 芋艿:待实现,需要前置;
316 // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣 332 // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
317 333
@@ -321,6 +337,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -321,6 +337,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
321 .setOrderId(tradeOrderDO.getId())); 337 .setOrderId(tradeOrderDO.getId()));
322 } 338 }
323 339
  340 + // 下单时扣减商品库存
  341 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));
  342 +
  343 + // 删除购物车商品
  344 + Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
  345 + if (CollUtil.isNotEmpty(cartIds)) {
  346 + cartService.deleteCart(userId, cartIds);
  347 + }
  348 +
324 // 生成预支付 349 // 生成预支付
325 createPayOrder(tradeOrderDO, orderItems, calculateRespBO); 350 createPayOrder(tradeOrderDO, orderItems, calculateRespBO);
326 351
@@ -357,8 +382,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -357,8 +382,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
357 // 1、拼团活动 382 // 1、拼团活动
358 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { 383 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
359 // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 384 // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录
360 - combinationRecordApi.updateCombinationRecordStatus(new CombinationRecordUpdateStatusReqDTO().setUserId(order.getUserId())  
361 - .setOrderId(order.getId()).setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()).setStartTime(LocalDateTime.now())); 385 + combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now());
362 } 386 }
363 // TODO 芋艿:发送订单变化的消息 387 // TODO 芋艿:发送订单变化的消息
364 388
@@ -371,7 +395,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -371,7 +395,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
371 // 增加用户经验 395 // 增加用户经验
372 getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); 396 getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId());
373 // 增加用户佣金 397 // 增加用户佣金
374 - getSelf().addBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, order.getId()); 398 + getSelf().addBrokerageAsync(order.getUserId(), order.getId());
375 } 399 }
376 400
377 /** 401 /**
@@ -473,11 +497,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -473,11 +497,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
473 */ 497 */
474 private TradeOrderDO validateOrderDeliverable(Long id) { 498 private TradeOrderDO validateOrderDeliverable(Long id) {
475 TradeOrderDO order = validateOrderExists(id); 499 TradeOrderDO order = validateOrderExists(id);
476 - // 校验订单是否是待发货状态  
477 - // TODO @puhui999:已经发货,可以重新发货,修改信息;  
478 - if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) {  
479 - throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);  
480 - }  
481 // 校验订单是否退款 500 // 校验订单是否退款
482 if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { 501 if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) {
483 throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); 502 throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE);
@@ -543,20 +562,35 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -543,20 +562,35 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
543 } 562 }
544 563
545 @Override 564 @Override
  565 + // TODO @puhui999:考虑事务性
546 public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) { 566 public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) {
547 // 校验交易订单 567 // 校验交易订单
548 TradeOrderDO order = validateOrderExists(reqVO.getId()); 568 TradeOrderDO order = validateOrderExists(reqVO.getId());
549 if (order.getPayStatus()) { 569 if (order.getPayStatus()) {
550 throw exception(ORDER_UPDATE_PRICE_FAIL_PAID); 570 throw exception(ORDER_UPDATE_PRICE_FAIL_PAID);
551 } 571 }
552 - // TODO @puhui999:如果改价,需要校验下是否真的变化;  
553 -  
554 - // 更新  
555 - // TODO @puhui999:TradeOrderItemDO 需要做 adjustPrice 的分摊;另外,支付订单那的价格,需要 update 下; 572 + if (ObjectUtil.equal(order.getAdjustPrice(), reqVO.getAdjustPrice())) {
  573 + throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL);
  574 + }
  575 +
  576 + // TODO @puhui999:应该是按照 payPrice 分配;并且要考虑取余问题;payPrice 也要考虑,item 里的
  577 + List<TradeOrderItemDO> itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId());
  578 + // TradeOrderItemDO 需要做 adjustPrice 的分摊
  579 + int price = reqVO.getAdjustPrice() / itemDOs.size();
  580 + itemDOs.forEach(item -> {
  581 + item.setAdjustPrice(price);
  582 + });
  583 + // 更新 TradeOrderItem
  584 + // TODO @puhui999:不要整个对象去更新哈;应该 new 一下;
  585 + tradeOrderItemMapper.updateBatch(itemDOs);
  586 + // 更新订单
  587 + // TODO @puhui999:要考虑多次修改价格,不能单单的 payPrice + 价格;
556 TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO); 588 TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO);
557 update.setPayPrice(update.getPayPrice() + update.getAdjustPrice()); 589 update.setPayPrice(update.getPayPrice() + update.getAdjustPrice());
558 // TODO @芋艿:改价时,赠送的积分,要不要做改动??? 590 // TODO @芋艿:改价时,赠送的积分,要不要做改动???
559 tradeOrderMapper.updateById(update); 591 tradeOrderMapper.updateById(update);
  592 + // 更新支付订单
  593 + payOrderApi.updatePayOrderPriceById(order.getPayOrderId(), update.getPayPrice());
560 } 594 }
561 595
562 @Override 596 @Override
@@ -641,7 +675,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -641,7 +675,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
641 // 扣减用户经验 675 // 扣减用户经验
642 getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); 676 getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId);
643 // 更新分佣记录为已失效 677 // 更新分佣记录为已失效
644 - getSelf().cancelBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, id); 678 + getSelf().cancelBrokerageAsync(order.getUserId(), id);
645 } 679 }
646 680
647 @Override 681 @Override
@@ -751,16 +785,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -751,16 +785,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
751 785
752 786
753 @Async 787 @Async
754 - protected void addBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderId) { 788 + protected void addBrokerageAsync(Long userId, Long orderId) {
755 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); 789 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId);
756 List<BrokerageAddReqBO> list = convertList(orderItems, 790 List<BrokerageAddReqBO> list = convertList(orderItems,
757 item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); 791 item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId())));
758 - brokerageRecordService.addBrokerage(userId, bizType, list); 792 + brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, list);
759 } 793 }
760 794
761 @Async 795 @Async
762 - protected void cancelBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderItemId) {  
763 - brokerageRecordService.cancelBrokerage(userId, bizType, String.valueOf(orderItemId)); 796 + protected void cancelBrokerageAsync(Long userId, Long orderItemId) {
  797 + brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId));
764 } 798 }
765 799
766 /** 800 /**
yudao-module-member/yudao-module-member-biz/pom.xml
@@ -33,11 +33,6 @@ @@ -33,11 +33,6 @@
33 <artifactId>yudao-module-infra-api</artifactId> 33 <artifactId>yudao-module-infra-api</artifactId>
34 <version>${revision}</version> 34 <version>${revision}</version>
35 </dependency> 35 </dependency>
36 - <dependency>  
37 - <groupId>cn.iocoder.boot</groupId>  
38 - <artifactId>yudao-module-trade-api</artifactId>  
39 - <version>${revision}</version>  
40 - </dependency>  
41 36
42 <!-- 业务组件 --> 37 <!-- 业务组件 -->
43 <dependency> 38 <dependency>
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http
@@ -28,6 +28,17 @@ tenant-id: {{appTenentId}} @@ -28,6 +28,17 @@ tenant-id: {{appTenentId}}
28 "code": 9999 28 "code": 9999
29 } 29 }
30 30
  31 +### 请求 /social-login 接口 => 成功
  32 +POST {{appApi}}/member/auth/social-login
  33 +Content-Type: application/json
  34 +tenant-id: {{appTenentId}}
  35 +
  36 +{
  37 + "type": 34,
  38 + "code": "0e1oc9000CTjFQ1oim200bhtb61oc90g",
  39 + "state": "default"
  40 +}
  41 +
31 ### 请求 /weixin-mini-app-login 接口 => 成功 42 ### 请求 /weixin-mini-app-login 接口 => 成功
32 POST {{appApi}}/member/auth/weixin-mini-app-login 43 POST {{appApi}}/member/auth/weixin-mini-app-login
33 Content-Type: application/json 44 Content-Type: application/json
@@ -38,7 +49,6 @@ tenant-id: {{appTenentId}} @@ -38,7 +49,6 @@ tenant-id: {{appTenentId}}
38 "loginCode": "001frTkl21JUf94VGxol2hSlff1frTkR" 49 "loginCode": "001frTkl21JUf94VGxol2hSlff1frTkR"
39 } 50 }
40 51
41 -  
42 ### 请求 /logout 接口 => 成功 52 ### 请求 /logout 接口 => 成功
43 POST {{appApi}}/member/auth/logout 53 POST {{appApi}}/member/auth/logout
44 Content-Type: application/json 54 Content-Type: application/json
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java
@@ -27,4 +27,12 @@ public class AppAuthLoginRespVO { @@ -27,4 +27,12 @@ public class AppAuthLoginRespVO {
27 @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) 27 @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
28 private LocalDateTime expiresTime; 28 private LocalDateTime expiresTime;
29 29
  30 + /**
  31 + * 仅社交登录、社交绑定时会返回
  32 + *
  33 + * 为什么需要返回?微信公众号、微信小程序支付需要传递 openid 给支付接口
  34 + */
  35 + @Schema(description = "社交用户 openid", example = "qq768")
  36 + private String openid;
  37 +
30 } 38 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java
@@ -8,8 +8,6 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; @@ -8,8 +8,6 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
8 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; 8 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
9 import cn.iocoder.yudao.module.member.service.level.MemberLevelService; 9 import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
10 import cn.iocoder.yudao.module.member.service.user.MemberUserService; 10 import cn.iocoder.yudao.module.member.service.user.MemberUserService;
11 -import cn.iocoder.yudao.module.trade.api.brokerage.BrokerageApi;  
12 -import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO;  
13 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.tags.Tag; 12 import io.swagger.v3.oas.annotations.tags.Tag;
15 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
@@ -18,7 +16,6 @@ import org.springframework.web.bind.annotation.*; @@ -18,7 +16,6 @@ import org.springframework.web.bind.annotation.*;
18 16
19 import javax.annotation.Resource; 17 import javax.annotation.Resource;
20 import javax.validation.Valid; 18 import javax.validation.Valid;
21 -import java.util.Optional;  
22 19
23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
24 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 21 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -32,23 +29,16 @@ public class AppMemberUserController { @@ -32,23 +29,16 @@ public class AppMemberUserController {
32 29
33 @Resource 30 @Resource
34 private MemberUserService userService; 31 private MemberUserService userService;
35 -  
36 @Resource 32 @Resource
37 private MemberLevelService levelService; 33 private MemberLevelService levelService;
38 34
39 - @Resource  
40 - private BrokerageApi brokerageApi;  
41 -  
42 @GetMapping("/get") 35 @GetMapping("/get")
43 @Operation(summary = "获得基本信息") 36 @Operation(summary = "获得基本信息")
44 @PreAuthenticated 37 @PreAuthenticated
45 public CommonResult<AppMemberUserInfoRespVO> getUserInfo() { 38 public CommonResult<AppMemberUserInfoRespVO> getUserInfo() {
46 MemberUserDO user = userService.getUser(getLoginUserId()); 39 MemberUserDO user = userService.getUser(getLoginUserId());
47 MemberLevelDO level = levelService.getLevel(user.getLevelId()); 40 MemberLevelDO level = levelService.getLevel(user.getLevelId());
48 - BrokerageUserDTO brokerageUser = brokerageApi.getBrokerageUser(user.getId());  
49 - return success(MemberUserConvert.INSTANCE.convert(user, level)  
50 - .setBrokerageEnabled(Optional.ofNullable(brokerageUser).map(BrokerageUserDTO::getBrokerageEnabled).orElse(false))  
51 - ); 41 + return success(MemberUserConvert.INSTANCE.convert(user, level));
52 } 42 }
53 43
54 @PutMapping("/update") 44 @PutMapping("/update")
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java
@@ -25,7 +25,7 @@ public interface AuthConvert { @@ -25,7 +25,7 @@ public interface AuthConvert {
25 SmsCodeUseReqDTO convert(AppMemberUserResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp); 25 SmsCodeUseReqDTO convert(AppMemberUserResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp);
26 SmsCodeUseReqDTO convert(AppAuthSmsLoginReqVO reqVO, Integer scene, String usedIp); 26 SmsCodeUseReqDTO convert(AppAuthSmsLoginReqVO reqVO, Integer scene, String usedIp);
27 27
28 - AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean); 28 + AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean, String openid);
29 29
30 SmsCodeValidateReqDTO convert(AppAuthSmsValidateReqVO bean); 30 SmsCodeValidateReqDTO convert(AppAuthSmsValidateReqVO bean);
31 31
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
@@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
20 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 20 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
21 import cn.iocoder.yudao.module.system.api.social.SocialUserApi; 21 import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
22 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 22 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  23 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
23 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; 24 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
24 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; 25 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
25 import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; 26 import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants;
@@ -65,13 +66,14 @@ public class MemberAuthServiceImpl implements MemberAuthService { @@ -65,13 +66,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
65 MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword()); 66 MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword());
66 67
67 // 如果 socialType 非空,说明需要绑定社交用户 68 // 如果 socialType 非空,说明需要绑定社交用户
  69 + String openid = null;
68 if (reqVO.getSocialType() != null) { 70 if (reqVO.getSocialType() != null) {
69 - socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), 71 + openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
70 reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); 72 reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
71 } 73 }
72 74
73 // 创建 Token 令牌,记录登录日志 75 // 创建 Token 令牌,记录登录日志
74 - return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE); 76 + return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, openid);
75 } 77 }
76 78
77 @Override 79 @Override
@@ -86,32 +88,33 @@ public class MemberAuthServiceImpl implements MemberAuthService { @@ -86,32 +88,33 @@ public class MemberAuthServiceImpl implements MemberAuthService {
86 Assert.notNull(user, "获取用户失败,结果为空"); 88 Assert.notNull(user, "获取用户失败,结果为空");
87 89
88 // 如果 socialType 非空,说明需要绑定社交用户 90 // 如果 socialType 非空,说明需要绑定社交用户
  91 + String openid = null;
89 if (reqVO.getSocialType() != null) { 92 if (reqVO.getSocialType() != null) {
90 - socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), 93 + openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
91 reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); 94 reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
92 } 95 }
93 96
94 // 创建 Token 令牌,记录登录日志 97 // 创建 Token 令牌,记录登录日志
95 - return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_SMS); 98 + return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_SMS, openid);
96 } 99 }
97 100
98 @Override 101 @Override
99 public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { 102 public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) {
100 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 103 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
101 - Long userId = socialUserApi.getBindUserId(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), 104 + SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(),
102 reqVO.getCode(), reqVO.getState()); 105 reqVO.getCode(), reqVO.getState());
103 - if (userId == null) { 106 + if (socialUser == null) {
104 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 107 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
105 } 108 }
106 109
107 // 自动登录 110 // 自动登录
108 - MemberUserDO user = userService.getUser(userId); 111 + MemberUserDO user = userService.getUser(socialUser.getUserId());
109 if (user == null) { 112 if (user == null) {
110 throw exception(USER_NOT_EXISTS); 113 throw exception(USER_NOT_EXISTS);
111 } 114 }
112 115
113 // 创建 Token 令牌,记录登录日志 116 // 创建 Token 令牌,记录登录日志
114 - return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL); 117 + return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid());
115 } 118 }
116 119
117 @Override 120 @Override
@@ -129,14 +132,15 @@ public class MemberAuthServiceImpl implements MemberAuthService { @@ -129,14 +132,15 @@ public class MemberAuthServiceImpl implements MemberAuthService {
129 Assert.notNull(user, "获取用户失败,结果为空"); 132 Assert.notNull(user, "获取用户失败,结果为空");
130 133
131 // 绑定社交用户 134 // 绑定社交用户
132 - socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), 135 + String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
133 SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), "")); 136 SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), ""));
134 137
135 // 创建 Token 令牌,记录登录日志 138 // 创建 Token 令牌,记录登录日志
136 - return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL); 139 + return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid);
137 } 140 }
138 141
139 - private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, LoginLogTypeEnum logType) { 142 + private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile,
  143 + LoginLogTypeEnum logType, String openid) {
140 // 插入登陆日志 144 // 插入登陆日志
141 createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS); 145 createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS);
142 // 创建 Token 令牌 146 // 创建 Token 令牌
@@ -144,7 +148,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { @@ -144,7 +148,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
144 .setUserId(user.getId()).setUserType(getUserType().getValue()) 148 .setUserId(user.getId()).setUserType(getUserType().getValue())
145 .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT)); 149 .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
146 // 构建返回结果 150 // 构建返回结果
147 - return AuthConvert.INSTANCE.convert(accessTokenRespDTO); 151 + return AuthConvert.INSTANCE.convert(accessTokenRespDTO, openid);
148 } 152 }
149 153
150 @Override 154 @Override
@@ -231,7 +235,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { @@ -231,7 +235,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
231 public AppAuthLoginRespVO refreshToken(String refreshToken) { 235 public AppAuthLoginRespVO refreshToken(String refreshToken) {
232 OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken, 236 OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken,
233 OAuth2ClientConstants.CLIENT_ID_DEFAULT); 237 OAuth2ClientConstants.CLIENT_ID_DEFAULT);
234 - return AuthConvert.INSTANCE.convert(accessTokenDO); 238 + return AuthConvert.INSTANCE.convert(accessTokenDO, null);
235 } 239 }
236 240
237 private void createLogoutLog(Long userId) { 241 private void createLogoutLog(Long userId) {
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java
@@ -29,4 +29,13 @@ public interface PayOrderApi { @@ -29,4 +29,13 @@ public interface PayOrderApi {
29 */ 29 */
30 PayOrderRespDTO getOrder(Long id); 30 PayOrderRespDTO getOrder(Long id);
31 31
  32 + // TODO @puhui999:可以去掉 byId;然后 payOrderId 参数改成 id;
  33 + /**
  34 + * 更新支付订单价格
  35 + *
  36 + * @param payOrderId 支付单编号
  37 + * @param payPrice 支付单价格
  38 + */
  39 + void updatePayOrderPriceById(Long payOrderId, Integer payPrice);
  40 +
32 } 41 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -28,6 +28,7 @@ public interface ErrorCodeConstants { @@ -28,6 +28,7 @@ public interface ErrorCodeConstants {
28 ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); 28 ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}");
29 ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); 29 ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款");
30 ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1007002006, "支付订单调价失败,原因:支付订单已付款,不能调价"); 30 ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1007002006, "支付订单调价失败,原因:支付订单已付款,不能调价");
  31 + ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1007002007, "支付订单调价失败,原因:价格没有变化");
31 32
32 // ========== ORDER 模块(拓展单) 1007003000 ========== 33 // ========== ORDER 模块(拓展单) 1007003000 ==========
33 ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); 34 ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在");
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java
@@ -31,4 +31,9 @@ public class PayOrderApiImpl implements PayOrderApi { @@ -31,4 +31,9 @@ public class PayOrderApiImpl implements PayOrderApi {
31 return PayOrderConvert.INSTANCE.convert2(order); 31 return PayOrderConvert.INSTANCE.convert2(order);
32 } 32 }
33 33
  34 + @Override
  35 + public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) {
  36 + payOrderService.updatePayOrderPriceById(payOrderId, payPrice);
  37 + }
  38 +
34 } 39 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java
@@ -6,14 +6,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -6,14 +6,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 6 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
7 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 7 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;  
10 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; 9 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*;
11 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; 10 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
12 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; 11 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 12 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
14 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
  14 +import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient;
15 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 15 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
16 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 16 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
  17 +import com.google.common.collect.Maps;
17 import io.swagger.v3.oas.annotations.Operation; 18 import io.swagger.v3.oas.annotations.Operation;
18 import io.swagger.v3.oas.annotations.Parameter; 19 import io.swagger.v3.oas.annotations.Parameter;
19 import io.swagger.v3.oas.annotations.tags.Tag; 20 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -25,12 +26,17 @@ import javax.annotation.Resource; @@ -25,12 +26,17 @@ import javax.annotation.Resource;
25 import javax.servlet.http.HttpServletResponse; 26 import javax.servlet.http.HttpServletResponse;
26 import javax.validation.Valid; 27 import javax.validation.Valid;
27 import java.io.IOException; 28 import java.io.IOException;
28 -import java.util.*; 29 +import java.util.ArrayList;
  30 +import java.util.List;
  31 +import java.util.Map;
  32 +import java.util.Objects;
29 33
30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 34 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 35 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
32 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 36 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
33 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 37 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
  38 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
  39 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
34 40
35 @Tag(name = "管理后台 - 支付订单") 41 @Tag(name = "管理后台 - 支付订单")
36 @RestController 42 @RestController
@@ -70,13 +76,16 @@ public class PayOrderController { @@ -70,13 +76,16 @@ public class PayOrderController {
70 @PostMapping("/submit") 76 @PostMapping("/submit")
71 @Operation(summary = "提交支付订单") 77 @Operation(summary = "提交支付订单")
72 public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { 78 public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) {
73 - // 钱包支付需要 额外传 user_id 和 user_type 79 + // 1. 钱包支付事,需要额外传 user_id 和 user_type
74 if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) { 80 if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) {
75 - Map<String, String> channelExtras = reqVO.getChannelExtras() == null ? new HashMap<>(8) : reqVO.getChannelExtras();  
76 - channelExtras.put("user_id", String.valueOf(WebFrameworkUtils.getLoginUserId()));  
77 - channelExtras.put("user_type", String.valueOf(WebFrameworkUtils.getLoginUserType())); 81 + Map<String, String> channelExtras = reqVO.getChannelExtras() == null ?
  82 + Maps.newHashMapWithExpectedSize(2) : reqVO.getChannelExtras();
  83 + channelExtras.put(WalletPayClient.USER_ID_KEY, String.valueOf(getLoginUserId()));
  84 + channelExtras.put(WalletPayClient.USER_TYPE_KEY, String.valueOf(getLoginUserType()));
78 reqVO.setChannelExtras(channelExtras); 85 reqVO.setChannelExtras(channelExtras);
79 } 86 }
  87 +
  88 + // 2. 提交支付
80 PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP()); 89 PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP());
81 return success(respVO); 90 return success(respVO);
82 } 91 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java
@@ -37,7 +37,7 @@ public class AppPayWalletController { @@ -37,7 +37,7 @@ public class AppPayWalletController {
37 @Operation(summary = "获取钱包") 37 @Operation(summary = "获取钱包")
38 @PreAuthenticated 38 @PreAuthenticated
39 public CommonResult<AppPayWalletRespVO> getPayWallet() { 39 public CommonResult<AppPayWalletRespVO> getPayWallet() {
40 - PayWalletDO wallet = payWalletService.getOrCreatePayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); 40 + PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
41 return success(PayWalletConvert.INSTANCE.convert(wallet)); 41 return success(PayWalletConvert.INSTANCE.convert(wallet));
42 } 42 }
43 43
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java
@@ -11,9 +11,9 @@ public class AppPayWalletRespVO { @@ -11,9 +11,9 @@ public class AppPayWalletRespVO {
11 private Integer balance; 11 private Integer balance;
12 12
13 @Schema(description = "累计支出, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") 13 @Schema(description = "累计支出, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
14 - private Long totalExpense; 14 + private Integer totalExpense;
15 15
16 @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") 16 @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
17 - private Long totalRecharge; 17 + private Integer totalRecharge;
18 18
19 } 19 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.wallet; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.wallet;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO; 4 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
  6 +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO;
6 import org.mapstruct.Mapper; 7 import org.mapstruct.Mapper;
7 import org.mapstruct.factory.Mappers; 8 import org.mapstruct.factory.Mappers;
8 9
@@ -12,4 +13,7 @@ public interface PayWalletTransactionConvert { @@ -12,4 +13,7 @@ public interface PayWalletTransactionConvert {
12 PayWalletTransactionConvert INSTANCE = Mappers.getMapper(PayWalletTransactionConvert.class); 13 PayWalletTransactionConvert INSTANCE = Mappers.getMapper(PayWalletTransactionConvert.class);
13 14
14 PageResult<AppPayWalletTransactionRespVO> convertPage(PageResult<PayWalletTransactionDO> page); 15 PageResult<AppPayWalletTransactionRespVO> convertPage(PageResult<PayWalletTransactionDO> page);
  16 +
  17 + PayWalletTransactionDO convert(CreateWalletTransactionBO bean);
  18 +
15 } 19 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java
@@ -45,10 +45,10 @@ public class PayWalletDO extends BaseDO { @@ -45,10 +45,10 @@ public class PayWalletDO extends BaseDO {
45 /** 45 /**
46 * 累计支出,单位分 46 * 累计支出,单位分
47 */ 47 */
48 - private Long totalExpense; 48 + private Integer totalExpense;
49 /** 49 /**
50 * 累计充值,单位分 50 * 累计充值,单位分
51 */ 51 */
52 - private Long totalRecharge; 52 + private Integer totalRecharge;
53 53
54 } 54 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java
@@ -3,8 +3,7 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet; @@ -3,8 +3,7 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet;
3 3
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
6 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;  
7 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 6 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
8 import org.apache.ibatis.annotations.Mapper; 7 import org.apache.ibatis.annotations.Mapper;
9 8
10 @Mapper 9 @Mapper
@@ -16,52 +15,32 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; { @@ -16,52 +15,32 @@ public interface PayWalletMapper extends BaseMapperX&lt;PayWalletDO&gt; {
16 } 15 }
17 16
18 /** 17 /**
19 - * 当余额减少时候更新 18 + * 当消费退款时候, 更新钱包
20 * 19 *
21 - * @param bizType 业务类型  
22 - * @param balance 当前余额  
23 - * @param totalRecharge 当前累计充值  
24 - * @param totalExpense 当前累计支出  
25 - * @param price 支出的金额 20 + * @param price 消费金额
26 * @param id 钱包 id 21 * @param id 钱包 id
27 */ 22 */
28 - default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge,  
29 - Long totalExpense, Integer price, Long id) {  
30 - PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price);  
31 - if(bizType == PayWalletBizTypeEnum.PAYMENT){  
32 - updateDO.setTotalExpense(totalExpense + price);  
33 - }  
34 - if (bizType == PayWalletBizTypeEnum.RECHARGE_REFUND) {  
35 - updateDO.setTotalRecharge(totalRecharge - price);  
36 - }  
37 - return update(updateDO,  
38 - new LambdaQueryWrapper<PayWalletDO>().eq(PayWalletDO::getId, id)  
39 - .eq(PayWalletDO::getBalance, balance)  
40 - .ge(PayWalletDO::getBalance, price)); 23 + default int updateWhenConsumptionRefund(Integer price, Long id){
  24 + LambdaUpdateWrapper<PayWalletDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<PayWalletDO>()
  25 + .setSql(" balance = balance + " + price
  26 + + ", total_expense = total_expense - " + price)
  27 + .eq(PayWalletDO::getId, id);
  28 + return update(null, lambdaUpdateWrapper);
41 } 29 }
42 30
43 /** 31 /**
44 - * 当余额增加时候更新 32 + * 当消费时候, 更新钱包
45 * 33 *
46 - * @param bizType 业务类型  
47 - * @param balance 当前余额  
48 - * @param totalRecharge 当前累计充值  
49 - * @param totalExpense 当前累计支出  
50 - * @param price 金额 34 + * @param price 消费金额
51 * @param id 钱包 id 35 * @param id 钱包 id
52 */ 36 */
53 - default int updateWhenIncBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge,  
54 - Long totalExpense, Integer price, Long id) {  
55 - PayWalletDO updateDO = new PayWalletDO().setBalance(balance + price);  
56 - if (bizType == PayWalletBizTypeEnum.PAYMENT_REFUND) {  
57 - updateDO.setTotalExpense(totalExpense - price);  
58 - }  
59 - if (bizType == PayWalletBizTypeEnum.RECHARGE) {  
60 - updateDO.setTotalExpense(totalRecharge + price);  
61 - }  
62 - return update(updateDO,  
63 - new LambdaQueryWrapper<PayWalletDO>().eq(PayWalletDO::getId, id)  
64 - .eq(PayWalletDO::getBalance, balance)); 37 + default int updateWhenConsumption(Integer price, Long id){
  38 + LambdaUpdateWrapper<PayWalletDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<PayWalletDO>()
  39 + .setSql(" balance = balance - " + price
  40 + + ", total_expense = total_expense + " + price)
  41 + .eq(PayWalletDO::getId, id)
  42 + .ge(PayWalletDO::getBalance, price); // cas 逻辑
  43 + return update(null, lambdaUpdateWrapper);
65 } 44 }
66 } 45 }
67 46
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java
@@ -37,13 +37,13 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FO @@ -37,13 +37,13 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FO
37 @Slf4j 37 @Slf4j
38 public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { 38 public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> {
39 39
40 - private PayWalletService wallService; 40 + public static final String USER_ID_KEY = "user_id";
  41 + public static final String USER_TYPE_KEY = "user_type";
41 42
  43 + private PayWalletService wallService;
42 private PayWalletTransactionService walletTransactionService; 44 private PayWalletTransactionService walletTransactionService;
43 -  
44 - private PayOrderService payOrderService;  
45 -  
46 - private PayRefundService payRefundService; 45 + private PayOrderService orderService;
  46 + private PayRefundService refundService;
47 47
48 public WalletPayClient(Long channelId, NonePayClientConfig config) { 48 public WalletPayClient(Long channelId, NonePayClientConfig config) {
49 super(channelId, PayChannelEnum.WALLET.getCode(), config); 49 super(channelId, PayChannelEnum.WALLET.getCode(), config);
@@ -62,12 +62,12 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -62,12 +62,12 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
62 @Override 62 @Override
63 protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { 63 protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
64 try { 64 try {
65 - String userId = MapUtil.getStr(reqDTO.getChannelExtras(), "user_id");  
66 - String userType = MapUtil.getStr(reqDTO.getChannelExtras(), "user_type");  
67 - Assert.notEmpty(userId, "用户 id 不能为空");  
68 - Assert.notEmpty(userType, "用户类型不能为空");  
69 - PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType),  
70 - reqDTO.getOutTradeNo(), reqDTO.getPrice()); 65 + Long userId = MapUtil.getLong(reqDTO.getChannelExtras(), USER_ID_KEY);
  66 + Integer userType = MapUtil.getInt(reqDTO.getChannelExtras(), USER_TYPE_KEY);
  67 + Assert.notNull(userId, "用户 id 不能为空");
  68 + Assert.notNull(userType, "用户类型不能为空");
  69 + PayWalletTransactionDO transaction = wallService.orderPay(userId, userType, reqDTO.getOutTradeNo(),
  70 + reqDTO.getPrice());
71 return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), 71 return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(),
72 transaction.getCreateTime(), 72 transaction.getCreateTime(),
73 reqDTO.getOutTradeNo(), transaction); 73 reqDTO.getOutTradeNo(), transaction);
@@ -92,10 +92,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -92,10 +92,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
92 92
93 @Override 93 @Override
94 protected PayOrderRespDTO doGetOrder(String outTradeNo) { 94 protected PayOrderRespDTO doGetOrder(String outTradeNo) {
95 - if (payOrderService == null) {  
96 - payOrderService = SpringUtil.getBean(PayOrderService.class); 95 + if (orderService == null) {
  96 + orderService = SpringUtil.getBean(PayOrderService.class);
97 } 97 }
98 - PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); 98 + PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo);
99 // 支付交易拓展单不存在, 返回关闭状态 99 // 支付交易拓展单不存在, 返回关闭状态
100 if (orderExtension == null) { 100 if (orderExtension == null) {
101 return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()), 101 return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()),
@@ -147,10 +147,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -147,10 +147,10 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
147 147
148 @Override 148 @Override
149 protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { 149 protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
150 - if (payRefundService == null) {  
151 - payRefundService = SpringUtil.getBean(PayRefundService.class); 150 + if (refundService == null) {
  151 + refundService = SpringUtil.getBean(PayRefundService.class);
152 } 152 }
153 - PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); 153 + PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo);
154 // 支付退款单不存在, 返回退款失败状态 154 // 支付退款单不存在, 返回退款失败状态
155 if (payRefund == null) { 155 if (payRefund == null) {
156 return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(), 156 return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(),
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
@@ -33,7 +33,7 @@ public interface PayOrderService { @@ -33,7 +33,7 @@ public interface PayOrderService {
33 /** 33 /**
34 * 获得支付订单 34 * 获得支付订单
35 * 35 *
36 - * @param appId 应用编号 36 + * @param appId 应用编号
37 * @param merchantOrderId 商户订单编号 37 * @param merchantOrderId 商户订单编号
38 * @return 支付订单 38 * @return 支付订单
39 */ 39 */
@@ -75,7 +75,7 @@ public interface PayOrderService { @@ -75,7 +75,7 @@ public interface PayOrderService {
75 * 提交支付 75 * 提交支付
76 * 此时,会发起支付渠道的调用 76 * 此时,会发起支付渠道的调用
77 * 77 *
78 - * @param reqVO 提交请求 78 + * @param reqVO 提交请求
79 * @param userIp 提交 IP 79 * @param userIp 提交 IP
80 * @return 提交结果 80 * @return 提交结果
81 */ 81 */
@@ -93,12 +93,20 @@ public interface PayOrderService { @@ -93,12 +93,20 @@ public interface PayOrderService {
93 /** 93 /**
94 * 更新支付订单的退款金额 94 * 更新支付订单的退款金额
95 * 95 *
96 - * @param id 编号 96 + * @param id 编号
97 * @param incrRefundPrice 增加的退款金额 97 * @param incrRefundPrice 增加的退款金额
98 */ 98 */
99 void updateOrderRefundPrice(Long id, Integer incrRefundPrice); 99 void updateOrderRefundPrice(Long id, Integer incrRefundPrice);
100 100
101 /** 101 /**
  102 + * 更新支付订单价格
  103 + *
  104 + * @param payOrderId 支付单编号
  105 + * @param payPrice 支付单价格
  106 + */
  107 + void updatePayOrderPriceById(Long payOrderId, Integer payPrice);
  108 +
  109 + /**
102 * 获得支付订单 110 * 获得支付订单
103 * 111 *
104 * @param id 编号 112 * @param id 编号
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -412,6 +412,18 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -412,6 +412,18 @@ public class PayOrderServiceImpl implements PayOrderService {
412 } 412 }
413 413
414 @Override 414 @Override
  415 + public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) {
  416 + // TODO @puhui999:不能直接这样修改哈;应该只有未支付状态的订单才可以改;另外,如果价格如果没变,可以直接 return 哈;
  417 + PayOrderDO order = orderMapper.selectById(payOrderId);
  418 + if (order == null) {
  419 + throw exception(ORDER_NOT_FOUND);
  420 + }
  421 +
  422 + order.setPrice(payPrice);
  423 + orderMapper.updateById(order);
  424 + }
  425 +
  426 + @Override
415 public PayOrderExtensionDO getOrderExtension(Long id) { 427 public PayOrderExtensionDO getOrderExtension(Long id) {
416 return orderExtensionMapper.selectById(id); 428 return orderExtensionMapper.selectById(id);
417 } 429 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
@@ -12,12 +12,14 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; @@ -12,12 +12,14 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
12 public interface PayWalletService { 12 public interface PayWalletService {
13 13
14 /** 14 /**
15 - * 获取钱包信息,如果不存在创建钱包。由于用户注册时候不会创建钱包 15 + * 获取钱包信息
  16 + *
  17 + * 如果不存在,则创建钱包。由于用户注册时候不会创建钱包
16 * 18 *
17 * @param userId 用户编号 19 * @param userId 用户编号
18 * @param userType 用户类型 20 * @param userType 用户类型
19 */ 21 */
20 - PayWalletDO getOrCreatePayWallet(Long userId, Integer userType); 22 + PayWalletDO getOrCreateWallet(Long userId, Integer userType);
21 23
22 /** 24 /**
23 * 钱包订单支付 25 * 钱包订单支付
@@ -29,6 +31,14 @@ public interface PayWalletService { @@ -29,6 +31,14 @@ public interface PayWalletService {
29 */ 31 */
30 PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price); 32 PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price);
31 33
  34 + /**
  35 + * 钱包订单支付退款
  36 + *
  37 + * @param outRefundNo 外部退款号
  38 + * @param refundPrice 退款金额
  39 + * @param reason 退款原因
  40 + */
  41 + PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason);
32 42
33 /** 43 /**
34 * 扣减钱包余额 44 * 扣减钱包余额
@@ -43,7 +53,6 @@ public interface PayWalletService { @@ -43,7 +53,6 @@ public interface PayWalletService {
43 PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, 53 PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType,
44 Long bizId, PayWalletBizTypeEnum bizType, Integer price); 54 Long bizId, PayWalletBizTypeEnum bizType, Integer price);
45 55
46 -  
47 /** 56 /**
48 * 增加钱包余额 57 * 增加钱包余额
49 * 58 *
@@ -57,13 +66,4 @@ public interface PayWalletService { @@ -57,13 +66,4 @@ public interface PayWalletService {
57 PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, 66 PayWalletTransactionDO addWalletBalance(Long userId, Integer userType,
58 Long bizId, PayWalletBizTypeEnum bizType, Integer price); 67 Long bizId, PayWalletBizTypeEnum bizType, Integer price);
59 68
60 - /**  
61 - * 钱包订单支付退款  
62 - *  
63 - * @param outRefundNo 外部退款号  
64 - * @param refundPrice 退款金额  
65 - * @param reason 退款原因  
66 - */  
67 - PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason);  
68 -  
69 } 69 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
@@ -6,10 +6,10 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; @@ -6,10 +6,10 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
7 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
8 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; 8 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper;
9 -import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;  
10 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 9 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
11 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 10 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
12 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 11 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
  12 +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
14 import org.springframework.context.annotation.Lazy; 14 import org.springframework.context.annotation.Lazy;
15 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
@@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional; @@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional;
18 import javax.annotation.Resource; 18 import javax.annotation.Resource;
19 import java.time.LocalDateTime; 19 import java.time.LocalDateTime;
20 20
21 -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.TOO_MANY_REQUESTS;  
22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 21 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
23 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 22 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
24 import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; 23 import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT;
@@ -33,135 +32,55 @@ import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYM @@ -33,135 +32,55 @@ import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYM
33 @Slf4j 32 @Slf4j
34 public class PayWalletServiceImpl implements PayWalletService { 33 public class PayWalletServiceImpl implements PayWalletService {
35 34
36 - /**  
37 - * 余额支付的 no 前缀  
38 - */  
39 - private static final String WALLET_PAY_NO_PREFIX = "WP";  
40 - /**  
41 - * 余额退款的 no 前缀  
42 - */  
43 - private static final String WALLET_REFUND_NO_PREFIX = "WR";  
44 -  
45 - @Resource  
46 - private PayWalletMapper payWalletMapper;  
47 @Resource 35 @Resource
48 - private PayNoRedisDAO noRedisDAO;  
49 - 36 + private PayWalletMapper walletMapper;
50 @Resource 37 @Resource
51 - private PayWalletTransactionService payWalletTransactionService; 38 + private PayWalletTransactionService walletTransactionService;
52 @Resource 39 @Resource
53 @Lazy 40 @Lazy
54 - private PayOrderService payOrderService; 41 + private PayOrderService orderService;
55 @Resource 42 @Resource
56 @Lazy 43 @Lazy
57 - private PayRefundService payRefundService; 44 + private PayRefundService refundService;
58 45
59 @Override 46 @Override
60 - public PayWalletDO getOrCreatePayWallet(Long userId, Integer userType) {  
61 - PayWalletDO payWalletDO = payWalletMapper.selectByUserIdAndType(userId, userType);  
62 - if (payWalletDO == null) {  
63 - payWalletDO = new PayWalletDO();  
64 - payWalletDO.setUserId(userId);  
65 - payWalletDO.setUserType(userType);  
66 - payWalletDO.setBalance(0);  
67 - payWalletDO.setTotalExpense(0L);  
68 - payWalletDO.setTotalRecharge(0L);  
69 - payWalletDO.setCreateTime(LocalDateTime.now());  
70 - payWalletMapper.insert(payWalletDO); 47 + public PayWalletDO getOrCreateWallet(Long userId, Integer userType) {
  48 + PayWalletDO wallet = walletMapper.selectByUserIdAndType(userId, userType);
  49 + if (wallet == null) {
  50 + wallet = new PayWalletDO().setUserId(userId).setUserType(userType)
  51 + .setBalance(0).setTotalExpense(0).setTotalRecharge(0);
  52 + wallet.setCreateTime(LocalDateTime.now());
  53 + walletMapper.insert(wallet);
71 } 54 }
72 - return payWalletDO; 55 + return wallet;
73 } 56 }
74 57
75 -  
76 @Override 58 @Override
77 @Transactional(rollbackFor = Exception.class) 59 @Transactional(rollbackFor = Exception.class)
78 public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) { 60 public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) {
79 - // 判断支付交易拓展单是否存  
80 - PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); 61 + // 1. 判断支付交易拓展单是否存
  62 + PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo);
81 if (orderExtension == null) { 63 if (orderExtension == null) {
82 throw exception(ORDER_EXTENSION_NOT_FOUND); 64 throw exception(ORDER_EXTENSION_NOT_FOUND);
83 } 65 }
  66 + // 2. 扣减余额
84 return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price); 67 return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price);
85 } 68 }
86 69
87 @Override 70 @Override
88 - public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType,  
89 - Long bizId, PayWalletBizTypeEnum bizType, Integer price) {  
90 - // 1.1 获取钱包  
91 - PayWalletDO payWallet = getOrCreatePayWallet(userId, userType);  
92 - // 1.2 判断余额是否足够  
93 - int afterBalance = payWallet.getBalance() - price;  
94 - if (afterBalance < 0) {  
95 - throw exception(WALLET_BALANCE_NOT_ENOUGH);  
96 - }  
97 -  
98 - // 2.1 扣除余额  
99 - int number = payWalletMapper.updateWhenDecBalance(bizType,payWallet.getBalance(), payWallet.getTotalRecharge(),  
100 - payWallet.getTotalExpense(), price, payWallet.getId());  
101 - if (number == 0) {  
102 - throw exception(TOO_MANY_REQUESTS);  
103 - }  
104 - // 2.2 生成钱包流水  
105 - String walletNo = generateWalletNo(bizType);  
106 - PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId())  
107 - .setNo(walletNo).setPrice(-price).setBalance(afterBalance)  
108 - .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription());  
109 - payWalletTransactionService.createWalletTransaction(walletTransaction);  
110 - return walletTransaction;  
111 - }  
112 -  
113 - @Override  
114 - public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, Long bizId,  
115 - PayWalletBizTypeEnum bizType, Integer price) {  
116 - // 1.1 获取钱包  
117 - PayWalletDO payWallet = getOrCreatePayWallet(userId, userType);  
118 -  
119 - // 2.1 增加余额  
120 - int number = payWalletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(),  
121 - payWallet.getTotalExpense(), price, payWallet.getId());  
122 - if (number == 0) {  
123 - throw exception(TOO_MANY_REQUESTS);  
124 - }  
125 -  
126 - // 2.2 生成钱包流水  
127 - String walletNo = generateWalletNo(bizType);  
128 - PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId())  
129 - .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price)  
130 - .setBizId(String.valueOf(bizId)).setBizType(bizType.getType())  
131 - .setTitle(bizType.getDescription());  
132 - payWalletTransactionService.createWalletTransaction(newWalletTransaction);  
133 - return newWalletTransaction;  
134 - }  
135 -  
136 - private String generateWalletNo(PayWalletBizTypeEnum bizType) {  
137 - String no = "";  
138 - switch(bizType){  
139 - case PAYMENT :  
140 - no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX);  
141 - break;  
142 - case PAYMENT_REFUND :  
143 - no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX);  
144 - break;  
145 - default :  
146 - // TODO 待增加  
147 - }  
148 - return no;  
149 - }  
150 -  
151 - @Override  
152 @Transactional(rollbackFor = Exception.class) 71 @Transactional(rollbackFor = Exception.class)
153 public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) { 72 public PayWalletTransactionDO orderRefund(String outRefundNo, Integer refundPrice, String reason) {
154 // 1.1 判断退款单是否存在 73 // 1.1 判断退款单是否存在
155 - PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); 74 + PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo);
156 if (payRefund == null) { 75 if (payRefund == null) {
157 throw exception(REFUND_NOT_FOUND); 76 throw exception(REFUND_NOT_FOUND);
158 } 77 }
159 // 1.2 校验是否可以退款 78 // 1.2 校验是否可以退款
160 - Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice);  
161 -  
162 - PayWalletDO payWallet = payWalletMapper.selectById(walletId);  
163 - Assert.notNull(payWallet, "钱包 {} 不存在", walletId);  
164 - return addWalletBalance(payWallet.getUserId(), payWallet.getUserType(),payRefund.getId(), PAYMENT_REFUND, refundPrice); 79 + Long walletId = validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), refundPrice);
  80 + PayWalletDO wallet = walletMapper.selectById(walletId);
  81 + Assert.notNull(wallet, "钱包 {} 不存在", walletId);
  82 + // 2. 增加余额
  83 + return addWalletBalance(wallet.getUserId(), wallet.getUserType(), payRefund.getId(), PAYMENT_REFUND, refundPrice);
165 } 84 }
166 85
167 /** 86 /**
@@ -171,21 +90,76 @@ public class PayWalletServiceImpl implements PayWalletService { @@ -171,21 +90,76 @@ public class PayWalletServiceImpl implements PayWalletService {
171 * @param walletPayNo 钱包支付 no 90 * @param walletPayNo 钱包支付 no
172 */ 91 */
173 private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) { 92 private Long validateWalletCanRefund(Long refundId, String walletPayNo, Integer refundPrice) {
174 - // 查询钱包支付交易  
175 - PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo);  
176 - if (payWalletTransaction == null) { 93 + // 1. 校验钱包支付交易存在
  94 + PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransactionByNo(walletPayNo);
  95 + if (walletTransaction == null) {
177 throw exception(WALLET_TRANSACTION_NOT_FOUND); 96 throw exception(WALLET_TRANSACTION_NOT_FOUND);
178 } 97 }
179 // 原来的支付金额 98 // 原来的支付金额
180 - int amount = - payWalletTransaction.getPrice(); 99 + // TODO @jason:应该允许多次退款哈;
  100 + int amount = - walletTransaction.getPrice();
181 if (refundPrice != amount) { 101 if (refundPrice != amount) {
182 throw exception(WALLET_REFUND_AMOUNT_ERROR); 102 throw exception(WALLET_REFUND_AMOUNT_ERROR);
183 } 103 }
184 - PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction( 104 + PayWalletTransactionDO refundTransaction = walletTransactionService.getWalletTransaction(
185 String.valueOf(refundId), PAYMENT_REFUND); 105 String.valueOf(refundId), PAYMENT_REFUND);
186 if (refundTransaction != null) { 106 if (refundTransaction != null) {
187 throw exception(WALLET_REFUND_EXIST); 107 throw exception(WALLET_REFUND_EXIST);
188 } 108 }
189 - return payWalletTransaction.getWalletId(); 109 + return walletTransaction.getWalletId();
  110 + }
  111 +
  112 + @Override
  113 + public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType,
  114 + Long bizId, PayWalletBizTypeEnum bizType, Integer price) {
  115 + // 1. 获取钱包
  116 + PayWalletDO payWallet = getOrCreateWallet(userId, userType);
  117 +
  118 + // 2.1 扣除余额
  119 + int updateCounts = 0 ;
  120 + switch (bizType) {
  121 + case PAYMENT: {
  122 + updateCounts = walletMapper.updateWhenConsumption(price, payWallet.getId());
  123 + break;
  124 + }
  125 + case RECHARGE_REFUND: {
  126 + // TODO
  127 + break;
  128 + }
  129 + }
  130 + if (updateCounts == 0) {
  131 + throw exception(WALLET_BALANCE_NOT_ENOUGH);
  132 + }
  133 + // 2.2 生成钱包流水
  134 + Integer afterBalance = payWallet.getBalance() - price;
  135 + CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId())
  136 + .setPrice(-price).setBalance(afterBalance).setBizId(String.valueOf(bizId))
  137 + .setBizType(bizType.getType()).setTitle(bizType.getDescription());
  138 + return walletTransactionService.createWalletTransaction(bo);
190 } 139 }
  140 +
  141 + @Override
  142 + public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType,
  143 + Long bizId, PayWalletBizTypeEnum bizType, Integer price) {
  144 + // 1. 获取钱包
  145 + PayWalletDO payWallet = getOrCreateWallet(userId, userType);
  146 + switch (bizType) {
  147 + case PAYMENT_REFUND: {
  148 + // 更新退款
  149 + walletMapper.updateWhenConsumptionRefund(price, payWallet.getId());
  150 + break;
  151 + }
  152 + case RECHARGE: {
  153 + //TODO
  154 + break;
  155 + }
  156 + }
  157 +
  158 + // 2. 生成钱包流水
  159 + CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId())
  160 + .setPrice(price).setBalance(payWallet.getBalance()+price).setBizId(String.valueOf(bizId))
  161 + .setBizType(bizType.getType()).setTitle(bizType.getDescription());
  162 + return walletTransactionService.createWalletTransaction(bo);
  163 + }
  164 +
191 } 165 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java
@@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; 4 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
6 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 6 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
  7 +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO;
  8 +
  9 +import javax.validation.Valid;
7 10
8 /** 11 /**
9 * 钱包余额流水 Service 接口 12 * 钱包余额流水 Service 接口
@@ -25,10 +28,10 @@ public interface PayWalletTransactionService { @@ -25,10 +28,10 @@ public interface PayWalletTransactionService {
25 /** 28 /**
26 * 新增钱包余额流水 29 * 新增钱包余额流水
27 * 30 *
28 - * @param payWalletTransaction 余额流水  
29 - * @return id 31 + * @param bo 创建钱包流水 bo
  32 + * @return 新建的钱包 do
30 */ 33 */
31 - Long createWalletTransaction(PayWalletTransactionDO payWalletTransaction); 34 + PayWalletTransactionDO createWalletTransaction(@Valid CreateWalletTransactionBO bo);
32 35
33 /** 36 /**
34 * 根据 no,获取钱包余流水 37 * 根据 no,获取钱包余流水
@@ -45,4 +48,5 @@ public interface PayWalletTransactionService { @@ -45,4 +48,5 @@ public interface PayWalletTransactionService {
45 * @return 钱包流水 48 * @return 钱包流水
46 */ 49 */
47 PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type); 50 PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type);
  51 +
48 } 52 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java
@@ -2,10 +2,13 @@ package cn.iocoder.yudao.module.pay.service.wallet; @@ -2,10 +2,13 @@ package cn.iocoder.yudao.module.pay.service.wallet;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; 4 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO;
  5 +import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletTransactionConvert;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
7 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper; 8 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper;
  9 +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
8 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 10 import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
  11 +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO;
9 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
10 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
11 14
@@ -20,22 +23,31 @@ import javax.annotation.Resource; @@ -20,22 +23,31 @@ import javax.annotation.Resource;
20 @Slf4j 23 @Slf4j
21 public class PayWalletTransactionServiceImpl implements PayWalletTransactionService { 24 public class PayWalletTransactionServiceImpl implements PayWalletTransactionService {
22 25
  26 + /**
  27 + * 钱包流水的 no 前缀
  28 + */
  29 + private static final String WALLET_NO_PREFIX = "W";
  30 +
23 @Resource 31 @Resource
24 private PayWalletService payWalletService; 32 private PayWalletService payWalletService;
25 @Resource 33 @Resource
26 private PayWalletTransactionMapper payWalletTransactionMapper; 34 private PayWalletTransactionMapper payWalletTransactionMapper;
  35 + @Resource
  36 + private PayNoRedisDAO noRedisDAO;
27 37
28 @Override 38 @Override
29 public PageResult<PayWalletTransactionDO> getWalletTransactionPage(Long userId, Integer userType, 39 public PageResult<PayWalletTransactionDO> getWalletTransactionPage(Long userId, Integer userType,
30 AppPayWalletTransactionPageReqVO pageVO) { 40 AppPayWalletTransactionPageReqVO pageVO) {
31 - PayWalletDO wallet = payWalletService.getOrCreatePayWallet(userId, userType); 41 + PayWalletDO wallet = payWalletService.getOrCreateWallet(userId, userType);
32 return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO); 42 return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO);
33 } 43 }
34 44
35 @Override 45 @Override
36 - public Long createWalletTransaction(PayWalletTransactionDO payWalletTransaction) {  
37 - payWalletTransactionMapper.insert(payWalletTransaction);  
38 - return payWalletTransaction.getId(); 46 + public PayWalletTransactionDO createWalletTransaction(CreateWalletTransactionBO bo) {
  47 + PayWalletTransactionDO transaction = PayWalletTransactionConvert.INSTANCE.convert(bo)
  48 + .setNo(noRedisDAO.generate(WALLET_NO_PREFIX));
  49 + payWalletTransactionMapper.insert(transaction);
  50 + return transaction;
39 } 51 }
40 52
41 @Override 53 @Override
@@ -47,4 +59,5 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ @@ -47,4 +59,5 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ
47 public PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type) { 59 public PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type) {
48 return payWalletTransactionMapper.selectByBiz(bizId, type.getType()); 60 return payWalletTransactionMapper.selectByBiz(bizId, type.getType());
49 } 61 }
  62 +
50 } 63 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/CreateWalletTransactionBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.service.wallet.bo;
  2 +
  3 +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * 创建钱包流水 BO
  8 + *
  9 + * @author jason
  10 + */
  11 +@Data
  12 +public class CreateWalletTransactionBO {
  13 +
  14 + // TODO @jason:bo 的话,最好加个参数校验哈;
  15 +
  16 + /**
  17 + * 钱包编号
  18 + *
  19 + */
  20 + private Long walletId;
  21 +
  22 + /**
  23 + * 交易金额,单位分
  24 + *
  25 + * 正值表示余额增加,负值表示余额减少
  26 + */
  27 + private Integer price;
  28 +
  29 + /**
  30 + * 交易后余额,单位分
  31 + */
  32 + private Integer balance;
  33 +
  34 + /**
  35 + * 关联业务分类
  36 + *
  37 + * 枚举 {@link PayWalletBizTypeEnum#getType()}
  38 + */
  39 + private Integer bizType;
  40 +
  41 + /**
  42 + * 关联业务编号
  43 + */
  44 + private String bizId;
  45 +
  46 + /**
  47 + * 流水说明
  48 + */
  49 + private String title;
  50 +}
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.social; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.social;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
4 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 4 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  5 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
5 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; 6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
6 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 7 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
7 8
@@ -27,8 +28,9 @@ public interface SocialUserApi { @@ -27,8 +28,9 @@ public interface SocialUserApi {
27 * 绑定社交用户 28 * 绑定社交用户
28 * 29 *
29 * @param reqDTO 绑定信息 30 * @param reqDTO 绑定信息
  31 + * @return 社交用户 openid
30 */ 32 */
31 - void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); 33 + String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO);
32 34
33 /** 35 /**
34 * 取消绑定社交用户 36 * 取消绑定社交用户
@@ -38,16 +40,17 @@ public interface SocialUserApi { @@ -38,16 +40,17 @@ public interface SocialUserApi {
38 void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO); 40 void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO);
39 41
40 /** 42 /**
41 - * 获得社交用户的绑定用户编号  
42 - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! 43 + * 获得社交用户
  44 + *
43 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 45 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
44 * 46 *
45 * @param userType 用户类型 47 * @param userType 用户类型
46 * @param type 社交平台的类型 48 * @param type 社交平台的类型
47 * @param code 授权码 49 * @param code 授权码
48 * @param state state 50 * @param state state
49 - * @return 绑定用户编号 51 + * @return 社交用户
50 */ 52 */
51 - Long getBindUserId(Integer userType, Integer type, String code, String state); 53 + SocialUserRespDTO getSocialUser(Integer userType, Integer type,
  54 + String code, String state);
52 55
53 } 56 }
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.api.social.dto;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +
  7 +/**
  8 + * 社交用户 Response DTO
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Data
  13 +@NoArgsConstructor
  14 +@AllArgsConstructor
  15 +public class SocialUserRespDTO {
  16 +
  17 + /**
  18 + * 社交用户 openid
  19 + */
  20 + private String openid;
  21 +
  22 + /**
  23 + * 关联的用户编号
  24 + */
  25 + private Long userId;
  26 +
  27 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java
1 package cn.iocoder.yudao.module.system.api.social; 1 package cn.iocoder.yudao.module.system.api.social;
2 2
3 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 3 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  4 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
4 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; 5 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
5 import cn.iocoder.yudao.module.system.service.social.SocialUserService; 6 import cn.iocoder.yudao.module.system.service.social.SocialUserService;
6 import org.springframework.stereotype.Service; 7 import org.springframework.stereotype.Service;
@@ -26,8 +27,8 @@ public class SocialUserApiImpl implements SocialUserApi { @@ -26,8 +27,8 @@ public class SocialUserApiImpl implements SocialUserApi {
26 } 27 }
27 28
28 @Override 29 @Override
29 - public void bindSocialUser(SocialUserBindReqDTO reqDTO) {  
30 - socialUserService.bindSocialUser(reqDTO); 30 + public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
  31 + return socialUserService.bindSocialUser(reqDTO);
31 } 32 }
32 33
33 @Override 34 @Override
@@ -37,8 +38,8 @@ public class SocialUserApiImpl implements SocialUserApi { @@ -37,8 +38,8 @@ public class SocialUserApiImpl implements SocialUserApi {
37 } 38 }
38 39
39 @Override 40 @Override
40 - public Long getBindUserId(Integer userType, Integer type, String code, String state) {  
41 - return socialUserService.getBindUserId(userType, type, code, state); 41 + public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) {
  42 + return socialUserService.getSocialUser(userType, type, code, state);
42 } 43 }
43 44
44 } 45 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
9 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; 9 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
10 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 10 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
11 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 11 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  12 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
12 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; 13 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
13 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; 14 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
14 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; 15 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
@@ -155,14 +156,14 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -155,14 +156,14 @@ public class AdminAuthServiceImpl implements AdminAuthService {
155 @Override 156 @Override
156 public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) { 157 public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) {
157 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 158 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
158 - Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), 159 + SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(),
159 reqVO.getCode(), reqVO.getState()); 160 reqVO.getCode(), reqVO.getState());
160 - if (userId == null) { 161 + if (socialUser == null) {
161 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 162 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
162 } 163 }
163 164
164 // 获得用户 165 // 获得用户
165 - AdminUserDO user = userService.getUser(userId); 166 + AdminUserDO user = userService.getUser(socialUser.getUserId());
166 if (user == null) { 167 if (user == null) {
167 throw exception(USER_NOT_EXISTS); 168 throw exception(USER_NOT_EXISTS);
168 } 169 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.social; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.social;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
4 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 4 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  5 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
5 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 6 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
6 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 7 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
7 8
@@ -50,8 +51,9 @@ public interface SocialUserService { @@ -50,8 +51,9 @@ public interface SocialUserService {
50 * 绑定社交用户 51 * 绑定社交用户
51 * 52 *
52 * @param reqDTO 绑定信息 53 * @param reqDTO 绑定信息
  54 + * @return 社交用户 openid
53 */ 55 */
54 - void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); 56 + String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO);
55 57
56 /** 58 /**
57 * 取消绑定社交用户 59 * 取消绑定社交用户
@@ -64,15 +66,16 @@ public interface SocialUserService { @@ -64,15 +66,16 @@ public interface SocialUserService {
64 void unbindSocialUser(Long userId, Integer userType, Integer type, String openid); 66 void unbindSocialUser(Long userId, Integer userType, Integer type, String openid);
65 67
66 /** 68 /**
67 - * 获得社交用户的绑定用户编号  
68 - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! 69 + * 获得社交用户
  70 + *
69 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 71 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
70 * 72 *
71 * @param userType 用户类型 73 * @param userType 用户类型
72 * @param type 社交平台的类型 74 * @param type 社交平台的类型
73 * @param code 授权码 75 * @param code 授权码
74 * @param state state 76 * @param state state
75 - * @return 绑定用户编号 77 + * @return 社交用户
76 */ 78 */
77 - Long getBindUserId(Integer userType, Integer type, String code, String state); 79 + SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state);
  80 +
78 } 81 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java
@@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert; @@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert;
5 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 5 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
6 import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; 6 import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
7 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 7 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  8 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
8 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; 9 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
9 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 10 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
10 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; 11 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
@@ -98,7 +99,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -98,7 +99,7 @@ public class SocialUserServiceImpl implements SocialUserService {
98 99
99 @Override 100 @Override
100 @Transactional 101 @Transactional
101 - public void bindSocialUser(SocialUserBindReqDTO reqDTO) { 102 + public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
102 // 获得社交用户 103 // 获得社交用户
103 SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState()); 104 SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState());
104 Assert.notNull(socialUser, "社交用户不能为空"); 105 Assert.notNull(socialUser, "社交用户不能为空");
@@ -115,6 +116,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -115,6 +116,7 @@ public class SocialUserServiceImpl implements SocialUserService {
115 .userId(reqDTO.getUserId()).userType(reqDTO.getUserType()) 116 .userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
116 .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build(); 117 .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build();
117 socialUserBindMapper.insert(socialUserBind); 118 socialUserBindMapper.insert(socialUserBind);
  119 + return socialUser.getOpenid();
118 } 120 }
119 121
120 @Override 122 @Override
@@ -130,7 +132,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -130,7 +132,7 @@ public class SocialUserServiceImpl implements SocialUserService {
130 } 132 }
131 133
132 @Override 134 @Override
133 - public Long getBindUserId(Integer userType, Integer type, String code, String state) { 135 + public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) {
134 // 获得社交用户 136 // 获得社交用户
135 SocialUserDO socialUser = authSocialUser(type, code, state); 137 SocialUserDO socialUser = authSocialUser(type, code, state);
136 Assert.notNull(socialUser, "社交用户不能为空"); 138 Assert.notNull(socialUser, "社交用户不能为空");
@@ -141,7 +143,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -141,7 +143,7 @@ public class SocialUserServiceImpl implements SocialUserService {
141 if (socialUserBind == null) { 143 if (socialUserBind == null) {
142 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 144 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
143 } 145 }
144 - return socialUserBind.getUserId(); 146 + return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId());
145 } 147 }
146 148
147 /** 149 /**
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
7 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 7 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
8 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 8 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  9 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
9 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; 10 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
10 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; 11 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
11 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; 12 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@@ -235,8 +236,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { @@ -235,8 +236,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
235 AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class); 236 AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class);
236 // mock 方法(绑定的用户编号) 237 // mock 方法(绑定的用户编号)
237 Long userId = 1L; 238 Long userId = 1L;
238 - when(socialUserService.getBindUserId(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),  
239 - eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(userId); 239 + when(socialUserService.getSocialUser(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),
  240 + eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), userId));
240 // mock(用户) 241 // mock(用户)
241 AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); 242 AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId));
242 when(userService.getUser(eq(userId))).thenReturn(user); 243 when(userService.getUser(eq(userId))).thenReturn(user);
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4 import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; 4 import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
5 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 5 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  7 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
7 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; 8 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
8 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 9 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
9 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; 10 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
@@ -195,10 +196,11 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { @@ -195,10 +196,11 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest {
195 .setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(socialUser.getId())); 196 .setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(socialUser.getId()));
196 197
197 // 调用 198 // 调用
198 - socialUserService.bindSocialUser(reqDTO); 199 + String openid = socialUserService.bindSocialUser(reqDTO);
199 // 断言 200 // 断言
200 List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectList(); 201 List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectList();
201 assertEquals(1, socialUserBinds.size()); 202 assertEquals(1, socialUserBinds.size());
  203 + assertEquals(socialUser.getOpenid(), openid);
202 } 204 }
203 205
204 @Test 206 @Test
@@ -232,25 +234,26 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { @@ -232,25 +234,26 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest {
232 } 234 }
233 235
234 @Test 236 @Test
235 - public void testGetBindUserId() { 237 + public void testGetSocialUser() {
236 // 准备参数 238 // 准备参数
237 Integer userType = UserTypeEnum.ADMIN.getValue(); 239 Integer userType = UserTypeEnum.ADMIN.getValue();
238 Integer type = SocialTypeEnum.GITEE.getType(); 240 Integer type = SocialTypeEnum.GITEE.getType();
239 String code = "tudou"; 241 String code = "tudou";
240 String state = "yuanma"; 242 String state = "yuanma";
241 // mock 社交用户 243 // mock 社交用户
242 - SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(type).setCode(code).setState(state);  
243 - socialUserMapper.insert(socialUser); 244 + SocialUserDO socialUserDO = randomPojo(SocialUserDO.class).setType(type).setCode(code).setState(state);
  245 + socialUserMapper.insert(socialUserDO);
244 // mock 社交用户的绑定 246 // mock 社交用户的绑定
245 Long userId = randomLong(); 247 Long userId = randomLong();
246 SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType).setUserId(userId) 248 SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType).setUserId(userId)
247 - .setSocialType(type).setSocialUserId(socialUser.getId()); 249 + .setSocialType(type).setSocialUserId(socialUserDO.getId());
248 socialUserBindMapper.insert(socialUserBind); 250 socialUserBindMapper.insert(socialUserBind);
249 251
250 // 调用 252 // 调用
251 - Long result = socialUserService.getBindUserId(userType, type, code, state); 253 + SocialUserRespDTO socialUser = socialUserService.getSocialUser(userType, type, code, state);
252 // 断言 254 // 断言
253 - assertEquals(userId, result); 255 + assertEquals(userId, socialUser.getUserId());
  256 + assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid());
254 } 257 }
255 258
256 } 259 }
yudao-server/src/main/resources/application-local.yaml
@@ -173,8 +173,10 @@ wx: @@ -173,8 +173,10 @@ wx:
173 key-prefix: wx # Redis Key 的前缀 173 key-prefix: wx # Redis Key 的前缀
174 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 174 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
175 miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 175 miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档
176 - appid: wx62056c0d5e8db250  
177 - secret: 333ae72f41552af1e998fe1f54e1584a 176 +# appid: wx62056c0d5e8db250
  177 +# secret: 333ae72f41552af1e998fe1f54e1584a
  178 + appid: wx63c280fe3248a3e7 # wenhualian的接口测试号
  179 + secret: 6f270509224a7ae1296bbf1c8cb97aed
178 config-storage: 180 config-storage:
179 type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 181 type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取
180 key-prefix: wa # Redis Key 的前缀 182 key-prefix: wa # Redis Key 的前缀