소스 검색

中车对接

tjxt 3 달 전
부모
커밋
60c7da3c9b
60개의 변경된 파일3400개의 추가작업 그리고 0개의 파일을 삭제
  1. 32 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderDeliverGoods.java
  2. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderFileItem.java
  3. 25 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderGoodsAppendixItem.java
  4. 34 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderGoodsItem.java
  5. 64 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderInvoice.java
  6. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OutgoingGoods.java
  7. 45 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OutgoingList.java
  8. 46 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/PendingOrderRecord.java
  9. 27 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/SpuSpecItem.java
  10. 19 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/StandardCatalog.java
  11. 43 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/Stocks.java
  12. 96 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/ZCR.java
  13. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/aftersale/domain/OutgoingGoodsItem.java
  14. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/MallAfterSaleNoQueryBo.java
  15. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/MallOrderNoQueryBo.java
  16. 31 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/MessageBo.java
  17. 27 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/ModuleCheckBo.java
  18. 32 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderCancelAuditBo.java
  19. 26 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderConfirmBo.java
  20. 45 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderDeliverBo.java
  21. 31 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderDeliveredNoticeBo.java
  22. 20 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderDetailBo.java
  23. 34 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderGoodsAppendBo.java
  24. 32 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderRejectBo.java
  25. 20 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OutgoingQueryBo.java
  26. 35 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/PendingOrderListBo.java
  27. 26 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/TrackQueryBo.java
  28. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/UserLoginBo.java
  29. 43 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/ZCTokenBo.java
  30. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/invoice/domain/WaitInvoiceApply.java
  31. 38 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementApplyOrdersBo.java
  32. 29 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementConfirmBo.java
  33. 32 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementConfirmPaymentBo.java
  34. 16 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementDetailBo.java
  35. 20 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementPaymentDetailBo.java
  36. 32 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/domain/SettlementConfirmOrderItem.java
  37. 51 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/domain/SettlementOrderItem.java
  38. 47 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/vo/SettlementApplyOrdersVo.java
  39. 63 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/vo/SettlementDetailVo.java
  40. 33 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/vo/SettlementPaymentDetailVo.java
  41. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/MallAfterSaleNoVo.java
  42. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/MallOrderNoVo.java
  43. 25 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/MessageVo.java
  44. 21 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/ModuleCheckVo.java
  45. 20 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/OrderDeliverVo.java
  46. 149 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/OrderDetailVo.java
  47. 18 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/OutgoingVo.java
  48. 42 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/PendingOrderListVo.java
  49. 15 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/StocksVo.java
  50. 32 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/TrackVo.java
  51. 15 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/OrderNoDto.java
  52. 154 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ProductCategoryRemoteVo.java
  53. 25 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ProductPriceInventoryRemoteVo.java
  54. 45 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/StocksResult.java
  55. 15 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/StocksResultDto.java
  56. 49 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/zhongche/domain/Prices.java
  57. 16 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/zhongche/vo/PricesVo.java
  58. 728 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePullController.java
  59. 500 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java
  60. 134 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/util/SM2SignUtil.java

+ 32 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderDeliverGoods.java

@@ -0,0 +1,32 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.math.BigDecimal;
+
+/**
+ * 订单发货商品 (orderDeliverGoods)
+ * 对应 5.3.5.4.2 订单发货商品-orderDeliverGoods
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderDeliverGoods {
+    /**
+     * 商品sku
+     * 必填
+     */
+    private String goodsId;
+
+    /**
+     * 商品发货数量
+     * 必填
+     */
+    private BigDecimal num;
+
+    /**
+     * 根据订单标识判断必填,JSON格式。如["imgUrl1","imgUrl2"]
+     */
+    private String voucher;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderFileItem.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+// 1.2.1 订单附件
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderFileItem {
+    /**
+     * 附件名称
+     */
+    private String name;
+    /**
+     * 附件地址
+     */
+    private String url;
+}

+ 25 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderGoodsAppendixItem.java

@@ -0,0 +1,25 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.util.List;
+
+/**
+ * 订单接单商品附录 (orderGoodsAppendix)
+ * 对应 5.3.3.4.2 订单接单商品附录-orderGoodsAppendix
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderGoodsAppendixItem {
+    /**
+     * 商品sku
+     */
+    private String goodsId;
+
+    /**
+     * 协商发货时间,格式YYYY-MM-DD
+     */
+    private String negotiateDeliveryTime;
+}

+ 34 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderGoodsItem.java

@@ -0,0 +1,34 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+// 1.2.3 订单商品 (orderGoods)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderGoodsItem {
+    /**
+     * 商品sku
+     */
+    private String goodsId;
+    /**
+     * 商品数量,最多精确到小数点后4位。
+     */
+    private BigDecimal num;
+    /**
+     * 商品价格。单位元,最多精确到分。
+     */
+    private BigDecimal price;
+    /**
+     * 商品总金额。单位元,最多精确到分。商品数量 * 商品价格,四舍五入,精确到分。
+     */
+    private BigDecimal subAmount;
+    /**
+     * 期望交货时间,格式YYYY-MM-DD
+     */
+    private String wishDeliveryDate;
+}

+ 64 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OrderInvoice.java

@@ -0,0 +1,64 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+//1.2.2 订单发票 (orderInvoice)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderInvoice {
+    /**
+     * 发票类型(2增值税专用发票;3 电子票)
+     */
+    private String invoiceType;
+    /**
+     * 发票抬头类型:4:个人,5:单位
+     */
+    private String selectedInvoiceTitle;
+    /**
+     * 发票抬头 (如果selectedInvoiceTitle=5则此字段必须)
+     */
+    private String companyName;
+    /**
+     * 发票内容 1:明细,100:大类。备注:若增值税专用发票则只能选1 明细
+     */
+    private String invoiceContent;
+    /**
+     * 增专票收票人姓名
+     */
+    private String invoiceName;
+    /**
+     * 收票人电话
+     */
+    private String invoicePhone;
+    /**
+     * 增专票收票人所在地址
+     */
+    private String invoiceFullAddress;
+    /**
+     * 专票资质公司名称
+     */
+    private String regCompanyName;
+    /**
+     * 专票资质纳税人识别号
+     */
+    private String regCode;
+    /**
+     * 专票资质注册地址
+     */
+    private String regAddr;
+    /**
+     * 专票资质注册电话
+     */
+    private String regPhone;
+    /**
+     * 专票资质注册银行
+     */
+    private String regBank;
+    /**
+     * 专票资质银行账号
+     */
+    private String regBankAccount;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OutgoingGoods.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OutgoingGoods {
+    /**
+     * 商品sku
+     */
+    private String goodsId;
+    /**
+     * 商品发货数量
+     */
+    private BigDecimal num;
+}

+ 45 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/OutgoingList.java

@@ -0,0 +1,45 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 发货单列表项 (outgoingList)
+ * 对应 5.3.8.5.2 发货单列表-outgoingList
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OutgoingList {
+    /**
+     * 中车电子商城订单号
+     */
+    private String orderNo;
+    /**
+     * 发货单编号
+     */
+    private String outgoingCode;
+    /**
+     * 发货单状态:0已发货 1已收货
+     */
+    private String outgoingStatus;
+    /**
+     * 配送方式:1快递发货 2自行配送 3采购自提
+     */
+    private String deliveryType;
+    /**
+     * 物流单号
+     */
+    private String expressCode;
+    /**
+     * 物流公司
+     */
+    private String expressCompanyName;
+    /**
+     * 发货商品列表
+     */
+    private List<OutgoingGoods> outgoingGoods;
+}

+ 46 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/PendingOrderRecord.java

@@ -0,0 +1,46 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 订单列表项 (records)
+ * 对应 5.3.6.5.2 订单列表-records
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PendingOrderRecord {
+    /**
+     * 中车电子商城订单号
+     */
+    private String orderNo;
+
+    /**
+     * 是否预购单。0否、1是。
+     */
+    private Integer preOrder;
+
+    /**
+     * 订单金额。单位元,最多精确到分。
+     */
+    private BigDecimal orderAmount;
+
+    /**
+     * 运费。单位元,最多精确到分。
+     */
+    private BigDecimal freight;
+
+    /**
+     * 备注
+     */
+    private String memo;
+
+    /**
+     * 订单创建时间,格式YYYYMMDDHHMMSS
+     */
+    private String orderTime;
+}

+ 27 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/SpuSpecItem.java

@@ -0,0 +1,27 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SpuSpecItem {
+    /**
+     * SPU规格ID
+     */
+    private String spuSpecId;
+    /**
+     * 规格名称
+     */
+    private String specName;
+    /**
+     * 规格值
+     */
+    private String value;
+    /**
+     * 规格值图片链接
+     */
+    private String picUrl;
+}

+ 19 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/StandardCatalog.java

@@ -0,0 +1,19 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.Data;
+
+/**
+ * author
+ * 时间:2026/1/6,9:29
+ */
+@Data
+public class StandardCatalog {
+    /**
+     * 平台品目id
+     */
+    private String standardCatalogId;
+    /**
+     * 平台品目名称
+     */
+    private String standardCatalogName;
+}

+ 43 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/Stocks.java

@@ -0,0 +1,43 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.Data;
+
+
+//商品库存
+@Data
+public class Stocks {
+    /**
+     * 商品sku
+     */
+    private String goodsId;
+    /**
+     * 地区id
+     */
+    private String areaId;
+    /**
+     * 库存状态:
+     * 1有货 现货。下单立即发货
+     * 2 有货 在途。正在内部配货,预计 2~6 天到达本仓库
+     * 3 有货 可配货。下单后从有货仓库配货
+     * 4 预订
+     * 5 无货
+     */
+    private String stockState;
+    /**
+     * 库存状态描述
+     */
+    private String stockStateDesc;
+    /**
+     * 剩余数量。
+     * 支持无库存下单商品返回(-999)
+     * 当值为-1时,为未查询到。
+     * stockState=1或stockState=2时,入参goodsNum<50,该值为实际库存。
+     * 入参50<=goodsNum<=100时,该值为-1。
+     * 入参goodsNum>100,该值等于goodsNum。(这种情况并未返回真实库存)
+     */
+    private Integer remainNum;
+    /**
+     * 预计发货时间,详情展示格式为:预计2024-01-09 发货
+     */
+    private String estimatedShippingTime;
+}

+ 96 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/ZCR.java

