浏览代码

支付关单处理

刘俊驰 6 月之前
父节点
当前提交
8cd32356e7

+ 59 - 12
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/open/UserPaymentClient.java

@@ -11,20 +11,17 @@ import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
 import com.microsvc.toolkit.middleware.payment.common.api.PaymentServiceContext;
 import com.microsvc.toolkit.middleware.payment.common.api.entity.PaymentResp;
 import com.microsvc.toolkit.middleware.payment.common.api.entity.RefundResp;
+import com.microsvc.toolkit.middleware.payment.common.api.enums.PaymentStatus;
 import com.yeepay.g3.sdk.yop.encrypt.DigitalEnvelopeDTO;
 import com.yeepay.g3.sdk.yop.utils.DigitalEnvelopeUtils;
 import com.yeepay.g3.sdk.yop.utils.RSAKeyUtils;
 import com.yonge.cooleshow.biz.dal.entity.PaymentMerchantConfig;
 import com.yonge.cooleshow.biz.dal.entity.TenantMember;
 import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
-import com.yonge.cooleshow.biz.dal.service.PaymentMerchantConfigService;
-import com.yonge.cooleshow.biz.dal.service.TenantMemberService;
-import com.yonge.cooleshow.biz.dal.service.UserOrderRefundBillService;
-import com.yonge.cooleshow.biz.dal.service.UserOrderService;
-import com.yonge.cooleshow.biz.dal.service.UserPaymentCoreService;
-import com.yonge.cooleshow.biz.dal.service.UserPaymentOrderService;
+import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
 import com.yonge.cooleshow.common.enums.EPayerType;
+import com.yonge.cooleshow.common.enums.payment.EPaymentStatus;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -33,12 +30,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
 
 import javax.servlet.http.HttpServletRequest;
 import java.security.PrivateKey;
@@ -101,6 +94,60 @@ public class UserPaymentClient {
         return paymentServiceContext.getPaymentService(vendor).returnNotifyResult(request);
     }
 
+    /**
+     * 关闭订单测试
+     * @param orderNo 订单号
+     * @return R<UserPaymentOrderVo.UserPaymentOrder>
+     */
+    @ApiOperation(value = "关闭订单测试", notes = "关闭订单测试")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "orderNo", value = "订单号", dataType = "String")
+    })
+    @GetMapping("/closed/{orderNo}")
+    public R<Object> testOrderClosed(@PathVariable("orderNo") String orderNo) {
+
+        // 支付订单详情
+        UserPaymentOrderWrapper.UserPaymentOrder paymentOrder = userPaymentOrderService.getUserPaymentOrderByOrderNo( orderNo);
+        if (Objects.isNull(paymentOrder)) {
+            throw BizException.from("订单不存在");
+        }
+
+        // 测试订单关闭
+        PaymentResp paymentResp = userPaymentCoreService.closedPayment( paymentOrder);
+
+        return R.from(paymentResp);
+    }
+
+    @ApiOperation(value = "关单消息回调", notes = "三方支付平台关单消息通知")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "vendor", value = "服务提供方", dataType = "String")
+    })
+    @RequestMapping(value = "/closed/callback/{vendor}", method = {RequestMethod.GET, RequestMethod.POST})
+    public String closed(@PathVariable("vendor") String vendor, HttpServletRequest request) {
+
+        // 支付回调消息
+        PaymentResp paymentResp = paymentServiceContext.getPaymentService(vendor).callbackNotifyForClosed(request);
+        // 关单回调对象为空或关闭失败,直接返回忽略后续流程
+        if (Objects.isNull(paymentResp) || paymentResp.getPaymentStatus() != PaymentStatus.CLOSED) {
+            return null;
+        }
+        log.info("closed vendor={}, paymentResp={}", vendor, JSON.toJSONString(paymentResp));
+
+        // 支付订单确认
+        UserPaymentOrderWrapper.UserPaymentOrder paymentOrder = userPaymentOrderService.getUserPaymentOrderByTranNo(paymentResp.getTransNo());
+        if (Objects.isNull(paymentOrder) || paymentOrder.getStatus() == EPaymentStatus.PAID || paymentOrder.getStatus() == EPaymentStatus.CLOSED) {
+            return paymentResp.getMsg();
+        }
+        // 关单订单编号
+        paymentResp.setMerOrderNo(paymentOrder.getOrderNo());
+
+        // 执行支付回调流程
+        userPaymentCoreService.executePaymentCallback(paymentResp);
+
+        return paymentServiceContext.getPaymentService(vendor).returnNotifyResult(request);
+    }
+
+
     @ApiOperation(value = "用户付款", notes = "用户付款")
     @PostMapping("/executePayment/v2")
     public R<UserPaymentOrderWrapper.PaymentReq> executePayment(@Validated @RequestBody UserPaymentOrderWrapper.PaymentOrderReqConfig config,

+ 11 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/UserOrderController.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.student.controller;
 
 import cn.hutool.extra.servlet.ServletUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.microsvc.toolkit.common.response.template.R;
 import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
@@ -392,5 +393,15 @@ public class UserOrderController extends BaseController {
         return HttpResponseResult.succeed(orderPayTypeResp);
     }
 
+    @ApiOperation(value = "订单定时同步测试", notes = "订单定时同步测试")
+    @GetMapping("/payment/testPaymentSync")
+    public R<JSONObject> testPaymentSync() {
+
+        // 定时扫描待支付订单是否已超时
+        userPaymentCoreService.scanPaymentTimeoutOrderRecord();
+
+        return R.defaultR();
+    }
+
 
 }

