Commit 3976011af0d9090160a739e72bfd0b2895e8ec6b
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
Showing
36 changed files
with
314 additions
and
201 deletions
sql/mysql/pay_wallet.sql
| ... | ... | @@ -8,8 +8,8 @@ CREATE TABLE `pay_wallet` |
| 8 | 8 | `user_id` bigint NOT NULL COMMENT '用户编号', |
| 9 | 9 | `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', |
| 10 | 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 | 13 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 14 | 14 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 15 | 15 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java
| ... | ... | @@ -27,7 +27,7 @@ public class BrokerageApiImpl implements BrokerageApi { |
| 27 | 27 | |
| 28 | 28 | @Override |
| 29 | 29 | public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { |
| 30 | - return brokerageUserService.bindUser(userId, bindUserId, isNewUser); | |
| 30 | + return brokerageUserService.bindBrokerageUser(userId, bindUserId, isNewUser); | |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | } | ... | ... |
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 | 19 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 20 | 20 | private LocalDateTime createTime; |
| 21 | 21 | |
| 22 | - | |
| 23 | 22 | // ========== 用户信息 ========== |
| 24 | 23 | |
| 25 | 24 | @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") |
| ... | ... | @@ -27,7 +26,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { |
| 27 | 26 | @Schema(description = "用户昵称", example = "李四") |
| 28 | 27 | private String nickname; |
| 29 | 28 | |
| 30 | - | |
| 31 | 29 | // ========== 推广信息 ========== |
| 32 | 30 | |
| 33 | 31 | @Schema(description = "推广用户数量(一级)", example = "20019") |
| ... | ... | @@ -37,7 +35,6 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { |
| 37 | 35 | @Schema(description = "推广订单金额", example = "20019") |
| 38 | 36 | private Integer brokerageOrderPrice; |
| 39 | 37 | |
| 40 | - | |
| 41 | 38 | // ========== 提现信息 ========== |
| 42 | 39 | |
| 43 | 40 | @Schema(description = "已提现金额", example = "20019") | ... | ... |
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 | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; |
| 6 | +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO; | |
| 6 | 7 | import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; |
| 8 | 9 | import io.swagger.v3.oas.annotations.Operation; |
| ... | ... | @@ -11,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; |
| 11 | 12 | import org.springframework.validation.annotation.Validated; |
| 12 | 13 | import org.springframework.web.bind.annotation.GetMapping; |
| 13 | 14 | import org.springframework.web.bind.annotation.RequestMapping; |
| 15 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 14 | 16 | import org.springframework.web.bind.annotation.RestController; |
| 15 | 17 | |
| 16 | 18 | import javax.validation.Valid; |
| ... | ... | @@ -40,4 +42,14 @@ public class AppBrokerageRecordController { |
| 40 | 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 | 37 | @PreAuthenticated |
| 38 | 38 | public CommonResult<AppBrokerageUserRespVO> getBrokerageUser() { |
| 39 | 39 | AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() |
| 40 | + .setBrokerageEnabled(true) | |
| 40 | 41 | .setPrice(2000) |
| 41 | 42 | .setFrozenPrice(3000); |
| 42 | 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 | 53 | // TODO 芋艿:临时 mock => |
| 46 | 54 | @GetMapping("/get-summary") |
| 47 | 55 | @Operation(summary = "获得个人分销统计") |
| ... | ... | @@ -49,7 +57,7 @@ public class AppBrokerageUserController { |
| 49 | 57 | public CommonResult<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() { |
| 50 | 58 | AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO() |
| 51 | 59 | .setYesterdayPrice(1) |
| 52 | - .setPrice(2) | |
| 60 | + .setBrokeragePrice(2) | |
| 53 | 61 | .setFrozenPrice(3) |
| 54 | 62 | .setWithdrawPrice(4) |
| 55 | 63 | .setFirstBrokerageUserCount(166) |
| ... | ... | @@ -84,16 +92,16 @@ public class AppBrokerageUserController { |
| 84 | 92 | public CommonResult<PageResult<AppBrokerageUserRankByPriceRespVO>> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { |
| 85 | 93 | AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() |
| 86 | 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 | 96 | AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() |
| 89 | 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 | 99 | AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() |
| 92 | 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 | 102 | AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() |
| 95 | 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 | 105 | return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); |
| 98 | 106 | } |
| 99 | 107 | |
| ... | ... | @@ -105,11 +113,11 @@ public class AppBrokerageUserController { |
| 105 | 113 | AppBrokerageUserChildSummaryPageReqVO pageReqVO) { |
| 106 | 114 | AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO() |
| 107 | 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 | 117 | .setBrokerageTime(LocalDateTime.now()); |
| 110 | 118 | AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO() |
| 111 | 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 | 121 | .setBrokerageTime(LocalDateTime.now()); |
| 114 | 122 | return success(new PageResult<>(asList(vo1, vo2), 10L)); |
| 115 | 123 | } |
| ... | ... | @@ -118,15 +126,9 @@ public class AppBrokerageUserController { |
| 118 | 126 | @GetMapping("/get-rank-by-price") |
| 119 | 127 | @Operation(summary = "获得分销用户排行(基于佣金)") |
| 120 | 128 | @Parameter(name = "times", description = "时间段", required = true) |
| 121 | - public CommonResult<Integer> getBrokerageUserRankByPrice( | |
| 129 | + public CommonResult<Integer> bindBrokerageUser( | |
| 122 | 130 | @RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) { |
| 123 | 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 | 19 | private String avatar; |
| 20 | 20 | |
| 21 | 21 | @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 22 | - private Integer price; | |
| 22 | + private Integer brokeragePrice; | |
| 23 | 23 | |
| 24 | 24 | @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") |
| 25 | 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 | 14 | private Integer withdrawPrice; |
| 15 | 15 | |
| 16 | 16 | @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") |
| 17 | - private Integer price; | |
| 17 | + private Integer brokeragePrice; | |
| 18 | 18 | |
| 19 | 19 | @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") |
| 20 | 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
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 | 7 | @Data |
| 8 | 8 | public class AppBrokerageUserRespVO { |
| 9 | 9 | |
| 10 | + @Schema(description = "是否有分销资格", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 11 | + private Boolean brokerageEnabled; | |
| 12 | + | |
| 10 | 13 | @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") |
| 11 | 14 | private Integer price; |
| 12 | 15 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java
| ... | ... | @@ -41,7 +41,7 @@ public interface BrokerageRecordConvert { |
| 41 | 41 | : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); |
| 42 | 42 | return new BrokerageRecordDO().setUserId(user.getId()) |
| 43 | 43 | .setBizType(bizType.getType()).setBizId(bizId) |
| 44 | - .setPrice(brokeragePrice).setTotalPrice(user.getPrice()) | |
| 44 | + .setPrice(brokeragePrice).setTotalPrice(user.getBrokeragePrice()) | |
| 45 | 45 | .setTitle(title) |
| 46 | 46 | .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokeragePrice / 100.0))) |
| 47 | 47 | .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime); | ... | ... |
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 | 43 | private LocalDateTime bindUserTime; |
| 44 | 44 | |
| 45 | 45 | /** |
| 46 | - * 推广资格 | |
| 46 | + * 是否有分销资格 | |
| 47 | 47 | */ |
| 48 | 48 | private Boolean brokerageEnabled; |
| 49 | 49 | /** |
| ... | ... | @@ -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/service/brokerage/user/BrokerageUserService.java
| ... | ... | @@ -103,6 +103,6 @@ public interface BrokerageUserService { |
| 103 | 103 | * @param isNewUser 是否为新用户 |
| 104 | 104 | * @return 是否绑定 |
| 105 | 105 | */ |
| 106 | - boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); | |
| 106 | + boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser); | |
| 107 | 107 | |
| 108 | 108 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java
| ... | ... | @@ -135,7 +135,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { |
| 135 | 135 | |
| 136 | 136 | // TODO @疯狂:因为现在 user 会存在使用验证码直接注册,所以 isNewUser 不太好传递;我们是不是可以约定绑定的时间,createTime 在 30 秒内,就认为新用户; |
| 137 | 137 | @Override |
| 138 | - public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { | |
| 138 | + public boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser) { | |
| 139 | 139 | // TODO @疯狂:userId 为空,搞到参数校验里哇; |
| 140 | 140 | if (userId == null) { |
| 141 | 141 | throw exception(0); |
| ... | ... | @@ -146,7 +146,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { |
| 146 | 146 | BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); |
| 147 | 147 | if (brokerageUser == null) { // 分销用户不存在的情况:1. 新注册;2. 旧数据;3. 分销功能关闭后又打开 |
| 148 | 148 | isNewBrokerageUser = true; |
| 149 | - brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0); | |
| 149 | + brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setBrokeragePrice(0).setFrozenPrice(0); | |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | 152 | // 2.1 校验能否绑定 | ... | ... |
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 | 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 | 42 | ### 请求 /weixin-mini-app-login 接口 => 成功 |
| 32 | 43 | POST {{appApi}}/member/auth/weixin-mini-app-login |
| 33 | 44 | Content-Type: application/json |
| ... | ... | @@ -38,7 +49,6 @@ tenant-id: {{appTenentId}} |
| 38 | 49 | "loginCode": "001frTkl21JUf94VGxol2hSlff1frTkR" |
| 39 | 50 | } |
| 40 | 51 | |
| 41 | - | |
| 42 | 52 | ### 请求 /logout 接口 => 成功 |
| 43 | 53 | POST {{appApi}}/member/auth/logout |
| 44 | 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 | 27 | @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 28 | 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/convert/auth/AuthConvert.java
| ... | ... | @@ -25,7 +25,7 @@ public interface AuthConvert { |
| 25 | 25 | SmsCodeUseReqDTO convert(AppMemberUserResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp); |
| 26 | 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 | 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 | 20 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; |
| 21 | 21 | import cn.iocoder.yudao.module.system.api.social.SocialUserApi; |
| 22 | 22 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 23 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 23 | 24 | import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; |
| 24 | 25 | import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; |
| 25 | 26 | import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; |
| ... | ... | @@ -65,13 +66,14 @@ public class MemberAuthServiceImpl implements MemberAuthService { |
| 65 | 66 | MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword()); |
| 66 | 67 | |
| 67 | 68 | // 如果 socialType 非空,说明需要绑定社交用户 |
| 69 | + String openid = null; | |
| 68 | 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 | 72 | reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); |
| 71 | 73 | } |
| 72 | 74 | |
| 73 | 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 | 79 | @Override |
| ... | ... | @@ -86,32 +88,33 @@ public class MemberAuthServiceImpl implements MemberAuthService { |
| 86 | 88 | Assert.notNull(user, "获取用户失败,结果为空"); |
| 87 | 89 | |
| 88 | 90 | // 如果 socialType 非空,说明需要绑定社交用户 |
| 91 | + String openid = null; | |
| 89 | 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 | 94 | reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); |
| 92 | 95 | } |
| 93 | 96 | |
| 94 | 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 | 101 | @Override |
| 99 | 102 | public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { |
| 100 | 103 | // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 |
| 101 | - Long userId = socialUserApi.getBindUserId(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), | |
| 104 | + SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), | |
| 102 | 105 | reqVO.getCode(), reqVO.getState()); |
| 103 | - if (userId == null) { | |
| 106 | + if (socialUser == null) { | |
| 104 | 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 | 112 | if (user == null) { |
| 110 | 113 | throw exception(USER_NOT_EXISTS); |
| 111 | 114 | } |
| 112 | 115 | |
| 113 | 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 | 120 | @Override |
| ... | ... | @@ -129,14 +132,15 @@ public class MemberAuthServiceImpl implements MemberAuthService { |
| 129 | 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 | 136 | SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), "")); |
| 134 | 137 | |
| 135 | 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 | 145 | createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS); |
| 142 | 146 | // 创建 Token 令牌 |
| ... | ... | @@ -144,7 +148,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { |
| 144 | 148 | .setUserId(user.getId()).setUserType(getUserType().getValue()) |
| 145 | 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 | 154 | @Override |
| ... | ... | @@ -231,7 +235,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { |
| 231 | 235 | public AppAuthLoginRespVO refreshToken(String refreshToken) { |
| 232 | 236 | OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken, |
| 233 | 237 | OAuth2ClientConstants.CLIENT_ID_DEFAULT); |
| 234 | - return AuthConvert.INSTANCE.convert(accessTokenDO); | |
| 238 | + return AuthConvert.INSTANCE.convert(accessTokenDO, null); | |
| 235 | 239 | } |
| 236 | 240 | |
| 237 | 241 | private void createLogoutLog(Long userId) { | ... | ... |
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 | 11 | private Integer balance; |
| 12 | 12 | |
| 13 | 13 | @Schema(description = "累计支出, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") |
| 14 | - private Long totalExpense; | |
| 14 | + private Integer totalExpense; | |
| 15 | 15 | |
| 16 | 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 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO; |
| 5 | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 6 | +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; | |
| 6 | 7 | import org.mapstruct.Mapper; |
| 7 | 8 | import org.mapstruct.factory.Mappers; |
| 8 | 9 | |
| ... | ... | @@ -12,4 +13,7 @@ public interface PayWalletTransactionConvert { |
| 12 | 13 | PayWalletTransactionConvert INSTANCE = Mappers.getMapper(PayWalletTransactionConvert.class); |
| 13 | 14 | |
| 14 | 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
| ... | ... | @@ -37,8 +37,6 @@ public class PayWalletDO extends BaseDO { |
| 37 | 37 | */ |
| 38 | 38 | private Integer userType; |
| 39 | 39 | |
| 40 | - // TODO @jason:三个都搞 integer?应该要统一哈 | |
| 41 | - | |
| 42 | 40 | /** |
| 43 | 41 | * 余额,单位分 |
| 44 | 42 | */ |
| ... | ... | @@ -47,10 +45,10 @@ public class PayWalletDO extends BaseDO { |
| 47 | 45 | /** |
| 48 | 46 | * 累计支出,单位分 |
| 49 | 47 | */ |
| 50 | - private Long totalExpense; | |
| 48 | + private Integer totalExpense; | |
| 51 | 49 | /** |
| 52 | 50 | * 累计充值,单位分 |
| 53 | 51 | */ |
| 54 | - private Long totalRecharge; | |
| 52 | + private Integer totalRecharge; | |
| 55 | 53 | |
| 56 | 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 | 3 | |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | 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 | 7 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 8 | |
| 10 | 9 | @Mapper |
| ... | ... | @@ -15,56 +14,33 @@ public interface PayWalletMapper extends BaseMapperX<PayWalletDO> { |
| 15 | 14 | PayWalletDO::getUserType, userType); |
| 16 | 15 | } |
| 17 | 16 | |
| 18 | - // TODO @jason:减少时,需要 update price -= ? where price >= ?,避免并发问题。现在基于 price 来过滤,虽然也能解决并发问题,但是冲突概率会高一点;可以看到 TradeBrokerageUserMapper 的做法; | |
| 19 | 17 | /** |
| 20 | - * 当余额减少时候更新 | |
| 18 | + * 当消费退款时候, 更新钱包 | |
| 21 | 19 | * |
| 22 | - * @param bizType 业务类型 | |
| 23 | - * @param balance 当前余额 | |
| 24 | - * @param totalRecharge 当前累计充值 | |
| 25 | - * @param totalExpense 当前累计支出 | |
| 26 | - * @param price 支出的金额 | |
| 20 | + * @param price 消费金额 | |
| 27 | 21 | * @param id 钱包 id |
| 28 | 22 | */ |
| 29 | - default int updateWhenDecBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, | |
| 30 | - Long totalExpense, Integer price, Long id) { | |
| 31 | - // TODO @jason:这种偏判断的,最红放在 service 层;mapper 可以写多个方法; | |
| 32 | - PayWalletDO updateDO = new PayWalletDO().setBalance(balance - price); | |
| 33 | - if(bizType == PayWalletBizTypeEnum.PAYMENT){ | |
| 34 | - updateDO.setTotalExpense(totalExpense + price); | |
| 35 | - } | |
| 36 | - if (bizType == PayWalletBizTypeEnum.RECHARGE_REFUND) { | |
| 37 | - updateDO.setTotalRecharge(totalRecharge - price); | |
| 38 | - } | |
| 39 | - return update(updateDO, | |
| 40 | - new LambdaQueryWrapper<PayWalletDO>().eq(PayWalletDO::getId, id) | |
| 41 | - .eq(PayWalletDO::getBalance, balance) | |
| 42 | - .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); | |
| 43 | 29 | } |
| 44 | 30 | |
| 45 | - // TODO @jason:类似上面的修改建议哈; | |
| 46 | 31 | /** |
| 47 | - * 当余额增加时候更新 | |
| 32 | + * 当消费时候, 更新钱包 | |
| 48 | 33 | * |
| 49 | - * @param bizType 业务类型 | |
| 50 | - * @param balance 当前余额 | |
| 51 | - * @param totalRecharge 当前累计充值 | |
| 52 | - * @param totalExpense 当前累计支出 | |
| 53 | - * @param price 金额 | |
| 34 | + * @param price 消费金额 | |
| 54 | 35 | * @param id 钱包 id |
| 55 | 36 | */ |
| 56 | - default int updateWhenIncBalance(PayWalletBizTypeEnum bizType, Integer balance, Long totalRecharge, | |
| 57 | - Long totalExpense, Integer price, Long id) { | |
| 58 | - PayWalletDO updateDO = new PayWalletDO().setBalance(balance + price); | |
| 59 | - if (bizType == PayWalletBizTypeEnum.PAYMENT_REFUND) { | |
| 60 | - updateDO.setTotalExpense(totalExpense - price); | |
| 61 | - } | |
| 62 | - if (bizType == PayWalletBizTypeEnum.RECHARGE) { | |
| 63 | - updateDO.setTotalExpense(totalRecharge + price); | |
| 64 | - } | |
| 65 | - return update(updateDO, | |
| 66 | - new LambdaQueryWrapper<PayWalletDO>().eq(PayWalletDO::getId, id) | |
| 67 | - .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); | |
| 68 | 44 | } |
| 69 | 45 | } |
| 70 | 46 | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java
| ... | ... | @@ -62,13 +62,12 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> { |
| 62 | 62 | @Override |
| 63 | 63 | protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 64 | 64 | try { |
| 65 | - // TODO @jason:直接 getLong 和 getInt 会不会更简洁哈 | |
| 66 | - String userId = MapUtil.getStr(reqDTO.getChannelExtras(), USER_ID_KEY); | |
| 67 | - String userType = MapUtil.getStr(reqDTO.getChannelExtras(), USER_TYPE_KEY); | |
| 68 | - Assert.notEmpty(userId, "用户 id 不能为空"); | |
| 69 | - Assert.notEmpty(userType, "用户类型不能为空"); | |
| 70 | - PayWalletTransactionDO transaction = wallService.orderPay(Long.valueOf(userId), Integer.valueOf(userType), | |
| 71 | - 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()); | |
| 72 | 71 | return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), |
| 73 | 72 | transaction.getCreateTime(), |
| 74 | 73 | reqDTO.getOutTradeNo(), transaction); | ... | ... |
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 | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
| 7 | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 8 | 8 | import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; |
| 9 | -import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | |
| 10 | 9 | import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; |
| 11 | 10 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 12 | 11 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 12 | +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; | |
| 13 | 13 | import lombok.extern.slf4j.Slf4j; |
| 14 | 14 | import org.springframework.context.annotation.Lazy; |
| 15 | 15 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional; |
| 18 | 18 | import javax.annotation.Resource; |
| 19 | 19 | import java.time.LocalDateTime; |
| 20 | 20 | |
| 21 | -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.TOO_MANY_REQUESTS; | |
| 22 | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 23 | 22 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; |
| 24 | 23 | import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; |
| ... | ... | @@ -33,21 +32,9 @@ import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYM |
| 33 | 32 | @Slf4j |
| 34 | 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 | 35 | @Resource |
| 46 | 36 | private PayWalletMapper walletMapper; |
| 47 | 37 | @Resource |
| 48 | - private PayNoRedisDAO noRedisDAO; | |
| 49 | - | |
| 50 | - @Resource | |
| 51 | 38 | private PayWalletTransactionService walletTransactionService; |
| 52 | 39 | @Resource |
| 53 | 40 | @Lazy |
| ... | ... | @@ -61,7 +48,7 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 61 | 48 | PayWalletDO wallet = walletMapper.selectByUserIdAndType(userId, userType); |
| 62 | 49 | if (wallet == null) { |
| 63 | 50 | wallet = new PayWalletDO().setUserId(userId).setUserType(userType) |
| 64 | - .setBalance(0).setTotalExpense(0L).setTotalRecharge(0L); | |
| 51 | + .setBalance(0).setTotalExpense(0).setTotalRecharge(0); | |
| 65 | 52 | wallet.setCreateTime(LocalDateTime.now()); |
| 66 | 53 | walletMapper.insert(wallet); |
| 67 | 54 | } |
| ... | ... | @@ -125,70 +112,54 @@ public class PayWalletServiceImpl implements PayWalletService { |
| 125 | 112 | @Override |
| 126 | 113 | public PayWalletTransactionDO reduceWalletBalance(Long userId, Integer userType, |
| 127 | 114 | Long bizId, PayWalletBizTypeEnum bizType, Integer price) { |
| 128 | - // 1.1 获取钱包 | |
| 115 | + // 1. 获取钱包 | |
| 129 | 116 | PayWalletDO payWallet = getOrCreateWallet(userId, userType); |
| 130 | - // 1.2 判断余额是否足够 | |
| 131 | - int afterBalance = payWallet.getBalance() - price; | |
| 132 | - if (afterBalance < 0) { | |
| 133 | - throw exception(WALLET_BALANCE_NOT_ENOUGH); | |
| 134 | - } | |
| 135 | 117 | |
| 136 | - // TODO jason:建议基于 where price >= 来做哈;然后抛出 WALLET_BALANCE_NOT_ENOUGH | |
| 137 | 118 | // 2.1 扣除余额 |
| 138 | - int number = walletMapper.updateWhenDecBalance(bizType, payWallet.getBalance(), | |
| 139 | - payWallet.getTotalRecharge(), payWallet.getTotalExpense(), price, payWallet.getId()); | |
| 140 | - if (number == 0) { | |
| 141 | - throw exception(TOO_MANY_REQUESTS); | |
| 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); | |
| 142 | 132 | } |
| 143 | - | |
| 144 | 133 | // 2.2 生成钱包流水 |
| 145 | - // TODO @jason:walletNo 交给 payWalletTransactionService 自己生成哈; | |
| 146 | - String walletNo = generateWalletNo(bizType); | |
| 147 | - PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) | |
| 148 | - .setNo(walletNo).setPrice(-price).setBalance(afterBalance) | |
| 149 | - .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()).setTitle(bizType.getDescription()); | |
| 150 | - // TODO @jason:是不是可以 createWalletTransaction 搞个 bo 参数,然后 PayWalletTransactionDO 交回给 walletTransactionService 更好;然后把参数简化下 | |
| 151 | - walletTransactionService.createWalletTransaction(walletTransaction); | |
| 152 | - return walletTransaction; | |
| 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); | |
| 153 | 139 | } |
| 154 | 140 | |
| 155 | 141 | @Override |
| 156 | 142 | public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, |
| 157 | 143 | Long bizId, PayWalletBizTypeEnum bizType, Integer price) { |
| 158 | - // 1.1 获取钱包 | |
| 144 | + // 1. 获取钱包 | |
| 159 | 145 | PayWalletDO payWallet = getOrCreateWallet(userId, userType); |
| 160 | - | |
| 161 | - // 2.1 增加余额 | |
| 162 | - // TODO @jason:类似上面的思路哈; | |
| 163 | - int number = walletMapper.updateWhenIncBalance(bizType, payWallet.getBalance(), payWallet.getTotalRecharge(), | |
| 164 | - payWallet.getTotalExpense(), price, payWallet.getId()); | |
| 165 | - if (number == 0) { | |
| 166 | - throw exception(TOO_MANY_REQUESTS); | |
| 167 | - } | |
| 168 | - | |
| 169 | - // 2.2 生成钱包流水 | |
| 170 | - String walletNo = generateWalletNo(bizType); | |
| 171 | - PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) | |
| 172 | - .setNo(walletNo).setPrice(price).setBalance(payWallet.getBalance()+price) | |
| 173 | - .setBizId(String.valueOf(bizId)).setBizType(bizType.getType()) | |
| 174 | - .setTitle(bizType.getDescription()); | |
| 175 | - walletTransactionService.createWalletTransaction(newWalletTransaction); | |
| 176 | - return newWalletTransaction; | |
| 177 | - } | |
| 178 | - | |
| 179 | - private String generateWalletNo(PayWalletBizTypeEnum bizType) { | |
| 180 | - // TODO @jason:对于余额来说,是不是直接 W+序号就行了,它其实不关注业务;;;不然就耦合啦 | |
| 181 | - String no = ""; | |
| 182 | - switch(bizType){ | |
| 183 | - case PAYMENT: | |
| 184 | - no = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); | |
| 146 | + switch (bizType) { | |
| 147 | + case PAYMENT_REFUND: { | |
| 148 | + // 更新退款 | |
| 149 | + walletMapper.updateWhenConsumptionRefund(price, payWallet.getId()); | |
| 185 | 150 | break; |
| 186 | - case PAYMENT_REFUND: | |
| 187 | - no = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); | |
| 151 | + } | |
| 152 | + case RECHARGE: { | |
| 153 | + //TODO | |
| 188 | 154 | break; |
| 189 | - default : | |
| 155 | + } | |
| 190 | 156 | } |
| 191 | - return no; | |
| 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); | |
| 192 | 163 | } |
| 193 | 164 | |
| 194 | 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 | 4 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 6 | 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 | 12 | * 钱包余额流水 Service 接口 |
| ... | ... | @@ -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 | 37 | * 根据 no,获取钱包余流水 |
| ... | ... | @@ -45,4 +48,5 @@ public interface PayWalletTransactionService { |
| 45 | 48 | * @return 钱包流水 |
| 46 | 49 | */ |
| 47 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; |
| 5 | +import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletTransactionConvert; | |
| 5 | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
| 6 | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 7 | 8 | import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper; |
| 9 | +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | |
| 8 | 10 | import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; |
| 11 | +import cn.iocoder.yudao.module.pay.service.wallet.bo.CreateWalletTransactionBO; | |
| 9 | 12 | import lombok.extern.slf4j.Slf4j; |
| 10 | 13 | import org.springframework.stereotype.Service; |
| 11 | 14 | |
| ... | ... | @@ -20,10 +23,17 @@ import javax.annotation.Resource; |
| 20 | 23 | @Slf4j |
| 21 | 24 | public class PayWalletTransactionServiceImpl implements PayWalletTransactionService { |
| 22 | 25 | |
| 26 | + /** | |
| 27 | + * 钱包流水的 no 前缀 | |
| 28 | + */ | |
| 29 | + private static final String WALLET_NO_PREFIX = "W"; | |
| 30 | + | |
| 23 | 31 | @Resource |
| 24 | 32 | private PayWalletService payWalletService; |
| 25 | 33 | @Resource |
| 26 | 34 | private PayWalletTransactionMapper payWalletTransactionMapper; |
| 35 | + @Resource | |
| 36 | + private PayNoRedisDAO noRedisDAO; | |
| 27 | 37 | |
| 28 | 38 | @Override |
| 29 | 39 | public PageResult<PayWalletTransactionDO> getWalletTransactionPage(Long userId, Integer userType, |
| ... | ... | @@ -33,9 +43,11 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ |
| 33 | 43 | } |
| 34 | 44 | |
| 35 | 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 | 53 | @Override |
| ... | ... | @@ -47,4 +59,5 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionServ |
| 47 | 59 | public PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type) { |
| 48 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 4 | 4 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 5 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 5 | 6 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; |
| 6 | 7 | import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; |
| 7 | 8 | |
| ... | ... | @@ -27,8 +28,9 @@ public interface SocialUserApi { |
| 27 | 28 | * 绑定社交用户 |
| 28 | 29 | * |
| 29 | 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 | 40 | void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO); |
| 39 | 41 | |
| 40 | 42 | /** |
| 41 | - * 获得社交用户的绑定用户编号 | |
| 42 | - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! | |
| 43 | + * 获得社交用户 | |
| 44 | + * | |
| 43 | 45 | * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 |
| 44 | 46 | * |
| 45 | 47 | * @param userType 用户类型 |
| 46 | 48 | * @param type 社交平台的类型 |
| 47 | 49 | * @param code 授权码 |
| 48 | 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 | 1 | package cn.iocoder.yudao.module.system.api.social; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 4 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 4 | 5 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; |
| 5 | 6 | import cn.iocoder.yudao.module.system.service.social.SocialUserService; |
| 6 | 7 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -26,8 +27,8 @@ public class SocialUserApiImpl implements SocialUserApi { |
| 26 | 27 | } |
| 27 | 28 | |
| 28 | 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 | 34 | @Override |
| ... | ... | @@ -37,8 +38,8 @@ public class SocialUserApiImpl implements SocialUserApi { |
| 37 | 38 | } |
| 38 | 39 | |
| 39 | 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 | 9 | import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; |
| 10 | 10 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; |
| 11 | 11 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 12 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 12 | 13 | import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; |
| 13 | 14 | import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; |
| 14 | 15 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; |
| ... | ... | @@ -155,14 +156,14 @@ public class AdminAuthServiceImpl implements AdminAuthService { |
| 155 | 156 | @Override |
| 156 | 157 | public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) { |
| 157 | 158 | // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 |
| 158 | - Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), | |
| 159 | + SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), | |
| 159 | 160 | reqVO.getCode(), reqVO.getState()); |
| 160 | - if (userId == null) { | |
| 161 | + if (socialUser == null) { | |
| 161 | 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 | 167 | if (user == null) { |
| 167 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 4 | 4 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 5 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 5 | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; |
| 6 | 7 | import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; |
| 7 | 8 | |
| ... | ... | @@ -50,8 +51,9 @@ public interface SocialUserService { |
| 50 | 51 | * 绑定社交用户 |
| 51 | 52 | * |
| 52 | 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 | 66 | void unbindSocialUser(Long userId, Integer userType, Integer type, String openid); |
| 65 | 67 | |
| 66 | 68 | /** |
| 67 | - * 获得社交用户的绑定用户编号 | |
| 68 | - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! | |
| 69 | + * 获得社交用户 | |
| 70 | + * | |
| 69 | 71 | * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 |
| 70 | 72 | * |
| 71 | 73 | * @param userType 用户类型 |
| 72 | 74 | * @param type 社交平台的类型 |
| 73 | 75 | * @param code 授权码 |
| 74 | 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 | 5 | import cn.iocoder.yudao.framework.common.util.http.HttpUtils; |
| 6 | 6 | import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; |
| 7 | 7 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 8 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 8 | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; |
| 9 | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; |
| 10 | 11 | import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; |
| ... | ... | @@ -98,7 +99,7 @@ public class SocialUserServiceImpl implements SocialUserService { |
| 98 | 99 | |
| 99 | 100 | @Override |
| 100 | 101 | @Transactional |
| 101 | - public void bindSocialUser(SocialUserBindReqDTO reqDTO) { | |
| 102 | + public String bindSocialUser(SocialUserBindReqDTO reqDTO) { | |
| 102 | 103 | // 获得社交用户 |
| 103 | 104 | SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState()); |
| 104 | 105 | Assert.notNull(socialUser, "社交用户不能为空"); |
| ... | ... | @@ -115,6 +116,7 @@ public class SocialUserServiceImpl implements SocialUserService { |
| 115 | 116 | .userId(reqDTO.getUserId()).userType(reqDTO.getUserType()) |
| 116 | 117 | .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build(); |
| 117 | 118 | socialUserBindMapper.insert(socialUserBind); |
| 119 | + return socialUser.getOpenid(); | |
| 118 | 120 | } |
| 119 | 121 | |
| 120 | 122 | @Override |
| ... | ... | @@ -130,7 +132,7 @@ public class SocialUserServiceImpl implements SocialUserService { |
| 130 | 132 | } |
| 131 | 133 | |
| 132 | 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 | 137 | SocialUserDO socialUser = authSocialUser(type, code, state); |
| 136 | 138 | Assert.notNull(socialUser, "社交用户不能为空"); |
| ... | ... | @@ -141,7 +143,7 @@ public class SocialUserServiceImpl implements SocialUserService { |
| 141 | 143 | if (socialUserBind == null) { |
| 142 | 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 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 7 | 7 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; |
| 8 | 8 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 9 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 9 | 10 | import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; |
| 10 | 11 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; |
| 11 | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| ... | ... | @@ -235,8 +236,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { |
| 235 | 236 | AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class); |
| 236 | 237 | // mock 方法(绑定的用户编号) |
| 237 | 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 | 241 | // mock(用户) |
| 241 | 242 | AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); |
| 242 | 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 | 4 | import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; |
| 5 | 5 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 6 | 6 | import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; |
| 7 | +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; | |
| 7 | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; |
| 8 | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; |
| 9 | 10 | import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; |
| ... | ... | @@ -195,10 +196,11 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { |
| 195 | 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 | 201 | List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectList(); |
| 201 | 202 | assertEquals(1, socialUserBinds.size()); |
| 203 | + assertEquals(socialUser.getOpenid(), openid); | |
| 202 | 204 | } |
| 203 | 205 | |
| 204 | 206 | @Test |
| ... | ... | @@ -232,25 +234,26 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { |
| 232 | 234 | } |
| 233 | 235 | |
| 234 | 236 | @Test |
| 235 | - public void testGetBindUserId() { | |
| 237 | + public void testGetSocialUser() { | |
| 236 | 238 | // 准备参数 |
| 237 | 239 | Integer userType = UserTypeEnum.ADMIN.getValue(); |
| 238 | 240 | Integer type = SocialTypeEnum.GITEE.getType(); |
| 239 | 241 | String code = "tudou"; |
| 240 | 242 | String state = "yuanma"; |
| 241 | 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 | 246 | // mock 社交用户的绑定 |
| 245 | 247 | Long userId = randomLong(); |
| 246 | 248 | SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType).setUserId(userId) |
| 247 | - .setSocialType(type).setSocialUserId(socialUser.getId()); | |
| 249 | + .setSocialType(type).setSocialUserId(socialUserDO.getId()); | |
| 248 | 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 | 173 | key-prefix: wx # Redis Key 的前缀 |
| 174 | 174 | http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 |
| 175 | 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 | 180 | config-storage: |
| 179 | 181 | type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 |
| 180 | 182 | key-prefix: wa # Redis Key 的前缀 | ... | ... |