Browse Source

trade:完成支付成功后的回调,更新订单为已支付

YunaiV 2 years ago
parent
commit
e96422a47e
16 changed files with 267 additions and 43 deletions
  1. 6 2
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
  2. 13 0
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java
  3. 6 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
  4. 14 13
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java
  5. 7 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java
  6. 9 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java
  7. 90 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
  8. 30 9
      yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java
  9. 3 3
      yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql
  10. 10 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java
  11. 48 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderRespDTO.java
  12. 3 7
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
  13. 12 0
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java
  14. 10 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java
  15. 5 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java
  16. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java

+ 6 - 2
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java

@@ -20,8 +20,12 @@ public interface ErrorCodeConstants {
     ErrorCode ORDER_CREATE_ADDRESS_NOT_FOUND = new ErrorCode(1011000006, "收货地址不存在");
 
     ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
-    ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000010, "交易订单不存在");
-    ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000011, "交易订单项更新售后状态失败,请重试");
+    ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
+    ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
+    ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "交易订单更新支付状态失败,订单不是【未支付】状态");
+    ErrorCode ORDER_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "交易订单更新支付状态失败,支付单编号不匹配");
+    ErrorCode ORDER_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
+    ErrorCode ORDER_UPDATE_PAID_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
 
     // ==========  After Sale 模块 1-011-000-000 ==========
     ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");

+ 13 - 0
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java

@@ -42,6 +42,19 @@ public enum TradeOrderStatusEnum implements IntArrayValuable {
         return ARRAYS;
     }
 
+    // ========== 问:为什么写了很多 isXXX 和 haveXXX 的判断逻辑呢? ==========
+    // ========== 答:方便找到某一类判断,哪些业务正在使用 ==========
+
+    /**
+     * 判断指定状态,是否正处于【未付款】状态
+     *
+     * @param status 指定状态
+     * @return 是否
+     */
+    public static boolean isUnpaid(Integer status) {
+        return ObjectUtil.equal(PAID.getStatus(), status);
+    }
+
     /**
      * 判断指定状态,是否正处于【已取消】状态
      *

+ 6 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java

@@ -21,6 +21,8 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
 @Api(tags = "用户 App - 交易订单")
 @RestController
 @RequestMapping("/trade/order")
@@ -49,13 +51,15 @@ public class AppTradeOrderController {
         String clientIp = ServletUtil.getClientIP(servletRequest);
         // 创建交易订单,预支付记录
         Long orderId = tradeOrderService.createOrder(loginUserId, clientIp, createReqVO);
-        return CommonResult.success(orderId);
+        return success(orderId);
     }
 
     @PostMapping("/update-paid")
     @ApiOperation(value = "更新订单为已支付", notes = "由 pay-module 支付服务,进行回调,可见 PayNotifyJob")
     public CommonResult<Boolean> updateOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
-        return null;
+        tradeOrderService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
+                notifyReqDTO.getPayOrderId());
+        return success(true);
     }
 
     @GetMapping("/get")

+ 14 - 13
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java

@@ -95,6 +95,13 @@ public class TradeOrderDO extends BaseDO {
     private String remark;
 
     // ========== 价格 + 支付基本信息 ==========
+
+    /**
+     * 支付订单编号
+     *
+     * 对接 pay-module-biz 支付服务的支付订单编号,即 PayOrderDO 的 id 编号
+     */
+    private Long payOrderId;
     /**
      * 是否已支付
      *
@@ -106,6 +113,12 @@ public class TradeOrderDO extends BaseDO {
      * 付款时间
      */
     private LocalDateTime payTime;
+    /**
+     * 支付成功的支付渠道
+     *
+     * 对应 PayChannelEnum 枚举
+     */
+    private String payChannelCode;
 
     // ========== 价格 + 支付基本信息 ==========
     // 价格文档 - 淘宝:https://open.taobao.com/docV3.htm?docId=108471&docType=1