+ 10 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentCoreService.java

@@ -85,4 +85,14 @@ public interface UserPaymentCoreService {
     void refundPayment(String orderNo,  String reason);
 
     void refundOnly(String reason, String orderNo);
+
+
+    /**
+     * 关闭订单
+     *
+     * @param userInfo     JwtUserInfo
+     * @param paymentOrder UserPaymentOrder
+     * @return PaymentResp
+     */
+    PaymentResp closedPayment( UserPaymentOrderWrapper.UserPaymentOrder paymentOrder);
 }

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentOrderService.java

@@ -59,4 +59,6 @@ public interface UserPaymentOrderService   {
      *
      */
     void save(UserPaymentOrderWrapper.UserPaymentOrder orderReq);
+
+    UserPaymentOrderWrapper.UserPaymentOrder getUserPaymentOrderByTranNo(String transNo);
 }

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java

@@ -732,7 +732,7 @@ public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<Customer
                         if (message == null) {
                             continue;
                         }
-                        Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
+                        String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
                         log.info("batchSendPrivateMessage GROUP tencentCloud senderId={}, ret={}", senderId, ret);
                     }
                 } else {
@@ -741,7 +741,7 @@ public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<Customer
                         if (message == null) {
                             continue;
                         }
-                        Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
+                        String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
                         log.info("batchSendPrivateMessage GROUP rongCloud senderId={}, ret={}", senderId, ret);
                     }
                 }

+ 6 - 6
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java

@@ -393,12 +393,12 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
                         .msgContent(TencentRequest.TextMessageBody.builder().text(customerMessage).build())
                         .build();
 
-                Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
+                String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
                 log.info("registerUserBindCustomerService GROUP tencentCloud senderId={}, ret={}", build.getSenderId(), ret);
             } else {
                 // 融云IM消息
                 TxtMessage message = new TxtMessage(customerMessage, "");
-                Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
+                String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
                 log.info("registerUserBindCustomerService GROUP rongCloud senderId={}, ret={}", build.getSenderId(), ret);
             }
 
@@ -460,12 +460,12 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
                         .msgContent(TencentRequest.TextMessageBody.builder().text(sendMessage).build())
                         .build();
 
-                Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
+                String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
                 log.info("registerUserBindCustomerService GROUP tencentCloud senderId={}, ret={}", build.getSenderId(), ret);
             } else {
                 // 融云IM消息
                 TxtMessage message = new TxtMessage(sendMessage, "");
-                Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
+                String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
                 log.info("registerUserBindCustomerService GROUP rongCloud senderId={}, ret={}", build.getSenderId(), ret);
             }
         } catch (Exception e) {
@@ -559,7 +559,7 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
                         if (message == null) {
                             continue;
                         }
-                        Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
+                        String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getMsgType()).tencentMessage(message));
                         log.info("batchSendPrivateMessage GROUP tencentCloud senderId={}, ret={}", senderId, ret);
                     }
                 } else {
@@ -568,7 +568,7 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
                         if (message == null){
                             continue;
                         }
-                        Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
+                        String ret = imPluginContext.getPluginService().sendPrivateMessage(build.objectName(message.getType()).rongCloueMessage(message));
                         log.info("batchSendPrivateMessage GROUP rongCloud senderId={}, ret={}", senderId, ret);
                     }
                 }

