| 
					
				 | 
			
			
				@@ -1,12 +1,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -36,13 +33,11 @@ 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; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -63,13 +58,6 @@ 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -178,83 +166,60 @@ 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) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String str = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.warn("[submitOrder--------->unifiedOrderResp][订单id({})000000支付开始]", reqVO.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        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()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 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()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            log.warn("如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功:{}", unifiedOrderResp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return PayOrderConvert.INSTANCE.convert(order, unifiedOrderResp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ErrorCode err = new ErrorCode(1,e.getMessage() + "===" + str); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw exception(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 此处需要读取最新的状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            order = orderMapper.selectById(order.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.warn("如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功:{}", unifiedOrderResp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return PayOrderConvert.INSTANCE.convert(order, unifiedOrderResp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -591,6 +556,11 @@ public class PayOrderServiceImpl implements PayOrderService { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void updatePayOrder(PayOrderDO order) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        orderMapper.updateById(order); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 同步单个支付单 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 |