@@ -156,18 +169,6 @@ public class TradeOrderDO extends BaseDO {
      * + {@link #adjustPrice}
      */
     private Integer payPrice;
-    /**
-     * 支付订单编号
-     *
-     * 对接 pay-module-biz 支付服务的支付订单编号,即 PayOrderDO 的 id 编号
-     */
-    private Long payOrderId;
-    /**
-     * 支付成功的支付渠道
-     *
-     * 对应 PayChannelEnum 枚举
-     */
-    private Integer payChannel;
 
     // ========== 收件 + 物流基本信息 ==========
     /**
@@ -206,7 +207,7 @@ public class TradeOrderDO extends BaseDO {
     /**
      * 收件人地区编号
      */
-    private Long receiverAreaId;
+    private Integer receiverAreaId;
     /**
      * 收件人邮编
      */

+ 7 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java

@@ -2,8 +2,15 @@ package cn.iocoder.yudao.module.trade.dal.mysql.order;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 @Mapper
 public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
+
+    default int updateByIdAndStatus(Long id, Integer status, TradeOrderDO update) {
+        return update(update, new LambdaUpdateWrapper<TradeOrderDO>()
+                .eq(TradeOrderDO::getId, id).eq(TradeOrderDO::getStatus, status));
+    }
+
 }

+ 9 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java

@@ -33,6 +33,14 @@ public interface TradeOrderService {
      */
     TradeOrderDO getOrder(Long userId, Long orderId);
 
+    /**
+     * 更新交易订单已支付
+     *
+     * @param id 交易订单编号
+     * @param payOrderId 支付订单编号
+     */
+    void updateOrderPaid(Long id, Long payOrderId);
+
     // =================== Order Item ===================
 
     /**
@@ -54,4 +62,5 @@ public interface TradeOrderService {
      */
     void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus,
                                         Integer newAfterSaleStatus, Integer refundPrice);
+
 }

+ 90 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java

@@ -3,13 +3,17 @@ package cn.iocoder.yudao.module.trade.service.order;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.core.KeyValue;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.module.member.api.address.AddressApi;
 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
+import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
@@ -30,6 +34,7 @@ import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
 import cn.iocoder.yudao.module.trade.enums.order.*;
 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -42,6 +47,7 @@ import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND;
 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
 
 /**
@@ -51,6 +57,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
  * @since 2022-08-26
  */
 @Service
+@Slf4j
 public class TradeOrderServiceImpl implements TradeOrderService {
 
     @Resource
@@ -110,6 +117,84 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         return order;
     }
 