+ 55 - 18
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentCoreServiceImpl.java

@@ -234,7 +234,7 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
             }
 
             // 订单已关闭返回异常信息,更新订单状态为已支付,后续流程不处理,允许用户进行退款操作
-            if (EPaymentStatus.CLOSED == paymentOrder.getStatus() && StringUtils.isNotBlank(paymentOrder.getErrorMsg())) {
+            if (EPaymentStatus.CLOSED == paymentOrder.getStatus()) {
 
                 // 支付成功
                 if (PaymentStatus.SUCCESSED == paymentResp.getPaymentStatus()) {
@@ -266,14 +266,14 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
                 }
 
                 // 支付失败
-                if (PaymentStatus.FAILED == paymentResp.getPaymentStatus()) {
+                if (PaymentStatus.FAILED == paymentResp.getPaymentStatus() || PaymentStatus.CLOSED == paymentResp.getPaymentStatus()) {
 
                     // 支付失败,取消订单且更新订单状态
                     UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
                         .builder()
                         .transNo(paymentResp.getTransNo())
                         .id(paymentOrder.getId())
-                        .status(EPaymentStatus.FAIL)
+                        .status(PaymentStatus.FAILED == paymentResp.getPaymentStatus() ? EPaymentStatus.FAIL: EPaymentStatus.CLOSED)
                         .updateTime(DateTime.now().toDate())
                         .build();
                     userPaymentOrderService.updateById(order);
@@ -413,7 +413,15 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
 
                 // 提示订单支付已完成
                 throw new BizException("订单支付已完成");
-            }
+            } else
+
+            // 三方订单关闭
+            if ((PaymentStatus.CLOSED == paymentResp.getPaymentStatus() || PaymentStatus.FAILED == paymentResp.getPaymentStatus())
+                && EPaymentStatus.CLOSED != paymentOrder.getStatus()) {
+
+                // 更新订单状态为已关闭
+                closeWaitOrder(paymentOrder);
+            } else
 
             // 订单未支付,后续直接更新订单状态为已关闭
             if (PaymentStatus.PENDDING == paymentResp.getPaymentStatus()) {
@@ -446,8 +454,6 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
                                 // 更新订单退款异常信息
                                 userPaymentOrderService.updateById(order);
 
-                                // 订单关闭后的数据处理流程
-                                userOrderService.payCancel(userOrderService.detail(order.getId()));
                             });
                             throw new BizException("查询交易中,请耐心等待!");
                         }
@@ -923,17 +929,7 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
             if (StringUtils.isEmpty(paymentOrder.getTransNo())
                     && (EPaymentStatus.WAIT_PAY == paymentOrder.getStatus()||EPaymentStatus.PAYING == paymentOrder.getStatus())) {
 
-                // 直接关闭订单
-                UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
-                    .builder()
-                    .id(paymentOrder.getId())
-                    .status(EPaymentStatus.CLOSED)
-                    .updateTime(DateTime.now().toDate())
-                    .build();
-                userPaymentOrderService.updateById(order);
-
-                // 订单关闭后的数据处理流程
-                userOrderService.payCancel(userOrderService.detail(order.getId()));
+                closeWaitOrder(paymentOrder);
 
             } else {
                 // 获取三方支付订单信息,根据订单状处理
@@ -953,6 +949,20 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
 
     }
 
