From 2b2d030165b0e5df755a76e25f99a95dc6fd82ca Mon Sep 17 00:00:00 2001 From: DaxPay Dev Date: Tue, 14 Jul 2026 18:47:27 +0800 Subject: [PATCH] =?UTF-8?q?refactor(pay):=20=E4=B8=9A=E5=8A=A1=E5=8D=95=20?= =?UTF-8?q?orderNo=20=E4=B8=8E=E8=B5=84=E9=87=91=20tradeNo=20=E5=88=86?= =?UTF-8?q?=E7=A6=BB=EF=BC=8C=E6=94=B6=E6=95=9B=E8=AE=A2=E5=8D=95=E5=AE=B9?= =?UTF-8?q?=E5=99=A8=E8=BE=B9=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 独立生成 ORD/PAY 号,默认上送 orderNo,relationOrderNo 落 trade 作反查权威 - payBody 仅落容器,trade 去掉 payBody/expiredTime - 容器新增 failed 态,失败与关单/超时区分;对外与管理端同时暴露双号 --- _config/sql/update-tables.sql | 22 +++++++ .../trade/NormalPayOrderAdminService.java | 3 +- .../strategy/pay/PayStrategyContext.java | 6 +- .../trade/enums/GatewayOrderStatusEnum.java | 2 + .../trade/enums/NormalPayOrderStatusEnum.java | 6 +- .../trade/order/convert/PayTradeConvert.java | 11 ++-- .../order/dao/NormalPayOrderManager.java | 9 ++- .../trade/order/dao/PayTradeManager.java | 7 +++ .../trade/order/entity/GatewayPayOrder.java | 11 +++- .../trade/order/entity/NormalPayOrder.java | 26 ++++---- .../payment/trade/order/entity/PayTrade.java | 17 ++---- .../order/result/NormalPayOrderResult.java | 4 ++ .../runtime/service/pay/NormalPayService.java | 14 ++--- .../runtime/service/pay/PayAssistService.java | 45 +++++++++++--- .../service/pay/PayUniHandleService.java | 61 ++++++++++++++++--- .../trade/pay/NormalPayOrderResult.java | 7 ++- .../result/trade/pay/NormalPayResult.java | 8 ++- .../service/GatewayPayHandleService.java | 19 +++--- .../convert/UnipayNormalPayOrderConvert.java | 7 ++- .../i18n/en-US/enum/gateway_order_status.json | 3 +- .../i18n/en-US/enum/normal_order_status.json | 3 +- .../i18n/id-ID/enum/gateway_order_status.json | 9 +-- .../i18n/id-ID/enum/normal_order_status.json | 7 ++- .../i18n/ja-JP/enum/gateway_order_status.json | 9 +-- .../i18n/ja-JP/enum/normal_order_status.json | 7 ++- .../i18n/ko-KR/enum/gateway_order_status.json | 11 ++-- .../i18n/ko-KR/enum/normal_order_status.json | 9 +-- .../i18n/ms-MY/enum/gateway_order_status.json | 5 +- .../i18n/ms-MY/enum/normal_order_status.json | 5 +- .../i18n/th-TH/enum/gateway_order_status.json | 11 ++-- .../i18n/th-TH/enum/normal_order_status.json | 9 +-- .../i18n/vi-VN/enum/gateway_order_status.json | 7 ++- .../i18n/vi-VN/enum/normal_order_status.json | 5 +- .../i18n/zh-CN/enum/gateway_order_status.json | 1 + .../i18n/zh-CN/enum/normal_order_status.json | 1 + .../i18n/zh-HK/enum/gateway_order_status.json | 1 + .../i18n/zh-HK/enum/normal_order_status.json | 1 + .../i18n/zh-TW/enum/gateway_order_status.json | 1 + .../i18n/zh-TW/enum/normal_order_status.json | 1 + .../core/util/TradeNoGenerateUtil.java | 10 ++- 40 files changed, 281 insertions(+), 120 deletions(-) diff --git a/_config/sql/update-tables.sql b/_config/sql/update-tables.sql index 51be403ff..5173d21fd 100644 --- a/_config/sql/update-tables.sql +++ b/_config/sql/update-tables.sql @@ -133,3 +133,25 @@ COMMENT ON COLUMN "public"."pay_gateway_order"."channel_app_id" IS '通道应用 ALTER TABLE "public"."pay_refund_order" ADD COLUMN IF NOT EXISTS "channel_app_id" varchar(128); COMMENT ON COLUMN "public"."pay_refund_order"."channel_app_id" IS '通道应用AppId(继承自原支付单)'; + +-- ---------------------------- +-- 支付订单号体系: orderNo(业务单) 与 tradeNo(资金) 分离; payBody 仅容器; trade 去掉 pay_body/expired_time +-- ---------------------------- +ALTER TABLE "public"."pay_normal_order" ADD COLUMN IF NOT EXISTS "order_no" varchar(64); +COMMENT ON COLUMN "public"."pay_normal_order"."order_no" IS '平台业务单号(与 trade_no 独立; 普通通道默认上送)'; + +ALTER TABLE "public"."pay_gateway_order" ADD COLUMN IF NOT EXISTS "pay_body" text; +COMMENT ON COLUMN "public"."pay_gateway_order"."pay_body" IS '支付参数体(已拉起缓存, 仅容器)'; +ALTER TABLE "public"."pay_gateway_order" ADD COLUMN IF NOT EXISTS "pay_body_type" varchar(32); +COMMENT ON COLUMN "public"."pay_gateway_order"."pay_body_type" IS '支付参数体类型'; + +-- 实际上送串索引(回调反查) +CREATE INDEX IF NOT EXISTS "idx_pay_trade_relation_order_no" ON "public"."pay_trade" ("relation_order_no"); +CREATE INDEX IF NOT EXISTS "idx_pay_normal_order_order_no" ON "public"."pay_normal_order" ("order_no"); + +-- trade 瘦身: pay_body / pay_body_type / expired_time 迁出或废弃(若列存在则删除) +ALTER TABLE "public"."pay_trade" DROP COLUMN IF EXISTS "pay_body"; +ALTER TABLE "public"."pay_trade" DROP COLUMN IF EXISTS "pay_body_type"; +ALTER TABLE "public"."pay_trade" DROP COLUMN IF EXISTS "expired_time"; + +COMMENT ON COLUMN "public"."pay_trade"."relation_order_no" IS '实际上送通道的商户订单号(普通=order_no, 特殊=变形号; 回调反查权威)'; diff --git a/daxpay-payment/daxpay-payment-admin/src/main/java/cn/daxpay/open/payment/admin/service/trade/NormalPayOrderAdminService.java b/daxpay-payment/daxpay-payment-admin/src/main/java/cn/daxpay/open/payment/admin/service/trade/NormalPayOrderAdminService.java index 387e85373..06dde4367 100644 --- a/daxpay-payment/daxpay-payment-admin/src/main/java/cn/daxpay/open/payment/admin/service/trade/NormalPayOrderAdminService.java +++ b/daxpay-payment/daxpay-payment-admin/src/main/java/cn/daxpay/open/payment/admin/service/trade/NormalPayOrderAdminService.java @@ -55,13 +55,12 @@ public class NormalPayOrderAdminService { NormalPayOrderResult result = NormalPayOrderConvert.CONVERT.toResult(entity); // 联表查询资金凭证, 补充交易字段 PayTrade trade = payTradeManager.findByContainerId(id, cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum.NORMAL.getCode()).orElse(null); + // payBody 仅在容器, Convert 已映射; 此处补资金凭证字段 if (Objects.nonNull(trade)) { result.setTradeNo(trade.getTradeNo()); result.setOutOrderNo(trade.getOutOrderNo()); result.setFundStatus(trade.getStatus()); result.setRefundableBalance(trade.getRefundableBalance()); - result.setPayBody(trade.getPayBody()); - result.setPayBodyType(trade.getPayBodyType()); } return result; } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/strategy/pay/PayStrategyContext.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/strategy/pay/PayStrategyContext.java index 13beb4436..2bd880a72 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/strategy/pay/PayStrategyContext.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/strategy/pay/PayStrategyContext.java @@ -1,5 +1,6 @@ package cn.daxpay.open.payment.strategy.pay; +import cn.daxpay.open.payment.trade.order.entity.NormalPayOrder; import cn.daxpay.open.payment.trade.order.entity.PayTrade; import cn.daxpay.open.payment.unipay.param.trade.pay.NormalPayParam; import lombok.Getter; @@ -8,7 +9,7 @@ import lombok.experimental.Accessors; /// # 支付策略执行上下文(请求级,显式传参) /// -/// 持有单笔支付策略管线的"资金凭证 + 通道配置 + 路由参数"三要素, +/// 持有单笔支付策略管线的"资金凭证 + 业务容器 + 通道配置 + 路由参数", /// 每次支付/同步/关闭创建新实例,显式传递,不进 ThreadLocal。 /// /// close/sync 策略直接从本类读取路由参数(channelMchNo / capability / channelAppId / clientIp), @@ -25,6 +26,9 @@ public class PayStrategyContext { /// 资金交易凭证(记录本笔资金动作的状态与通道回执) private PayTrade trade; + /// 普通支付业务容器(pay 流程查询/创建后填入; 重入读 payBody 用) + private NormalPayOrder normalOrder; + /// 普通支付请求参数(pay 流程必填;sync/close 流程可为空) private NormalPayParam payParam; diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/GatewayOrderStatusEnum.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/GatewayOrderStatusEnum.java index 68793f1ec..e5e74ea0b 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/GatewayOrderStatusEnum.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/GatewayOrderStatusEnum.java @@ -20,6 +20,8 @@ public enum GatewayOrderStatusEnum implements I18nSupport { PAYING("paying"), /// 已支付 PAID("paid"), + /// 支付失败(资金态 fail,与主动关单 closed 区分) + FAILED("failed"), /// 已关闭 CLOSED("closed"), /// 已过期 diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/NormalPayOrderStatusEnum.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/NormalPayOrderStatusEnum.java index 800923870..27fd4e0a1 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/NormalPayOrderStatusEnum.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/enums/NormalPayOrderStatusEnum.java @@ -19,9 +19,11 @@ public enum NormalPayOrderStatusEnum implements I18nSupport { WAIT_PAY("wait_pay"), /// 已支付 PAID("paid"), - /// 已关闭 + /// 支付失败(资金态 fail,与主动关单 closed 区分) + FAILED("failed"), + /// 已关闭(主动关单/撤销) CLOSED("closed"), - /// 已过期 + /// 已过期(超时关单) EXPIRED("expired"), ; diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/convert/PayTradeConvert.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/convert/PayTradeConvert.java index e7aa8cf43..438bed33b 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/convert/PayTradeConvert.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/convert/PayTradeConvert.java @@ -8,15 +8,18 @@ import org.mapstruct.factory.Mappers; /// # 支付交易转换器 /// -/// 仅从 PayTrade 映射对外支付响应;同名字段(status/bizOrderNo/payBody 等)自动映射, -/// 仅声明改名字段 +/// 仅从 PayTrade 映射部分字段; orderNo/payBody 属容器, 由 [PayAssistService#buildResult] 组装 @Mapper public interface PayTradeConvert { PayTradeConvert CONVERT = Mappers.getMapper(PayTradeConvert.class); - /// PayTrade → NormalPayResult + /// PayTrade → NormalPayResult(不含 orderNo/payBody, 需配合容器) @Mapping(target = "orderId", source = "id") - @Mapping(target = "orderNo", source = "tradeNo") + @Mapping(target = "tradeNo", source = "tradeNo") + @Mapping(target = "orderNo", ignore = true) + @Mapping(target = "bizOrderNo", ignore = true) + @Mapping(target = "payBody", ignore = true) + @Mapping(target = "payBodyType", ignore = true) NormalPayResult toResult(PayTrade trade); } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/NormalPayOrderManager.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/NormalPayOrderManager.java index 177175382..a1a1b7b9e 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/NormalPayOrderManager.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/NormalPayOrderManager.java @@ -17,6 +17,13 @@ import java.util.Optional; @Repository public class NormalPayOrderManager extends BaseManager { + /// 根据平台业务单号查询(按商户号自动租户隔离) + public Optional findByOrderNo(String orderNo) { + return lambdaQuery() + .eq(NormalPayOrder::getOrderNo, orderNo) + .oneOpt(); + } + /// 根据业务单号查询(按商户号自动租户隔离) public Optional findByBizOrderNo(String bizOrderNo) { return lambdaQuery() @@ -24,7 +31,7 @@ public class NormalPayOrderManager extends BaseManager findByBizOrderNo(String bizOrderNo, String appId) { return lambdaQuery() .eq(NormalPayOrder::getBizOrderNo, bizOrderNo) diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/PayTradeManager.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/PayTradeManager.java index 3a3771d1f..5838b1777 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/PayTradeManager.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/dao/PayTradeManager.java @@ -42,6 +42,13 @@ public class PayTradeManager extends BaseManager { .oneOpt(); } + /// 根据实际上送串(relationOrderNo/submitNo)反查 + public Optional findByRelationOrderNo(String relationOrderNo) { + return lambdaQuery() + .eq(PayTrade::getRelationOrderNo, relationOrderNo) + .oneOpt(); + } + /// 根据容器ID查询(按商户号自动租户隔离) public Optional findByContainerId(Long containerId) { return lambdaQuery() diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/GatewayPayOrder.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/GatewayPayOrder.java index cbeacaf3d..749c25011 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/GatewayPayOrder.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/GatewayPayOrder.java @@ -23,13 +23,14 @@ import java.util.List; /// 业务容器统一落在 trade.order(与 NormalPayOrder 同包)。 /// 聚合扫码/收银台预下单场景: 创建时不知具体通道, 仅承载收款意图。 /// 用户真正支付时再创建 pay_trade(trade_type=gateway) 并回填 channel/product/method。 +/// 网关 orderNo 为预下单 URL 号, 与资金 tradeNo 身份分离。 @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) @TableName(value = "pay_gateway_order", autoResultMap = true) public class GatewayPayOrder extends MchBaseEntity { - /// 平台网关单号(URL 用) + /// 平台网关业务单号(URL 用, 预下单即生成, 可无 trade) private String orderNo; /// 商户业务单号 @@ -140,12 +141,18 @@ public class GatewayPayOrder extends MchBaseEntity { /// 活动类型 private String promotionType; + /// 支付参数体(已拉起缓存,仅落容器) + private String payBody; + + /// 支付参数体类型 + private String payBodyType; + // ===== 通道关联订单号(部分通道专用)===== /// 透传订单号(三方通道产生的透传订单号) private String transOrderNo; - /// 特殊通道关联订单号(部分通道订单号有前缀/长度限制时使用) + /// 实际上送通道的商户订单号(展示冗余;反查权威在 pay_trade.relation_order_no) private String relationOrderNo; diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/NormalPayOrder.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/NormalPayOrder.java index 741b4de46..90bd312b7 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/NormalPayOrder.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/NormalPayOrder.java @@ -21,14 +21,17 @@ import java.util.List; /// /// 业务容器统一落在 trade.order(与 GatewayPayOrder 等同包,纯持久化无编排 service)。 /// 普通支付场景的容器,承载商户业务单信息(bizOrderNo / 商品标题 / 回调地址 等) -/// 与 pay_trade 一对一关联(trade_type = normal) -/// 冗余存储金额/支付/时间线字段,便于后台查询无需 JOIN pay_trade +/// 与 pay_trade 一对一关联(trade_type = normal,当前实现;模型上 orderNo 与 tradeNo 身份分离)。 +/// 冗余存储金额/支付/时间线字段,便于后台查询无需 JOIN pay_trade。 @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) @TableName(value = "pay_normal_order", autoResultMap = true) public class NormalPayOrder extends MchBaseEntity { + /// 平台业务单号(容器身份,与 tradeNo 独立生成;普通通道默认作为上送号) + private String orderNo; + /// 商户业务单号 private String bizOrderNo; @@ -51,7 +54,7 @@ public class NormalPayOrder extends MchBaseEntity { /// 商户附加参数(回调原样返回) private String attach; - /// 业务单过期时间 + /// 业务单过期时间(超时关单权威,不落 pay_trade) private OffsetDateTime expiredTime; // ===== 金额(冗余自 PayTrade,方便查询)===== @@ -81,12 +84,12 @@ public class NormalPayOrder extends MchBaseEntity { /// @see ProductEnum private String product; - // ===== 支付请求参数(下单时写入)===== + // ===== 支付请求参数(下单时写入,审计保留)===== /// 微信 openid(jsapi/app/miniapp) private String openid; - /// 付款码(被扫支付) + /// 付款码(被扫支付,终态后仍保留供审计) private String barCode; // ===== 时间线(冗余,查询展示用)===== @@ -115,7 +118,7 @@ public class NormalPayOrder extends MchBaseEntity { /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayProviderEnum private String provider; - /// 付款用户 ID(支付宝 userID/微信AppId 等) + /// 付款用户标识(支付宝 user_id、微信 openid 等,非通道 AppId) private String buyerId; /// 通道方记录的支付产品 @@ -130,22 +133,19 @@ public class NormalPayOrder extends MchBaseEntity { /// 活动类型 private String promotionType; - /// 支付参数体(如微信 prepay_id 组装串,非空表示已拉起支付,免重复请求通道) + /// 支付参数体(如微信 prepay_id 组装串,非空表示已拉起支付,免重复请求通道;仅落容器) private String payBody; /// 支付参数体类型(jsapi/sdk/app) private String payBodyType; - // ===== 关联订单号===== - - /// 订单号 通常上送给支付通道使用, 特殊情况下会上送[#relationOrderNo] - private String orderNo; + // ===== 关联订单号 ===== /// 透传订单号(三方通道产生的透传订单号) private String transOrderNo; - /// 特殊通道关联订单号(部分通道订单号有前缀/长度限制时使用) - /// 如果没有特殊情况, 直接使用交易订单号作为关联订单号, 通常 + /// 实际上送通道的商户订单号(展示冗余;反查权威在 pay_trade.relation_order_no) + /// 普通通道与 orderNo 一致;特殊通道为变形号 private String relationOrderNo; // ===== 请求信息(关单/同步/退款透传依赖 + 审计)===== diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/PayTrade.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/PayTrade.java index 3a2fb3a83..5d2175886 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/PayTrade.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/entity/PayTrade.java @@ -16,14 +16,15 @@ import java.time.OffsetDateTime; /// /// 统一资金交易表,记录每一笔资金动作(普通支付/预授权冻结/预授权捕获/周期代扣/合单子单) /// 与容器层(业务单/协议)分离,通过 trade_type + 容器关联字段建立联系。 -/// 仅保留资金动作固有属性与通道调用命脉字段;业务上下文/路由参数/通道回执统一归容器。 +/// 仅保留资金动作固有属性与通道反查命脉字段;业务上下文/路由/payBody/回执统一归容器。 +/// 过期时间只在容器,本表不存 expiredTime。 @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) @TableName("pay_trade") public class PayTrade extends MchBaseEntity { - /// 支付交易号(各种交易的) + /// 资金交易号(平台生成,与业务单 orderNo 独立) private String tradeNo; /// 交易形态 @@ -59,22 +60,14 @@ public class PayTrade extends MchBaseEntity { /// 关闭时间 private OffsetDateTime closeTime; - /// 超时时间 - private OffsetDateTime expiredTime; - /// 订单来源 private String source; /// 通道订单号(三方通道返回的订单号,通道 close/sync 调用参数 + 回调反查索引) private String outOrderNo; - /// 支付参数体(如微信 prepay_id 组装串,非空表示已拉起支付,免重复请求通道) - private String payBody; - - /// 支付参数体类型(jsapi/sdk/app) - private String payBodyType; - - /// 特殊通道关联订单号(部分通道订单号有前缀/长度限制时使用) + /// 实际上送通道的商户订单号(回调/关退同步反查权威) + /// 普通通道 = 容器 orderNo;特殊通道(前缀/长度限制)= 变形号,可与 orderNo 不同 private String relationOrderNo; /// 应用号 diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/result/NormalPayOrderResult.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/result/NormalPayOrderResult.java index ec4d7dbb7..c6538bb05 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/result/NormalPayOrderResult.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/order/result/NormalPayOrderResult.java @@ -28,6 +28,10 @@ public class NormalPayOrderResult extends BaseResult { @Schema(description = "应用号") private String appId; + /// 平台业务单号 + @Schema(description = "平台业务单号") + private String orderNo; + /// 商户业务单号 @Schema(description = "商户业务单号") private String bizOrderNo; diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/NormalPayService.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/NormalPayService.java index b67cbbe63..796c82f80 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/NormalPayService.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/NormalPayService.java @@ -76,9 +76,11 @@ public class NormalPayService { payStrategy.doBeforePay(context); // 查询已有订单并校验,结果填充到 context payAssistService.findAndCheckOrder(payParam.getBizOrderNo(), context); - // 已拉起支付则返回缓存的支付参数 - if (Objects.nonNull(context.getTrade()) && StrUtil.isNotBlank(context.getTrade().getPayBody())) { - return payAssistService.buildResult(context.getTrade()); + // 已拉起支付则返回缓存的支付参数(payBody 仅在容器) + if (Objects.nonNull(context.getNormalOrder()) + && StrUtil.isNotBlank(context.getNormalOrder().getPayBody()) + && Objects.nonNull(context.getTrade())) { + return payAssistService.buildResult(context.getTrade(), context.getNormalOrder()); } // 订单不存在则新建(填充 context) if (Objects.isNull(context.getTrade())) { @@ -122,11 +124,7 @@ public class NormalPayService { } // trade.status 在 complete=false 时保持 PROCESSING(createOrder 时已设) trade.setOutOrderNo(result.getOutOrderNo()); - // payBody/payBodyType 留 trade(已拉起缓存标记) - trade.setPayBody(result.getPayBody()); - trade.setPayBodyType(Objects.nonNull(result.getPayBodyType()) - ? result.getPayBodyType().getCode() : null); - // 回执字段写容器, 由 payAfterHandel 统一处理 + // 回执与 payBody 写容器, 由 payAfterHandel 统一处理 payUniHandleService.payAfterHandel(trade, result); return payAssistService.buildResult(trade); } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayAssistService.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayAssistService.java index b51ffafc4..ce4a92821 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayAssistService.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayAssistService.java @@ -13,7 +13,6 @@ import cn.daxpay.open.payment.trade.enums.PayFundStatusEnum; import cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum; import cn.daxpay.open.payment.common.util.PayUtil; import cn.daxpay.open.payment.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.trade.order.convert.PayTradeConvert; import cn.daxpay.open.payment.trade.order.dao.NormalPayOrderManager; import cn.daxpay.open.payment.trade.order.entity.NormalPayOrder; import cn.daxpay.open.payment.trade.order.dao.PayTradeManager; @@ -22,7 +21,6 @@ import cn.daxpay.open.payment.trade.runtime.mq.NormalPayTimeoutMessage; import cn.daxpay.open.payment.trade.runtime.mq.PayArtemisConstants; import cn.daxpay.open.payment.unipay.param.trade.pay.NormalPayParam; import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPayResult; -import cn.hutool.core.util.StrUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -46,6 +44,7 @@ public class PayAssistService { /// 创建支付订单(容器 + 资金交易),填充到 context /// 调用方需保证 appId 和 product 已解析完毕 + /// orderNo 与 tradeNo 独立生成; 普通通道实际上送串 relationOrderNo 默认=orderNo @Transactional(rollbackFor = Exception.class) public void createOrder(NormalPayParam payParam, PayStrategyContext context) { String appId = payParam.getAppId(); @@ -56,8 +55,14 @@ public class PayAssistService { var channel = productEnum.getChannel(); // 终端信息 String terminalNo = payParam.getTerminal() != null ? payParam.getTerminal().getTerminalNo() : null; + // 双号独立生成 + String orderNo = TradeNoGenerateUtil.order(); + String tradeNo = TradeNoGenerateUtil.pay(); // 创建容器 NormalPayOrder(含冗余字段,方便查询) NormalPayOrder normalOrder = new NormalPayOrder(); + normalOrder.setOrderNo(orderNo); + // 普通通道默认上送 orderNo, 特殊通道下单后再覆盖 relation + normalOrder.setRelationOrderNo(orderNo); normalOrder.setBizOrderNo(payParam.getBizOrderNo()); normalOrder.setTitle(payParam.getTitle()); normalOrder.setDescription(payParam.getDescription()); @@ -90,7 +95,7 @@ public class PayAssistService { // 创建资金交易 PayTrade PayTrade trade = new PayTrade(); trade.setAppId(appId); - trade.setTradeNo(TradeNoGenerateUtil.pay()); + trade.setTradeNo(tradeNo); trade.setTradeType(PayTradeTypeEnum.NORMAL.getCode()); trade.setContainerId(normalOrder.getId()); trade.setAmount(amount); @@ -99,9 +104,12 @@ public class PayAssistService { trade.setPostedAmount(0L); trade.setRefundableBalance(amount); trade.setStatus(PayFundStatusEnum.PROCESSING.getCode()); + // 实际上送串权威: 默认=orderNo, 特殊通道支付返回后可覆盖 + trade.setRelationOrderNo(orderNo); trade.setSource(cn.daxpay.open.platform.core.enums.pay.trade.TradeSourceEnum.MCH_API.getCode()); payTradeManager.save(trade); context.setTrade(trade); + context.setNormalOrder(normalOrder); // 注册超时关单延时消息(按订单过期时间定时投递) this.registerTimeoutClose(trade.getTradeNo(), normalOrder.getBizOrderNo(), expiredTime); } @@ -136,6 +144,7 @@ public class PayAssistService { } this.checkOrder(normalOrder, trade); context.setTrade(trade); + context.setNormalOrder(normalOrder); } /// 检查订单状态 @@ -146,7 +155,8 @@ public class PayAssistService { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.alreadySuccess"); } if (Objects.equals(bizStatus, NormalPayOrderStatusEnum.CLOSED.getCode()) - || Objects.equals(bizStatus, NormalPayOrderStatusEnum.EXPIRED.getCode())) { + || Objects.equals(bizStatus, NormalPayOrderStatusEnum.EXPIRED.getCode()) + || Objects.equals(bizStatus, NormalPayOrderStatusEnum.FAILED.getCode())) { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.failedOrClosed"); } // 资金状态检查 @@ -155,7 +165,8 @@ public class PayAssistService { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.alreadySuccess"); } if (Objects.equals(fundStatus, PayFundStatusEnum.CLOSE.getCode()) - || Objects.equals(fundStatus, PayFundStatusEnum.FAIL.getCode())) { + || Objects.equals(fundStatus, PayFundStatusEnum.FAIL.getCode()) + || Objects.equals(fundStatus, PayFundStatusEnum.CANCEL.getCode())) { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.failedOrClosed"); } // 超时检查 @@ -165,9 +176,29 @@ public class PayAssistService { } } - /// 根据 PayTrade 构建支付结果 + /// 根据 PayTrade + 容器构建支付结果(orderNo/payBody 取自容器) public NormalPayResult buildResult(PayTrade trade) { - return PayTradeConvert.CONVERT.toResult(trade); + NormalPayOrder order = null; + if (trade.getContainerId() != null) { + order = payNormalOrderManager.findById(trade.getContainerId()).orElse(null); + } + return buildResult(trade, order); + } + + /// 根据资金凭证与业务容器构建支付结果 + public NormalPayResult buildResult(PayTrade trade, NormalPayOrder order) { + NormalPayResult result = new NormalPayResult(); + result.setOrderId(order != null ? order.getId() : trade.getContainerId()); + result.setBizOrderNo(order != null ? order.getBizOrderNo() : null); + // 业务单号与资金交易号分离暴露 + result.setOrderNo(order != null ? order.getOrderNo() : null); + result.setTradeNo(trade.getTradeNo()); + result.setStatus(trade.getStatus()); + if (order != null) { + result.setPayBody(order.getPayBody()); + result.setPayBodyType(order.getPayBodyType()); + } + return result; } /// 获取支付超时时间 diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayUniHandleService.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayUniHandleService.java index c7a06ab04..000254aa0 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayUniHandleService.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/PayUniHandleService.java @@ -24,7 +24,7 @@ import java.util.Objects; /// # 交易统一处理服务 /// /// 支付成功/失败/关闭后的统一处理逻辑, 按 trade_type 回写对应业务容器。 -/// 通道回执字段(含 payBody)统一写容器, trade 仅保留资金态与 outOrderNo 等。 +/// 通道回执字段(含 payBody)统一写容器; trade 仅资金态、outOrderNo、relationOrderNo(实际上送串)。 @Slf4j @Service @RequiredArgsConstructor @@ -36,8 +36,12 @@ public class PayUniHandleService { /// 支付发起后处理 /// 不论是否完成都更新交易单; 仅资金状态为 SUCCESS 时同步容器为 PAID。 - /// 回执字段(transOrderNo/buyerId 等)写容器。 + /// 回执字段(transOrderNo/buyerId/payBody 等)写容器; 特殊 relation 同步写 trade。 public void payAfterHandel(PayTrade trade, PayTradeResultBo result) { + // 特殊通道返回的上送变形号写 trade 反查权威 + if (result.getRelationOrderNo() != null) { + trade.setRelationOrderNo(result.getRelationOrderNo()); + } // 按 status/tradeType 回写入账金额后再落库 updateTradeWithPosted(trade); if (isGateway(trade)) { @@ -91,13 +95,13 @@ public class PayUniHandleService { markContainerPaid(trade); } - /// 支付失败处理 + /// 支付失败处理: 资金态 FAIL, 容器态 FAILED(与主动关单 closed 区分) public void payFail(PayTrade trade, String errMsg) { OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); trade.setStatus(PayFundStatusEnum.FAIL.getCode()); trade.setCloseTime(now); updateTradeWithPosted(trade); - this.markContainerClosed(trade, now, false, errMsg); + this.markContainerFailed(trade, now, errMsg); } /// 支付关闭处理 @@ -161,6 +165,28 @@ public class PayUniHandleService { } } + /// 支付失败: 容器 FAILED + private void markContainerFailed(PayTrade trade, OffsetDateTime now, String errMsg) { + String msg = truncateErrorMsg(errMsg); + if (isGateway(trade)) { + GatewayPayOrder order = gatewayPayOrderManager.findById(trade.getContainerId()).orElse(null); + if (order != null) { + order.setStatus(GatewayOrderStatusEnum.FAILED.getCode()); + order.setCloseTime(now); + order.setErrorMsg(msg); + gatewayPayOrderManager.updateById(order); + } + return; + } + NormalPayOrder normalOrder = payNormalOrderManager.findById(trade.getContainerId()).orElse(null); + if (normalOrder != null) { + normalOrder.setStatus(NormalPayOrderStatusEnum.FAILED.getCode()); + normalOrder.setCloseTime(now); + normalOrder.setErrorMsg(msg); + payNormalOrderManager.updateById(normalOrder); + } + } + private void markContainerClosed(PayTrade trade, OffsetDateTime now, boolean expired, String errMsg) { if (isGateway(trade)) { GatewayPayOrder order = gatewayPayOrderManager.findById(trade.getContainerId()).orElse(null); @@ -170,7 +196,7 @@ public class PayUniHandleService { : GatewayOrderStatusEnum.CLOSED.getCode()); order.setCloseTime(now); if (errMsg != null) { - order.setErrorMsg(errMsg); + order.setErrorMsg(truncateErrorMsg(errMsg)); } gatewayPayOrderManager.updateById(order); } @@ -183,21 +209,32 @@ public class PayUniHandleService { : NormalPayOrderStatusEnum.CLOSED.getCode()); normalOrder.setCloseTime(now); if (errMsg != null) { - normalOrder.setErrorMsg(errMsg); + normalOrder.setErrorMsg(truncateErrorMsg(errMsg)); } payNormalOrderManager.updateById(normalOrder); } } + /// 错误信息截断, 避免通道超长报文撑爆列 + private static String truncateErrorMsg(String errMsg) { + if (errMsg == null) { + return null; + } + return errMsg.length() <= 500 ? errMsg : errMsg.substring(0, 500); + } + private void applyNormalReceipts(NormalPayOrder order, PayTradeResultBo result) { order.setTransOrderNo(result.getTransOrderNo()); - order.setRelationOrderNo(result.getRelationOrderNo()); + // 特殊通道返回变形上送号时回写容器展示; 空则保留创建时的 orderNo 副本 + if (result.getRelationOrderNo() != null) { + order.setRelationOrderNo(result.getRelationOrderNo()); + } order.setBuyerId(result.getBuyerId()); order.setTradeProduct(result.getTradeProduct()); order.setTradeWay(result.getTradeWay()); order.setBankType(result.getBankType()); order.setPromotionType(result.getPromotionType()); - // 支付参数体落容器, 作为已拉起缓存标记 + // 支付参数体仅落容器, 作为已拉起缓存标记 order.setPayBody(result.getPayBody()); order.setPayBodyType(Objects.nonNull(result.getPayBodyType()) ? result.getPayBodyType().getCode() : null); @@ -206,12 +243,18 @@ public class PayUniHandleService { private void applyGatewayReceipts(GatewayPayOrder order, PayTradeResultBo result) { order.setTransOrderNo(result.getTransOrderNo()); - order.setRelationOrderNo(result.getRelationOrderNo()); + if (result.getRelationOrderNo() != null) { + order.setRelationOrderNo(result.getRelationOrderNo()); + } order.setBuyerId(result.getBuyerId()); order.setTradeProduct(result.getTradeProduct()); order.setTradeWay(result.getTradeWay()); order.setBankType(result.getBankType()); order.setPromotionType(result.getPromotionType()); + // 支付参数体仅落容器 + order.setPayBody(result.getPayBody()); + order.setPayBodyType(Objects.nonNull(result.getPayBodyType()) + ? result.getPayBodyType().getCode() : null); order.setErrorMsg(null); } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayOrderResult.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayOrderResult.java index 5c738d249..3c505d71b 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayOrderResult.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayOrderResult.java @@ -22,9 +22,14 @@ public class NormalPayOrderResult { @Schema(description = "商户订单号") private String bizOrderNo; - @Schema(description = "支付订单号") + /// 平台业务单号(容器 orderNo) + @Schema(description = "平台业务单号") private String orderNo; + /// 资金交易号(tradeNo) + @Schema(description = "资金交易号") + private String tradeNo; + /// 通道系统交易号 @Schema(description = "通道支付订单号") private String outOrderNo; diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayResult.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayResult.java index 867cff5fd..6e7e02877 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayResult.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/result/trade/pay/NormalPayResult.java @@ -20,10 +20,14 @@ public class NormalPayResult { @Schema(description = "商户订单号") private String bizOrderNo; - /// 订单号 - @Schema(description = "订单号") + /// 平台业务单号(容器 orderNo) + @Schema(description = "平台业务单号") private String orderNo; + /// 资金交易号(tradeNo, 与 orderNo 独立) + @Schema(description = "资金交易号") + private String tradeNo; + /// 支付状态 @Schema(description = "支付状态") private String status; diff --git a/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/gateway/service/GatewayPayHandleService.java b/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/gateway/service/GatewayPayHandleService.java index 620c03e09..d1dee6c82 100644 --- a/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/gateway/service/GatewayPayHandleService.java +++ b/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/gateway/service/GatewayPayHandleService.java @@ -84,7 +84,8 @@ public class GatewayPayHandleService { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.gateway.channelLocked"); } - if (StrUtil.isNotBlank(existing.getPayBody())) { + // payBody 仅在容器, 已拉起则幂等返回 + if (StrUtil.isNotBlank(order.getPayBody())) { return this.buildResult(order, existing); } } else { @@ -144,6 +145,8 @@ public class GatewayPayHandleService { trade.setPostedAmount(0L); trade.setRefundableBalance(order.getAmount()); trade.setStatus(PayFundStatusEnum.PROCESSING.getCode()); + // 默认上送网关业务单号; 特殊通道返回后可覆盖 + trade.setRelationOrderNo(order.getOrderNo()); trade.setSource(TradeSourceEnum.AGGRESS_PAY.getCode()); payTradeManager.save(trade); @@ -167,11 +170,7 @@ public class GatewayPayHandleService { trade.setPayTime(result.getFinishTime()); } trade.setOutOrderNo(result.getOutOrderNo()); - // payBody/payBodyType 留 trade(已拉起缓存标记) - trade.setPayBody(result.getPayBody()); - trade.setPayBodyType(Objects.nonNull(result.getPayBodyType()) - ? result.getPayBodyType().getCode() : null); - // 回执字段写容器, 由 payAfterHandel 统一处理 + // 回执与 payBody 写容器, 由 payAfterHandel 统一处理 payUniHandleService.payAfterHandel(trade, result); return this.buildResult(order, trade); } @@ -222,9 +221,11 @@ public class GatewayPayHandleService { return new NormalPayResult() .setOrderId(order.getId()) .setBizOrderNo(order.getBizOrderNo()) - .setOrderNo(trade.getTradeNo()) + // 网关业务单号 vs 资金交易号分离 + .setOrderNo(order.getOrderNo()) + .setTradeNo(trade.getTradeNo()) .setStatus(trade.getStatus()) - .setPayBody(trade.getPayBody()) - .setPayBodyType(trade.getPayBodyType()); + .setPayBody(order.getPayBody()) + .setPayBodyType(order.getPayBodyType()); } } diff --git a/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/trade/convert/UnipayNormalPayOrderConvert.java b/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/trade/convert/UnipayNormalPayOrderConvert.java index 66bd7dcfd..f1a46aa12 100644 --- a/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/trade/convert/UnipayNormalPayOrderConvert.java +++ b/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/trade/convert/UnipayNormalPayOrderConvert.java @@ -19,10 +19,13 @@ public interface UnipayNormalPayOrderConvert { UnipayNormalPayOrderConvert CONVERT = Mappers.getMapper(UnipayNormalPayOrderConvert.class); /// NormalPayOrder + PayTrade → 对外 NormalPayOrderResult - // 改名 - @Mapping(target = "orderNo", source = "trade.tradeNo") + // 业务单号取容器, 资金交易号取 trade + @Mapping(target = "orderNo", source = "order.orderNo") + @Mapping(target = "tradeNo", source = "trade.tradeNo") // 多源同名消歧:资金态取 trade,业务容器取 order @Mapping(target = "status", source = "trade.status") + @Mapping(target = "outOrderNo", source = "trade.outOrderNo") + @Mapping(target = "refundableBalance", source = "trade.refundableBalance") @Mapping(target = "bizOrderNo", source = "order.bizOrderNo") @Mapping(target = "channel", source = "order.channel") @Mapping(target = "method", source = "order.method") diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/gateway_order_status.json index 0c4848e41..613ac35c7 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "Wait Pay", + "wait_pay": "Pending payment", "paying": "Paying", "paid": "Paid", + "failed": "Failed", "closed": "Closed", "expired": "Expired" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/normal_order_status.json index 87520f8da..e0a431ef8 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "Pending", + "wait_pay": "Pending payment", "paid": "Paid", + "failed": "Failed", "closed": "Closed", "expired": "Expired" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/gateway_order_status.json index db4e88ec4..ef760435e 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "Tunggu Bayar", - "paying": "Pembayaran", - "paid": "Dibayar", - "closed": "Tertutup", + "wait_pay": "Menunggu bayar", + "paying": "Membayar", + "paid": "Lunas", + "failed": "Gagal", + "closed": "Ditutup", "expired": "Kedaluwarsa" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/normal_order_status.json index a36137ea7..9f4b69e31 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/id-ID/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "Tertunda", - "paid": "Dibayar", - "closed": "Tertutup", + "wait_pay": "Menunggu bayar", + "paid": "Lunas", + "failed": "Gagal", + "closed": "Ditutup", "expired": "Kedaluwarsa" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/gateway_order_status.json index 33241ba15..bca1a48a6 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "支払いを待つ", - "paying": "支払い中", - "paid": "有料", - "closed": "閉店", + "wait_pay": "支払待ち", + "paying": "支払中", + "paid": "支払済", + "failed": "支払失敗", + "closed": "クローズ", "expired": "期限切れ" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/normal_order_status.json index b36ca8909..72b5f9149 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ja-JP/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "保留中", - "paid": "有料", - "closed": "閉店", + "wait_pay": "支払待ち", + "paid": "支払済", + "failed": "支払失敗", + "closed": "クローズ", "expired": "期限切れ" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/gateway_order_status.json index 2d5b2fe70..42c2ac334 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "기다려 지불", - "paying": "지불 중", - "paid": "유급의", - "closed": "닫은", - "expired": "만료됨" + "wait_pay": "결제 대기", + "paying": "결제 중", + "paid": "결제 완료", + "failed": "결제 실패", + "closed": "종료", + "expired": "만료" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/normal_order_status.json index 2f816ce7e..3bc5353cf 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ko-KR/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "보류 중", - "paid": "유급의", - "closed": "닫은", - "expired": "만료됨" + "wait_pay": "결제 대기", + "paid": "결제 완료", + "failed": "결제 실패", + "closed": "종료", + "expired": "만료" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/gateway_order_status.json index d987af4ab..31e6af37f 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "Tunggu Bayar", + "wait_pay": "Menunggu bayar", "paying": "Membayar", "paid": "Dibayar", - "closed": "tertutup", + "failed": "Gagal", + "closed": "Ditutup", "expired": "Tamat tempoh" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/normal_order_status.json index 6331d141d..ee199ea63 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/ms-MY/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "Belum selesai", + "wait_pay": "Menunggu bayar", "paid": "Dibayar", - "closed": "tertutup", + "failed": "Gagal", + "closed": "Ditutup", "expired": "Tamat tempoh" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/gateway_order_status.json index 56ac45f70..45929994b 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "รอจ่ายเงิน", - "paying": "การจ่ายเงิน", - "paid": "จ่าย", - "closed": "ปิด", - "expired": "หมดอายุแล้ว" + "wait_pay": "รอชำระ", + "paying": "กำลังชำระ", + "paid": "ชำระแล้ว", + "failed": "ล้มเหลว", + "closed": "ปิดแล้ว", + "expired": "หมดอายุ" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/normal_order_status.json index 7d67eb99f..fdfbcc811 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/th-TH/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "รอดำเนินการ", - "paid": "จ่าย", - "closed": "ปิด", - "expired": "หมดอายุแล้ว" + "wait_pay": "รอชำระ", + "paid": "ชำระแล้ว", + "failed": "ล้มเหลว", + "closed": "ปิดแล้ว", + "expired": "หมดอายุ" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/gateway_order_status.json index 4dca25971..9a2c1acd3 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/gateway_order_status.json @@ -1,7 +1,8 @@ { - "wait_pay": "Chờ trả tiền", - "paying": "Thanh toán", - "paid": "Trả", + "wait_pay": "Chờ thanh toán", + "paying": "Đang thanh toán", + "paid": "Đã thanh toán", + "failed": "Thất bại", "closed": "Đã đóng", "expired": "Hết hạn" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/normal_order_status.json index d8efd4d23..0676962bc 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/vi-VN/enum/normal_order_status.json @@ -1,6 +1,7 @@ { - "wait_pay": "Chưa giải quyết", - "paid": "Trả", + "wait_pay": "Chờ thanh toán", + "paid": "Đã thanh toán", + "failed": "Thất bại", "closed": "Đã đóng", "expired": "Hết hạn" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/gateway_order_status.json index 5bbf1c68c..bad164b03 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/gateway_order_status.json @@ -2,6 +2,7 @@ "wait_pay": "待支付", "paying": "支付中", "paid": "已支付", + "failed": "支付失败", "closed": "已关闭", "expired": "已过期" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/normal_order_status.json index ce170154e..5deb52e08 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/normal_order_status.json @@ -1,6 +1,7 @@ { "wait_pay": "待支付", "paid": "已支付", + "failed": "支付失败", "closed": "已关闭", "expired": "已过期" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/gateway_order_status.json index 21c0c1904..00971fd69 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/gateway_order_status.json @@ -2,6 +2,7 @@ "wait_pay": "待支付", "paying": "支付中", "paid": "已支付", + "failed": "支付失敗", "closed": "已關閉", "expired": "已過期" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/normal_order_status.json index 2a77906bb..4a046b39c 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-HK/enum/normal_order_status.json @@ -1,6 +1,7 @@ { "wait_pay": "待支付", "paid": "已支付", + "failed": "支付失敗", "closed": "已關閉", "expired": "已過期" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/gateway_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/gateway_order_status.json index 21c0c1904..00971fd69 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/gateway_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/gateway_order_status.json @@ -2,6 +2,7 @@ "wait_pay": "待支付", "paying": "支付中", "paid": "已支付", + "failed": "支付失敗", "closed": "已關閉", "expired": "已過期" } diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/normal_order_status.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/normal_order_status.json index 2a77906bb..4a046b39c 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/normal_order_status.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-TW/enum/normal_order_status.json @@ -1,6 +1,7 @@ { "wait_pay": "待支付", "paid": "已支付", + "failed": "支付失敗", "closed": "已關閉", "expired": "已過期" } diff --git a/daxpay-platform/daxpay-platform-core/src/main/java/cn/daxpay/open/platform/core/util/TradeNoGenerateUtil.java b/daxpay-platform/daxpay-platform-core/src/main/java/cn/daxpay/open/platform/core/util/TradeNoGenerateUtil.java index 02803f74d..5271cbe90 100644 --- a/daxpay-platform/daxpay-platform-core/src/main/java/cn/daxpay/open/platform/core/util/TradeNoGenerateUtil.java +++ b/daxpay-platform/daxpay-platform-core/src/main/java/cn/daxpay/open/platform/core/util/TradeNoGenerateUtil.java @@ -6,14 +6,20 @@ import lombok.Setter; /// # 各类型订单号生成工具类 /// /// 格式: {环境前缀}{3字母类型}{雪花ID}, 例如 PRODPAY1872635419283456 -/// 类型使用3字母缩写: PAY(支付) REF(退款) +/// 类型使用3字母缩写: ORD(业务单) PAY(资金交易) REF(退款) +/// orderNo 与 tradeNo 独立生成, 禁止混用 @Setter public final class TradeNoGenerateUtil { /// 环境前缀, 例如 PROD / DEV 等, 为空时不追加 private static String env; - /// 生成支付订单号 + /// 生成平台业务单号(orderNo, 容器维度, 默认上送通道) + public static String order() { + return prefix() + "ORD" + IdUtil.getSnowflakeNextId(); + } + + /// 生成资金交易号(tradeNo, 资金动作维度) public static String pay() { return prefix() + "PAY" + IdUtil.getSnowflakeNextId(); }