|
|
@@ -28,6 +28,7 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.text.MessageFormat;
|
|
|
+import java.time.Duration;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
|
@@ -75,8 +76,8 @@ public class ConsumeRequestCheck {
|
|
|
RemoteMealTypeVo remoteMealTypeVo = commonCheck.getMealType(consumeDate);
|
|
|
if (ObjectUtil.isEmpty(remoteMealTypeVo)) {
|
|
|
return commonCheck.createErrorResponse(400, ApiErrorTypeConstants.NOT_FOUND, "不在交易时段",
|
|
|
- MessageFormat.format("非营业时段,不允许交易。消费时间[{0}]",
|
|
|
- DateUtil.format(consumeDate, "HH:mm:ss")));
|
|
|
+ MessageFormat.format("非营业时段,不允许交易。消费时间[{0}]",
|
|
|
+ DateUtil.format(consumeDate, "HH:mm:ss")));
|
|
|
}
|
|
|
// 设置消费记录的当前餐类
|
|
|
bo.setMealType(Long.valueOf(remoteMealTypeVo.getTypeId()));
|
|
|
@@ -84,7 +85,7 @@ public class ConsumeRequestCheck {
|
|
|
XfCardLimitedVo xfCardLimitedVo = new XfCardLimitedVo();
|
|
|
int statusFlag = bo.getStatusFlag();
|
|
|
if (statusFlag == Integer.parseInt(ConsumeRecordTypeEnum.XFJXF_1.code())
|
|
|
- || statusFlag == Integer.parseInt(ConsumeRecordTypeEnum.XFJXF_4.code())) {
|
|
|
+ || statusFlag == Integer.parseInt(ConsumeRecordTypeEnum.XFJXF_4.code())) {
|
|
|
|
|
|
// 设备是否可以消费验证
|
|
|
result = checkTermLimitedAndOther(bo, useTermVo, userCardVo, remoteMealTypeVo);
|
|
|
@@ -107,7 +108,7 @@ public class ConsumeRequestCheck {
|
|
|
return R.ok();
|
|
|
}
|
|
|
|
|
|
- private R<ErrorInfo> obtainResult(R<ErrorInfo> result){
|
|
|
+ private R<ErrorInfo> obtainResult(R<ErrorInfo> result) {
|
|
|
ErrorInfo data = result.getData();
|
|
|
String details = Optional.ofNullable(data).map(ErrorInfo::getDetils).orElse("超过消费限制");
|
|
|
String msg = Optional.ofNullable(data).map(ErrorInfo::getMessage).orElse("消费限制判断存在问题");
|
|
|
@@ -152,12 +153,12 @@ public class ConsumeRequestCheck {
|
|
|
}
|
|
|
if (consumeMoney.compareTo(totalBalance) > 0) {
|
|
|
return commonCheck.createErrorResponse(400, ApiErrorTypeConstants.CONSUME_CHECK_FAIL, "账户余额不足",
|
|
|
- MessageFormat.format("总余额[{0}],消费金额[{1}]", totalBalance, consumeMoney));
|
|
|
+ MessageFormat.format("总余额[{0}],消费金额[{1}]", totalBalance, consumeMoney));
|
|
|
}
|
|
|
// 计算扣费后的余额
|
|
|
BigDecimal balance = totalBalance.subtract(consumeMoney);
|
|
|
bo.setBalance(balance);
|
|
|
- baseBusiness.resetUserBalance(bo.getUserId(),balance);
|
|
|
+ baseBusiness.resetUserBalance(bo.getUserId(), balance);
|
|
|
return R.ok();
|
|
|
}
|
|
|
|
|
|
@@ -172,19 +173,24 @@ public class ConsumeRequestCheck {
|
|
|
* @return 如果原始消费记录ID重复,返回包含错误信息的响应对象;否则返回成功的响应对象
|
|
|
*/
|
|
|
private R<ErrorInfo> checkRepeatOriginalId(ConsumptionBo bo) {
|
|
|
- Set<String> originalIdSet = RedisUtils.getCacheSet(CacheNames.XF_ORIGINAL_ID);
|
|
|
+ //Set<String> originalIdSet = RedisUtils.getCacheSet(CacheNames.XF_ORIGINAL_ID);
|
|
|
|
|
|
String originalId = bo.getOriginalId();
|
|
|
if (ObjectUtil.isEmpty(originalId)) {
|
|
|
originalId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
|
|
|
- bo.getTermRecordId().shortValue(), bo.getUserNo().shortValue(), 0);
|
|
|
+ bo.getTermRecordId().shortValue(), bo.getUserNo().shortValue(), 0);
|
|
|
}
|
|
|
- if (originalIdSet.contains(originalId)) {
|
|
|
+ String originalIdCache = RedisUtils.getCacheMapValue(CacheNames.XF_ORIGINAL_ID, originalId);
|
|
|
+ if (originalIdCache != null && originalIdCache.equals(originalId)) {
|
|
|
return commonCheck.createErrorResponse(400, ApiErrorTypeConstants.CONSUME_CHECK_FAIL, "原始消费记录存在",
|
|
|
- MessageFormat.format("原始消费记录已存在:{0}", originalId));
|
|
|
+ MessageFormat.format("原始消费记录已存在:{0}", originalId));
|
|
|
}
|
|
|
bo.setOriginalId(originalId);
|
|
|
|
|
|
+ // 将当笔原始消费记录标识放入缓存,4小时过期
|
|
|
+ RedisUtils.setCacheMapValue(CacheNames.XF_ORIGINAL_ID, originalId, originalId);
|
|
|
+ RedisUtils.expire(CacheNames.XF_ORIGINAL_ID, Duration.ofHours(4));
|
|
|
+
|
|
|
return R.ok();
|
|
|
}
|
|
|
|
|
|
@@ -284,7 +290,7 @@ public class ConsumeRequestCheck {
|
|
|
R<ErrorInfo> result = task.get();
|
|
|
// 如果发现错误且尚未设置错误结果
|
|
|
if (result != null && R.isError(result) &&
|
|
|
- firstError.compareAndSet(null, result)) {
|
|
|
+ firstError.compareAndSet(null, result)) {
|
|
|
// 取消其他任务(通过中断)
|
|
|
taskExecutor.getThreadPoolExecutor().getQueue().clear();
|
|
|
}
|
|
|
@@ -321,30 +327,30 @@ public class ConsumeRequestCheck {
|
|
|
long intervalMin = (currentSec - lastPaySec) / 60;
|
|
|
|
|
|
return intervalMin < ctx.getTermSwipeInterval() ?
|
|
|
- commonCheck.createError(TradeStatusEnum.TimeInterval) : null;
|
|
|
+ commonCheck.createError(TradeStatusEnum.TimeInterval) : null;
|
|
|
}
|
|
|
|
|
|
private R<ErrorInfo> validateSingleLimit(TermConsumeValidationContext ctx) {
|
|
|
if (ctx.getTermSingleMoney().compareTo(BigDecimal.ZERO) <= 0) return null;
|
|
|
return ctx.getConsumeValue().compareTo(ctx.getTermSingleMoney()) > 0 ?
|
|
|
- commonCheck.createError(TradeStatusEnum.OnceBigMoney) : null;
|
|
|
+ commonCheck.createError(TradeStatusEnum.OnceBigMoney) : null;
|
|
|
}
|
|
|
|
|
|
private R<ErrorInfo> validateCardValidity(TermConsumeValidationContext ctx) {
|
|
|
if (ctx.getFactoryId() == 0 || !ctx.isTermUseValidity()) return null;
|
|
|
return ctx.getCurrentTime().isAfter(ctx.getExpiryTime()) ?
|
|
|
- commonCheck.createError(TradeStatusEnum.CardValidDate) : null;
|
|
|
+ commonCheck.createError(TradeStatusEnum.CardValidDate) : null;
|
|
|
}
|
|
|
|
|
|
private R<ErrorInfo> validateCardType(TermConsumeValidationContext ctx) {
|
|
|
int mask = 1 << (ctx.getCardType() - 1);
|
|
|
return (mask & ctx.getTermCardType()) == 0 ?
|
|
|
- commonCheck.createError(TradeStatusEnum.CardTypeLimit) : null;
|
|
|
+ commonCheck.createError(TradeStatusEnum.CardTypeLimit) : null;
|
|
|
}
|
|
|
|
|
|
private R<ErrorInfo> validateMealLimit(TermConsumeValidationContext ctx) {
|
|
|
return ctx.getTermMealCount() > 0 && ctx.getMealCount() >= ctx.getTermMealCount() ?
|
|
|
- commonCheck.createError(TradeStatusEnum.MealLimitTimes) : null;
|
|
|
+ commonCheck.createError(TradeStatusEnum.MealLimitTimes) : null;
|
|
|
}
|
|
|
|
|
|
private R<ErrorInfo> validateDailyLimit(TermConsumeValidationContext ctx) {
|