+    private void closeWaitOrder(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder) {
+        // 直接关闭订单
+        UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
+            .builder()
+            .id(paymentOrder.getId())
+            .status(EPaymentStatus.CLOSED)
+            .updateTime(DateTime.now().toDate())
+            .build();
+        userPaymentOrderService.updateById(order);
+
+        // 订单关闭后的数据处理流程
+        userOrderService.payCancel(userOrderService.detail(order.getId()));
+    }
+
 
     /**
      * 扫描支付超时定时
@@ -978,7 +988,7 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
         UserPaymentOrderWrapper.UserPaymentOrderQuery payingQuery = UserPaymentOrderWrapper.UserPaymentOrderQuery
             .builder()
             .paymentStatus(Lists.newArrayList(OrderStatusEnum.parse(EPaymentStatus.PAYING)))
-            .endTime(DateTime.now().plusMinutes(120).toDate())
+//            .endTime(DateTime.now().plusMinutes(120).toDate())
             .build();
         // 查询支付中订单数
         userPaymentOrderService.selectPage(page, payingQuery);
@@ -1425,4 +1435,31 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
         return refundFlag;
     }
 
+    /**
+     * 关闭订单
+     *
+     * @param userInfo     JwtUserInfo
+     * @param paymentOrder UserPaymentOrder
+     * @return PaymentResp
+     */
+    @Override
+    public PaymentResp closedPayment( UserPaymentOrderWrapper.UserPaymentOrder paymentOrder) {
+
+        // 开启调试模式允许关闭订单
+        if (Optional.ofNullable(paymentServiceContext.getProperties().getDebug()).orElse(false)) {
+            // 关闭支付订单
+            PaymentClose paymentClose = paymentServiceContext.getPaymentService(paymentOrder.getPaymentVendor())
+                .close(paymentOrder.getTransNo(), "订单超时", paymentOrder.getOrderNo());
+            log.info("closedPayment VENDOR: {}, CHANNEL: {} paymentClose={}", paymentOrder.getPaymentVendor(),
+                paymentOrder.getPaymentChannel(), JSON.toJSONString(paymentClose));
+        }
+
+        // 查询订单信息
+        PaymentResp paymentResp = paymentServiceContext.getPaymentService(paymentOrder.getPaymentVendor())
+            .query(paymentOrder.getTransNo(), paymentOrder.getOrderNo());
+        log.info("closedPayment VENDOR: {}, CHANNEL: {} paymentResp={}", paymentOrder.getPaymentVendor(),
+            paymentOrder.getPaymentChannel(), JSON.toJSONString(paymentResp));
+
+        return paymentResp;
+    }
 }

+ 29 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentOrderServiceImpl.java

@@ -201,6 +201,7 @@ public class UserPaymentOrderServiceImpl  implements UserPaymentOrderService {
                 newestPayment.setStatus(TradeStatusEnum.succeeded);
                 break;
             case CLOSED:
+                // 关闭状态需要三方回掉
                 newestPayment.setStatus(TradeStatusEnum.close);
                 break;
             case PAYING:
@@ -246,4 +247,32 @@ public class UserPaymentOrderServiceImpl  implements UserPaymentOrderService {
         orderReq.setId(userOrder.getId());
     }
 
+    @Override
+    public UserPaymentOrderWrapper.UserPaymentOrder getUserPaymentOrderByTranNo(String transNo) {
+
+        // 查询订单信息
+        UserOrderPayment one = userOrderPaymentService.lambdaQuery()
+            .eq(UserOrderPayment::getTransNo, transNo)
+            .last("LIMIT 1")
+            .one();
+
+        if (one == null) {
+            return null;
+        }
+        UserOrder one1 = userOrderService.lambdaQuery()
+            .eq(UserOrder::getOrderNo, one.getOrderNo())
+            .last("limit 1")
+            .one();
+
+
+        if (one1.getPaymentVersion().equals(EPaymentVersion.V1)) {
+            throw new BizException("支付方式不支持");
+        }
+
+        // 查询订单支付信息
+
+        return UserPaymentOrderWrapper.UserPaymentOrder.from(one1, one);
+
+    }
+
 }

+ 1 - 1
pom.xml

@@ -24,7 +24,7 @@
 		<redisson.version>3.11.5</redisson.version>
 		<maven.test.skip>true</maven.test.skip>
 		<cbs.version>1.0.16</cbs.version>
-		<microsvc.version>1.0.8</microsvc.version>
+		<microsvc.version>1.1.4</microsvc.version>
 	</properties>