+    @Override
+    public void updateOrderPaid(Long id, Long payOrderId) {
+        // 校验并获得交易订单
+        KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPaid(id, payOrderId);
+        TradeOrderDO order = orderResult.getKey();
+        PayOrderRespDTO payOrder = orderResult.getValue();
+
+        // 更新 TradeOrderDO 状态为已支付,等待发货
+        int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(),
+                new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayed(true)
+                        .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode()));
+        if (updateCount == 0) {
+            throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
+        }
+
+        // TODO 芋艿:发送订单变化的消息
+
+        // TODO 芋艿:发送站内信
+
+        // TODO 芋艿:OrderLog
+    }
+
+    /**
+     * 校验交易订单满足被支付的条件
+     *
+     * 1. 交易订单未支付
+     * 2. 支付单已支付
+     *
+     * @param id 交易订单编号
+     * @param payOrderId 支付订单编号
+     * @return 交易订单
+     */
+    private KeyValue<TradeOrderDO, PayOrderRespDTO> validateOrderPaid(Long id, Long payOrderId) {
+        // 校验订单是否存在
+        TradeOrderDO order = tradeOrderMapper.selectById(id);
+        if (order == null) {
+            throw exception(ORDER_NOT_FOUND);
+        }
+        // 校验订单未支付
+        if (TradeOrderStatusEnum.isUnpaid(order.getStatus())) { // 状态
+            log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]",
+                    id, JsonUtils.toJsonString(order));
+            throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
+        }
+        // 校验支付订单匹配
+        if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
+            log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
+                    id, payOrderId, JsonUtils.toJsonString(order));
+            throw exception(ORDER_UPDATE_PAID_PAY_ORDER_ID_ERROR);
+        }
+
+        // 校验支付单是否存在
+        PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
+        if (payOrder == null) {
+            log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
+            throw exception(PAY_ORDER_NOT_FOUND);
+        }
+        // 校验支付单已支付
+        if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
+            log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
+                     id, payOrderId, JsonUtils.toJsonString(payOrder));
+            throw exception(ORDER_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS);
+        }
+        // 校验支付金额一致
+        if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPayPrice())) {
+            log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
+                     id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
+            throw exception(ORDER_UPDATE_PAID_PAY_PRICE_NOT_MATCH);
+        }
+        // 校验支付订单匹配(二次)
+        if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) {
+            log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
+                    id, payOrderId, JsonUtils.toJsonString(payOrder));
+            throw exception(ORDER_UPDATE_PAID_PAY_ORDER_ID_ERROR);
+        }
+        return new KeyValue<>(order, payOrder);
+    }
+
     /**
      * 校验商品 SKU 是否可出售
      *
@@ -120,7 +205,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(convertSet(items, Item::getSkuId));
         // SKU 不存在
         if (items.size() != skus.size()) {
-            throw exception(ErrorCodeConstants.ORDER_CREATE_SKU_NOT_FOUND);
+            throw exception(ORDER_CREATE_SKU_NOT_FOUND);
         }
         // 校验是否禁用 or 库存不足
         Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
@@ -233,13 +318,15 @@ public class TradeOrderServiceImpl implements TradeOrderService {
         // 创建支付单,用于后续的支付
         PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert(
                 tradeOrderDO, tradeOrderItemDOs, spus, tradeOrderProperties);
-        Long payOrderId = payOrderApi.createPayOrder(payOrderCreateReqDTO);
+        Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO);
 
         // 更新到交易单上
         tradeOrderMapper.updateById(new TradeOrderDO().setId(tradeOrderDO.getId()).setPayOrderId(payOrderId));
     }
 
-    // =================== Order ===================
+
+
+    // =================== Order Item ===================
 
     @Override
     public TradeOrderItemDO getOrderItem(Long userId, Long itemId) {

+ 30 - 9
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java

@@ -6,6 +6,8 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 import cn.iocoder.yudao.module.member.api.address.AddressApi;
 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
+import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
+import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
@@ -109,7 +111,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
         // mock 方法(用户收件地址的校验)
         AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
                 .setMobile("15601691300").setAreaId(3306L).setPostCode("85757").setDetailAddress("土豆村");
-        when(addressApi.getAddress(eq(userId), eq(10L))).thenReturn(addressRespDTO);
+        when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);
         // mock 方法(价格计算)
         PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
                 .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
@@ -131,7 +133,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
             return true;
         }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
         // mock 方法(创建支付单)
-        when(payOrderApi.createPayOrder(argThat(createReqDTO -> {
+        when(payOrderApi.createOrder(argThat(createReqDTO -> {
             assertEquals(createReqDTO.getAppId(), 888L);
             assertEquals(createReqDTO.getUserIp(), userIp);
             assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空
@@ -169,7 +171,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
         assertEquals(tradeOrderDO.getAdjustPrice(), 0);
         assertEquals(tradeOrderDO.getPayPrice(), 80);
         assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
-        assertNull(tradeOrderDO.getPayChannel());
+        assertNull(tradeOrderDO.getPayChannelCode());
         assertNull(tradeOrderDO.getDeliveryTemplateId());
         assertNull(tradeOrderDO.getExpressNo());
         assertFalse(tradeOrderDO.getDeliveryStatus());
@@ -177,7 +179,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
         assertNull(tradeOrderDO.getReceiveTime());
         assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
         assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");
-        assertEquals(tradeOrderDO.getReceiverAreaId(), 3306L);
+        assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);
         assertEquals(tradeOrderDO.getReceiverPostCode(), 85757);
         assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");
         assertEquals(tradeOrderDO.getAfterSaleStatus(), TradeOrderAfterSaleStatusEnum.NONE.getStatus());
@@ -241,11 +243,30 @@ public class TradeOrderServiceTest extends BaseDbUnitTest {
             assertEquals(reqDTO.getOrderId(), tradeOrderId);
             return true;
         }));
-//        //mock 支付订单信息
-//        when(payOrderApi.createPayOrder(any())).thenReturn(1L);
-
-//        //价格
-//        assertEquals(calculateRespDTO.getOrder().getItems().get(0).getPresentPrice(), tradeOrderItemDO.getPresentPrice());
     }
 
+    @Test
+    public void updateOrderPaid() {
+        // mock 数据(TradeOrder)
+        TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
+            o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
+            o.setPayOrderId(10L).setPayPrice(100).setPayTime(null);
+        });
+        tradeOrderMapper.insert(order);
+        // 准备参数
+        Long id = 1L;
+        Long payOrderId = 10L;
+        // mock 方法(支付单)
+        when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class,
+                o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub")
+                        .setMerchantOrderId("1")).setAmount(100));
+        // 调用
+        tradeOrderService.updateOrderPaid(id, payOrderId);
+        // 断言
+        TradeOrderDO dbOrder = tradeOrderMapper.selectById(id);
+        assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.PAID.getStatus());
+        assertTrue(dbOrder.getPayed());
+        assertNotNull(dbOrder.getPayTime());
+        assertEquals(dbOrder.getPayChannelCode(), "wx_pub");
+    }
 }

+ 3 - 3
yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql

@@ -21,9 +21,9 @@ CREATE TABLE IF NOT EXISTS "trade_order" (
      "adjust_price" int NOT NULL,
      "pay_price" int NOT NULL,
      "pay_order_id" int,
-     "pay_channel" int,
-     "delivery_template_id" int,
-     "express_no" int,
+     "pay_channel_code" varchar,
+     "delivery_template_id" bigint,
+     "express_no" varchar,
      "delivery_status" bit NOT NULL,
      "delivery_time" datetime,
      "receive_time" datetime,

+ 10 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.pay.api.order;
 
 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
 
 import javax.validation.Valid;
 
@@ -18,6 +19,14 @@ public interface PayOrderApi {
      * @param reqDTO 创建请求
      * @return 支付单编号
      */
