Commit eef3c4ae authored by zhangfeng's avatar zhangfeng

礼品兑换完善校验

parent bc3631f0
......@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
......@@ -20,12 +21,15 @@ public class RedeemRewardReqVO {
private Long rewardId;
@ApiModelProperty(value = "兑换数量", required = true)
@NotNull(message = "兑换数量不能为空")
private Integer rewardCount;
@ApiModelProperty(value = "兑换方式,同领取方式(1上门领取,2包邮到家,3邮寄到付)", required = true)
@NotNull(message = "兑换方式不能为空")
private Integer redeemType;
@ApiModelProperty(value = "兑换入口(后台,app,web)", required = true)
@NotNull(message = "兑换入口不能为空")
private Integer entrance;
@ApiModelProperty(value = "费用数字(两位小数)")
......
......@@ -29,5 +29,6 @@ public interface ErrorCodeConstants {
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 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;
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.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.RewardStatusEnum;
import cn.iocoder.yudao.module.reward.service.reward.RewardService;
......@@ -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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
......@@ -70,19 +72,47 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
@Override
@Transactional(rollbackFor = Exception.class)
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) {
AppRedeemRewardReqVO appRedeemRewardReqVO = (AppRedeemRewardReqVO) redeemRewardReqVO;
SmsCodeUseReqDTO smsCodeUseReqDTO = new SmsCodeUseReqDTO();
UserRespDTO memberUserApiUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId());
if (memberUserApiUser == null) {
throw exception(USER_NOT_EXISTS);
}
smsCodeUseReqDTO.setMobile(memberUserApiUser.getMobile());
smsCodeUseReqDTO.setMobile(memberUser.getMobile());
smsCodeUseReqDTO.setCode(appRedeemRewardReqVO.getCode());
smsCodeUseReqDTO.setUsedIp(getClientIP());
smsCodeUseReqDTO.setScene(SmsSceneEnum.MEMBER_REDEEM_REWARD.getScene());
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());
if (rewardDO == null) {
......@@ -102,25 +132,22 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
if (!Arrays.asList(split).contains(String.valueOf(redeemRewardReqVO.getRedeemType()))) {
throw exception(REWARD_PICK_METHOD_NOT_ALLOW);
}
verifyMemberUser(redeemRewardReqVO, rewardDO);
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);
return rewardDO;
}
private void verifyRecipientInfo(RedeemRewardReqVO redeemRewardReqVO, UserRespDTO memberUser) {
if (redeemRewardReqVO.getRedeemType() == RewardPickMethedEnum.SELF_PICKUP.getValue()) {
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) {
......@@ -172,6 +199,11 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
}
int totalCount = 0;
for (RedeemRewardReqVO redeemRewardReqVO : redeemRewardReqVOList) {
UserRespDTO memberUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId());
if (memberUser == null) {
throw exception(USER_NOT_EXISTS);
}
verifyRecipientInfo(redeemRewardReqVO, memberUser);
// 每个兑换VO校验一遍
// 兑换方式不匹配,后台不校验
if (redeemRewardReqVO.getEntrance() != PlatformTypeEnum.BACKEND.getValue()) {
......@@ -181,7 +213,7 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
throw exception(REWARD_PICK_METHOD_NOT_ALLOW);
}
}
verifyMemberUser(redeemRewardReqVO, rewardDO);
verifyMemberUser(redeemRewardReqVO, rewardDO, memberUser.getHoldScore());
// 记录兑换总数
totalCount += redeemRewardReqVO.getRewardCount();
// 判断兑换总数是否大于礼物数量
......@@ -243,13 +275,7 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
smsCodeApi.sendSmsCode(smsCodeSendReqDTO);
}
private void verifyMemberUser(RedeemRewardReqVO redeemRewardReqVO, RewardDO rewardDO) {
// 查询会员积分
UserRespDTO memberUser = memberUserApi.getUser(redeemRewardReqVO.getMemberId());
if (memberUser == null) {
throw exception(USER_NOT_EXISTS);
}
Integer holdScore = memberUser.getHoldScore();
private void verifyMemberUser(RedeemRewardReqVO redeemRewardReqVO, RewardDO rewardDO, Integer holdScore) {
// 会员积分不够
if (holdScore < 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
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.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 {}
dict.unknown.error = Not in dict {0}: {1}
......
......@@ -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.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.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
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