|
|
@@ -61,7 +61,8 @@ import com.github.binarywang.wxpay.exception.WxPayException;
|
|
|
import com.github.binarywang.wxpay.service.WxPayService;
|
|
|
import lombok.Data;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
|
|
+import com.fs.live.mq.LiveGoodsRocketMQTemplate;
|
|
|
+import org.apache.commons.lang.ObjectUtils;
|
|
|
import org.redisson.api.RLock;
|
|
|
import org.redisson.api.RedissonClient;
|
|
|
import org.springframework.aop.framework.AopContext;
|
|
|
@@ -109,7 +110,7 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
@Autowired
|
|
|
private CloudHostProper cloudHostProper;
|
|
|
@Autowired
|
|
|
- private RocketMQTemplate rocketMQTemplate;
|
|
|
+ private LiveGoodsRocketMQTemplate liveGoodsRocketMQTemplate;
|
|
|
@Autowired
|
|
|
private FsStoreOrderScrmMapper fsStoreOrderScrmMapper;
|
|
|
@Autowired
|
|
|
@@ -146,20 +147,20 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
try {
|
|
|
String orderKey = redisCache.getCacheObject("orderKey:" + liveOrder.getOrderKey());
|
|
|
if (StringUtils.isEmpty(orderKey)) {
|
|
|
- timer.finish("fail:orderKeyExpired");
|
|
|
+ // timer.finish("fail:orderKeyExpired");
|
|
|
return R.error("订单已过期");
|
|
|
}
|
|
|
String creatingKey = LiveOrderOptConstants.LOCK_ORDER_KEY_CREATING + liveOrder.getOrderKey();
|
|
|
if (!redisCache.setIfAbsent(creatingKey, "1", 30, TimeUnit.SECONDS)) {
|
|
|
- timer.finish("fail:orderCreating");
|
|
|
+ // timer.finish("fail:orderCreating");
|
|
|
return R.error("订单正在创建中,请勿重复提交");
|
|
|
}
|
|
|
- timer.step("orderKeyCheck");
|
|
|
+ // timer.step("orderKeyCheck");
|
|
|
|
|
|
R validateResult = validateCreateParam(liveOrder);
|
|
|
- timer.step("validateParam");
|
|
|
+ // timer.step("validateParam");
|
|
|
if (validateResult != null) {
|
|
|
- timer.finish("fail:validate");
|
|
|
+ // timer.finish("fail:validate");
|
|
|
return validateResult;
|
|
|
}
|
|
|
|
|
|
@@ -167,37 +168,37 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
Integer purchaseNum = Integer.parseInt(liveOrder.getTotalNum());
|
|
|
|
|
|
LiveGoods goods = getLiveGoodsCached(liveOrder.getLiveId(), liveOrder.getProductId());
|
|
|
- timer.step("loadLiveGoods");
|
|
|
+ // timer.step("loadLiveGoods");
|
|
|
if (goods == null) {
|
|
|
- timer.finish("fail:goodsNotFound");
|
|
|
+ // timer.finish("fail:goodsNotFound");
|
|
|
return R.error("当前商品不存在");
|
|
|
}
|
|
|
|
|
|
R stockResult = deductStockIfNeeded(liveOrder, goods);
|
|
|
- timer.step("deductStock");
|
|
|
+ // timer.step("deductStock");
|
|
|
if (stockResult != null) {
|
|
|
- timer.finish("fail:stock");
|
|
|
+ // timer.finish("fail:stock");
|
|
|
return stockResult;
|
|
|
}
|
|
|
|
|
|
if (liveService.selectLiveByLiveId(liveOrder.getLiveId()) == null) {
|
|
|
- timer.finish("fail:liveNotFound");
|
|
|
+ // timer.finish("fail:liveNotFound");
|
|
|
return R.error("当前直播不存在");
|
|
|
}
|
|
|
- timer.step("loadLive");
|
|
|
+ // timer.step("loadLive");
|
|
|
|
|
|
FsStoreProductScrm fsStoreProduct = fsStoreProductService.selectFsStoreRedisProductById(liveOrder.getProductId());
|
|
|
- timer.step("loadProduct");
|
|
|
+ // timer.step("loadProduct");
|
|
|
if (fsStoreProduct == null) {
|
|
|
- timer.finish("fail:productNotFound");
|
|
|
+ // timer.finish("fail:productNotFound");
|
|
|
return R.error("商品不存在,购买失败");
|
|
|
}
|
|
|
if (fsStoreProduct.getIsShow() == 0 || goods.getStatus() == 0) {
|
|
|
- timer.finish("fail:productOffShelf");
|
|
|
+ // timer.finish("fail:productOffShelf");
|
|
|
return R.error("商品已下架,购买失败");
|
|
|
}
|
|
|
if (!"1".equals(fsStoreProduct.getIsAudit())) {
|
|
|
- timer.finish("fail:productNotAudit");
|
|
|
+ // timer.finish("fail:productNotAudit");
|
|
|
return R.error("商品已下架,购买失败");
|
|
|
}
|
|
|
|
|
|
@@ -205,23 +206,23 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
if (liveOrder.getAttrValueId() != null) {
|
|
|
attrValue = getProductAttrValueCached(liveOrder.getAttrValueId());
|
|
|
}
|
|
|
- timer.step("loadAttrValue");
|
|
|
+ // timer.step("loadAttrValue");
|
|
|
|
|
|
checkPurchaseLimit(userId, fsStoreProduct, purchaseNum);
|
|
|
- timer.step("checkPurchaseLimit");
|
|
|
+ // timer.step("checkPurchaseLimit");
|
|
|
|
|
|
publishStockUpdate(goods.getGoodsId(), purchaseNum);
|
|
|
- timer.step("publishStockUpdate");
|
|
|
+ // timer.step("publishStockUpdate");
|
|
|
|
|
|
FsStoreOrderScrm storeOrder = buildStoreOrder(liveOrder, fsStoreProduct, attrValue, goods);
|
|
|
- timer.step("buildStoreOrder");
|
|
|
+ // timer.step("buildStoreOrder");
|
|
|
LiveCouponUser couponToUse = resolveCoupon(liveOrder, userId, storeOrder);
|
|
|
- timer.step("resolveCoupon");
|
|
|
+ // timer.step("resolveCoupon");
|
|
|
|
|
|
Integer flag = fsStoreOrderScrmMapper.insertFsStoreOrder(storeOrder);
|
|
|
- timer.step("insertOrder");
|
|
|
+ // timer.step("insertOrder");
|
|
|
if (flag == null || flag == 0) {
|
|
|
- timer.finish("fail:insertOrder");
|
|
|
+ // timer.finish("fail:insertOrder");
|
|
|
return R.error("订单创建失败");
|
|
|
}
|
|
|
|
|
|
@@ -231,27 +232,27 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
liveCouponUserService.updateLiveCouponUser(couponToUse);
|
|
|
redisCache.deleteObject(LiveOrderOptConstants.CACHE_LIVE_COUPON_USER + couponToUse.getId());
|
|
|
}
|
|
|
- timer.step("updateCoupon");
|
|
|
+ // timer.step("updateCoupon");
|
|
|
|
|
|
insertOrderItem(storeOrder, fsStoreProduct, attrValue, liveOrder.getTotalNum());
|
|
|
- timer.step("insertOrderItem");
|
|
|
+ // timer.step("insertOrderItem");
|
|
|
orderStatusService.create(storeOrder.getId(), OrderLogEnum.CREATE_ORDER.getValue(),
|
|
|
OrderLogEnum.CREATE_ORDER.getDesc());
|
|
|
- timer.step("orderStatusLog");
|
|
|
+ // timer.step("orderStatusLog");
|
|
|
|
|
|
StoreConfig config = getStoreConfigCached();
|
|
|
- timer.step("loadStoreConfig");
|
|
|
+ // timer.step("loadStoreConfig");
|
|
|
String redisKey = StoreConstants.REDIS_ORDER_OUTTIME_UNPAY + storeOrder.getId();
|
|
|
if (config != null && config.getUnPayTime() != null && config.getUnPayTime() > 0) {
|
|
|
redisCache.setCacheObject(redisKey, storeOrder.getId(), config.getUnPayTime(), TimeUnit.MINUTES);
|
|
|
} else {
|
|
|
redisCache.setCacheObject(redisKey, storeOrder.getId(), 30, TimeUnit.MINUTES);
|
|
|
}
|
|
|
- timer.step("redisUnpayKey");
|
|
|
+ // timer.step("redisUnpayKey");
|
|
|
|
|
|
redisCache.deleteObject("orderKey:" + liveOrder.getOrderKey());
|
|
|
redisCache.deleteObject(LiveOrderOptConstants.LOCK_ORDER_KEY_CREATING + liveOrder.getOrderKey());
|
|
|
- timer.step("cleanupOrderKey");
|
|
|
+ // timer.step("cleanupOrderKey");
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
calendar.setTime(storeOrder.getCreateTime());
|
|
|
@@ -260,13 +261,13 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
}
|
|
|
String payLimitTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
|
|
|
|
|
|
- timer.finish("ok orderId=" + storeOrder.getId());
|
|
|
+ // timer.finish("ok orderId=" + storeOrder.getId());
|
|
|
return R.ok("下单成功").put("order", storeOrder).put("payLimitTime", payLimitTime);
|
|
|
} catch (CustomException e) {
|
|
|
- timer.finish("fail:" + e.getMessage());
|
|
|
+ // timer.finish("fail:" + e.getMessage());
|
|
|
throw e;
|
|
|
} catch (Exception e) {
|
|
|
- timer.finish("fail:" + e.getMessage());
|
|
|
+ // timer.finish("fail:" + e.getMessage());
|
|
|
log.error("[createOpt] 订单创建失败", e);
|
|
|
return R.error("订单创建失败:" + e.getMessage());
|
|
|
}
|
|
|
@@ -279,62 +280,62 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
RLock lock = redissonClient.getLock(String.format(LOCK_KEY_PAY, orderId));
|
|
|
try {
|
|
|
boolean locked = lock.tryLock(500, 30000, TimeUnit.MILLISECONDS);
|
|
|
- timer.step("tryLock");
|
|
|
+ // timer.step("tryLock");
|
|
|
if (!locked) {
|
|
|
- timer.finish("fail:lockBusy");
|
|
|
+ // timer.finish("fail:lockBusy");
|
|
|
return R.error("订单正在处理中,请勿重复提交");
|
|
|
}
|
|
|
|
|
|
FsStoreOrderScrm order = fsStoreOrderScrmService.selectFsStoreOrderById(orderId);
|
|
|
- timer.step("loadOrder");
|
|
|
+ // timer.step("loadOrder");
|
|
|
if (order == null) {
|
|
|
- timer.finish("fail:orderNotFound");
|
|
|
+ // timer.finish("fail:orderNotFound");
|
|
|
return R.error("订单不存在");
|
|
|
}
|
|
|
if (order.getStatus() != null && order.getStatus() != OrderInfoEnum.STATUS_0.getValue()) {
|
|
|
- timer.finish("fail:orderPaid");
|
|
|
+ // timer.finish("fail:orderPaid");
|
|
|
return R.error("当前订单已支付");
|
|
|
}
|
|
|
|
|
|
String payingFlag = redisCache.getCacheObject("isPaying:" + orderId);
|
|
|
- timer.step("checkPayingFlag");
|
|
|
+ // timer.step("checkPayingFlag");
|
|
|
if (StringUtils.isNotEmpty(payingFlag) && payingFlag.equals(order.getId().toString())) {
|
|
|
- timer.finish("fail:paying");
|
|
|
+ // timer.finish("fail:paying");
|
|
|
return R.error("正在支付中...");
|
|
|
}
|
|
|
|
|
|
R preCheck = checkExistingPayments(orderId);
|
|
|
- timer.step("checkExistingPayments");
|
|
|
+ // timer.step("checkExistingPayments");
|
|
|
if (preCheck != null) {
|
|
|
- timer.finish("fail:existingPayment");
|
|
|
+ // timer.finish("fail:existingPayment");
|
|
|
return preCheck;
|
|
|
}
|
|
|
|
|
|
FsUserScrm user = getUserCached(order.getUserId());
|
|
|
- timer.step("loadUser");
|
|
|
+ // timer.step("loadUser");
|
|
|
if (user == null) {
|
|
|
- timer.finish("fail:userNotFound");
|
|
|
+ // timer.finish("fail:userNotFound");
|
|
|
return R.error("用户OPENID不存在");
|
|
|
}
|
|
|
|
|
|
applyPayTypeAmount(order, param);
|
|
|
fsStoreOrderScrmService.updateFsStoreOrder(order);
|
|
|
- timer.step("applyPayTypeAndUpdateOrder");
|
|
|
+ // timer.step("applyPayTypeAndUpdateOrder");
|
|
|
|
|
|
R payResult = invokeThirdPartyPay(order, user, param, timer);
|
|
|
- timer.finish("pay");
|
|
|
+ // timer.finish("pay");
|
|
|
return payResult;
|
|
|
} catch (InterruptedException e) {
|
|
|
Thread.currentThread().interrupt();
|
|
|
- timer.finish("fail:interrupted");
|
|
|
+ // timer.finish("fail:interrupted");
|
|
|
return R.error("支付处理被中断,请稍后重试");
|
|
|
} catch (CustomException e) {
|
|
|
redisCache.deleteObject("isPaying:" + orderId);
|
|
|
- timer.finish("fail:" + e.getMessage());
|
|
|
+ // timer.finish("fail:" + e.getMessage());
|
|
|
throw e;
|
|
|
} catch (Exception e) {
|
|
|
redisCache.deleteObject("isPaying:" + orderId);
|
|
|
- timer.finish("fail:" + e.getMessage());
|
|
|
+ // timer.finish("fail:" + e.getMessage());
|
|
|
log.error("[payOpt] 支付异常 orderId={}", orderId, e);
|
|
|
return R.error("支付失败:" + e.getMessage());
|
|
|
} finally {
|
|
|
@@ -382,7 +383,7 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
LiveGoodsUploadMqVo vo = LiveGoodsUploadMqVo.builder().goodsId(goodsId).goodsNum(purchaseNum).build();
|
|
|
try {
|
|
|
if ("北京卓美".equals(cloudHostProper.getCompanyName())) {
|
|
|
- rocketMQTemplate.syncSend("live-goods-upload", JSON.toJSONString(vo));
|
|
|
+ liveGoodsRocketMQTemplate.syncSend(LiveOrderOptConstants.TOPIC_LIVE_GOODS_UPLOAD, JSON.toJSONString(vo));
|
|
|
} else {
|
|
|
liveGoodsMapper.updateStock(goodsId, purchaseNum);
|
|
|
}
|
|
|
@@ -477,6 +478,11 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
}
|
|
|
|
|
|
BigDecimal finalPay = payPrice.subtract(discountMoney);
|
|
|
+ // 券全覆盖时兜底 0.1 元,保证可走支付回调
|
|
|
+ if (discountMoney != null && discountMoney.compareTo(BigDecimal.ZERO) > 0
|
|
|
+ && (discountMoney.compareTo(payPrice) >= 0 || finalPay.compareTo(BigDecimal.ZERO) <= 0)) {
|
|
|
+ finalPay = new BigDecimal("0.1");
|
|
|
+ }
|
|
|
storeOrder.setPayPrice(finalPay);
|
|
|
storeOrder.setPayMoney(finalPay);
|
|
|
return storeOrder;
|
|
|
@@ -490,8 +496,11 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
if (couponUser == null || couponUser.getStatus() != 0) {
|
|
|
return null;
|
|
|
}
|
|
|
- if (!couponUser.getUserId().equals(userId)) {
|
|
|
- throw new CustomException("非法操作");
|
|
|
+ if (couponUser.getUserId() == null) {
|
|
|
+ throw new CustomException("优惠券无归属,请联系管理员进行处理!");
|
|
|
+ }
|
|
|
+ if (!Long.valueOf(couponUser.getUserId()).equals(userId)) {
|
|
|
+ throw new CustomException("优惠券归属异常,请联系管理员进行处理!");
|
|
|
}
|
|
|
if (storeOrder.getCouponId() == null) {
|
|
|
return null;
|
|
|
@@ -589,7 +598,7 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
if ("3".equals(order.getPayType())) {
|
|
|
IFsStoreOrderScrmService proxy = (IFsStoreOrderScrmService) AopContext.currentProxy();
|
|
|
proxy.payConfirm(2, order.getId(), null, null, null, null);
|
|
|
- timer.step("payConfirmOffline");
|
|
|
+ // timer.step("payConfirmOffline");
|
|
|
return R.ok().put("payType", param.getPayType());
|
|
|
}
|
|
|
return R.error("支付金额异常");
|
|
|
@@ -597,10 +606,10 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
if (order.getPayMoney().compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
return R.error("支付金额异常");
|
|
|
}
|
|
|
- timer.step("payAmountValidate");
|
|
|
+ // timer.step("payAmountValidate");
|
|
|
|
|
|
MiniAppPayBundle bundle = getMiniAppPayBundleCached(param.getAppId());
|
|
|
- timer.step("loadMiniAppPayBundle");
|
|
|
+ // timer.step("loadMiniAppPayBundle");
|
|
|
|
|
|
String payCode = SnowflakeUtil.nextIdStr();
|
|
|
FsStorePaymentScrm storePayment = buildBasePayment(order, user, param, payCode);
|
|
|
@@ -609,7 +618,7 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
storePayment.setMerConfigId(bundle.getMerchantAppConfig().getId());
|
|
|
storePayment.setAppId(bundle.getPlayConfig().getAppid() == null ? "" : bundle.getPlayConfig().getAppid());
|
|
|
fsStorePaymentScrmMapper.insertFsStorePayment(storePayment);
|
|
|
- timer.step("insertPayment");
|
|
|
+ // timer.step("insertPayment");
|
|
|
|
|
|
MerchantAppConfig merchantAppConfig = bundle.getMerchantAppConfig();
|
|
|
if ("hf".equals(merchantAppConfig.getMerchantType())) {
|
|
|
@@ -636,9 +645,9 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
} catch (Exception e) {
|
|
|
log.error("分账出错 orderId={}", order.getId(), e);
|
|
|
}
|
|
|
- timer.step("huiFuPrepareDiv");
|
|
|
+ // timer.step("huiFuPrepareDiv");
|
|
|
HuifuCreateOrderResult result = huiFuService.createOrder(o);
|
|
|
- timer.step("huiFuRemoteCreateOrder");
|
|
|
+ // timer.step("huiFuRemoteCreateOrder");
|
|
|
if (result.getResp_code() != null
|
|
|
&& ("00000000".equals(result.getResp_code()) || "00000100".equals(result.getResp_code()))) {
|
|
|
FsStorePaymentScrm mt = new FsStorePaymentScrm();
|
|
|
@@ -667,7 +676,7 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
payConfig.setKeyPath(fsPayConfig.getKeyPath());
|
|
|
payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
|
|
|
wxPayService.setConfig(payConfig);
|
|
|
- timer.step("wxPrepareConfig");
|
|
|
+ // timer.step("wxPrepareConfig");
|
|
|
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
|
|
|
orderRequest.setOpenid(user.getMaOpenId());
|
|
|
orderRequest.setBody("直播订单支付");
|
|
|
@@ -677,7 +686,7 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
|
|
try {
|
|
|
WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
|
|
|
- timer.step("wxRemoteCreateOrder");
|
|
|
+ // timer.step("wxRemoteCreateOrder");
|
|
|
redisCache.setCacheObject("isPaying:" + order.getId(), order.getId().toString(), 1, TimeUnit.MINUTES);
|
|
|
return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType", param.getPayType());
|
|
|
} catch (WxPayException e) {
|
|
|
@@ -891,7 +900,8 @@ public class LiveOrderOptServiceImpl implements ILiveOrderOptService {
|
|
|
Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList.stream()
|
|
|
.collect(Collectors.toMap(FsShippingTemplatesScrm::getId, FsShippingTemplatesScrm::getType));
|
|
|
Map<Long, FsShippingTemplatesRegionScrm> shippingTemplatesRegionMap = shippingTemplatesRegionList.stream()
|
|
|
- .collect(Collectors.toMap(FsShippingTemplatesRegionScrm::getTempId, r -> r, (a, b) -> b));
|
|
|
+ .collect(Collectors.toMap(FsShippingTemplatesRegionScrm::getTempId, r -> r,
|
|
|
+ (a, b) -> a.getCityId() != null ? a : b));
|
|
|
Long tempId = Long.valueOf(fsStoreProduct.getTempId());
|
|
|
Integer templateType = shippingTemplatesMap.get(tempId);
|
|
|
FsStoreProductAttrValueScrm productAttrValue = knownAttrValue != null
|