From 22365a84b9e181c2fc2d9084c90024a2728d200e Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 30 Jun 2026 17:02:03 +0800
Subject: [PATCH] feat(order): 添加XT支付功能和确认收款功能

---
 src/main/java/cc/mrbird/febs/mall/controller/dependentStation/ApiMallOrderController.java  |   45 ++++++++++++++
 src/main/java/cc/mrbird/febs/mall/controller/dependentStation/constant/OrderConstants.java |    3 
 src/main/java/cc/mrbird/febs/mall/dto/XtPayCreateOrderDto.java                             |   18 ++++++
 src/main/java/cc/mrbird/febs/mall/service/IApiMallOrderInfoService.java                    |    2 
 src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java                  |   30 ++++++++++
 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java            |   15 +++++
 src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java                 |   12 ++++
 src/main/java/cc/mrbird/febs/mall/dto/ApiOrderPayDto.java                                  |    2 
 src/main/resources/templates/febs/views/modules/order/orderList.html                       |   16 +++++
 src/main/java/cc/mrbird/febs/mall/service/IAdminMallOrderService.java                      |    2 
 10 files changed, 141 insertions(+), 4 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java
index efb8e51..6c251ae 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java
@@ -135,6 +135,18 @@
     }
 
     /**
+     * 订单列表-确认收款
+     *
+     * @param id
+     * @return
+     */
+    @GetMapping("insurePay/{id}")
+    @ControllerEndpoint(operation = "订单列表-确认收款", exceptionMessage = "操作失败")
+    public FebsResponse insurePay(@NotNull(message = "{required}") @PathVariable Long id) {
+        return adminMallOrderService.insurePay(id);
+    }
+
+    /**
      * 订单列表-取消发货
      *
      * @param id
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/ApiMallOrderController.java b/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/ApiMallOrderController.java
index 1c27fb6..2cf681e 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/ApiMallOrderController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/ApiMallOrderController.java
@@ -176,6 +176,49 @@
         return new FebsResponse().success().data(iXcxPayService.getTemplateId());
     }
 
+    // ==================== XT 支付 ====================
+
+    /**
+     * 创建订单并通过 XT 支付
+     * <p>
+     * 流程:创建订单 → 通过 XT 支付链接
+     * <p>
+     */
+    @ApiOperation(value = "创建订单-XT支付", notes = "创建订单并返回XT支付")
+    @PostMapping(value = "/createOrderByXtPay")
+    @Limit(key = "createOrderByXtPay", period = 1, count = 1, name = "XT下单", prefix = "limit", limitType = LimitType.IP)
+    public FebsResponse createOrderByXtPay(@RequestBody @Validated XtPayCreateOrderDto lwPayDto) {
+        // 1. 创建订单
+        AddOrderDto addOrderDto = lwPayDto.getOrder();
+        Long orderId = mallOrderInfoService.createOrder(addOrderDto);
+
+        // 2. 获取订单详情
+        MallOrderInfo order = mallOrderInfoService.getById(orderId);
+        if (order != null
+                && OrderStatusEnum.WAIT_PAY.getValue() == order.getStatus()
+        ){
+            return mallOrderInfoService.createOrderByXtPay();
+        }
+        return new FebsResponse().fail().message("Payment channel exception");
+    }
+
+    @ApiOperation(value = "XT支付", notes = "XT支付")
+    @PostMapping(value = "/payOrderByXtPay", produces = "application/json")
+    public FebsResponse payOrderByXtPay(@RequestBody @Validated ApiOrderPayDto payDto) {
+
+        Long orderId = payDto.getOrderId();
+        Integer payType = payDto.getPayType();
+        // 2. 获取订单详情
+        MallOrderInfo order = mallOrderInfoService.getById(orderId);
+        if (order != null
+                && OrderConstants.PAY_TYPE_XT == payType
+                && OrderStatusEnum.WAIT_PAY.getValue() == order.getStatus()
+        ){
+            return mallOrderInfoService.createOrderByXtPay();
+        }
+        return new FebsResponse().fail().message("Payment channel exception");
+    }
+
     // ==================== LWPAY 支付 ====================
 
     /**
@@ -260,7 +303,7 @@
                 result.put("orderNo", order.getOrderNo());
                 result.put("amount", order.getAmount());
                 result.put("payUrl", payUrl);
-                return new FebsResponse().success().data(result).message("下单成功");
+                return new FebsResponse().success().data(result).message("success");
             } catch (Exception e) {
                 log.error("LWPAY 代收下单失败: orderId={}", orderId, e);
                 return new FebsResponse().fail().message("Payment channel exception: " + e.getMessage());
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/constant/OrderConstants.java b/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/constant/OrderConstants.java
index 39b8621..8add63c 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/constant/OrderConstants.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/dependentStation/constant/OrderConstants.java
@@ -29,12 +29,13 @@
     public static final String ORDER_STATE = "order_state";
 
     /**
-     * 支付方式 1-微信 2-支付宝 3-USDT
+     * 支付方式 1-微信 2-支付宝 3-USDT 4-LWPAY支付 5-XT支付
      */
     public static final Integer PAY_TYPE_WECHAT = 1;
     public static final Integer PAY_TYPE_ALIPAY = 2;
     public static final Integer PAY_TYPE_USDT = 3;
     public static final Integer PAY_TYPE_SYSTEM = 4;
