Commit eef3c4ae authored by zhangfeng's avatar zhangfeng

礼品兑换完善校验

parent bc3631f0
...@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty; ...@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
...@@ -20,12 +21,15 @@ public class RedeemRewardReqVO { ...@@ -20,12 +21,15 @@ public class RedeemRewardReqVO {
private Long rewardId; private Long rewardId;
@ApiModelProperty(value = "兑换数量", required = true) @ApiModelProperty(value = "兑换数量", required = true)
@NotNull(message = "兑换数量不能为空")
private Integer rewardCount; private Integer rewardCount;
@ApiModelProperty(value = "兑换方式,同领取方式(1上门领取,2包邮到家,3邮寄到付)", required = true) @ApiModelProperty(value = "兑换方式,同领取方式(1上门领取,2包邮到家,3邮寄到付)", required = true)
@NotNull(message = "兑换方式不能为空")
private Integer redeemType; private Integer redeemType;
@ApiModelProperty(value = "兑换入口(后台,app,web)", required = true) @ApiModelProperty(value = "兑换入口(后台,app,web)", required = true)
@NotNull(message = "兑换入口不能为空")
private Integer entrance; private Integer entrance;
@ApiModelProperty(value = "费用数字(两位小数)") @ApiModelProperty(value = "费用数字(两位小数)")
......
...@@ -29,5 +29,6 @@ public interface ErrorCodeConstants { ...@@ -29,5 +29,6 @@ public interface ErrorCodeConstants {
ErrorCode REDEEM_IMPORT_MAX_COUNT = new ErrorCode(1001011023, "redeem.import.max.count"); ErrorCode REDEEM_IMPORT_MAX_COUNT = new ErrorCode(1001011023, "redeem.import.max.count");
ErrorCode REDEEM_CANCEL_STATUS_ERROR = new ErrorCode(1001011024, "redeem.cancel.status.error"); ErrorCode REDEEM_CANCEL_STATUS_ERROR = new ErrorCode(1001011024, "redeem.cancel.status.error");
ErrorCode REWARD_NODE_AND_POINTS_LIST_ERROR = new ErrorCode(1001011025, "reward.node.and.points.list.error"); ErrorCode REWARD_NODE_AND_POINTS_LIST_ERROR = new ErrorCode(1001011025, "reward.node.and.points.list.error");
ErrorCode REWARD_REDEEM_RECIPIENT_ERROR = new ErrorCode(1001011026, "reward.redeem.recipient.error");
} }
...@@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO; ...@@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO;
import cn.iocoder.yudao.module.reward.dal.dataobject.reward.RewardDO; import cn.iocoder.yudao.module.reward.dal.dataobject.reward.RewardDO;
import cn.iocoder.yudao.module.reward.dal.mysql.redeem.RewardRedeemMapper; import cn.iocoder.yudao.module.reward.dal.mysql.redeem.RewardRedeemMapper;
import cn.iocoder.yudao.module.reward.dal.mysql.reward.RewardMapper; import cn.iocoder.yudao.module.reward.dal.mysql.reward.RewardMapper;
import cn.iocoder.yudao.module.reward.enums.RewardPickMethedEnum;
import cn.iocoder.yudao.module.reward.enums.RewardRedeemStatusEnum; import cn.iocoder.yudao.module.reward.enums.RewardRedeemStatusEnum;
import cn.iocoder.yudao.module.reward.enums.RewardStatusEnum; import cn.iocoder.yudao.module.reward.enums.RewardStatusEnum;
import cn.iocoder.yudao.module.reward.service.reward.RewardService; import cn.iocoder.yudao.module.reward.service.reward.RewardService;
...@@ -26,6 +27,7 @@ import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; ...@@ -26,6 +27,7 @@ import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock; import org.redisson.api.RLock;
import org.redisson.api.RedissonClient; import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -70,19 +72,47 @@ public class RedeemRewardApiImpl implements RedeemRewardApi { ...@@ -70,19 +72,47 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean redeemReward(RedeemRewardReqVO redeemRewardReqVO) { public Boolean redeemReward(RedeemRewardReqVO redeemRewardReqVO) {
UserRespDTO memberUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId());
if (memberUser == null) {
throw exception(USER_NOT_EXISTS);
}
// 验证短信验证码
if (redeemRewardReqVO.getEntrance() != PlatformTypeEnum.BACKEND.getValue() && redeemRewardReqVO instanceof AppRedeemRewardReqVO) { if (redeemRewardReqVO.getEntrance() != PlatformTypeEnum.BACKEND.getValue() && redeemRewardReqVO instanceof AppRedeemRewardReqVO) {
AppRedeemRewardReqVO appRedeemRewardReqVO = (AppRedeemRewardReqVO) redeemRewardReqVO; AppRedeemRewardReqVO appRedeemRewardReqVO = (AppRedeemRewardReqVO) redeemRewardReqVO;
SmsCodeUseReqDTO smsCodeUseReqDTO = new SmsCodeUseReqDTO(); SmsCodeUseReqDTO smsCodeUseReqDTO = new SmsCodeUseReqDTO();
UserRespDTO memberUserApiUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId()); smsCodeUseReqDTO.setMobile(memberUser.getMobile());
if (memberUserApiUser == null) {
throw exception(USER_NOT_EXISTS);
}
smsCodeUseReqDTO.setMobile(memberUserApiUser.getMobile());
smsCodeUseReqDTO.setCode(appRedeemRewardReqVO.getCode()); smsCodeUseReqDTO.setCode(appRedeemRewardReqVO.getCode());
smsCodeUseReqDTO.setUsedIp(getClientIP()); smsCodeUseReqDTO.setUsedIp(getClientIP());
smsCodeUseReqDTO.setScene(SmsSceneEnum.MEMBER_REDEEM_REWARD.getScene()); smsCodeUseReqDTO.setScene(SmsSceneEnum.MEMBER_REDEEM_REWARD.getScene());
smsCodeApi.useSmsCode(smsCodeUseReqDTO); smsCodeApi.useSmsCode(smsCodeUseReqDTO);
} }
// 校验收货人信息
verifyRecipientInfo(redeemRewardReqVO, memberUser);
// 校验礼品
RewardDO rewardDO = getAndVerifyRewardDO(redeemRewardReqVO);
// 校验会员
verifyMemberUser(redeemRewardReqVO, rewardDO, memberUser.getHoldScore());
String lockKey = "reward:redeem:lock:" + redeemRewardReqVO.getRewardId();
RLock lock = redissonClient.getLock(lockKey);
try {
if (!lock.tryLock(2, 10, TimeUnit.SECONDS)) {
throw exception(GET_LOCK_FAILED);
}
// 添加兑换记录
Long redeemId = addRedeemRecord(redeemRewardReqVO, rewardDO);
// 更新会员积分
updateMemberScore(redeemRewardReqVO, rewardDO, redeemId);
// 更新礼品
redeemReward(rewardDO, redeemRewardReqVO.getRewardCount());
} catch (InterruptedException e) {
throw exception(GET_LOCK_FAILED);
} finally {
lock.unlock();
}
return true;
}
private RewardDO getAndVerifyRewardDO(RedeemRewardReqVO redeemRewardReqVO) {
// 查询礼品 // 查询礼品
RewardDO rewardDO = rewardMapper.selectById(redeemRewardReqVO.getRewardId()); RewardDO rewardDO = rewardMapper.selectById(redeemRewardReqVO.getRewardId());
if (rewardDO == null) { if (rewardDO == null) {
...@@ -102,25 +132,22 @@ public class RedeemRewardApiImpl implements RedeemRewardApi { ...@@ -102,25 +132,22 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
if (!Arrays.asList(split).contains(String.valueOf(redeemRewardReqVO.getRedeemType()))) { if (!Arrays.asList(split).contains(String.valueOf(redeemRewardReqVO.getRedeemType()))) {
throw exception(REWARD_PICK_METHOD_NOT_ALLOW); throw exception(REWARD_PICK_METHOD_NOT_ALLOW);
} }
verifyMemberUser(redeemRewardReqVO, rewardDO); return rewardDO;
String lockKey = "reward:redeem:lock:" + redeemRewardReqVO.getRewardId(); }
RLock lock = redissonClient.getLock(lockKey);
try { private void verifyRecipientInfo(RedeemRewardReqVO redeemRewardReqVO, UserRespDTO memberUser) {
if (!lock.tryLock(2, 10, TimeUnit.SECONDS)) { if (redeemRewardReqVO.getRedeemType() == RewardPickMethedEnum.SELF_PICKUP.getValue()) {
throw exception(GET_LOCK_FAILED); if (StringUtils.isBlank(redeemRewardReqVO.getRecipientName())) {
redeemRewardReqVO.setRecipientName(memberUser.getNickname());
}
if (StringUtils.isBlank(redeemRewardReqVO.getRecipientPhoneNum())) {
redeemRewardReqVO.setRecipientPhoneNum(memberUser.getMobile());
}
} else {
if (StringUtils.isAnyBlank(redeemRewardReqVO.getRecipientName(), redeemRewardReqVO.getRecipientPhoneNum(), redeemRewardReqVO.getRecipientAddress())) {
throw exception(REWARD_REDEEM_RECIPIENT_ERROR);
} }
// 添加兑换记录
Long redeemId = addRedeemRecord(redeemRewardReqVO, rewardDO);
// 更新会员积分
updateMemberScore(redeemRewardReqVO, rewardDO, redeemId);
// 更新礼品
redeemReward(rewardDO, redeemRewardReqVO.getRewardCount());
} catch (InterruptedException e) {
throw exception(GET_LOCK_FAILED);
} finally {
lock.unlock();
} }
return true;
} }
private void redeemReward(RewardDO reward, Integer rewardCount) { private void redeemReward(RewardDO reward, Integer rewardCount) {
...@@ -172,6 +199,11 @@ public class RedeemRewardApiImpl implements RedeemRewardApi { ...@@ -172,6 +199,11 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
} }
int totalCount = 0; int totalCount = 0;
for (RedeemRewardReqVO redeemRewardReqVO : redeemRewardReqVOList) { for (RedeemRewardReqVO redeemRewardReqVO : redeemRewardReqVOList) {
UserRespDTO memberUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId());
if (memberUser == null) {
throw exception(USER_NOT_EXISTS);
}
verifyRecipientInfo(redeemRewardReqVO, memberUser);
// 每个兑换VO校验一遍 // 每个兑换VO校验一遍
// 兑换方式不匹配,后台不校验 // 兑换方式不匹配,后台不校验
if (redeemRewardReqVO.getEntrance() != PlatformTypeEnum.BACKEND.getValue()) { if (redeemRewardReqVO.getEntrance() != PlatformTypeEnum.BACKEND.getValue()) {
...@@ -181,7 +213,7 @@ public class RedeemRewardApiImpl implements RedeemRewardApi { ...@@ -181,7 +213,7 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
throw exception(REWARD_PICK_METHOD_NOT_ALLOW); throw exception(REWARD_PICK_METHOD_NOT_ALLOW);
} }
} }
verifyMemberUser(redeemRewardReqVO, rewardDO); verifyMemberUser(redeemRewardReqVO, rewardDO, memberUser.getHoldScore());
// 记录兑换总数 // 记录兑换总数
totalCount += redeemRewardReqVO.getRewardCount(); totalCount += redeemRewardReqVO.getRewardCount();
// 判断兑换总数是否大于礼物数量 // 判断兑换总数是否大于礼物数量
...@@ -243,13 +275,7 @@ public class RedeemRewardApiImpl implements RedeemRewardApi { ...@@ -243,13 +275,7 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
smsCodeApi.sendSmsCode(smsCodeSendReqDTO); smsCodeApi.sendSmsCode(smsCodeSendReqDTO);
} }
private void verifyMemberUser(RedeemRewardReqVO redeemRewardReqVO, RewardDO rewardDO) { private void verifyMemberUser(RedeemRewardReqVO redeemRewardReqVO, RewardDO rewardDO, Integer holdScore) {
// 查询会员积分
UserRespDTO memberUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId());
if (memberUser == null) {
throw exception(USER_NOT_EXISTS);
}
Integer holdScore = memberUser.getHoldScore();
// 会员积分不够 // 会员积分不够
if (holdScore < rewardDO.getPointsRequire() * redeemRewardReqVO.getRewardCount()) { if (holdScore < rewardDO.getPointsRequire() * redeemRewardReqVO.getRewardCount()) {
throw exception(REWARD_SCORE_NOT_ENOUGH, "userId:" + redeemRewardReqVO.getMemberId() + ",holdScore:" + holdScore, "requireScore:" + rewardDO.getPointsRequire() * redeemRewardReqVO.getRewardCount()); throw exception(REWARD_SCORE_NOT_ENOUGH, "userId:" + redeemRewardReqVO.getMemberId() + ",holdScore:" + holdScore, "requireScore:" + rewardDO.getPointsRequire() * redeemRewardReqVO.getRewardCount());
......
...@@ -1025,6 +1025,7 @@ reward.count.not.enough = reward count not enough ...@@ -1025,6 +1025,7 @@ reward.count.not.enough = reward count not enough
reward.redeem.count.not.allow = bulk redemption is limited to a maximum of 10 pieces at a time reward.redeem.count.not.allow = bulk redemption is limited to a maximum of 10 pieces at a time
reward.redeem.allow.count.error = the number of redemptions allowed by the individual has been exceeded:{} reward.redeem.allow.count.error = the number of redemptions allowed by the individual has been exceeded:{}
reward.node.and.points.list.error = reward node and points create error reward.node.and.points.list.error = reward node and points create error
reward.redeem.recipient.error = recipient info information is incomplete
redeem.import.max.count = allow maximum number of imports is {} redeem.import.max.count = allow maximum number of imports is {}
dict.unknown.error = Not in dict {0}: {1} dict.unknown.error = Not in dict {0}: {1}
......
...@@ -1023,6 +1023,7 @@ reward.count.not.enough = \u793C\u54C1\u6570\u91CF\u4E0D\u8DB3 ...@@ -1023,6 +1023,7 @@ reward.count.not.enough = \u793C\u54C1\u6570\u91CF\u4E0D\u8DB3
reward.redeem.count.not.allow = \u6279\u91CF\u5151\u6362\u6BCF\u6B21\u6700\u591A\u5341\u6761 reward.redeem.count.not.allow = \u6279\u91CF\u5151\u6362\u6BCF\u6B21\u6700\u591A\u5341\u6761
reward.redeem.allow.count.error = \u5DF2\u8D85\u51FA\u4E2A\u4EBA\u5141\u8BB8\u5151\u6362\u6B21\u6570\uFF1A{} reward.redeem.allow.count.error = \u5DF2\u8D85\u51FA\u4E2A\u4EBA\u5141\u8BB8\u5151\u6362\u6B21\u6570\uFF1A{}
reward.node.and.points.list.error = \u521B\u5EFA\u793C\u54C1\u7F51\u70B9\u6216\u6240\u9700\u79EF\u5206\u9519\u8BEF reward.node.and.points.list.error = \u521B\u5EFA\u793C\u54C1\u7F51\u70B9\u6216\u6240\u9700\u79EF\u5206\u9519\u8BEF
reward.redeem.recipient.error = \u793C\u54C1\u6536\u8D27\u4EBA\u4FE1\u606F\u4E0D\u5168
get.lock.failed = \u670D\u52A1\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5 get.lock.failed = \u670D\u52A1\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
reward.redeem.not.exist = \u793C\u54C1\u5151\u6362\u8BB0\u5F55\u4E0D\u5B58\u5728 reward.redeem.not.exist = \u793C\u54C1\u5151\u6362\u8BB0\u5F55\u4E0D\u5B58\u5728
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment