|
@@ -1,9 +1,12 @@
|
|
|
package cn.newfeifan.mall.module.pay.service.order;
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.date.DatePattern;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.hutool.extra.spring.SpringUtil;
|
|
|
+import cn.newfeifan.mall.framework.common.exception.ErrorCode;
|
|
|
import cn.newfeifan.mall.framework.common.pojo.PageResult;
|
|
|
import cn.newfeifan.mall.framework.common.util.date.LocalDateTimeUtils;
|
|
|
import cn.newfeifan.mall.framework.common.util.number.MoneyUtils;
|
|
@@ -33,11 +36,13 @@ import cn.newfeifan.mall.module.pay.service.channel.PayChannelService;
|
|
|
import cn.newfeifan.mall.module.pay.service.notify.PayNotifyService;
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
+import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
@@ -58,6 +63,13 @@ import static cn.newfeifan.mall.module.pay.enums.ErrorCodeConstants.*;
|
|
|
@Slf4j
|
|
|
public class PayOrderServiceImpl implements PayOrderService {
|
|
|
|
|
|
+ public static final String TRADE_NO = "trade_no:";
|
|
|
+ public static final String FUYOU_TRADE_ORDER_NO_PREFIX = "16103-";
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ StringRedisTemplate stringRedisTemplate;
|
|
|
+
|
|
|
+
|
|
|
@Resource
|
|
|
private PayProperties payProperties;
|
|
|
|
|
@@ -84,10 +96,10 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|
|
@Override
|
|
|
public PayOrderDO getOrderByStatus(PayOrderDO payOrderDO) {
|
|
|
//添加验证是否支付成功
|
|
|
- if(payOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())){
|
|
|
+ if (payOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())) {
|
|
|
//修改程序,当微信支付回调的时候再次向微信请求查询pay订单的支付状态
|
|
|
- log.info("============支付成功查询:支付订单号{}",payOrderDO.getId());
|
|
|
- log.info("============支付成功查询:支付订单详情{}",payOrderDO);
|
|
|
+ log.info("============支付成功查询:支付订单号{}", payOrderDO.getId());
|
|
|
+ log.info("============支付成功查询:支付订单详情{}", payOrderDO);
|
|
|
PayOrderExtensionDO payOrderExtensionDO = orderExtensionMapper.selectByPayId(payOrderDO.getId());
|
|
|
syncOrder(payOrderExtensionDO);
|
|
|
}
|
|
@@ -101,10 +113,10 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|
|
public PayOrderDO getOrderByStatus(Long id) {
|
|
|
//添加验证是否支付成功
|
|
|
PayOrderDO payOrderDO = orderMapper.selectById(id);
|
|
|
- if(payOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())){
|
|
|
+ if (payOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())) {
|
|
|
//修改程序,当微信支付回调的时候再次向微信请求查询pay订单的支付状态
|
|
|
- log.info("============支付成功查询:支付订单号{}",payOrderDO.getId());
|
|
|
- log.info("============支付成功查询:支付订单详情{}",payOrderDO);
|
|
|
+ log.info("============支付成功查询:支付订单号{}", payOrderDO.getId());
|
|
|
+ log.info("============支付成功查询:支付订单详情{}", payOrderDO);
|
|
|
PayOrderExtensionDO payOrderExtensionDO = orderExtensionMapper.selectByPayId(payOrderDO.getId());
|
|
|
syncOrder(payOrderExtensionDO);
|
|
|
}
|
|
@@ -166,63 +178,87 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|
|
.setRefundPrice(0);
|
|
|
order.setParentPayOrderId(reqDTO.getParentPayOrderId());//设置父支付订单ID
|
|
|
order.setExpireTime(order.getExpireTime());//把父支付订单的过期时间,设置到子订单
|
|
|
+ order.setPayOrderNo(generate(FUYOU_TRADE_ORDER_NO_PREFIX));
|
|
|
orderMapper.insert(order);
|
|
|
return order.getId();
|
|
|
}
|
|
|
|
|
|
+ private String generate(String prefix) {
|
|
|
+ // 递增序号
|
|
|
+ String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN);
|
|
|
+ String key = TRADE_NO + noPrefix;
|
|
|
+ Long no = stringRedisTemplate.opsForValue().increment(key);
|
|
|
+ // 设置过期时间
|
|
|
+ stringRedisTemplate.expire(key, Duration.ofMinutes(1L));
|
|
|
+ return noPrefix + no;
|
|
|
+ }
|
|
|
+
|
|
|
@Override // 注意,这里不能添加事务注解,避免调用支付渠道失败时,将 PayOrderExtensionDO 回滚了
|
|
|
public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) {
|
|
|
|
|
|
- log.warn("[submitOrder--------->unifiedOrderResp][订单id({})000000支付开始]", reqVO.getId());
|
|
|
-
|
|
|
+ String str = "";
|
|
|
|
|
|
- // 1.1 获得 PayOrderDO ,并校验其是否存在
|
|
|
- PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
|
|
|
- // 1.32 校验支付渠道是否有效
|
|
|
- PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
|
|
|
- PayClient client = channelService.getPayClient(channel.getId());
|
|
|
-
|
|
|
- log.warn("[submitOrder--------->unifiedOrderResp][订单id({})1111111支付渠道校验通过]", order.getId());
|
|
|
-
|
|
|
- // 2. 插入 PayOrderExtensionDO
|
|
|
- String no = noRedisDAO.generate(payProperties.getOrderNoPrefix());
|
|
|
- PayOrderExtensionDO orderExtension = PayOrderConvert.INSTANCE.convert(reqVO, userIp)
|
|
|
- .setOrderId(order.getId()).setNo(no)
|
|
|
- .setChannelId(channel.getId()).setChannelCode(channel.getCode())
|
|
|
- .setStatus(PayOrderStatusEnum.WAITING.getStatus());
|
|
|
- orderExtensionMapper.insert(orderExtension);
|
|
|
-
|
|
|
- log.warn("[submitOrder--------->unifiedOrderResp][订单id({})2222222支付渠道校验通过]", order.getId());
|
|
|
-
|
|
|
- // 3. 调用三方接口
|
|
|
- PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderConvert.INSTANCE.convert2(reqVO, userIp)
|
|
|
- // 商户相关的字段
|
|
|
- .setOutTradeNo(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性!
|
|
|
- .setSubject(order.getSubject()).setBody(order.getBody())
|
|
|
- .setNotifyUrl(genChannelOrderNotifyUrl(channel))
|
|
|
- .setReturnUrl(reqVO.getReturnUrl())
|
|
|
- // 订单相关字段
|
|
|
- .setPrice(order.getPrice()).setExpireTime(order.getExpireTime());
|
|
|
- PayOrderRespDTO unifiedOrderResp = client.unifiedOrder(unifiedOrderReqDTO);
|
|
|
-
|
|
|
- log.warn("[submitOrder--------->unifiedOrderResp][订单id({})333333支付完成,支付状态({})]", order.getId(), unifiedOrderResp.getStatus());
|
|
|
-
|
|
|
- // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功
|
|
|
- if (unifiedOrderResp != null) {
|
|
|
- getSelf().notifyOrder(channel, unifiedOrderResp);
|
|
|
- // 如有渠道错误码,则抛出业务异常,提示用户
|
|
|
- if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) {
|
|
|
- throw exception(PAY_ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(),
|
|
|
- unifiedOrderResp.getChannelErrorMsg());
|
|
|
+ try {
|
|
|
+// int i = 0/0;
|
|
|
+ log.warn("[submitOrder--------->unifiedOrderResp][订单id({})000000支付开始]", reqVO.getId());
|
|
|
+ str = "支付开始";
|
|
|
+
|
|
|
+
|
|
|
+ // 1.1 获得 PayOrderDO ,并校验其是否存在
|
|
|
+ PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
|
|
|
+ // 1.32 校验支付渠道是否有效
|
|
|
+ PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
|
|
|
+ PayClient client = channelService.getPayClient(channel.getId());
|
|
|
+
|
|
|
+ log.warn("[submitOrder--------->unifiedOrderResp][订单id({})1111111支付渠道校验通过]", order.getId());
|
|
|
+ str = "支付渠道校验通过";
|
|
|
+
|
|
|
+ // 2. 插入 PayOrderExtensionDO
|
|
|
+ String no = noRedisDAO.generate(payProperties.getOrderNoPrefix());
|
|
|
+ PayOrderExtensionDO orderExtension = PayOrderConvert.INSTANCE.convert(reqVO, userIp)
|
|
|
+ .setOrderId(order.getId()).setNo(no)
|
|
|
+ .setChannelId(channel.getId()).setChannelCode(channel.getCode())
|
|
|
+ .setStatus(PayOrderStatusEnum.WAITING.getStatus());
|
|
|
+ orderExtensionMapper.insert(orderExtension);
|
|
|
+
|
|
|
+ log.warn("[submitOrder--------->unifiedOrderResp][订单id({})2222222支付渠道校验通过]", order.getId());
|
|
|
+ str = "222支付渠道校验通过";
|
|
|
+
|
|
|
+ // 3. 调用三方接口
|
|
|
+ PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderConvert.INSTANCE.convert2(reqVO, userIp)
|
|
|
+ // 商户相关的字段
|
|
|
+ .setOutTradeNo(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性!
|
|
|
+ .setSubject(order.getSubject()).setBody(order.getBody())
|
|
|
+ .setNotifyUrl(genChannelOrderNotifyUrl(channel))
|
|
|
+ .setReturnUrl(reqVO.getReturnUrl())
|
|
|
+ // 订单相关字段
|
|
|
+ .setPrice(order.getPrice()).setExpireTime(order.getExpireTime());
|
|
|
+ PayOrderRespDTO unifiedOrderResp = client.unifiedOrder(unifiedOrderReqDTO);
|
|
|
+
|
|
|
+ log.warn("[submitOrder--------->unifiedOrderResp][订单id({})333333支付完成,支付状态({})]", order.getId(), unifiedOrderResp.getStatus());
|
|
|
+ str = "调用三方接口";
|
|
|
+
|
|
|
+ // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功
|
|
|
+ if (unifiedOrderResp != null) {
|
|
|
+ getSelf().notifyOrder(channel, unifiedOrderResp);
|
|
|
+ // 如有渠道错误码,则抛出业务异常,提示用户
|
|
|
+ if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) {
|
|
|
+ throw exception(PAY_ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(),
|
|
|
+ unifiedOrderResp.getChannelErrorMsg());
|
|
|
+ }
|
|
|
+ // 此处需要读取最新的状态
|
|
|
+ order = orderMapper.selectById(order.getId());
|
|
|
}
|
|
|
- // 此处需要读取最新的状态
|
|
|
- order = orderMapper.selectById(order.getId());
|
|
|
+ log.warn("如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功:{}", unifiedOrderResp);
|
|
|
+ return PayOrderConvert.INSTANCE.convert(order, unifiedOrderResp);
|
|
|
+ } catch (Exception e) {
|
|
|
+ ErrorCode err = new ErrorCode(1,e.getMessage() + "===" + str);
|
|
|
+ throw exception(err);
|
|
|
}
|
|
|
- log.warn("如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功:{}", unifiedOrderResp);
|
|
|
- return PayOrderConvert.INSTANCE.convert(order, unifiedOrderResp);
|
|
|
}
|
|
|
|
|
|
- private PayOrderDO validateOrderCanSubmit(Long id) {
|
|
|
+ @Override
|
|
|
+ public PayOrderDO validateOrderCanSubmit(Long id) {
|
|
|
PayOrderDO order = orderMapper.selectById(id);
|
|
|
if (order == null) { // 是否存在
|
|
|
throw exception(PAY_ORDER_NOT_FOUND);
|
|
@@ -526,7 +562,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|
|
return false;
|
|
|
}
|
|
|
PayOrderRespDTO respDTO = payClient.getOrder(orderExtension.getNo());
|
|
|
- log.info("===========微信回调结果PayOrderRespDTO:{}",respDTO);
|
|
|
+ log.info("===========微信回调结果PayOrderRespDTO:{}", respDTO);
|
|
|
// 1.2 回调支付结果
|
|
|
notifyOrder(orderExtension.getChannelId(), respDTO);
|
|
|
|