@@ -0,0 +1,96 @@
+package org.dromara.external.api.zhongche.domain;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * author
+ * 时间:2026/1/5,19:16
+ */
+@Data
+@NoArgsConstructor
+public class ZCR<T> implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 成功
+     */
+    private static final String SUCCESS = "0";
+
+    /**
+     * 0代表请求成功,其他标识是失败,  Y
+     */
+    private String respCode;
+    /**
+     * 当出现错误时候,错误信息填充在本字段   N
+     */
+    private String respMsg;
+
+    /**
+     * 业务响应参数    N
+     */
+    private T data;
+
+    /**
+     * 签名    Y
+     */
+    private String sign;
+
+    /**
+     * token
+     */
+    private String accessToken;
+
+    /**
+     * 有效期  访问令牌有效期,单位秒,建议24小时 24小时返回值为
+     * 24*60*60 = 86400
+     */
+    private Integer expiresIn;
+
+    public static <T> ZCR<T> tokenOk(String accessToken, Integer expiresIn) {
+        return resetRToken(SUCCESS, "",null,"", accessToken,expiresIn);
+    }
+
+
+
+    public static <T> ZCR<T> ok(T data,String sign) {
+        return resetR(SUCCESS, "", data, sign);
+    }
+
+    public static <T> ZCR<T> ok(T data) {
+        return resetR(SUCCESS, "", data, "" );
+    }
+    public static <T> ZCR<T> ok(String respMsg, T data,String sign) {
+        return resetR(SUCCESS, respMsg, data, sign);
+    }
+
+    public static <T> ZCR<T> fail(String code, String msg) {
+        return resetR(code, msg,null,"");
+    }
+
+    public static <T> ZCR<T> resetR(String respCode, String respMsg, T data, String sign) {
+        ZCR ZCR = new ZCR<>();
+        ZCR.setRespCode(respCode);
+        ZCR.setRespMsg(respMsg);
+        ZCR.setData(data);
+        ZCR.setSign(sign);
+        return ZCR;
+    }
+
+    public static <T> ZCR<T> resetRToken(String respCode, String respMsg, T data, String sign, String accessToken, Integer expiresIn) {
+        ZCR ZCR = new ZCR<>();
+        ZCR.setRespCode(respCode);
+        ZCR.setRespMsg(respMsg);
+        ZCR.setData(data);
+        ZCR.setSign(sign);
+        ZCR.setAccessToken(accessToken);
+        ZCR.setExpiresIn(expiresIn);
+        return ZCR;
+    }
+
+
+
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/aftersale/domain/OutgoingGoodsItem.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.zhongche.domain.aftersale.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 发货商品项
+ * 对应接口文档 5.4.7.5.3 售后单新品发货商品(outgoingGoods)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OutgoingGoodsItem {
+    /**
+     * 商品sku
+     * 必填,长度200
+     */
+    private String goodsId;
+
+    /**
+     * 商品数量
+     * 必填
+     */
+    private BigDecimal num;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/MallAfterSaleNoQueryBo.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询电商售后单号的业务请求参数
+ * (对应请求体中 data 字段 Base64 解码后的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MallAfterSaleNoQueryBo {
+
+    /**
+     * 中车电子商城售后单编号
+     * 必填,长度20
+     */
+    private String afterSaleNo;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/MallOrderNoQueryBo.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询电商订单号的业务请求参数
+ * data字段Base64解码后的JSON对应的实体类
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MallOrderNoQueryBo {
+
+    /**
+     * 中车电子商城订单编号
+     * 必填,长度20
+     */
+    private String orderNo;
+}

+ 31 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/MessageBo.java

@@ -0,0 +1,31 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 消息监听接口的业务请求参数
+ * (对应请求体中 data 字段 Base64 解码后的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MessageBo {
+    /**
+     * 消息id
+     */
+    private String id;
+    /**
+     * 消息类型
+     */
+    private String type;
+    /**
+     * 消息内容,格式为json对象
+     */
+    private Object content;
+    /**
+     * 推送时间,格式YYYYMMDDHHMMSS
+     */
+    private String time;
+}

+ 27 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/ModuleCheckBo.java

@@ -0,0 +1,27 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 非必接模块接入校验的业务请求参数
+ * (对应请求体中 data 字段 Base64 解码后的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ModuleCheckBo {
+
+    /**
+     * 电商账号
+     * 必填,长度50
+     */
+    private String account;
+
+    /**
+     * 模块类型:10对账、11开票、12结算、13仅退款
+     * 必填,长度3
+     */
+    private String moduleType;
+}

+ 32 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderCancelAuditBo.java

@@ -0,0 +1,32 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 审核订单取消的业务请求参数
+ * 对应 5.3.12.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderCancelAuditBo {
+    /**
+     * 中车电子商城订单号
+     * 必填
+     */
+    private String orderNo;
+
+    /**
+     * 取消审核状态。1:通过 2:不通过。
+     * 必填
+     */
+    private String state;
+
+    /**
+     * 不通过原因。
+     * 必填
+     */
+    private String rejectReason;
+}

+ 26 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderConfirmBo.java

@@ -0,0 +1,26 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 接单的业务请求参数
+ * 对应 5.3.2.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderConfirmBo {
+    /**
+     * 中车电子商城订单号
+     * 必填
+     */
+    private String orderNo;
+
+    /**
+     * 电商平台订单号
+     * 必填
+     */
+    private String mallOrderNo;
+}

+ 45 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderDeliverBo.java

@@ -0,0 +1,45 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.OrderDeliverGoods;
+
+import java.util.List;
+
+/**
+ * 发货的业务请求参数
+ * 对应 5.3.5.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderDeliverBo {
+    /**
+     * 中车电子商城订单号
+     * 必填
+     */
+    private String orderNo;
+
+    /**
+     * 配送方式:1快递发货 2自行配送 3采购自提
+     * 必填
+     */
+    private String deliveryType;
+
+    /**
+     * 物流单号。当配送方式为1快递发货时必填。
+     */
+    private String expressCode;
+
+    /**
+     * 物流公司。当配送方式为1快递发货时必填。
+     */
+    private String expressCompanyName;
+
+    /**
+     * 订单发货商品列表
+     * 必填
+     */
+    private List<OrderDeliverGoods> orderDeliverGoods;
+}

+ 31 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderDeliveredNoticeBo.java

@@ -0,0 +1,31 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 妥投通知的业务请求参数
+ * 对应 5.3.7.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderDeliveredNoticeBo {
+    /**
+     * 中车电子商城发货单编号。订单、售后换发货返回的发货单编号。
+     * 必填
+     */
+    private String outgoingCode;
+
+    /**
+     * 发货单来源:1:订单、2:售后。
+     * 必填
+     */
+    private String outgoingSource;
+
+    /**
+     * 妥投凭证,不超过6张,JSON格式。如["imgUrl1","imgUrl2"]。
+     */
+    private String voucher;
+}

+ 20 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderDetailBo.java

@@ -0,0 +1,20 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.*;
+
+/**
+ * 查询订单详情的业务请求参数
+ * 对应 5.3.1.4.1 业务参数
+ */
+//@Data
+//@NoArgsConstructor
+//@AllArgsConstructor
+@Setter
+@Getter
+public class OrderDetailBo {
+    /**
+     * 中车电子商城订单号
+     * 必填
+     */
+    private String orderNo;
+}

+ 34 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderGoodsAppendBo.java

@@ -0,0 +1,34 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.OrderGoodsAppendixItem;
+
+import java.util.List;
+
+/**
+ * 同步商品协商发货时间的业务请求参数
+ * 对应 5.3.3.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderGoodsAppendBo {
+    /**
+     * 中车电子商城订单号
+     * 必填
+     */
+    private String orderNo;
+
+    /**
+     * 电商平台订单号
+     * 必填
+     */
+    private String mallOrderNo;
+
+    /**
+     * 订单接单商品附录
+     */
+    private List<OrderGoodsAppendixItem> orderGoodsAppendix;
+}

+ 32 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OrderRejectBo.java

@@ -0,0 +1,32 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 拒单的业务请求参数
+ * 对应 5.3.4.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderRejectBo {
+    /**
+     * 中车电子商城订单号
+     * 必填
+     */
+    private String orderNo;
+
+    /**
+     * 电商平台订单号
+     * 必填
+     */
+    private String mallOrderNo;
+
+    /**
+     * 拒单原因
+     * 必填
+     */
+    private String rejectReason;
+}

+ 20 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/OutgoingQueryBo.java

@@ -0,0 +1,20 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询发货单信息的业务请求参数
+ * 对应 5.3.8.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OutgoingQueryBo {
+    /**
+     * 供应商订单号
+     * 必填
+     */
+    private String orderNo;
+}

+ 35 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/PendingOrderListBo.java

@@ -0,0 +1,35 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询待处理订单列表的业务请求参数
+ * 对应 5.3.6.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PendingOrderListBo {
+    /**
+     * 当前页
+     * 必填
+     */
+    private Integer current;
+
+    /**
+     * 每页显示条数。默认每页10条,每页最多30条。
+     */
+    private Integer size;
+
+    /**
+     * 电商账号
+     */
+    private String account;
+
+    /**
+     * 订单类型。0:待处理预订单、1待处理订单,如果不传则默认1。
+     */
+    private String orderType;
+}

+ 26 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/TrackQueryBo.java

@@ -0,0 +1,26 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询物流信息的业务请求参数 (data字段解码后的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TrackQueryBo {
+
+    /**
+     * 中车电子商城发货单编号
+     * 必填
+     */
+    private String outgoingCode;
+
+    /**
+     * 运单类型 (0:订单, 1:换新单)
+     * 必填
+     */
+    private String waybillType;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/UserLoginBo.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.Data;
+
+/**
+ * author
+ * 时间:2026/1/5,19:51
+ */
+@Data
+public class UserLoginBo {
+
+    /**
+     * 账户名称
+     */
+    private String username;
+
+    /**
+     * 账户密码
+     */
+    private String password;
+}

+ 43 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/bo/ZCTokenBo.java

@@ -0,0 +1,43 @@
+package org.dromara.external.api.zhongche.domain.bo;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * author
+ * 时间:2026/1/5,19:11
+ */
+@Data
+public class ZCTokenBo {
+    /**
+     * 接口版本   Y
+     */
+    private String version;
+
+    /**
+     * 时间戳,格式YYYYMMDDHHMMSS  Y
+     */
+
+    private String timestamp;
+
+    /**
+     * 开发者id,中车电子商城提供  Y
+     */
+    private String clientId;
+
+    /**
+     * 请求token
+     */
+    private String accessToken;
+
+    /**
+     * 业务请求参数   Y
+     */
+    private String data;
+
+    /**
+     * 签名    Y
+     */
+    private String sign;
+
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/invoice/domain/WaitInvoiceApply.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.zhongche.domain.invoice.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 待开票申请单列表项
+ * 对应接口文档 5.7.8.5.2 待开票申请订单列表-invoiceApplys
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WaitInvoiceApply {
+    /**
+     * 申请单编号
+     * 必填,长度50
+     */
+    private String applyNo;
+
+    /**
+     * 开票金额
+     * 必填
+     */
+    private BigDecimal invoiceAmount;
+}

+ 38 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementApplyOrdersBo.java

@@ -0,0 +1,38 @@
+package org.dromara.external.api.zhongche.domain.settlement.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询结算单订单列表的请求参数
+ * 对应接口文档 5.9.2.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementApplyOrdersBo {
+    /**
+     * 当前页
+     * 必填,长度11
+     */
+    private Integer current;
+
+    /**
+     * 每页显示条数
+     * 非必填,长度11;默认每页30条,每页最多50条
+     */
+    private Integer size;
+
+    /**
+     * 电商账号
+     * 必填,长度50
+     */
+    private String account;
+
+    /**
+     * 开票申请编号
+     * 必填,长度50
+     */
+    private String applyNo;
+}

+ 29 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementConfirmBo.java

@@ -0,0 +1,29 @@
+package org.dromara.external.api.zhongche.domain.settlement.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.settlement.domain.SettlementConfirmOrderItem;
+
+import java.util.List;
+
+/**
+ * 结算单确认结算的请求参数
+ * 对应接口文档 5.9.3.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementConfirmBo {
+    /**
+     * 供应商结算单号
+     * 必填,长度20
+     */
+    private String applyNo;
+
+    /**
+     * 结算订单列表
+     * 非必填
+     */
+    private List<SettlementConfirmOrderItem> settlementOrders;
+}

+ 32 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementConfirmPaymentBo.java

@@ -0,0 +1,32 @@
+package org.dromara.external.api.zhongche.domain.settlement.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 结算单确认收款的请求参数
+ * 对应接口文档 5.9.5.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementConfirmPaymentBo {
+    /**
+     * 供应商结算单号
+     * 必填,长度20
+     */
+    private String applyNo;
+
+    /**
+     * 是否收款
+     * 必填,长度3;枚举值:0-异常、1-正常
+     */
+    private String status;
+
+    /**
+     * 异常原因
+     * 非必填;仅status为0(异常)时必填
+     */
+    private String errorMsg;
+}

+ 16 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementDetailBo.java

@@ -0,0 +1,16 @@
+package org.dromara.external.api.zhongche.domain.settlement.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementDetailBo {
+    /**
+     * 供应商结算单号
+     * 必填,长度20
+     */
+    private String applyNo;
+}

+ 20 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/bo/SettlementPaymentDetailBo.java

@@ -0,0 +1,20 @@
+package org.dromara.external.api.zhongche.domain.settlement.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 结算单付款详情的请求参数
+ * 对应接口文档 5.9.4.4.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementPaymentDetailBo {
+    /**
+     * 供应商结算单号
+     * 必填,长度20
+     */
+    private String applyNo;
+}

+ 32 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/domain/SettlementConfirmOrderItem.java

@@ -0,0 +1,32 @@
+package org.dromara.external.api.zhongche.domain.settlement.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 结算单申请订单子项
+ * 对应接口文档 5.9.3.4.2 结算单申请订单列表-settlementOrder
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementConfirmOrderItem {
+    /**
+     * 中车电子商城订单号
+     * 必填,长度20
+     */
+    private String orderNo;
+
+    /**
+     * 订单状态
+     * 必填,长度3;枚举值:0-异常、1-正常
+     */
+    private String status;
+
+    /**
+     * 异常原因
+     * 非必填;仅status为0(异常)时需传
+     */
+    private String errorMsg;
+}

+ 51 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/domain/SettlementOrderItem.java

@@ -0,0 +1,51 @@
+package org.dromara.external.api.zhongche.domain.settlement.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.math.BigDecimal;
+
+/**
+ * 结算单申请订单列表项
+ * 对应接口文档 5.9.2.5.2 结算单申请订单列表-settlementOrders
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementOrderItem {
+    /**
+     * 中车电子商城订单号
+     * 必填,长度20
+     */
+    private String orderNo;
+
+    /**
+     * 采购平台订单号
+     * 必填,长度50
+     */
+    private String purchaserOrderNo;
+
+    /**
+     * 电商订单号
+     * 必填,长度100
+     */
+    private String mallOrderNo;
+
+    /**
+     * 订单金额
+     * 必填
+     */
+    private BigDecimal orderAmount;
+
+    /**
+     * 售后退款金额
+     * 必填
+     */
+    private BigDecimal refundAmount;
+
+    /**
+     * 订单申请结算的金额(订单金额-售后退款金额)
+     * 必填
+     */
+    private BigDecimal applyMoney;
+}

+ 47 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/vo/SettlementApplyOrdersVo.java

@@ -0,0 +1,47 @@
+package org.dromara.external.api.zhongche.domain.settlement.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.settlement.domain.SettlementOrderItem;
+
+import java.util.List;
+
+/**
+ * 查询结算单订单列表的响应参数
+ * 对应接口文档 5.9.2.5.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementApplyOrdersVo {
+    /**
+     * 当前页
+     * 必填
+     */
+    private Integer current;
+
+    /**
+     * 每页显示条数
+     * 必填
+     */
+    private Integer size;
+
+    /**
+     * 总页数
+     * 必填
+     */
+    private Integer pages;
+
+    /**
+     * 总条数
+     * 必填
+     */
+    private Integer total;
+
+    /**
+     * 发票申请订单列表
+     * 必填
+     */
+    private List<SettlementOrderItem> settlementOrders;
+}

+ 63 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/vo/SettlementDetailVo.java

@@ -0,0 +1,63 @@
+package org.dromara.external.api.zhongche.domain.settlement.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementDetailVo {
+    /**
+     * 采购单位名称
+     * 必填,长度200
+     */
+    private String purchaserName;
+
+    /**
+     * 采购申请单编号
+     * 必填,长度50
+     */
+    private String purchaserApplyNo;
+
+    /**
+     * 采购申请单名称
+     * 必填,长度50
+     */
+    private String purchaserApplyName;
+
+    /**
+     * 申请人
+     * 必填
+     */
+    private String applyUser;
+
+    /**
+     * 申请时间
+     * 必填,长度50
+     */
+    private String applyTime;
+
+    /**
+     * 备注
+     * 必填,长度70(最多70个字符)
+     */
+    private String memo;
+
+    /**
+     * 结算申请金额
+     * 必填
+     */
+    private BigDecimal settlementMoney;
+
+    /**
+     * 结算状态
+     * 必填,长度20;枚举值:
+     * 10-待确认、11-待修改、12-待开票、13-开票中待确认、
+     * 14-待收款、15-已完成、16-已作废、17-待付款、
+     * 18-付款退回、19-开票退回
+     */
+    private String status;
+}

+ 33 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/settlement/vo/SettlementPaymentDetailVo.java

@@ -0,0 +1,33 @@
+package org.dromara.external.api.zhongche.domain.settlement.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 结算单付款详情的响应参数
+ * 对应接口文档 5.9.4.5.1 业务参数
+ * 注:payVoucher为JSON格式字符串(如["imgUrl1","imgUrl2"]),需自行解析为列表
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SettlementPaymentDetailVo {
+    /**
+     * 付款单号
+     * 必填,长度200
+     */
+    private String payNo;
+
+    /**
+     * 付款凭证
+     * 必填,长度50;JSON格式字符串,示例:["imgUrl1","imgUrl2"]
+     */
+    private String payVoucher;
+
+    /**
+     * 付款时间
+     * 必填;格式:yyyy-MM-dd HH:mm:ss
+     */
+    private String payTime;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/MallAfterSaleNoVo.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询电商售后单号的业务响应参数
+ * (对应响应体中 data 字段 Base64 编码前的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MallAfterSaleNoVo {
+
+    /**
+     * 电商平台售后单号
+     * 必填
+     */
+    private String mallAfterSaleNo;
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/MallOrderNoVo.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 查询电商订单号的业务响应参数
+ * 响应data字段Base64编码前的JSON对应的实体类
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MallOrderNoVo {
+
+    /**
+     * 电商平台订单号
+     * 必填
+     */
+    private String mallOrderNo;
+}

+ 25 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/MessageVo.java

@@ -0,0 +1,25 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 消息监听接口的业务响应参数
+ * (对应响应体中 data 字段 Base64 编码前的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MessageVo {
+    /**
+     * 结果:0-失败 1-成功
+     */
+    private String result;
+    /**
+     * 失败原因
+     */
+    private String message;
+
+
+}

+ 21 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/ModuleCheckVo.java

@@ -0,0 +1,21 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 非必接模块接入校验的业务响应参数
+ * (对应响应体中 data 字段 Base64 编码前的内容)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ModuleCheckVo {
+
+    /**
+     * 检测结果,1已接入、0未接入
+     * 必填
+     */
+    private String checkResult;
+}

+ 20 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/OrderDeliverVo.java

@@ -0,0 +1,20 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 发货的业务响应参数
+ * 对应 5.3.5.5.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderDeliverVo {
+    /**
+     * 发货单编号
+     * 必填
+     */
+    private String outgoingCode;
+}

+ 149 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/OrderDetailVo.java

@@ -0,0 +1,149 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.OrderFileItem;
+import org.dromara.external.api.zhongche.domain.OrderGoodsItem;
+import org.dromara.external.api.zhongche.domain.OrderInvoice;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderDetailVo {
+    /**
+     * 中车电子商城订单号
+     */
+    private String orderNo;
+    /**
+     * 采购平台订单号
+     */
+    private String purchaserOrderNo;
+    /**
+     * 订单类型 0普通订单 1预购单 2预存单
+     */
+    private Integer preOrder;
+    /**
+     * 电商平台订单号。需要确认接单或拒绝接单后才有值。
+     */
+    private String mallOrderNo;
+    /**
+     * 订单状态:0预购 1待接单 2待发货 3已部分发货 4已发货 5已完成 6已退换货 9已取消
+     */
+    private String orderStatus;
+    /**
+     * 订单金额。单位元,最多精确到分。订单金额等于:订单下商品的subAmount总和+运费。
+     */
+    private BigDecimal orderAmount;
+    /**
+     * 运费。单位元,最多精确到分。
+     */
+    private BigDecimal freight;
+    /**
+     * 订单商品列表
+     */
+    private List<OrderGoodsItem> orderGoods;
+    /**
+     * 收货人
+     */
+    private String name;
+    /**
+     * 一级地址编码:收货人省份地址编码
+     */
+    private String provinceId;
+    /**
+     * 二级地址编码:收货人市级地址编码
+     */
+    private String cityId;
+    /**
+     * 三级地址编码:收货人县(区)级地址编码
+     */
+    private String countyId;
+    /**
+     * 四级地址编码:收货人乡镇地址编码(如果该地区有四级地址,则必须传递四级地址,没有四级地址则传 0)
+     */
+    private String townId;
+    /**
+     * 详细地址
+     */
+    private String address;
+    /**
+     * 邮编
+     */
+    private String zip;
+    /**
+     * 手机号
+     */
+    private String mobile;
+    /**
+     * 座机号
+     */
+    private String phone;
+    /**
+     * 邮箱
+     */
+    private String email;
+    /**
+     * 备注
+     */
+    private String memo;
+    /**
+     * 订单创建时间,格式YYYY-MM-DD HH:MM:SS
+     */
+    private String orderTime;
+    /**
+     * 下单人名称
+     */
+    private String buyer;
+    /**
+     * 下单人电话
+     */
+    private String buyerMobile;
+    /**
+     * 采购单位
+     */
+    private String purchaserName;
+    /**
+     * 采购部门。格式:山西省烟草公司-省公司总部-省公司-规范办
+     */
+    private String purchaserDeptName;
+    /**
+     * 支付方式。01:账期支付;02:按单支付;03:混合支付
+     */
+    private String paymentType;
+    /**
+     * 订单发票信息
+     */
+    private OrderInvoice orderInvoice;
+    /**
+     * 是否需要发货凭证;0否 1货物照片
+     */
+    private String voucher;
+    /**
+     * 支付渠道。1:微信;2:支付宝
+     */
+    private String payClient;
+    /**
+     * 支付流水号
+     */
+    private String paySerialNum;
+    /**
+     * 账期支付金额,单位元,最多精确到分。支付方式为混合支付必填。
+     */
+    private BigDecimal payAccount;
+    /**
+     * 现金支付金额,单位元,最多精确到分。支付方式为混合支付必填。
+     */
+    private BigDecimal payMoney;
+    /**
+     * 预存支付金额,单位元,最多精确到分。
+     */
+    private BigDecimal payPrestore;
+    /**
+     * 订单附件列表
+     */
+    private List<OrderFileItem> files;
+}

+ 18 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/OutgoingVo.java

@@ -0,0 +1,18 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.OutgoingList;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OutgoingVo {
+    /**
+     * 发货单列表
+     */
+    private List<OutgoingList> outgoingList;
+}

+ 42 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/PendingOrderListVo.java

@@ -0,0 +1,42 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.PendingOrderRecord;
+
+import java.util.List;
+
+/**
+ * 查询待处理订单列表的业务响应参数
+ * 对应 5.3.6.5.1 业务参数
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PendingOrderListVo {
+    /**
+     * 当前页
+     */
+    private Integer current;
+
+    /**
+     * 每页显示条数
+     */
+    private Integer size;
+
+    /**
+     * 总页数
+     */
+    private Integer pages;
+
+    /**
+     * 总条数
+     */
+    private Integer total;
+
+    /**
+     * 待处理订单列表
+     */
+    private List<PendingOrderRecord> records;
+}

+ 15 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/StocksVo.java

@@ -0,0 +1,15 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.Data;
+import org.dromara.external.api.zhongche.domain.Stocks;
+
+import java.util.List;
+
+/**
+ * author
+ * 时间:2026/1/7,16:16
+ */
+@Data
+public class StocksVo {
+    List<Stocks> stocks;
+}

+ 32 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/vo/TrackVo.java

@@ -0,0 +1,32 @@
+package org.dromara.external.api.zhongche.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.external.api.zhongche.domain.DeliveryTrack;
+
+import java.util.List;
+
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TrackVo {
+    /**
+     * 物流单号
+     * 非必填
+     */
+    private String expressCode;
+
+    /**
+     * 物流公司
+     * 非必填
+     */
+    private String expressCompanyName;
+
+    /**
+     * 物流信息列表
+     * 非必填
+     */
+    private List<DeliveryTrack> deliveryTrack;
+}

+ 15 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/OrderNoDto.java

@@ -0,0 +1,15 @@
+package org.dromara.product.api.domain.dto;
+
+import lombok.Data;
+
+/**
+ * author
+ * 时间:2026/1/8,9:18
+ */
+@Data
+public class OrderNoDto {
+    /**
+     * 订单编号
+     */
+    private String orderId;
+}

+ 154 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ProductCategoryRemoteVo.java

@@ -0,0 +1,154 @@
+package org.dromara.product.api.domain;
+
+
+import lombok.Data;
+
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+
+/**
+ * 产品分类视图对象 product_category
+ *
+ * @author LionLi
+ * @date 2025-12-11
+ */
+@Data
+
+public class ProductCategoryRemoteVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 分类编号
+     */
+    private String categoryNo;
+
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+
+    /**
+     * 祖籍列表
+     */
+    private String ancestors;
+
+    /**
+     * 分类层级(1=一级,2=二级, 3三级)
+     */
+    private Long classLevel;
+
+    /**
+     * 是否显示(1=显示,0=隐藏)
+     */
+    private Long isShow;
+
+    /**
+     * 是否在GPS中显示
+     */
+    private Long isShowGps;
+
+    /**
+     * 折扣率(可能为JSON或文本)
+     */
+    private BigDecimal discountRate;
+
+    /**
+     * 拼音码(用于快速检索)
+     */
+    private String pyCode;
+
+    /**
+     * 分类描述
+     */
+    private String classDescription;
+
+    /**
+     * 数据来源
+     */
+
+    private String dataSource;
+
+    /**
+     * 自定义标签1
+     */
+
+    private String oneLable1;
+
+    /**
+     * 自定义标签2
+     */
+
+    private String oneLable2;
+
+    /**
+     * 自定义链接1
+     */
+
+    private String oneLink1;
+
+    /**
+     * 自定义链接2
+     */
+
+    private String oneLink2;
+
+    /**
+     * 排序值,默认为0
+     */
+
+    private Long sort;
+
+    /**
+     * 颜色(如CSS颜色值)
+     */
+    private String color;
+
+    /**
+     * 采购编号
+     */
+
+
+    private String purchaseNo;
+
+    /**
+     * 采购名称
+     */
+    private String purchaseName;
+
+    /**
+     * 采购负责人编号
+     */
+    private String purchaseManagerNo;
+
+    /**
+     * 采购负责人姓名
+     */
+    private String purchaseManagerName;
+
+    /**
+     * 所属平台(0=Web, 1=小程序)
+     */
+    private Long platform;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 25 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ProductPriceInventoryRemoteVo.java

@@ -0,0 +1,25 @@
+package org.dromara.product.api.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * author
+ * 时间:2026/1/7,18:47
+ */
+@Data
+public class ProductPriceInventoryRemoteVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 关联 product_base.id
+     */
+    private String goodsId;
+
+    private BigDecimal dsPrice;
+
+    private BigDecimal price;
+
+
+}

+ 45 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/StocksResult.java

@@ -0,0 +1,45 @@
+package org.dromara.product.api.domain.zhongche.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+
+//商品库存
+@Data
+public class StocksResult implements Serializable {
+    /**
+     * 商品sku
+     */
+    private String goodsId;
+    /**
+     * 地区id
+     */
+    private String areaId;
+    /**
+     * 库存状态:
+     * 1有货 现货。下单立即发货
+     * 2 有货 在途。正在内部配货,预计 2~6 天到达本仓库
+     * 3 有货 可配货。下单后从有货仓库配货
+     * 4 预订
+     * 5 无货
+     */
+    private String stockState;
+    /**
+     * 库存状态描述
+     */
+    private String stockStateDesc;
+    /**
+     * 剩余数量。
+     * 支持无库存下单商品返回(-999)
+     * 当值为-1时,为未查询到。
+     * stockState=1或stockState=2时,入参goodsNum<50,该值为实际库存。
+     * 入参50<=goodsNum<=100时,该值为-1。
+     * 入参goodsNum>100,该值等于goodsNum。(这种情况并未返回真实库存)
+     */
+    private Integer remainNum;
+    /**
+     * 预计发货时间,详情展示格式为:预计2024-01-09 发货
+     */
+    private String estimatedShippingTime;
+}

+ 15 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/StocksResultDto.java

@@ -0,0 +1,15 @@
+package org.dromara.product.api.domain.zhongche.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * author
+ * 时间:2026/1/7,16:16
+ */
+@Data
+public class StocksResultDto implements Serializable {
+    List<StocksResult> stocks;
+}

+ 49 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/zhongche/domain/Prices.java

@@ -0,0 +1,49 @@
+package org.dromara.common.core.domain.zhongche.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * author
+ * 时间:2026/1/6,10:14
+ */
+@Data
+public class Prices implements Serializable {
+    /**
+     * 商品sku
+     *
+     */
+    private String goodsId;
+
+    /**
+     * 电商价格。单位元,最多精确到分。值为-1时,表示未查询到。
+     *
+     */
+    private BigDecimal dsPrice;
+
+    /**
+     * 协议价格。单位元,最多精确到分。为-1时,表示未查询到。
+     *
+     */
+    private BigDecimal price;
+
+    /**
+     * 未税价
+     *
+     */
+    private BigDecimal taxFreePrice;
+
+    /**
+     * 税率
+     *
+     */
+    private BigDecimal tax;
+
+    /**
+     * 税收编码
+     *
+     */
+    private String taxCode;
+}

+ 16 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/zhongche/vo/PricesVo.java

@@ -0,0 +1,16 @@
+package org.dromara.common.core.domain.zhongche.vo;
+
+import lombok.Data;
+import org.dromara.common.core.domain.zhongche.domain.Prices;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * author
+ * 时间:2026/1/6,10:16
+ */
+@Data
+public class PricesVo implements Serializable {
+    private List<Prices>  prices;
+}

+ 728 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePullController.java

@@ -0,0 +1,728 @@
+package org.dromara.external.controller.zhongche;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.date.DateUtil;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONUtil;
+import lombok.RequiredArgsConstructor;
+import org.dromara.external.api.zhongche.domain.*;
+import org.dromara.external.api.zhongche.domain.aftersale.bo.*;
+import org.dromara.external.api.zhongche.domain.aftersale.vo.*;
+import org.dromara.external.api.zhongche.domain.bo.*;
+import org.dromara.external.api.zhongche.domain.invoice.bo.*;
+import org.dromara.external.api.zhongche.domain.invoice.vo.InvoiceApplyDetailVo;
+import org.dromara.external.api.zhongche.domain.invoice.vo.InvoiceApplyOrdersVo;
+import org.dromara.external.api.zhongche.domain.invoice.vo.InvoiceApplyWaitlistVo;
+import org.dromara.external.api.zhongche.domain.settlement.bo.*;
+import org.dromara.external.api.zhongche.domain.settlement.vo.SettlementApplyOrdersVo;
+import org.dromara.external.api.zhongche.domain.settlement.vo.SettlementDetailVo;
+import org.dromara.external.api.zhongche.domain.settlement.vo.SettlementPaymentDetailVo;
+import org.dromara.external.api.zhongche.domain.vo.*;
+import org.dromara.external.util.SM2SignUtil;
+import org.springframework.validation.annotation.Validated;
+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.RestController;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * author
+ * 时间:2026/1/5,19:03
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/api")
+public class ZhongChePullController {
+
+    // 中车地区查询接口地址(替换为真实域名)
+    private static final String AREA_QUERY_URL = "https://{中车域名}";
+
+    // 中车提供的配置(替换为真实值)
+    private static final String CLIENT_ID = "KFZiA6EknYf";
+    private static final String ACCESS_TOKEN = "1261127442808451075";
+    private static final String PRIVATE_KEY = "你的私钥(16进制)"; // 电商平台私钥
+    private static final String ZC_PUBLIC_KEY = "中车公钥(16进制)"; // 中车公钥
+    private static final String VERSION = "1.0";
+
+    private final SM2SignUtil sm2SignUtil;
+
+    //5	中车电子商城提供服务
+    //5.1	基础数据服务
+
+    //5.1.1	地区查询
+    @PostMapping("/area/query")
+    public ZCR<AreaVo> areaQuery(@RequestBody AreaQueryBo bo) {
+        //获取response.body
+        ZCR<String> responseDto = doZcPost("/api/area/query", bo);
+        //TODO 2 签名校验
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        //解析业务响应参数
+        ZCR<AreaVo> zcr = parseZcResponse(responseDto, AreaVo.class);
+        return zcr;
+    }
+
+    private Boolean verifyResponseSign(ZCR<String> responseDto) {
+        String sign = responseDto.getSign();
+        if (sign == null){
+            return false;
+        }
+        return true;
+    }
+
+
+    private <B> ZCR<String> doZcPost(String apiPath, B bo) {
+        // 1. 业务参数 -> JSON -> Base64
+        String bizJson = JSONUtil.toJsonStr(bo);
+        String dataBase64 = Base64.encode(bizJson, StandardCharsets.UTF_8);
+
+        // 2. 构建 token 请求体
+        ZCTokenBo zcTokenBo = getZcTokenBo(dataBase64);
+        String requestJson = JSONUtil.toJsonStr(zcTokenBo);
+
+        // 3. HTTP POST
+        HttpResponse httpResponse = HttpRequest
+            .post(AREA_QUERY_URL + apiPath)
+            .charset(StandardCharsets.UTF_8)
+            .body(requestJson)
+            .timeout(60000)
+            .execute();
+
+        // 4. 响应体转 DTO
+        String responseBody = httpResponse.body();
+        ZCR<String> responseDto = JSONUtil.toBean(responseBody, ZCR.class);
+
+        // 5. 响应码校验
+        if (!"0".equals(responseDto.getRespCode())) {
+            return ZCR.fail(responseDto.getRespCode(), responseDto.getRespMsg());
+        }
+
+        return responseDto;
+    }
+
+    private ZCTokenBo getZcTokenBo(String data) {
+        ZCTokenBo zcTokenBo = new ZCTokenBo();
+        zcTokenBo.setVersion(VERSION);
+        zcTokenBo.setTimestamp(DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss"));
+        zcTokenBo.setAccessToken(ACCESS_TOKEN);
+        zcTokenBo.setClientId(CLIENT_ID);
+        zcTokenBo.setData(data);
+        zcTokenBo.setSign("");
+        return zcTokenBo;
+    }
+
+
+    //5.2 商品服务
+
+    //TODO 5.2.1	商品导入
+    @PostMapping("/egoods/import")
+    public ZCR<GoodsImportVo> egoodsImport(@RequestBody GoodsImportBo bo) {
+
+        ZCR<String> responseDto = doZcPost("/api/egoods/import", bo);
+        //TODO 6.2 签名校验
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        //解析业务响应参数
+        ZCR<GoodsImportVo> zcr = parseZcResponse(responseDto, GoodsImportVo.class);
+        return zcr;
+
+    }
+    private <V> ZCR<V> parseZcResponse(ZCR<String> responseDto, Class<V> voClass) {
+        // Base64 解码 data
+        String respBizJson = Base64.decodeStr(
+            responseDto.getData(),
+            StandardCharsets.UTF_8
+        );
+
+        // JSON → VO
+        V vo = JSONUtil.toBean(respBizJson, voClass);
+
+        return ZCR.ok(vo);
+    }
+
+
+    //TODO 5.2.2	商品价格变更
+    @PostMapping("/egoods/price/update")
+    public ZCR<GoodsPriceUpdateVo> egoodsPriceUpdate(@RequestBody GoodsImportBo bo) {
+
+        ZCR<String> responseDto = doZcPost("/api/egoods/price/update", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsPriceUpdateVo> zcr = parseZcResponse(responseDto, GoodsPriceUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.2.3	商品上下架状态变更
+    @PostMapping("/egoods/status/update")
+    public ZCR<GoodsStatusUpdateVo> egoodsStatusUpdate(@RequestBody GoodsStatusUpdateBo bo) {
+
+        ZCR<String> responseDto = doZcPost("/api/egoods/status/update", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsStatusUpdateVo> zcr = parseZcResponse(responseDto, GoodsStatusUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.2.4	商品图片变更
+    @PostMapping("/egoods/imgs/update")
+    public ZCR<GoodsImageUpdateVo> egoodsImgsUpdate(@RequestBody GoodsImageUpdateBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/egoods/imgs/update", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsImageUpdateVo> zcr = parseZcResponse(responseDto, GoodsImageUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.2.5	商品规格信息变更
+    @PostMapping("/egoods/properties/update")
+    public ZCR<GoodsUpdateVo> egoodsPropertiesUpdate(@RequestBody GoodsPropertiesUpdateBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/egoods/properties/update", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.2.6	商品详情信息变更
+    @PostMapping("/egoods/detail/update")
+    public ZCR<GoodsUpdateVo> egoodsDetailUpdate(@RequestBody GoodsDetailBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/egoods/detail/update", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //5.3	订单服务
+
+    //TODO 5.3.1	查询订单详情
+    @PostMapping("/mall/order/detail")
+    public ZCR<OrderDetailVo> mallOrderDetail(@RequestBody OrderDetailBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/detail", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<OrderDetailVo> zcr = parseZcResponse(responseDto, OrderDetailVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.2	接单
+    @PostMapping("/mall/order/confirm")
+    public ZCR<GoodsUpdateVo> mallOrderConfirm(@RequestBody OrderConfirmBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/confirm", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.3	同步商品协商发货时间
+    @PostMapping("/mall/order/goods/append")
+    public ZCR<GoodsUpdateVo> mallOrderGoodsAppend(@RequestBody OrderGoodsAppendBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/goods/append", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.4	拒单
+    @PostMapping("/mall/order/reject")
+    public ZCR<GoodsUpdateVo> mallOrderReject(@RequestBody OrderRejectBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/reject", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.5	发货
+    @PostMapping("/mall/order/deliver/goods")
+    public ZCR<OrderDeliverVo> mallOrderDeliverGoods(@RequestBody OrderDeliverBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/deliver/goods", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<OrderDeliverVo> zcr = parseZcResponse(responseDto, OrderDeliverVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.3.6	查询待处理订单列表
+    @PostMapping("/mall/order/pending/list")
+    public ZCR<PendingOrderListVo> mallOrderPendingList(@RequestBody ZCTokenBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/pending/list", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<PendingOrderListVo> zcr = parseZcResponse(responseDto, PendingOrderListVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.7	妥投通知
+    @PostMapping("/mall/order/delivered/notice")
+    public ZCR<GoodsUpdateVo> mallOrderDeliveredNotice(@RequestBody OrderDeliveredNoticeBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/delivered/notice", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.8	查询发货单信息
+    @PostMapping("/mall/order/query/outgoing")
+    public ZCR<OutgoingVo> mallOrderQueryOutgoing(@RequestBody OutgoingQueryBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/query/outgoing", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<OutgoingVo> zcr = parseZcResponse(responseDto, OutgoingVo.class);
+        return zcr;
+    }
+
+    //TODO 5.3.12	审核订单取消
+    /*
+        //请求业务参数
+        OrderCancelAuditBo orderCancelAuditBo = new OrderCancelAuditBo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/order/cancel/audit/judge")
+    public ZCR<GoodsUpdateVo> mallOrderCancelAuditJudge(@RequestBody OrderCancelAuditBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/order/cancel/audit/judge", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+
+
+    //5.4	售后服务
+
+    //TODO 5.4.1	查询售后单详情
+    /*
+        //请求业务参数
+        AfterSaleDetailBo afterSaleDetailBo = new AfterSaleDetailBo();
+        //响应业务参数
+        AfterSaleDetailVo afterSaleDetailVo = new AfterSaleDetailVo();
+        AfterSaleReason afterSaleReason = new AfterSaleReason();
+        AfterSaleGoods afterSaleGoods = new AfterSaleGoods();
+        AfterSalePick afterSalePick = new AfterSalePick();
+        ImageList imageList = new ImageList();
+        AfterSaleReturn afterSaleReturn = new AfterSaleReturn();
+     */
+    @PostMapping("/mall/aftersale/detail")
+    public ZCR<AfterSaleDetailVo> mallAftersaleDetail(@RequestBody AfterSaleDetailBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/detail", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<AfterSaleDetailVo> zcr = parseZcResponse(responseDto, AfterSaleDetailVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.2	接受售后
+    @PostMapping("/mall/aftersale/confirm")
+    public ZCR<GoodsUpdateVo> mallAftersaleConfirm(@RequestBody AfterSaleConfirmBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/confirm", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.3	拒绝售后
+    @PostMapping("/mall/aftersale/reject")
+    public ZCR<GoodsUpdateVo> mallAftersaleReject(@RequestBody AfterSaleRejectBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/reject", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.4	确认收到退货
+    @PostMapping("/mall/aftersale/return/goods/received")
+    public ZCR<GoodsUpdateVo> mallAftersaleReturnGoodsReceived(@RequestBody AfterSaleReturnReceivedBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/return/goods/received", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.5	换货新品发货
+    @PostMapping("/mall/aftersale/deliver/goods")
+    public ZCR<AfterSaleDeliverGoodsVo> mallAftersaleDeliverGoods(@RequestBody AfterSaleDeliverGoodsBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/deliver/goods", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<AfterSaleDeliverGoodsVo> zcr = parseZcResponse(responseDto, AfterSaleDeliverGoodsVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.6	查询待处理售后单列表
+    @PostMapping("/mall/aftersale/pending/list")
+    public ZCR<AfterSalePendingListVo> mallAftersalePendingList(@RequestBody AfterSalePendingListBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/pending/list", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<AfterSalePendingListVo> zcr = parseZcResponse(responseDto, AfterSalePendingListVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.7	查询换货新品发货单信息
+    @PostMapping("/mall/aftersale/query/outgoing")
+    public ZCR<AfterSaleQueryOutgoingVo> mallAftersaleQueryOutgoing(@RequestBody AfterSaleQueryOutgoingBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/query/outgoing", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<AfterSaleQueryOutgoingVo> zcr = parseZcResponse(responseDto, AfterSaleQueryOutgoingVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.8	线下售后
+    @PostMapping("/mall/aftersale/offline/create")
+    public ZCR<AfterSaleOfflineCreateVo> mallAftersaleOfflineCreate(@RequestBody AfterSaleOfflineCreateBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/offline/create", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<AfterSaleOfflineCreateVo> zcr = parseZcResponse(responseDto, AfterSaleOfflineCreateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.4.9	确认退款
+    @PostMapping("/mall/aftersale/refund")
+    public ZCR<GoodsUpdateVo> mallAftersaleRefund(@RequestBody AfterSaleRefundBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/aftersale/refund", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //5.7	开票服务
+
+    //TODO 5.7.1	查询开票信息
+    /*
+        //请求业务参数
+        InvoiceApplyDetailBo invoiceApplyDetailBo = new InvoiceApplyDetailBo();
+        //响应业务参数
+        InvoiceApplyDetailVo invoiceApplyDetailVo = new InvoiceApplyDetailVo();
+        InvoiceReceiver invoiceReceiver = new InvoiceReceiver();
+     */
+    @PostMapping("/mall/invoice/apply/detail")
+    public ZCR<InvoiceApplyDetailVo> mallInvoiceApplyDetail(@RequestBody InvoiceApplyDetailBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/apply/detail", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<InvoiceApplyDetailVo> zcr = parseZcResponse(responseDto, InvoiceApplyDetailVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.7.2	查询开票申请订单列表
+    /*
+        //请求业务参数
+        InvoiceApplyOrdersBo invoiceApplyOrdersBo = new InvoiceApplyOrdersBo();
+        //响应业务参数
+        InvoiceApplyOrdersVo invoiceApplyOrdersVo = new InvoiceApplyOrdersVo();
+        InvoiceOrder invoiceOrder = new InvoiceOrder();
+     */
+    @PostMapping("/mall/invoice/apply/orders")
+    public ZCR<InvoiceApplyOrdersVo> mallInvoiceApplyOrders(@RequestBody InvoiceApplyOrdersBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/apply/orders", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<InvoiceApplyOrdersVo> zcr = parseZcResponse(responseDto, InvoiceApplyOrdersVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.7.3    拒绝开票
+
+    @PostMapping("/mall/invoice/apply/reject")
+    public ZCR<GoodsUpdateVo> mallInvoiceApplyReject(@RequestBody InvoiceApplyRejectBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/apply/reject", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.7.4	电商同步开票信息
+    /*
+        //请求业务参数
+        InvoiceSyncInvoiceInfosBo invoiceSyncInvoiceInfosBo = new InvoiceSyncInvoiceInfosBo();
+        InvoiceInfo invoiceInfo = new InvoiceInfo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/invoice/sync/invoiceinfos")
+    public ZCR<GoodsUpdateVo> mallInvoiceSyncInvoiceInfos(@RequestBody InvoiceSyncInvoiceInfosBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/sync/invoiceinfos", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.7.5 同步纸质发票邮寄信息
+    /*
+        //请求业务参数
+        InvoiceSyncWaybillBo invoiceSyncWaybillBo = new InvoiceSyncWaybillBo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/invoice/sync/waybill")
+    public ZCR<GoodsUpdateVo> mallInvoiceSyncWaybill(@RequestBody InvoiceSyncWaybillBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/sync/waybill", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+    //TODO 5.7.6 发票妥投通知
+    /*
+        //请求业务参数
+        InvoiceDeliveredNoticeBo invoiceDeliveredNoticeBo = new InvoiceDeliveredNoticeBo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/invoice/delivered/notice")
+    public ZCR<GoodsUpdateVo> mallInvoiceDeliveredNotice(@RequestBody InvoiceDeliveredNoticeBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/delivered/notice", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+
+
+    }
+
+    //TODO 5.7.7	查询待开票申请单列表
+    /*
+        //请求业务参数
+        InvoiceApplyWaitlistBo invoiceApplyWaitListBo = new InvoiceApplyWaitlistBo();
+
+        //响应业务参数
+        WaitInvoiceApply waitInvoiceApply = new WaitInvoiceApply();
+        InvoiceApplyWaitlistVo invoiceApplyWaitlistVo = new InvoiceApplyWaitlistVo();
+     */
+    @PostMapping("/mall/invoice/apply/waitlist")
+    public ZCR<InvoiceApplyWaitlistVo> mallInvoiceApplyWaitList(@RequestBody InvoiceApplyWaitlistBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/apply/waitlist", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<InvoiceApplyWaitlistVo> zcr = parseZcResponse(responseDto, InvoiceApplyWaitlistVo.class);
+        return zcr;
+
+
+    }
+
+    //TODO 5.7.8	电商同意退票
+    /*
+        //请求业务参数
+        InvoiceRefundAgreeBo invoiceRefundAgreeBo = new InvoiceRefundAgreeBo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/invoice/refund/agree")
+    public ZCR<GoodsUpdateVo> mallInvoiceRefundAgree(@RequestBody InvoiceRefundAgreeBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/refund/agree", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.7.9	电商确认完成退票
+    /*
+        //请求业务参数
+        InvoiceRefundFinishBo invoiceRefundFinishBo = new InvoiceRefundFinishBo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/invoice/refund/finish")
+    public ZCR<GoodsUpdateVo> mallInvoiceRefundFinish(@RequestBody InvoiceRefundFinishBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/refund/finish", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.7.10 电商拒绝退票申请
+    /*
+        //请求业务参数
+        InvoiceRefundRejectBo invoiceRefundRejectBo = new InvoiceRefundRejectBo();
+        //响应业务参数
+        GoodsUpdateVo goodsUpdateVo = new GoodsUpdateVo();
+     */
+    @PostMapping("/mall/invoice/refund/reject")
+    public ZCR<GoodsUpdateVo> mallInvoiceRefundReject(@RequestBody InvoiceRefundRejectBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/invoice/refund/reject", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+
+    }
+
+    //5.9 结算服务
+
+    //TODO 5.9.1	查询结算单详情
+    @PostMapping("/mall/settlement/detail")
+    public ZCR<SettlementDetailVo> mallSettlementDetail(@RequestBody SettlementDetailBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/settlement/detail", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<SettlementDetailVo> zcr = parseZcResponse(responseDto, SettlementDetailVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.9.2	查询结算单订单列表
+    @PostMapping("/mall/settlement/apply/orders")
+    public ZCR<SettlementApplyOrdersVo> mallSettlementApplyOrders(@RequestBody SettlementApplyOrdersBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/settlement/apply/orders", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<SettlementApplyOrdersVo> zcr = parseZcResponse(responseDto, SettlementApplyOrdersVo.class);
+        return zcr;
+
+    }
+
+
+    //TODO 5.9.3	结算单确认结算
+    @PostMapping("/mall/settlement/confirm")
+    public ZCR<GoodsUpdateVo> mallSettlementConfirm(@RequestBody SettlementConfirmBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/settlement/confirm", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+
+
+    }
+
+    //TODO 5.9.4	结算单付款详情
+    @PostMapping("/mall/settlement/payment/detail")
+    public ZCR<SettlementPaymentDetailVo> mallSettlementPaymentDetail( @RequestBody SettlementPaymentDetailBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/settlement/payment/detail", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<SettlementPaymentDetailVo> zcr = parseZcResponse(responseDto, SettlementPaymentDetailVo.class);
+        return zcr;
+
+    }
+
+    //TODO 5.9.5	结算单确认收款
+    @PostMapping("/mall/settlement/confirm/payment")
+    public ZCR<GoodsUpdateVo> mallSettlementConfirmPayment( @RequestBody SettlementConfirmPaymentBo bo) {
+        ZCR<String> responseDto = doZcPost("/api/mall/settlement/confirm/payment", bo);
+        Boolean aBoolean = verifyResponseSign(responseDto);
+        if (!aBoolean){
+            return ZCR.fail("5001", "响应签名验证失败");
+        }
+        ZCR<GoodsUpdateVo> zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        return zcr;
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}

+ 500 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java

@@ -0,0 +1,500 @@
+package org.dromara.external.controller.zhongche;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.domain.zhongche.domain.Goods;
+import org.dromara.common.core.domain.zhongche.domain.Prices;
+import org.dromara.common.core.domain.zhongche.vo.PricesVo;
+import org.dromara.common.json.utils.JsonUtils;
+import org.dromara.external.api.zhongche.domain.*;
+import org.dromara.external.api.zhongche.domain.bo.AreaStockBo;
+import org.dromara.external.api.zhongche.domain.bo.*;
+import org.dromara.external.api.zhongche.domain.vo.*;
+import org.dromara.external.api.zhongche.domain.Catalog;
+import org.dromara.external.service.IExternalProductCategoryService;
+import org.dromara.external.util.SM2SignUtil;
+import org.dromara.product.api.RemoteExternalOrderService;
+import org.dromara.product.api.RemoteProductService;
+import org.dromara.product.api.domain.ProductCategoryRemoteVo;
+import org.dromara.product.api.domain.zhongche.dto.StocksResultDto;
+import org.springframework.validation.annotation.Validated;
+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.RestController;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static org.dromara.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
+
+/**
+ * author
+ * 时间:2026/1/5,19:03
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/api/mall/auth")
+public class ZhongChePushController {
+    private final String url = "";
+    private final String key = GLOBAL_REDIS_KEY+"external:zhongche:token:";
+    private final String CLIENT_ID = "ZC_CLIENT_ID";
+
+    @DubboReference
+    private final RemoteProductService remoteProductService;
+
+    @DubboReference
+    private final RemoteExternalOrderService remoteOrderService;
+
+    private final IExternalProductCategoryService externalProductCategoryService;
+
+    private final SM2SignUtil sm2SignUtil;
+
+
+
+    //TODO 登录
+    @PostMapping("/login")
+    public ZCR login(@RequestBody ZCTokenBo zcTokenBo) {
+        //业务参数
+        UserLoginBo zcUserLoginBo = new UserLoginBo();
+
+        return null;
+    }
+
+    // 获取品目列表
+    @PostMapping("/catalog/query")
+    public ZCR<String> catelogQuery(@RequestBody ZCTokenBo zcTokenBo) {
+            //TODO  1. 公共请求参数校验
+            ZCR<Void> checkResult = checkPublicParams(zcTokenBo);
+            if (!"0".equals(checkResult.getRespCode())) {
+                // 校验失败,直接返回错误响应
+                return ZCR.fail(checkResult.getRespCode(), checkResult.getRespMsg());
+            }
+            // 2.业务参数校验
+            String bizJson = Base64.decodeStr(zcTokenBo.getData(), StandardCharsets.UTF_8);
+            if (!"{}".equals(bizJson.trim())){
+                return ZCR.fail("5007", "业务参数data格式错误,需为空JSON的Base64编码");
+            }
+
+            // TODO 3. AccessToken有效性校验
+            if (!checkAccessTokenValid(zcTokenBo.getAccessToken())) {
+                return ZCR.fail("5007", "accessToken无效或已过期");
+            }
+
+            // 4. 核心业务:查询品目列表并转换为文档要求的结构
+            List<Catalog> catalogVoList = remoteProductService.queryList()
+                .stream()
+                .map(this::convertToCatalogVo)
+                .collect(Collectors.toList());
+
+            // 5. 构造响应业务参数并Base64编码(放入ZCR的data字段)
+            CatalogsVo catalogVo = new CatalogsVo();
+            catalogVo.setCatalogs(catalogVoList);
+
+            // 业务参数→JSON→Base64编码
+            String respBizJson = JSONUtil.toJsonStr(catalogVo);
+            String respDataBase64 = Base64.encode(respBizJson, StandardCharsets.UTF_8);
+
+            //TODO 6. 生成响应签名(复用你的ZCR的sign字段)
+            String respSign = "";
+
+            // 7. 封装最终响应(严格复用你的ZCR.resetR)
+            return ZCR.ok(respDataBase64,respSign);
+    }
+
+    /**
+     * 数据库实体 → 中车品目VO(ProductCategory字段)
+     */
+    private Catalog convertToCatalogVo(ProductCategoryRemoteVo category) {
+        Catalog catalog = new Catalog();
+        // 以下字段映射需根据你的实体实际字段调整
+        catalog.setId(category.getCategoryNo());          // 品目id
+        catalog.setPid(category.getParentId().toString());   // 父id
+        catalog.setName(category.getCategoryName());      // 品目名称
+        catalog.setLevel(category.getClassLevel().toString()); // 品目级次
+        catalog.setState(category.getIsShow() == 1 ? 1 : 0); // 状态:1有效 0无效
+
+        // 标准品目(仅最细级填充)
+        /*if (StrUtil.isNotBlank(category.getStandardCatalogId())) {
+            StandardCatalogVo standardVo = new StandardCatalogVo();
+            standardVo.setStandardCatalogId(category.getStandardCatalogId());
+            standardVo.setStandardCatalogName(category.getStandardCatalogName());
+            vo.setStandardCatalog(standardVo);
+        }*/
+
+        catalog.setStandardCatalog(null);
+        return catalog;
+    }
+
+
+
+
+    //查询商品的库存情况
+
+    /**
+     * 请求业务参数
+     * AreaStockBo areaStock = new AreaStockBo();
+     * Goods goods = new Goods();
+     *
+     * 响应业务参数
+     * Stocks stocks = new Stocks();
+     * @param zcTokenBo
+     * @return
+     */
+    @PostMapping("/egoods/stock/query")
+    public ZCR<String> egoodsStockQuery(@RequestBody ZCTokenBo zcTokenBo) {
+            //TODO  1. 公共请求参数校验
+            ZCR<Void> checkResult = checkPublicParams(zcTokenBo);
+            if (!"0".equals(checkResult.getRespCode())) {
+                return ZCR.fail(checkResult.getRespCode(), checkResult.getRespMsg());
+            }
+            // TODO 2. AccessToken有效性校验
+            if (!checkAccessTokenValid(zcTokenBo.getAccessToken())) {
+                return ZCR.fail("5007", "accessToken无效或已过期");
+            }
+            //  3. 业务参数解析
+            AreaStockBo areaStockBo;
+            try {
+                // 解码data字段(Base64→JSON→业务BO)
+                String decodedData = Base64.decodeStr(zcTokenBo.getData(), StandardCharsets.UTF_8);
+                areaStockBo = JSONUtil.toBean(decodedData, AreaStockBo.class);
+            } catch (Exception e) {
+                return ZCR.fail("5007", "业务参数data解析失败:" + e.getMessage());
+            }
+            //  4. 业务参数校验
+            String validateMsg = validateBizParams(areaStockBo);
+            if (StrUtil.isNotBlank(validateMsg)) {
+                return ZCR.fail("5007", validateMsg);
+            }
+            // 5.核心业务:库存查询
+            String areaId = areaStockBo.getAreaId();
+            Map<String, Integer> collect = areaStockBo.getGoods().stream()
+                .collect(Collectors.toMap(Goods::getGoodsId,
+                    Goods::getGoodsNum));
+            StocksResultDto stocksResultDto = remoteProductService.queryProductStock(collect,areaId);
+
+            // 6. 构造响应业务参数
+            // JSON→Base64编码(响应data字段值)
+            String respBizJson = JSONUtil.toJsonStr(stocksResultDto);
+            String respDataBase64 = Base64.encode(respBizJson, StandardCharsets.UTF_8);
+            // 6. 生成响应签名
+            String respSign = "";
+
+            // 7. 封装最终响应
+            return ZCR.ok(respDataBase64, respSign);
+    }
+    private String validateBizParams(AreaStockBo areaStockBo) {
+        // 1. goods列表校验
+        if (CollUtil.isEmpty(areaStockBo.getGoods())) {
+            return "商品信息goods列表不能为空";
+        }
+        if (areaStockBo.getGoods().size() > 50) {
+            return "商品信息goods列表最多支持50个商品";
+        }
+
+        // 2. 遍历校验每个商品
+        for (int i = 0; i < areaStockBo.getGoods().size(); i++) {
+            Goods goods = areaStockBo.getGoods().get(i);
+            if (StrUtil.isBlank(goods.getGoodsId())) {
+                return "第" + (i + 1) + "个商品的goodsId(商品sku)不能为空";
+            }
+            if (goods.getGoodsNum() == null || goods.getGoodsNum() <= 0) {
+                return "第" + (i + 1) + "个商品的goodsNum(所需库存)必须大于0";
+            }
+        }
+
+        //TODO 3. areaId校验(虚拟库存可不填,有地区库存则必填)
+        //
+        /*boolean isVirtualStock = false; // 假设从配置获取:是否虚拟库存
+        if (!isVirtualStock && StrUtil.isBlank(areaStockBo.getAreaId())) {
+            return "非虚拟库存模式下,地区id areaId不能为空";
+        }*/
+
+        return null; // 校验通过
+    }
+
+    //TODO 查询商品价格
+    /*
+        //请求业务参数
+        Goods goods = new Goods();
+
+        //响应业务参数
+        PricesVo pricesVo = new PricesVo();
+     */
+    @PostMapping("/egoods/price/query")
+    public ZCR<String> egoodsPriceQuery(@RequestBody ZCTokenBo zcTokenBo) {
+            //TODO  1. 公共请求参数校验
+            ZCR<Void> checkResult = checkPublicParams(zcTokenBo);
+            if (!"0".equals(checkResult.getRespCode())) {
+                return ZCR.fail(checkResult.getRespCode(), checkResult.getRespMsg());
+            }
+
+            // TODO 2. AccessToken有效性校验
+            if (!checkAccessTokenValid(zcTokenBo.getAccessToken())) {
+                return ZCR.fail("5007", "accessToken无效或已过期");
+            }
+
+            // 3. 业务参数解析
+            GoodsPrieceBo goods;
+            // 解码data字段(Base64→JSON→业务BO)
+            String decodedData = Base64.decodeStr(zcTokenBo.getData(), StandardCharsets.UTF_8);
+            goods = JSONUtil.toBean(decodedData, GoodsPrieceBo.class);
+
+            // 4. 业务参数校验
+            String validateMsg = validateGoodsPriceParams(goods);
+            if (StrUtil.isNotBlank(validateMsg)) {
+                return ZCR.fail("5007", validateMsg);
+            }
+            // 5. 查询商品价格
+            List<String> goodsIds = List.of(goods.toString().split(","));
+            List<Prices> prices = remoteProductService.queryProductPrice(goodsIds);
+
+
+            // 6. 构造响应业务参数
+            // 封装响应根对象(包含prices列表)
+            PricesVo pricesVo = new PricesVo();
+            pricesVo.setPrices(prices);
+            System.out.println(pricesVo);
+
+            // JSON→Base64编码(响应data字段值)
+            String respBizJson = JSONUtil.toJsonStr(pricesVo);
+            String respDataBase64 = Base64.encode(respBizJson, StandardCharsets.UTF_8);
+
+            //  7. 生成响应签名
+            Map<String, String> map = new HashMap<>();
+            map.put("respCode", "0");
+            map.put("data", respBizJson);
+            String respSign = JsonUtils.toJsonString(map);
+
+            //8. 封装最终响应
+            return ZCR.ok(respDataBase64, respSign);
+    }
+    /**
+     * 业务参数校验(匹配4.4.4.1文档规则)
+     */
+    private String validateGoodsPriceParams(GoodsPrieceBo goods) {
+        // 1. goodsIds非空校验
+        if (StrUtil.isBlank(goods.getGoodsIds())) {
+            return "商品sku(goodsIds)不能为空";
+        }
+
+        // 2. 拆分goodsIds并校验格式/数量
+        String[] goodsIdArray = goods.getGoodsIds().split(",");
+        if (goodsIdArray.length == 0) {
+            return "商品sku(goodsIds)格式错误,多个sku需用英文逗号分隔";
+        }
+        // 3. 校验每个sku非空
+        for (int i = 0; i < goodsIdArray.length; i++) {
+            String goodsId = goodsIdArray[i].trim();
+            if (StrUtil.isBlank(goodsId)) {
+                return "第" + (i + 1) + "个商品sku为空,请检查goodsId格式";
+            }
+        }
+        return null; // 校验通过
+    }
+
+    //TODO 4.5查询物流信息(物流信息尚未实现)
+    @PostMapping("/get/track")
+    public ZCR<TrackVo> getTrack(@RequestBody ZCTokenBo zcTokenBo) {
+        //请求业务参数
+        DeliveryTrack deliveryTrack = new DeliveryTrack();
+
+        //响应业务参数
+        TrackVo trackVo = new TrackVo();
+        DeliveryTrack deliveryTrack1 = new DeliveryTrack();
+
+        return null;
+    }
+
+    //TODO 4.6 查询电商平台订单号
+    /*
+        //请求业务参数
+        MallOrderNoQueryBo mallOrderNoQueryBo = new MallOrderNoQueryBo();
+
+        //响应业务参数
+        MallOrderNoVo mallOrderNoVo = new MallOrderNoVo();
+     */
+    @PostMapping("/get/mallOrderNo")
+    public ZCR<String> getMallOrderNo(@RequestBody ZCTokenBo zcTokenBo) {
+        //1. 公共请求参数校验
+        ZCR<Void> checkResult = checkPublicParams(zcTokenBo);
+        if (!"0".equals(checkResult.getRespCode())) {
+            return ZCR.fail(checkResult.getRespCode(), checkResult.getRespMsg());
+        }
+
+        // TODO 2. AccessToken有效性校验
+        if (!checkAccessTokenValid(zcTokenBo.getAccessToken())) {
+            return ZCR.fail("5007", "accessToken无效或已过期");
+        }
+
+        //2. 业务参数解析(Base64→JSON→BO)
+        MallOrderNoQueryBo orderNoQueryBo;
+
+        // 解码data字段(核心:Base64解码为JSON字符串)
+        String decodedData = Base64.decodeStr(zcTokenBo.getData(), StandardCharsets.UTF_8);
+        // JSON转业务BO(你已创建的MallOrderNoQueryBo)
+        orderNoQueryBo = JSONUtil.toBean(decodedData, MallOrderNoQueryBo.class);
+
+        //3. 业务参数校验
+        String validateMsg = validateOrderParams(orderNoQueryBo);
+        if (StrUtil.isNotBlank(validateMsg)) {
+            return ZCR.fail("5007", validateMsg);
+        }
+
+        //5.查询电商订单号
+        String orderNo = orderNoQueryBo.getOrderNo();
+        String mallOrderNo = remoteOrderService.getOrderNo(orderNo);
+        // 6. 构造响应业务参数
+        MallOrderNoVo orderNoVo = new MallOrderNoVo();
+        orderNoVo.setMallOrderNo(mallOrderNo);
+        // VO→JSON→Base64编码(响应的data字段值)
+        String respBizJson = JSONUtil.toJsonStr(orderNoVo);
+        String respDataBase64 = Base64.encode(respBizJson, StandardCharsets.UTF_8);
+        //7. 生成响应签名
+        String respSign = "";
+        //8. 封装最终响应
+        return ZCR.ok(respDataBase64, respSign);
+    }
+    private String validateOrderParams(MallOrderNoQueryBo orderNoQueryBo) {
+        // 1. orderNo非空校验
+        if (StrUtil.isBlank(orderNoQueryBo.getOrderNo())) {
+            return "中车电子商城订单编号(orderNo)不能为空";
+        }
+
+        // 2. orderNo长度校验(≤20)
+        if (orderNoQueryBo.getOrderNo().length() > 20) {
+            return "中车电子商城订单编号(orderNo)长度不能超过20位";
+        }
+
+        return null; // 校验通过
+    }
+
+    //TODO 4.7 查询电商平台售后单号
+    @PostMapping("/get/mallAfterSaleNo")
+    public ZCR<MallAfterSaleNoVo> getMallAfterSaleNo(@RequestBody ZCTokenBo zcTokenBo) {
+        //请求业务参数
+        MallAfterSaleNoQueryBo mallAfterSaleNoQueryBo = new MallAfterSaleNoQueryBo();
+
+        //响应业务参数
+        MallAfterSaleNoVo mallAfterSaleNoVo = new MallAfterSaleNoVo();
+
+        return null;
+    }
+
+    //TODO 4.8 消息监听     消息类型枚举没做
+    @PostMapping("/message/listening")
+    public ZCR<MessageVo> listener(@RequestBody ZCTokenBo zcTokenBo) {
+        //请求业务参数
+        MessageBo messageBo = new MessageBo();
+
+        //响应业务参数
+        MessageVo messageVo = new MessageVo();
+
+        return null;
+    }
+
+    //TODO 4.9 非必接模块接入校验
+    @PostMapping("/notRequireApi/check")
+    public ZCR<ModuleCheckVo> notRequireApiCheck(@RequestBody ZCTokenBo zcTokenBo) {
+        //请求业务参数
+        ModuleCheckBo moduleCheckBo = new ModuleCheckBo();
+
+        //响应业务参数
+        MessageVo messageVo = new MessageVo();
+
+        return null;
+    }
+
+    //TODO 4.10 	查询运费
+    @PostMapping("egoods/getfreight")
+    public ZCR<FreightVo> getFreight(@RequestBody ZCTokenBo zcTokenBo) {
+        //请求业务参数
+        AreaStockBo areaStock = new AreaStockBo();
+
+        //响应业务参数
+        FreightVo freightVo = new FreightVo();
+
+        return null;
+    }
+
+
+    /**
+     * 校验公共请求参数(基于你的ZCTokenBo)
+     */
+    private ZCR<Void> checkPublicParams(ZCTokenBo zcTokenBo) {
+        // 1. 必填项非空校验(严格按文档4.2.4)
+        if (StrUtil.isBlank(zcTokenBo.getVersion())) {
+            return ZCR.fail("5007", "接口版本version不能为空");
+        }
+        if (StrUtil.isBlank(zcTokenBo.getTimestamp())) {
+            return ZCR.fail("5007", "时间戳timestamp不能为空(格式:YYYYMMDDHHMMSS)");
+        }
+        if (StrUtil.isBlank(zcTokenBo.getClientId())) {
+            return ZCR.fail("5007", "开发者id clientId不能为空");
+        }
+        if (StrUtil.isBlank(zcTokenBo.getData())) {
+            return ZCR.fail("5007", "业务参数data不能为空");
+        }
+        if (StrUtil.isBlank(zcTokenBo.getSign())) {
+            return ZCR.fail("5007", "签名sign不能为空");
+        }
+
+        // 2. TODO 版本校验(固定1.0.0)
+        /*if (!"1.0.0".equals(zcTokenBo.getVersion())) {
+            return ZCR.fail("1008", "仅支持接口版本1.0.0");
+        }*/
+
+        // 3. 时间戳格式校验(14位)
+        if (zcTokenBo.getTimestamp().length() != 14) {
+            return ZCR.fail("5007", "时间戳格式错误,需为14位YYYYMMDDHHMMSS");
+        }
+        if (zcTokenBo.getClientId() !=CLIENT_ID){
+            return ZCR.fail("5007", "clientId错误");
+        }
+
+        // 4.TODO  签名校验(验证中车请求的签名)
+        /*try {
+            boolean signValid = sm2SignUtil.sm2Verify(
+                JSONUtil.toJsonStr(SM2SignUtil.beanToFilteredMap(zcTokenBo)).getBytes(),
+                zcTokenBo.getSign(),
+                "中车提供的公钥(16进制)" // 替换为真实公钥
+            );
+            if (!signValid) {
+                return ZCR.fail("1010", "签名验证失败");
+            }
+        } catch (Exception e) {
+            return ZCR.fail("1011", "签名校验异常:" + e.getMessage());
+        }*/
+
+        // 校验通过
+        return ZCR.ok(null);
+    }
+
+
+
+    /**
+     * 校验AccessToken有效性(替换为你的真实逻辑)
+     */
+    private boolean checkAccessTokenValid(String accessToken) {
+        // 临时占位,需替换
+        return true;
+    }
+
+
+
+    /**
+     * 生成响应签名(按中车签名规则)
+     */
+    private String generateRespSign(String respDataBase64, String clientId){
+        // 临时占位,需替换
+        return "";
+    }
+}

+ 134 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/util/SM2SignUtil.java

@@ -0,0 +1,134 @@
+package org.dromara.external.util;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import org.bouncycastle.asn1.gm.GMNamedCurves;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Signer;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ParametersWithID;
+import org.bouncycastle.crypto.signers.SM2Signer;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+import org.dromara.external.api.zhongche.domain.bo.ZCTokenBo;
+import org.springframework.stereotype.Component;
+
+import java.math.BigInteger;
+import java.security.*;
+import java.util.*;
+
+/**
+ * 中车接口SM2withSM3签名工具类
+ */
+@Component
+public class SM2SignUtil {
+    // 注册BouncyCastleProvider(国密算法提供者)
+    static {
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+    }
+
+    // SM2曲线参数(固定,国密标准)
+    private static final X9ECParameters EC_PARAMS = GMNamedCurves.getByName("sm2p256v1");
+    private static final ECDomainParameters EC_DOMAIN_PARAMETERS = new ECDomainParameters(
+            EC_PARAMS.getCurve(), EC_PARAMS.getG(), EC_PARAMS.getN());
+
+    /**
+     * 生成中车接口签名(适配ZCTokenBo参数)
+     * @param zcTokenBo 请求参数对象
+     * @param privateKeyHex 开发者私钥(16进制字符串,中车提供)
+     * @return 签名值(Base64编码后)
+     * @throws Exception 签名异常
+     */
+    public static String generateZCRSign(ZCTokenBo zcTokenBo, String privateKeyHex) throws Exception {
+        // 步骤1:将ZCTokenBo转为Map,筛选并排序参数
+        Map<String, Object> paramMap = beanToFilteredMap(zcTokenBo);
+
+        // 步骤2:拼接为待签名字符串(JSON格式)
+        String signSource = JSONUtil.toJsonStr(paramMap);
+        // 注意:JSONUtil.toJsonStr默认会按字母序排列key,刚好符合排序要求
+
+        // 步骤3:SM2withSM3签名 + Base64编码
+        byte[] signBytes = sm2Sign(signSource.getBytes("UTF-8"), privateKeyHex);
+        return Base64.encode(signBytes);
+    }
+
+    /**
+     * 将ZCTokenBo转为筛选后的Map(去sign、去null)
+     */
+    public static Map<String, Object> beanToFilteredMap(ZCTokenBo zcTokenBo) {
+        Map<String, Object> map = new HashMap<>();
+        // 逐个添加公共参数,排除sign、排除null值
+        if (StrUtil.isNotBlank(zcTokenBo.getVersion())) {
+            map.put("version", zcTokenBo.getVersion());
+        }
+        if (StrUtil.isNotBlank(zcTokenBo.getTimestamp())) {
+            map.put("timestamp", zcTokenBo.getTimestamp());
+        }
+        if (StrUtil.isNotBlank(zcTokenBo.getClientId())) {
+            map.put("clientId", zcTokenBo.getClientId());
+        }
+        if (StrUtil.isNotBlank(zcTokenBo.getAccessToken())) {
+            map.put("accessToken", zcTokenBo.getAccessToken());
+        }
+        if (StrUtil.isNotBlank(zcTokenBo.getData())) {
+            map.put("data", zcTokenBo.getData());
+        }
+        // 排除sign字段,无需添加
+
+        // 按key的ASCII码升序排序(Hutool的MapUtil会按key自然排序,符合ASCII升序)
+        return MapUtil.sort(map);
+    }
+
+    /**
+     * SM2withSM3签名(私钥16进制字符串)
+     * @param data 待签名数据(字节数组)
+     * @param privateKeyHex 私钥(16进制,中车提供)
+     * @return 签名字节数组
+     */
+    public static byte[] sm2Sign(byte[] data, String privateKeyHex) throws Exception {
+        // 1. 解析私钥(16进制转ECPrivateKeyParameters)
+        byte[] privateKeyBytes = Hex.decode(privateKeyHex);
+        ECPrivateKeyParameters privateKeyParams = new ECPrivateKeyParameters(
+                new BigInteger(1, privateKeyBytes), EC_DOMAIN_PARAMETERS);
+
+        // 2. 初始化SM2签名器
+        Signer signer = new SM2Signer();
+        // SM2默认ID为1234567812345678(若中车有指定,需替换)
+        CipherParameters params = new ParametersWithID(privateKeyParams, "1234567812345678".getBytes());
+        signer.init(true, params);
+
+        // 3. 写入数据并签名
+        signer.update(data, 0, data.length);
+        return signer.generateSignature();
+    }
+
+    // ========== 可选:验签方法(用于验证签名是否正确) ==========
+    /**
+     * SM2验签(用于测试签名是否正确)
+     * @param data 原始数据
+     * @param signBase64 签名值(Base64编码)
+     * @param publicKeyHex 公钥(16进制,中车提供)
+     * @return 是否验签通过
+     */
+    public static boolean sm2Verify(byte[] data, String signBase64, String publicKeyHex) throws Exception {
+        byte[] signBytes = Base64.decode(signBase64);
+        byte[] publicKeyBytes = Hex.decode(publicKeyHex);
+
+        // 解析公钥
+        ECPrivateKeyParameters publicKeyParams = new ECPrivateKeyParameters(
+                new BigInteger(1, publicKeyBytes), EC_DOMAIN_PARAMETERS); // 此处仅示例,实际需解析公钥
+
+        Signer signer = new SM2Signer();
+        CipherParameters params = new ParametersWithID(publicKeyParams, "1234567812345678".getBytes());
+        signer.init(false, params);
+
+        signer.update(data, 0, data.length);
+        return signer.verifySignature(signBytes);
+    }
+}