+    public static final Integer PAY_TYPE_XT = 5;
     public static final String ORDER_PAY_TYPE = "order_pay_type";
 
     public static final String TRC20_SYSTEM_ADDRESS = "pay.trc20.address";
diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiOrderPayDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiOrderPayDto.java
index 3fbcf4b..85a6a8f 100644
--- a/src/main/java/cc/mrbird/febs/mall/dto/ApiOrderPayDto.java
+++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiOrderPayDto.java
@@ -17,6 +17,6 @@
     private Long orderId;
 
     @NotNull(message = "支付方式不能为空")
-    @ApiModelProperty(value = "支付方式 1-微信 2-支付宝 3-USDT 4-LwPAY", example = "you_ke_*****")
+    @ApiModelProperty(value = "支付方式 1-微信 2-支付宝 3-USDT 4-LwPAY 5-XTPAY", example = "you_ke_*****")
     private Integer payType;
 }
\ No newline at end of file
diff --git a/src/main/java/cc/mrbird/febs/mall/dto/XtPayCreateOrderDto.java b/src/main/java/cc/mrbird/febs/mall/dto/XtPayCreateOrderDto.java
new file mode 100644
index 0000000..d5d11ea
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/dto/XtPayCreateOrderDto.java
@@ -0,0 +1,18 @@
+package cc.mrbird.febs.mall.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+
+@Data
+@ApiModel(value = "XtPayCreateOrderDto", description = "支付下单参数")
+public class XtPayCreateOrderDto {
+
+    @Valid
+    @NotNull(message = "订单信息不能为空")
+    @ApiModelProperty(value = "订单信息", required = true)
+    private AddOrderDto order;
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/service/IAdminMallOrderService.java b/src/main/java/cc/mrbird/febs/mall/service/IAdminMallOrderService.java
index dc50e64..522296c 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/IAdminMallOrderService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/IAdminMallOrderService.java
@@ -80,4 +80,6 @@
     FebsResponse deliverPdfGoods(Long id);
 
     FebsResponse cancelDeliver(Long id);
+
+    FebsResponse insurePay(Long id);
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/service/IApiMallOrderInfoService.java b/src/main/java/cc/mrbird/febs/mall/service/IApiMallOrderInfoService.java
index ca463e4..c828f7d 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/IApiMallOrderInfoService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/IApiMallOrderInfoService.java
@@ -48,4 +48,6 @@
     FebsResponse createOrderVerify(ApiCreateOrderVerifyDto apiCreateOrderVerifyDto);
 
     FebsResponse chooseCoupon(ApiChooseCouponDto chooseCouponDto);
+
+    FebsResponse createOrderByXtPay();
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java
index 35c863c..900fa2d 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java
@@ -5,6 +5,7 @@
 import cc.mrbird.febs.common.enumerates.*;
 import cc.mrbird.febs.common.exception.FebsException;
 import cc.mrbird.febs.common.utils.ValidateEntityUtils;
+import cc.mrbird.febs.mall.controller.dependentStation.constant.OrderConstants;
 import cc.mrbird.febs.mall.dto.*;
 import cc.mrbird.febs.mall.entity.*;
 import cc.mrbird.febs.mall.mapper.*;
@@ -16,6 +17,7 @@
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.best.javaSdk.ClientParamEnum;
@@ -31,6 +33,7 @@
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 @Slf4j
@@ -617,6 +620,33 @@
     }
 
     @Override
