|
|
|
@@ -1,5 +1,31 @@ |
|
|
|
package com.iformall.service.impl; |
|
|
|
|
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Calendar; |
|
|
|
import java.util.Date; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Objects; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
|
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.beans.factory.annotation.Qualifier; |
|
|
|
import org.springframework.data.redis.core.RedisTemplate; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.transaction.annotation.Propagation; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSON; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|
|
|
@@ -10,34 +36,99 @@ import com.iformall.common.IdWorker; |
|
|
|
import com.iformall.common.ResultData; |
|
|
|
import com.iformall.domain.dto.OrderSaveDto; |
|
|
|
import com.iformall.domain.dto.WxSharingOrderDto; |
|
|
|
import com.iformall.domain.po.*; |
|
|
|
import com.iformall.domain.po.WxAppinfo; |
|
|
|
import com.iformall.domain.po.WxCUser; |
|
|
|
import com.iformall.domain.po.WxCardInfo; |
|
|
|
import com.iformall.domain.po.WxCoupon; |
|
|
|
import com.iformall.domain.po.WxCouponChannel; |
|
|
|
import com.iformall.domain.po.WxCouponMerchant; |
|
|
|
import com.iformall.domain.po.WxCouponOrder; |
|
|
|
import com.iformall.domain.po.WxCouponPassword; |
|
|
|
import com.iformall.domain.po.WxCouponSend; |
|
|
|
import com.iformall.domain.po.WxCreditHistory; |
|
|
|
import com.iformall.domain.po.WxMerchant; |
|
|
|
import com.iformall.domain.po.WxMerchantBUser; |
|
|
|
import com.iformall.domain.po.WxOrder; |
|
|
|
import com.iformall.domain.po.WxOrderGroup; |
|
|
|
import com.iformall.domain.po.WxOrderPress; |
|
|
|
import com.iformall.domain.po.WxPayAccount; |
|
|
|
import com.iformall.domain.po.WxPayOrder; |
|
|
|
import com.iformall.domain.po.base.TenantEntity; |
|
|
|
import com.iformall.domain.po.msg.FmInsideOrderSuccessMsg; |
|
|
|
import com.iformall.domain.vo.*; |
|
|
|
import com.iformall.enums.*; |
|
|
|
import com.iformall.domain.po.msg.UpdateCouponStockMsg; |
|
|
|
import com.iformall.domain.vo.WxCouponSendVo; |
|
|
|
import com.iformall.domain.vo.WxMerchantVo; |
|
|
|
import com.iformall.domain.vo.WxOrderCouponPressVo; |
|
|
|
import com.iformall.domain.vo.WxOrderCouponVo; |
|
|
|
import com.iformall.domain.vo.WxOrderPayExpVo; |
|
|
|
import com.iformall.domain.vo.WxOrderPayVo; |
|
|
|
import com.iformall.domain.vo.WxOrderQueryVo; |
|
|
|
import com.iformall.enums.EnumAssignTagsTrigger; |
|
|
|
import com.iformall.enums.EnumCacheKey; |
|
|
|
import com.iformall.enums.EnumCouponChannelStatus; |
|
|
|
import com.iformall.enums.EnumCouponConditionType; |
|
|
|
import com.iformall.enums.EnumCouponMerchantStatus; |
|
|
|
import com.iformall.enums.EnumCouponOrderStatus; |
|
|
|
import com.iformall.enums.EnumCouponPasswordStatus; |
|
|
|
import com.iformall.enums.EnumCouponPasswordSupport; |
|
|
|
import com.iformall.enums.EnumCouponSendSendType; |
|
|
|
import com.iformall.enums.EnumCouponSendType; |
|
|
|
import com.iformall.enums.EnumCouponStatus; |
|
|
|
import com.iformall.enums.EnumCouponTransfer; |
|
|
|
import com.iformall.enums.EnumCouponType; |
|
|
|
import com.iformall.enums.EnumMerchantStatus; |
|
|
|
import com.iformall.enums.EnumMerchantType; |
|
|
|
import com.iformall.enums.EnumMsgMqKey; |
|
|
|
import com.iformall.enums.EnumMsgMqTag; |
|
|
|
import com.iformall.enums.EnumMsgMqTopic; |
|
|
|
import com.iformall.enums.EnumMsgRecordType; |
|
|
|
import com.iformall.enums.EnumOrderPressType; |
|
|
|
import com.iformall.enums.EnumOrderStatus; |
|
|
|
import com.iformall.enums.EnumOrderType; |
|
|
|
import com.iformall.enums.EnumPayShare; |
|
|
|
import com.iformall.enums.EnumPayStatus; |
|
|
|
import com.iformall.enums.EnumPayType; |
|
|
|
import com.iformall.enums.EnumProfitSharingOrderType; |
|
|
|
import com.iformall.enums.EnumScoreType; |
|
|
|
import com.iformall.enums.EnumUserType; |
|
|
|
import com.iformall.enums.EnumValidStatus; |
|
|
|
import com.iformall.exception.MallinkException; |
|
|
|
import com.iformall.mapper.*; |
|
|
|
import com.iformall.mapper.WxAppinfoMapper; |
|
|
|
import com.iformall.mapper.WxCUserBasicInfoMapper; |
|
|
|
import com.iformall.mapper.WxCUserMapper; |
|
|
|
import com.iformall.mapper.WxCardInfoMapper; |
|
|
|
import com.iformall.mapper.WxCouponChannelMapper; |
|
|
|
import com.iformall.mapper.WxCouponMapper; |
|
|
|
import com.iformall.mapper.WxCouponMerchantMapper; |
|
|
|
import com.iformall.mapper.WxCouponOrderMapper; |
|
|
|
import com.iformall.mapper.WxCouponPasswordMapper; |
|
|
|
import com.iformall.mapper.WxMallMapper; |
|
|
|
import com.iformall.mapper.WxMerchantBUserMapper; |
|
|
|
import com.iformall.mapper.WxMerchantMapper; |
|
|
|
import com.iformall.mapper.WxOrderGroupMapper; |
|
|
|
import com.iformall.mapper.WxOrderMapper; |
|
|
|
import com.iformall.mapper.WxOrderPressMapper; |
|
|
|
import com.iformall.mapper.WxPayAccountMapper; |
|
|
|
import com.iformall.mapper.WxPayOrderMapper; |
|
|
|
import com.iformall.mq.MqBaseProducer; |
|
|
|
import com.iformall.service.*; |
|
|
|
import com.iformall.utils.*; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.beans.factory.annotation.Qualifier; |
|
|
|
import org.springframework.data.redis.core.RedisTemplate; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.transaction.annotation.Propagation; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.*; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import com.iformall.service.ExcelService; |
|
|
|
import com.iformall.service.WxAppinfoService; |
|
|
|
import com.iformall.service.WxCUserService; |
|
|
|
import com.iformall.service.WxCUserTagsService; |
|
|
|
import com.iformall.service.WxCouponActionLogService; |
|
|
|
import com.iformall.service.WxCouponSendService; |
|
|
|
import com.iformall.service.WxCreditHistoryService; |
|
|
|
import com.iformall.service.WxMsgLimitService; |
|
|
|
import com.iformall.service.WxOrderService; |
|
|
|
import com.iformall.service.WxPayOrderService; |
|
|
|
import com.iformall.service.WxProfitSharingOrderService; |
|
|
|
import com.iformall.service.WxScoreRulesService; |
|
|
|
import com.iformall.utils.Constant; |
|
|
|
import com.iformall.utils.DateUtils; |
|
|
|
import com.iformall.utils.PayUtils; |
|
|
|
import com.iformall.utils.PressUtils; |
|
|
|
import com.iformall.utils.RedisLock; |
|
|
|
import com.iformall.utils.Utility; |
|
|
|
|
|
|
|
@Service |
|
|
|
public class WxOrderServiceImpl implements WxOrderService { |
|
|
|
@@ -479,94 +570,165 @@ public class WxOrderServiceImpl implements WxOrderService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 减库存 |
|
|
|
* |
|
|
|
* @param user |
|
|
|
* @param coupon |
|
|
|
* @param couponIdStr |
|
|
|
*/ |
|
|
|
private void stockReduce(WxCUser user, WxCoupon coupon, String couponIdStr) { |
|
|
|
long time = System.currentTimeMillis() + RedisLock.TIMEOUT; |
|
|
|
String timeStr = String.valueOf(time); |
|
|
|
// 库存加锁 |
|
|
|
if (!redisLock.lock(couponIdStr, timeStr)) { |
|
|
|
logger.error("此券被锁定, couponId: " + couponIdStr); |
|
|
|
throw new MallinkException(ErrorCode.TOO_MANY_REQUEST); |
|
|
|
} |
|
|
|
|
|
|
|
// 检查 优惠券 库存 |
|
|
|
if (coupon.getRemainInventory() <= 0) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
logger.error("此券库存为0, couponId: " + couponIdStr); |
|
|
|
throw new MallinkException(ErrorCode.REMAIN_IS_EMPTY); |
|
|
|
} |
|
|
|
|
|
|
|
int count = 0; |
|
|
|
// 有价券 |
|
|
|
if (coupon.getSalePrice() > 0) { |
|
|
|
// 检查是否未支付订单 |
|
|
|
try { |
|
|
|
count = getUserOrderCount(user, coupon); |
|
|
|
} catch (Exception e) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
} |
|
|
|
if (count > 0) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
logger.error("此券有未支付的订单, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_UNPAID); |
|
|
|
} |
|
|
|
} |
|
|
|
//检查拼团中的数量 |
|
|
|
try { |
|
|
|
count = getUserOrderGroupCount(user, coupon); |
|
|
|
} catch (Exception e) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
} |
|
|
|
if (count >= coupon.getUseLimitQuantity()) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); |
|
|
|
} |
|
|
|
|
|
|
|
// 检查用户已购买数量 |
|
|
|
try { |
|
|
|
count = getUserCouponOrderCount(user, coupon); |
|
|
|
} catch (Exception e) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
} |
|
|
|
if (count >= coupon.getUseLimitQuantity()) { |
|
|
|
//解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// 减库存 |
|
|
|
int num = wxCouponMapper.reduceInventory(coupon.getId(), 1, coupon.getRemainInventory()); |
|
|
|
if (num <= 0) { |
|
|
|
logger.error("此券减库存失败, couponId: " + couponIdStr); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_FAIL); |
|
|
|
} |
|
|
|
} catch (RuntimeException e) { |
|
|
|
logger.error("此券减库存失败, couponId: " + couponIdStr); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_FAIL); |
|
|
|
} finally { |
|
|
|
// 解锁 |
|
|
|
redisLock.unlock(couponIdStr, timeStr); |
|
|
|
} |
|
|
|
} |
|
|
|
* 减库存 |
|
|
|
* |
|
|
|
* @param user |
|
|
|
* @param coupon |
|
|
|
* @param couponIdStr |
|
|
|
*/ |
|
|
|
private void stockReduce(WxCUser user, WxCoupon coupon, String couponIdStr) { |
|
|
|
|
|
|
|
long redisStock = redisLock.getCouponStock(Long.parseLong(couponIdStr)); |
|
|
|
if (redisStock<=0) { |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券库存已为零!"); |
|
|
|
} |
|
|
|
// 检查 优惠券 库存 |
|
|
|
if (coupon.getRemainInventory() <= 0) { |
|
|
|
throw new MallinkException(ErrorCode.REMAIN_IS_EMPTY); |
|
|
|
} |
|
|
|
|
|
|
|
int count = 0; |
|
|
|
// 有价券 |
|
|
|
if (coupon.getSalePrice() > 0) { |
|
|
|
// 检查是否未支付订单 |
|
|
|
try { |
|
|
|
count = getUserOrderCount(user, coupon); |
|
|
|
} catch (Exception e) { |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
} |
|
|
|
if (count > 0) { |
|
|
|
logger.error("此券有未支付的订单, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_UNPAID); |
|
|
|
} |
|
|
|
} |
|
|
|
//检查拼团中的数量 |
|
|
|
try { |
|
|
|
count = getUserOrderGroupCount(user, coupon); |
|
|
|
} catch (Exception e) { |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
} |
|
|
|
if (count >= coupon.getUseLimitQuantity()) { |
|
|
|
logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); |
|
|
|
} |
|
|
|
|
|
|
|
// 检查用户已购买数量 |
|
|
|
try { |
|
|
|
count = getUserCouponOrderCount(user, coupon); |
|
|
|
} catch (Exception e) { |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
} |
|
|
|
if (count >= coupon.getUseLimitQuantity()) { |
|
|
|
logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
//减库存,从redis中取,然后发mq消息同步到数据库 |
|
|
|
long stock = redisLock.decrease(EnumCacheKey.COUPON_STOCK.getMessage()+coupon.getId(), 1); |
|
|
|
if (stock <= 0 ) { |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券库存已为零!"); |
|
|
|
} |
|
|
|
UpdateCouponStockMsg msg = new UpdateCouponStockMsg(); |
|
|
|
msg.setCouponId(coupon.getId()); |
|
|
|
msg.setNumber(1); |
|
|
|
msg.setOperateType(UpdateCouponStockMsg.OPERATE_TYPE_DECREASE); |
|
|
|
msg.setMsgType(EnumMsgRecordType.COUPON_STOCK.getCode()); |
|
|
|
mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.STOCK.getCode(), "*", "decrease_stock_"+coupon.getId()); |
|
|
|
} catch (RuntimeException e) { |
|
|
|
logger.error("此券减库存失败, couponId: " + couponIdStr); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_FAIL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// /** |
|
|
|
// * 减库存 |
|
|
|
// * |
|
|
|
// * @param user |
|
|
|
// * @param coupon |
|
|
|
// * @param couponIdStr |
|
|
|
// */ |
|
|
|
// private void stockReduce(WxCUser user, WxCoupon coupon, String couponIdStr) { |
|
|
|
// long time = System.currentTimeMillis() + RedisLock.TIMEOUT; |
|
|
|
// String timeStr = String.valueOf(time); |
|
|
|
// // 库存加锁 |
|
|
|
// if (!redisLock.lock(couponIdStr, timeStr)) { |
|
|
|
// logger.error("此券被锁定, couponId: " + couponIdStr); |
|
|
|
// throw new MallinkException(ErrorCode.TOO_MANY_REQUEST); |
|
|
|
// } |
|
|
|
// |
|
|
|
// // 检查 优惠券 库存 |
|
|
|
// if (coupon.getRemainInventory() <= 0) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// logger.error("此券库存为0, couponId: " + couponIdStr); |
|
|
|
// throw new MallinkException(ErrorCode.REMAIN_IS_EMPTY); |
|
|
|
// } |
|
|
|
// |
|
|
|
// int count = 0; |
|
|
|
// // 有价券 |
|
|
|
// if (coupon.getSalePrice() > 0) { |
|
|
|
// // 检查是否未支付订单 |
|
|
|
// try { |
|
|
|
// count = getUserOrderCount(user, coupon); |
|
|
|
// } catch (Exception e) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
// } |
|
|
|
// if (count > 0) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// logger.error("此券有未支付的订单, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
// throw new MallinkException(ErrorCode.ORDER_UNPAID); |
|
|
|
// } |
|
|
|
// } |
|
|
|
// //检查拼团中的数量 |
|
|
|
// try { |
|
|
|
// count = getUserOrderGroupCount(user, coupon); |
|
|
|
// } catch (Exception e) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
// } |
|
|
|
// if (count >= coupon.getUseLimitQuantity()) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
// throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); |
|
|
|
// } |
|
|
|
// |
|
|
|
// // 检查用户已购买数量 |
|
|
|
// try { |
|
|
|
// count = getUserCouponOrderCount(user, coupon); |
|
|
|
// } catch (Exception e) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// throw new MallinkException(ErrorCode.DB_FAIL); |
|
|
|
// } |
|
|
|
// if (count >= coupon.getUseLimitQuantity()) { |
|
|
|
// //解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); |
|
|
|
// throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); |
|
|
|
// } |
|
|
|
// |
|
|
|
// try { |
|
|
|
// // 减库存 |
|
|
|
// int num = wxCouponMapper.reduceInventory(coupon.getId(), 1); |
|
|
|
// if (num <= 0) { |
|
|
|
// logger.error("此券减库存失败, couponId: " + couponIdStr); |
|
|
|
// throw new MallinkException(ErrorCode.ORDER_IS_FAIL); |
|
|
|
// } |
|
|
|
// } catch (RuntimeException e) { |
|
|
|
// logger.error("此券减库存失败, couponId: " + couponIdStr); |
|
|
|
// throw new MallinkException(ErrorCode.ORDER_IS_FAIL); |
|
|
|
// } finally { |
|
|
|
// // 解锁 |
|
|
|
// redisLock.unlock(couponIdStr, timeStr); |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
@Override |
|
|
|
public void stockBack(WxOrder updateOrder) { |
|
|
|
@@ -575,7 +737,7 @@ public class WxOrderServiceImpl implements WxOrderService { |
|
|
|
Long couponId = updateOrder.getProductId(); |
|
|
|
String couponIdStr = "" + couponId; |
|
|
|
//加锁 |
|
|
|
long time = System.currentTimeMillis() + RedisLock.TIMEOUT; |
|
|
|
long time = System.currentTimeMillis() + 300*RedisLock.TIMEOUT; |
|
|
|
String timeStr = String.valueOf(time); |
|
|
|
|
|
|
|
if (!redisLock.lock(couponIdStr, timeStr)) { |
|
|
|
@@ -602,6 +764,7 @@ public class WxOrderServiceImpl implements WxOrderService { |
|
|
|
logger.error("此券加库存失败, couponId: " + couponIdStr); |
|
|
|
throw new MallinkException(ErrorCode.ORDER_IS_FAIL); |
|
|
|
} |
|
|
|
redisLock.increase(EnumCacheKey.COUPON_STOCK.getMessage()+coupon.getId(), 1); |
|
|
|
} catch (Exception e) { |
|
|
|
logger.error("数据库更新失败,库存+1失败, e:" + e.getMessage()); |
|
|
|
throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "库存恢复失败"); |
|
|
|
@@ -1717,6 +1880,7 @@ public class WxOrderServiceImpl implements WxOrderService { |
|
|
|
throw new MallinkException(ErrorCode.SYS_REPEAT_SUBMIT_EXCEPTION); |
|
|
|
} |
|
|
|
cUserTokenRedisTemplate.opsForValue().set(key, user, 1000, TimeUnit.MILLISECONDS); |
|
|
|
|
|
|
|
order = saveFreeOrderForCoupon(user, coupon, orderSaveDto.getCouponChannelId(), orderSaveDto.getFormId(), null); |
|
|
|
if (order != null) { |
|
|
|
// 6. 下订单完成,发送内部消息 |
|
|
|
|