-    Long createPayOrder(@Valid PayOrderCreateReqDTO reqDTO);
+    Long createOrder(@Valid PayOrderCreateReqDTO reqDTO);
+
+    /**
+     * 获得支付单
+     *
+     * @param id 支付单编号
+     * @return 支付单
+     */
+    PayOrderRespDTO getOrder(Long id);
 
 }

+ 48 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderRespDTO.java

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.pay.api.order.dto;
+
+import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
+import lombok.Data;
+
+/**
+ * 支付单信息 Response DTO
+ *
+ * TODO 芋艿:还没定好字段
+ *
+ * @author 芋道源码
+ */
+@Data
+public class PayOrderRespDTO {
+
+    /**
+     * 订单编号,数据库自增
+     */
+    private Long id;
+    /**
+     * 渠道编码
+     *
+     * 枚举 PayChannelEnum
+     */
+    private String channelCode;
+
+    // ========== 商户相关字段 ==========
+    /**
+     * 商户订单编号
+     * 例如说,内部系统 A 的订单号。需要保证每个 PayMerchantDO 唯一
+     */
+    private String merchantOrderId;
+
+    // ========== 订单相关字段 ==========
+    /**
+     * 支付金额,单位:分
+     */
+    private Integer amount;
+    /**
+     * 支付状态
+     *
+     * 枚举 {@link PayOrderStatusEnum}
+     */
+    private Integer status;
+
+    // ========== 渠道相关字段 ==========
+
+}

+ 3 - 7
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java

@@ -28,9 +28,9 @@ public interface ErrorCodeConstants {
     ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001007,"微信渠道v3版本apiclient_key.pem不可为空");
     ErrorCode CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL = new ErrorCode(1007001008,"微信渠道v3版本中apiclient_cert.pem不可为空");
     ErrorCode PAY_CHANNEL_NOTIFY_VERIFY_FAILED = new ErrorCode(1007001009, "渠道通知校验失败");
-    /**
-     * ========== ORDER 模块 1-007-002-000 ==========
-     */
+
+    // ========== ORDER 模块 1-007-002-000 ==========
+
     ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在");
     ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付");
     ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付");
@@ -57,8 +57,4 @@ public interface ErrorCodeConstants {
     ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
     ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除");
 
-
-
-
-
 }

+ 12 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java

@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
+import java.util.Objects;
+
 /**
  * 支付订单的状态枚举
  *
@@ -26,4 +28,14 @@ public enum PayOrderStatusEnum implements IntArrayValuable {
         return new int[0];
     }
 
+    /**
+     * 判断是否支付成功
+     *
+     * @param status 状态
+     * @return 是否支付成功
+     */
+    public static boolean isSuccess(Integer status) {
+        return Objects.equals(status, SUCCESS.getStatus());
+    }
+
 }

+ 10 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java

@@ -1,6 +1,9 @@
 package cn.iocoder.yudao.module.pay.api.order;
 
 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
+import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
+import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 import org.springframework.stereotype.Service;
 
@@ -18,8 +21,14 @@ public class PayOrderApiImpl implements PayOrderApi {
     private PayOrderService payOrderService;
 
     @Override
-    public Long createPayOrder(PayOrderCreateReqDTO reqDTO) {
+    public Long createOrder(PayOrderCreateReqDTO reqDTO) {
         return payOrderService.createPayOrder(reqDTO);
     }
 
+    @Override
+    public PayOrderRespDTO getOrder(Long id) {
+        PayOrderDO order = payOrderService.getOrder(id);
+        return PayOrderConvert.INSTANCE.convert2(order);
+    }
+
 }

+ 5 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.order;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
+import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderDetailsRespVO;
 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExcelVO;
 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageItemRespVO;
@@ -41,13 +42,14 @@ public interface PayOrderConvert {
     List<PayOrderExcelVO> convertList02(List<PayOrderDO> list);
 
     /**
-     * 订单DO转自定义分页对象
+     * 订单 DO 转自定义分页对象
      *
      * @param bean 订单DO
      * @return 分页对象
      */
     PayOrderPageItemRespVO pageConvertItemPage(PayOrderDO bean);
 
+    // TODO 芋艿:优化下 convert 逻辑
     default PayOrderExcelVO excelConvert(PayOrderDO bean) {
         if (bean == null) {
             return null;
@@ -94,4 +96,6 @@ public interface PayOrderConvert {
 
     PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqDTO bean);
 
+    PayOrderRespDTO convert2(PayOrderDO bean);
+
 }

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java

@@ -93,7 +93,7 @@ public class PayOrderDO extends BaseDO {
     /**
      * 支付金额,单位:分
      */
-    private Long amount;
+    private Integer amount;
     /**
      * 渠道手续费,单位:百分比
      *