+    public FebsResponse insurePay(Long id) {
+        // 1. 查询订单
+        MallOrderInfo order = mallOrderInfoMapper.selectById(id);
+        if (order == null) {
+            return new FebsResponse().fail().message("订单不存在,刷新后重试");
+        }
+
+        // 2. 幂等检查(避免重复回调)
+        if (OrderStatusEnum.WAIT_PAY.getValue() != order.getStatus()) {
+            return new FebsResponse().fail().message("订单不是代付款状态");
+        }
+
+        // 3. 更新订单状态为待发货
+        mallOrderInfoMapper.update(
+                null,
+                Wrappers.lambdaUpdate(MallOrderInfo.class)
+                        .set(MallOrderInfo::getStatus, OrderStatusEnum.WAIT_SHIPPING.getValue())
+                        .set(MallOrderInfo::getPayTime, new Date())
+                        .set(MallOrderInfo::getPayMethod, "XT支付")
+                        .set(MallOrderInfo::getPayResult, "1")
+                        .eq(MallOrderInfo::getId, order.getId())
+        );
+
+        return new FebsResponse().success();
+    }
+
+    @Override
     public void deliverGoodsByOrderNo(DeliverGoodsDto deliverGoodsDto) {
         MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectByOrderNo(deliverGoodsDto.getOrderNo());
         if (mallOrderInfo == null) {
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
index 2a55786..07af1ff 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
@@ -1002,4 +1002,19 @@
         return new FebsResponse().success().data(objects);
     }
 
+    @Override
+    public FebsResponse createOrderByXtPay() {
+
+        DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                "PAY_LINK", "XT_LINK"
+        );
+        if (ObjectUtil.isEmpty(dataDictionaryCustom)){
+            return new FebsResponse().fail().message("Payment channel exception");
+        }
+        if (StrUtil.isEmpty(dataDictionaryCustom.getValue())){
+            return new FebsResponse().fail().message("Payment channel exception");
+        }
+        return new FebsResponse().success().data(dataDictionaryCustom.getValue());
+    }
+
 }
diff --git a/src/main/resources/templates/febs/views/modules/order/orderList.html b/src/main/resources/templates/febs/views/modules/order/orderList.html
index a9be387..93c8c58 100644
--- a/src/main/resources/templates/febs/views/modules/order/orderList.html
+++ b/src/main/resources/templates/febs/views/modules/order/orderList.html
@@ -357,6 +357,11 @@
                     cancelOrder(data.id);
                 });
             }
+            if (layEvent === 'insurePay') {
+                febs.modal.confirm('收款', '确认收款?', function () {
+                    insurePay(data.id);
+                });
+            }
             if (layEvent === 'deliverPdfGoods') {
                 febs.modal.confirm('一键发货', '确认一键发货?', function (index) {
                     layer.close(index);
@@ -396,6 +401,13 @@
 
         function cancelOrder(id) {
             febs.get(ctx + 'admin/order/cancelOrder/' + id, null, function () {
+                febs.alert.success('操作成功');
+                $query.click();
+            });
+        }
+
+        function insurePay(id) {
+            febs.get(ctx + 'admin/order/insurePay/' + id, null, function () {
                 febs.alert.success('操作成功');
                 $query.click();
             });
@@ -682,7 +694,9 @@
                         // {field: 'wxOrderNo', title: '支付订单号', minWidth: 120,align:'left'},
                         {title: '操作',
                             templet: function (d) {
-                                if(d.status === 2){
+                                if(d.status === 1){
+                                    return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="insurePay" shiro:hasPermission="user:update">确认收款</button>'
+                                }else if(d.status === 2){
                                     return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="deliverGoods" shiro:hasPermission="user:update">发货</button>'
                                     +'<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="seeOrder" shiro:hasPermission="user:update">详情</button>'
                                     // +''

--
Gitblit v1.9.1