diff --git a/_config/sql/update-tables.sql b/_config/sql/update-tables.sql index 6f5dac934..07617b7c2 100644 --- a/_config/sql/update-tables.sql +++ b/_config/sql/update-tables.sql @@ -209,3 +209,138 @@ ALTER TABLE device_qr_code ALTER COLUMN mch_no DROP NOT NULL; COMMENT ON COLUMN device_qr_code.batch_no IS '批次号(批量创建空白码时写入)'; COMMENT ON COLUMN device_qr_code.mch_no IS '所属商户号(空白码为空, 划拨后写入)'; +-- ------------------------------------------------------------ +-- 网关支付业务单(容器): 预下单时创建, 支付时再挂 pay_trade +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS pay_gateway_order ( + id int8 NOT NULL, + mch_no varchar(32) NOT NULL, + app_id varchar(32) NOT NULL, + order_no varchar(64) NOT NULL, + biz_order_no varchar(64) NOT NULL, + gateway_type varchar(32) NOT NULL, + title varchar(128) NOT NULL, + description varchar(512), + amount int8 NOT NULL, + currency varchar(8) NOT NULL DEFAULT 'CNY', + status varchar(32) NOT NULL, + notify_url varchar(256), + return_url varchar(256), + attach varchar(512), + expired_time timestamptz(6), + channel varchar(32), + method varchar(32), + product varchar(32), + capability varchar(64), + channel_mch_no varchar(64), + scene varchar(32), + device varchar(16), + pay_time timestamptz(6), + close_time timestamptz(6), + client_ip varchar(64), + terminal_no varchar(64), + goods_detail jsonb, + creator int8, + create_time timestamptz(6), + last_modifier int8, + last_modified_time timestamptz(6), + version int4 NOT NULL DEFAULT 0, + deleted bool NOT NULL DEFAULT false, + CONSTRAINT pk_pay_gateway_order PRIMARY KEY (id) +); + +COMMENT ON TABLE pay_gateway_order IS '网关支付业务单容器(聚合扫码/收银台预下单)'; +COMMENT ON COLUMN pay_gateway_order.id IS '主键'; +COMMENT ON COLUMN pay_gateway_order.mch_no IS '商户号'; +COMMENT ON COLUMN pay_gateway_order.app_id IS '应用号'; +COMMENT ON COLUMN pay_gateway_order.order_no IS '平台网关单号(URL用)'; +COMMENT ON COLUMN pay_gateway_order.biz_order_no IS '商户业务单号'; +COMMENT ON COLUMN pay_gateway_order.gateway_type IS '网关类型: cashier/aggregate'; +COMMENT ON COLUMN pay_gateway_order.title IS '标题'; +COMMENT ON COLUMN pay_gateway_order.description IS '描述'; +COMMENT ON COLUMN pay_gateway_order.amount IS '金额(最小货币单位)'; +COMMENT ON COLUMN pay_gateway_order.currency IS '币种'; +COMMENT ON COLUMN pay_gateway_order.status IS '业务状态: wait_pay/paying/paid/closed/expired'; +COMMENT ON COLUMN pay_gateway_order.notify_url IS '异步通知地址'; +COMMENT ON COLUMN pay_gateway_order.return_url IS '同步跳转地址'; +COMMENT ON COLUMN pay_gateway_order.attach IS '商户附加参数'; +COMMENT ON COLUMN pay_gateway_order.expired_time IS '过期时间'; +COMMENT ON COLUMN pay_gateway_order.channel IS '支付通道(支付后冗余)'; +COMMENT ON COLUMN pay_gateway_order.method IS '支付方式(支付后冗余)'; +COMMENT ON COLUMN pay_gateway_order.product IS '支付产品(支付后冗余)'; +COMMENT ON COLUMN pay_gateway_order.capability IS '支付能力(路由回填)'; +COMMENT ON COLUMN pay_gateway_order.channel_mch_no IS '通道商户号(路由回填)'; +COMMENT ON COLUMN pay_gateway_order.scene IS '收银场景 wechat_pay/alipay/union_pay'; +COMMENT ON COLUMN pay_gateway_order.device IS '最后发起设备 mobile/pc'; +COMMENT ON COLUMN pay_gateway_order.pay_time IS '支付成功时间'; +COMMENT ON COLUMN pay_gateway_order.close_time IS '关闭时间'; +COMMENT ON COLUMN pay_gateway_order.client_ip IS '客户端IP'; +COMMENT ON COLUMN pay_gateway_order.terminal_no IS '终端设备编码'; +COMMENT ON COLUMN pay_gateway_order.goods_detail IS '商品明细(jsonb)'; +COMMENT ON COLUMN pay_gateway_order.creator IS '创建者ID'; +COMMENT ON COLUMN pay_gateway_order.create_time IS '创建时间'; +COMMENT ON COLUMN pay_gateway_order.last_modifier IS '最后修改者ID'; +COMMENT ON COLUMN pay_gateway_order.last_modified_time IS '最后修改时间'; +COMMENT ON COLUMN pay_gateway_order.version IS '版本号(乐观锁)'; +COMMENT ON COLUMN pay_gateway_order.deleted IS '逻辑删除标记'; + +CREATE UNIQUE INDEX IF NOT EXISTS uk_pay_gateway_order_no ON pay_gateway_order (order_no) WHERE deleted = false; +CREATE UNIQUE INDEX IF NOT EXISTS uk_pay_gateway_biz ON pay_gateway_order (app_id, biz_order_no) WHERE deleted = false; +CREATE INDEX IF NOT EXISTS idx_pay_gateway_status_expired ON pay_gateway_order (status, expired_time); +CREATE INDEX IF NOT EXISTS idx_pay_gateway_mch_time ON pay_gateway_order (mch_no, create_time); + +-- ------------------------------------------------------------ +-- 网关聚合扫码配置(应用级一行) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS pay_gateway_aggregate_config ( + id int8 NOT NULL, + mch_no varchar(32) NOT NULL, + app_id varchar(32) NOT NULL, + wx_product varchar(32), + wx_method varchar(32), + alipay_product varchar(32), + alipay_method varchar(32), + union_product varchar(32), + union_method varchar(32), + auto_launch bool NOT NULL DEFAULT false, + creator int8, + create_time timestamptz(6), + last_modifier int8, + last_modified_time timestamptz(6), + version int4 NOT NULL DEFAULT 0, + deleted bool NOT NULL DEFAULT false, + CONSTRAINT pk_pay_gateway_aggregate_config PRIMARY KEY (id) +); + +COMMENT ON TABLE pay_gateway_aggregate_config IS '网关聚合扫码支付配置(应用级)'; +COMMENT ON COLUMN pay_gateway_aggregate_config.id IS '主键'; +COMMENT ON COLUMN pay_gateway_aggregate_config.mch_no IS '商户号'; +COMMENT ON COLUMN pay_gateway_aggregate_config.app_id IS '应用号'; +COMMENT ON COLUMN pay_gateway_aggregate_config.wx_product IS '微信场景支付产品'; +COMMENT ON COLUMN pay_gateway_aggregate_config.wx_method IS '微信场景支付方式'; +COMMENT ON COLUMN pay_gateway_aggregate_config.alipay_product IS '支付宝场景支付产品'; +COMMENT ON COLUMN pay_gateway_aggregate_config.alipay_method IS '支付宝场景支付方式'; +COMMENT ON COLUMN pay_gateway_aggregate_config.union_product IS '云闪付场景支付产品'; +COMMENT ON COLUMN pay_gateway_aggregate_config.union_method IS '云闪付场景支付方式'; +COMMENT ON COLUMN pay_gateway_aggregate_config.auto_launch IS '是否自动拉起支付'; +COMMENT ON COLUMN pay_gateway_aggregate_config.creator IS '创建者ID'; +COMMENT ON COLUMN pay_gateway_aggregate_config.create_time IS '创建时间'; +COMMENT ON COLUMN pay_gateway_aggregate_config.last_modifier IS '最后修改者ID'; +COMMENT ON COLUMN pay_gateway_aggregate_config.last_modified_time IS '最后修改时间'; +COMMENT ON COLUMN pay_gateway_aggregate_config.version IS '版本号(乐观锁)'; +COMMENT ON COLUMN pay_gateway_aggregate_config.deleted IS '逻辑删除标记'; + +CREATE UNIQUE INDEX IF NOT EXISTS uk_pay_gateway_aggregate_app ON pay_gateway_aggregate_config (app_id) WHERE deleted = false; + +-- ------------------------------------------------------------ +-- pay_trade: 冗余路由参数 + 业务单号 + 客户端IP, 消除 sync/close/callback 对容器的依赖 +-- ------------------------------------------------------------ +ALTER TABLE pay_trade ADD COLUMN IF NOT EXISTS biz_order_no varchar(64); +ALTER TABLE pay_trade ADD COLUMN IF NOT EXISTS channel_mch_no varchar(64); +ALTER TABLE pay_trade ADD COLUMN IF NOT EXISTS capability varchar(64); +ALTER TABLE pay_trade ADD COLUMN IF NOT EXISTS client_ip varchar(64); + +COMMENT ON COLUMN pay_trade.biz_order_no IS '商户业务单号(冗余自容器, 供同步/关闭/回调等流程直接读取)'; +COMMENT ON COLUMN pay_trade.channel_mch_no IS '通道商户号(路由回填, 冗余自容器, 供策略层直接读取)'; +COMMENT ON COLUMN pay_trade.capability IS '支付能力编码(路由回填, 冗余自容器, 供策略层直接读取)'; +COMMENT ON COLUMN pay_trade.client_ip IS '客户端IP(冗余自容器, 供关闭/同步等策略读取)'; diff --git a/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectCloseStrategy.java b/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectCloseStrategy.java index ccf8cb8e2..bfff13c1b 100644 --- a/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.adapay.service.direct.AdapayDirectConfigAssembler; import cn.daxpay.open.channel.adapay.service.payment.close.AdapayCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; @@ -29,13 +28,10 @@ public class AdapayDirectCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; PayTrade trade = context.getTrade(); - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 AdapaySdkCredential credential = adapayDirectConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return adapayCloseService.close(trade, credential, useCancel); } } diff --git a/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectSyncStrategy.java b/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectSyncStrategy.java index a5f442276..dbf396553 100644 --- a/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-adapay/src/main/java/cn/daxpay/open/channel/adapay/strategy/AdapayDirectSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.adapay.service.payment.sync.AdapaySyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,12 +27,9 @@ public class AdapayDirectSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 AdapaySdkCredential credential = adapayDirectConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return adapaySyncService.sync(context.getTrade(), credential); } } diff --git a/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/service/callback/AlipayCallbackService.java b/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/service/callback/AlipayCallbackService.java index f2721ebb7..5d1b40f3a 100644 --- a/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/service/callback/AlipayCallbackService.java +++ b/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/service/callback/AlipayCallbackService.java @@ -161,16 +161,12 @@ public class AlipayCallbackService { if (trade == null) { return null; } - NormalPayOrder normal = normalPayOrderManager.findById(trade.getContainerId()).orElse(null); - if (normal == null) { - return null; - } // 按支付产品分发: 服务商 / 直连 if (ProductEnum.ALIPAY_ISV.getCode().equals(trade.getProduct())) { return alipayIsvConfigAssembler.buildConfig(trade.getMchNo()); } return alipayDirectConfigAssembler.buildConfig( - trade.getMchNo(), normal.getChannelMchNo(), normal.getCapability()); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); } /// 提取 request 全部表单参数为 Map(多值取首项) diff --git a/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectCloseStrategy.java b/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectCloseStrategy.java index d4f597b94..dcda00431 100644 --- a/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectCloseStrategy.java @@ -4,7 +4,6 @@ import cn.daxpay.open.channel.alipay.client.credential.AlipaySdkCredential; import cn.daxpay.open.channel.alipay.service.direct.AlipayDirectConfigAssembler; import cn.daxpay.open.channel.alipay.service.payment.close.AlipayCloseService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -16,7 +15,7 @@ import org.springframework.stereotype.Service; /// # 支付宝直连支付关闭策略 /// /// 支付宝直连模式(ProductEnum.ALIPAY)下的支付关闭策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [AlipayDirectConfigAssembler]), 关闭执行委托给 [AlipayCloseService]。 @Slf4j @Service @@ -33,15 +32,12 @@ public class AlipayDirectCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - // 从上下文容器读取通道路由参数, 用于凭证解析 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); // 组装通道调用凭证 AlipaySdkCredential credential = alipayDirectConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return alipayCloseService.close(trade, credential, useCancel); } diff --git a/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectSyncStrategy.java b/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectSyncStrategy.java index 0ef57292f..93ff72d46 100644 --- a/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-alipay/src/main/java/cn/daxpay/open/channel/alipay/strategy/direct/AlipayDirectSyncStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.alipay.service.direct.AlipayDirectConfigAssembler; import cn.daxpay.open.channel.alipay.service.payment.sync.AlipaySyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Service; /// # 支付宝直连支付同步策略 /// /// 支付宝直连模式(ProductEnum.ALIPAY)下的支付同步策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [AlipayDirectConfigAssembler]), 同步执行委托给 [AlipaySyncService]。 @Slf4j @Service @@ -32,14 +31,10 @@ public class AlipayDirectSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - // 从上下文容器读取通道路由参数, 用于凭证解析 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装通道调用凭证 AlipaySdkCredential credential = alipayDirectConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return alipaySyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongCloseStrategy.java b/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongCloseStrategy.java index 581446174..95cf4acc1 100644 --- a/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.dougong.service.isv.DougongIsvConfigAssembler; import cn.daxpay.open.channel.dougong.service.payment.DougongCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -31,15 +30,12 @@ public class DougongCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); DougongSdkCredential credential = dougongIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); - String clientIp = normalOrder != null ? normalOrder.getClientIp() : null; - return dougongCloseService.close(trade, credential, useCancel, clientIp); + return dougongCloseService.close(trade, credential, useCancel, trade.getClientIp()); } } diff --git a/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongSyncStrategy.java b/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongSyncStrategy.java index db692035f..cd9e3350b 100644 --- a/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-dougong/src/main/java/cn/daxpay/open/channel/dougong/strategy/DougongSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.dougong.service.payment.DougongSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,12 +27,9 @@ public class DougongSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 DougongSdkCredential credential = dougongIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return dougongSyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectCloseStrategy.java b/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectCloseStrategy.java index bc595b6a8..e2c379523 100644 --- a/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectCloseStrategy.java @@ -4,7 +4,6 @@ import cn.daxpay.open.channel.douyin.client.credential.DouyinSdkCredential; import cn.daxpay.open.channel.douyin.service.direct.DouyinDirectConfigAssembler; import cn.daxpay.open.channel.douyin.service.payment.close.DouyinCloseService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -16,7 +15,7 @@ import org.springframework.stereotype.Service; /// # 抖音直连支付关闭策略 /// /// 抖音直连模式(ProductEnum.DOUYIN_PAY)下的支付关闭策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从交易凭证读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [DouyinDirectConfigAssembler]), 关闭执行委托给 [DouyinCloseService]。 @Slf4j @Service @@ -33,13 +32,10 @@ public class DouyinDirectCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; PayTrade trade = context.getTrade(); - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 DouyinSdkCredential credential = douyinDirectConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return douyinCloseService.close(trade, credential, useCancel); } } diff --git a/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectSyncStrategy.java b/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectSyncStrategy.java index ec69d1fe6..b707cf1f1 100644 --- a/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/DouyinDirectSyncStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.douyin.service.direct.DouyinDirectConfigAssembler; import cn.daxpay.open.channel.douyin.service.payment.sync.DouyinSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Service; /// # 抖音直连支付同步策略 /// /// 抖音直连模式(ProductEnum.DOUYIN_PAY)下的支付同步策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从交易凭证读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [DouyinDirectConfigAssembler]), 同步执行委托给 [DouyinSyncService]。 @Slf4j @Service @@ -32,12 +31,9 @@ public class DouyinDirectSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 DouyinSdkCredential credential = douyinDirectConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return douyinSyncService.sync(context.getTrade(), credential); } } diff --git a/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouCloseStrategy.java b/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouCloseStrategy.java index 113bd6fc7..45d191d1a 100644 --- a/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.fuyou.service.isv.FuyouIsvConfigAssembler; import cn.daxpay.open.channel.fuyou.service.payment.FuyouCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -31,13 +30,11 @@ public class FuyouCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); FuyouSdkCredential credential = fuyouIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return fuyouCloseService.close(trade, credential, useCancel); } } diff --git a/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouSyncStrategy.java b/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouSyncStrategy.java index 14d47a085..8a4fe330f 100644 --- a/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-fuyou/src/main/java/cn/daxpay/open/channel/fuyou/strategy/FuyouSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.fuyou.service.payment.FuyouSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,12 +27,9 @@ public class FuyouSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 FuyouSdkCredential credential = fuyouIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return fuyouSyncService.sync(context.getTrade(), credential); } } diff --git a/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtCloseStrategy.java b/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtCloseStrategy.java index de5efa8c7..98140f9b7 100644 --- a/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.hkrt.service.isv.HkrtIsvConfigAssembler; import cn.daxpay.open.channel.hkrt.service.payment.HkrtCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -34,18 +33,13 @@ public class HkrtCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - // 从上下文容器读取通道路由参数 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); // 组装通道调用凭证 HkrtSdkCredential credential = hkrtIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); - // 客户端IP取自原下单订单(超时关单等非HTTP场景亦可用) - String clientIp = normalOrder != null ? normalOrder.getClientIp() : null; - return hkrtCloseService.close(trade, credential, useCancel, clientIp); + return hkrtCloseService.close(trade, credential, useCancel, trade.getClientIp()); } } diff --git a/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtSyncStrategy.java b/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtSyncStrategy.java index 7001402aa..625c55cb7 100644 --- a/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-hkrt/src/main/java/cn/daxpay/open/channel/hkrt/strategy/HkrtSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.hkrt.service.payment.HkrtSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,14 +30,11 @@ public class HkrtSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - // 从上下文容器读取通道路由参数 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装通道调用凭证 HkrtSdkCredential credential = hkrtIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return hkrtSyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpayCloseStrategy.java b/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpayCloseStrategy.java index 40b43261f..93ef91654 100644 --- a/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpayCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpayCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.hmpay.service.isv.HmpayIsvConfigAssembler; import cn.daxpay.open.channel.hmpay.service.payment.HmpayCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -31,13 +30,10 @@ public class HmpayCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; PayTrade trade = context.getTrade(); - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 HmpaySdkCredential credential = hmpayIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return hmpayCloseService.close(trade, credential); } diff --git a/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpaySyncStrategy.java b/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpaySyncStrategy.java index 91458aa4b..8114ca967 100644 --- a/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpaySyncStrategy.java +++ b/daxpay-channel/daxpay-channel-hmpay/src/main/java/cn/daxpay/open/channel/hmpay/strategy/HmpaySyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.hmpay.service.payment.HmpaySyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,12 +27,9 @@ public class HmpaySyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 HmpaySdkCredential credential = hmpayIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return hmpaySyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaCloseStrategy.java b/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaCloseStrategy.java index c120f3618..4be2888d2 100644 --- a/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.lakala.service.isv.LakalaIsvConfigAssembler; import cn.daxpay.open.channel.lakala.service.payment.LakalaCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Service; /// # 拉卡拉服务商支付关闭策略 /// -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [LakalaIsvConfigAssembler]), 关闭执行委托给 [LakalaCloseService]。 /// /// 注意: 拉卡拉仅提供关单接口, 无撤销接口(useCancel 参数由 service 层忽略)。 @@ -34,18 +33,13 @@ public class LakalaCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - // 从上下文容器读取通道路由参数 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); // 组装通道调用凭证 LakalaSdkCredential credential = lakalaIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); - // 客户端IP取自原下单订单(超时关单等非HTTP场景亦可用) - String clientIp = normalOrder != null ? normalOrder.getClientIp() : null; - return lakalaCloseService.close(trade, credential, useCancel, clientIp); + return lakalaCloseService.close(trade, credential, useCancel, trade.getClientIp()); } } diff --git a/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaSyncStrategy.java b/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaSyncStrategy.java index 199279550..c1547ef02 100644 --- a/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-lakala/src/main/java/cn/daxpay/open/channel/lakala/strategy/LakalaSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.lakala.service.payment.LakalaSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,7 +13,7 @@ import org.springframework.stereotype.Service; /// # 拉卡拉服务商支付同步策略 /// -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [LakalaIsvConfigAssembler]), 同步执行委托给 [LakalaSyncService]。 @Slf4j @Service @@ -31,14 +30,10 @@ public class LakalaSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - // 从上下文容器读取通道路由参数 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装通道调用凭证 LakalaSdkCredential credential = lakalaIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return lakalaSyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaCloseStrategy.java b/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaCloseStrategy.java index 28af36561..4b652a757 100644 --- a/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.leshua.service.isv.LeshuaIsvConfigAssembler; import cn.daxpay.open.channel.leshua.service.payment.LeshuaCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -31,14 +30,10 @@ public class LeshuaCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; PayTrade trade = context.getTrade(); - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 LeshuaSdkCredential credential = leshuaIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); - String clientIp = normalOrder != null ? normalOrder.getClientIp() : null; - return leshuaCloseService.close(trade, credential, useCancel, clientIp); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); + return leshuaCloseService.close(trade, credential, useCancel, trade.getClientIp()); } } diff --git a/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaSyncStrategy.java b/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaSyncStrategy.java index d0ca14dde..de1dd1794 100644 --- a/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-leshua/src/main/java/cn/daxpay/open/channel/leshua/strategy/LeshuaSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.leshua.service.payment.LeshuaSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -30,12 +29,9 @@ public class LeshuaSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 LeshuaSdkCredential credential = leshuaIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return leshuaSyncService.sync(context.getTrade(), credential); } } diff --git a/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectCloseStrategy.java b/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectCloseStrategy.java index 68c5c06c7..c50552fad 100644 --- a/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.ums.service.direct.UmsDirectConfigAssembler; import cn.daxpay.open.channel.ums.service.payment.close.UmsCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; @@ -29,13 +28,11 @@ public class UmsDirectCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); UmsSdkCredential credential = umsDirectConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return umsCloseService.close(trade, credential, useCancel); } } diff --git a/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectSyncStrategy.java b/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectSyncStrategy.java index 1ce6feea5..3d1d2f1ab 100644 --- a/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-ums/src/main/java/cn/daxpay/open/channel/ums/strategy/UmsDirectSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.ums.service.payment.sync.UmsSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,12 +27,9 @@ public class UmsDirectSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 UmsSdkCredential credential = umsDirectConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return umsSyncService.sync(context.getTrade(), credential); } } diff --git a/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillCloseStrategy.java b/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillCloseStrategy.java index 4616d020b..9cf7b1de5 100644 --- a/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.vbill.service.isv.VbillIsvConfigAssembler; import cn.daxpay.open.channel.vbill.service.payment.VbillCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Service; /// # 随行付服务商支付关闭策略 /// -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从交易凭证读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [VbillIsvConfigAssembler]), 关闭执行委托给 [VbillCloseService]。 /// /// 注意: 随行付仅提供关单接口(`/query/close`), 无撤销接口(useCancel 参数由 service 层忽略)。 @@ -34,15 +33,12 @@ public class VbillCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - // 从上下文容器读取通道路由参数 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; PayTrade trade = context.getTrade(); + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装通道调用凭证 VbillSdkCredential credential = vbillIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return vbillCloseService.close(trade, credential, useCancel); } diff --git a/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillSyncStrategy.java b/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillSyncStrategy.java index 7ab8b1a88..fb359864b 100644 --- a/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-vbill/src/main/java/cn/daxpay/open/channel/vbill/strategy/VbillSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.vbill.service.payment.VbillSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,7 +13,7 @@ import org.springframework.stereotype.Service; /// # 随行付服务商支付同步策略 /// -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从交易凭证读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [VbillIsvConfigAssembler]), 同步执行委托给 [VbillSyncService]。 @Slf4j @Service @@ -31,14 +30,11 @@ public class VbillSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - // 从上下文容器读取通道路由参数 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装通道调用凭证 VbillSdkCredential credential = vbillIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return vbillSyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectCloseStrategy.java b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectCloseStrategy.java index 068c58ff3..a8bcb7501 100644 --- a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.wechat.service.direct.WechatDirectConfigAssembler; import cn.daxpay.open.channel.wechat.service.payment.close.WechatCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -16,7 +15,7 @@ import org.springframework.stereotype.Service; /// # 微信直连支付关闭策略 /// /// 微信直连模式(ProductEnum.WECHAT_PAY)下的支付关闭策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [WechatDirectConfigAssembler]), 关闭执行委托给 [WechatCloseService]。 /// /// 注意: 微信 V3 仅提供关单接口, 无撤销接口(useCancel 参数由 service 层忽略)。 @@ -35,15 +34,12 @@ public class WechatDirectCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - // 从上下文容器读取通道路由参数, 用于凭证解析 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); // 组装通道调用凭证 WechatSdkCredential credential = wechatDirectConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return wechatCloseService.close(trade, credential, useCancel); } diff --git a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectSyncStrategy.java b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectSyncStrategy.java index 8be45f48d..1922e85f0 100644 --- a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/WechatDirectSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.wechat.service.payment.sync.WechatSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Service; /// # 微信直连支付同步策略 /// /// 微信直连模式(ProductEnum.WECHAT_PAY)下的支付同步策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装通道凭证(委托 [WechatDirectConfigAssembler]), 同步执行委托给 [WechatSyncService]。 @Slf4j @Service @@ -32,14 +31,10 @@ public class WechatDirectSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - // 从上下文容器读取通道路由参数, 用于凭证解析 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装通道调用凭证 WechatSdkCredential credential = wechatDirectConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return wechatSyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvCloseStrategy.java b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvCloseStrategy.java index 317973451..d941276d9 100644 --- a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.wechat.service.isv.WechatIsvConfigAssembler; import cn.daxpay.open.channel.wechat.service.payment.isv.WechatIsvCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; @@ -16,7 +15,7 @@ import org.springframework.stereotype.Service; /// # 微信服务商支付关闭策略 /// /// 微信服务商模式(ProductEnum.WECHAT_ISV)下的支付关闭策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装服务商通道凭证(委托 [WechatIsvConfigAssembler]), 关闭执行委托给 [WechatCloseService]。 /// /// 注意: 微信 V3 仅提供关单接口, 无撤销接口(useCancel 参数由 service 层忽略)。 @@ -35,15 +34,12 @@ public class WechatIsvCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - // 从上下文容器读取通道路由参数, 用于凭证解析 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); // 组装服务商通道调用凭证 WechatSdkCredential credential = wechatIsvConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return wechatIsvCloseService.close(trade, credential, useCancel); } diff --git a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvSyncStrategy.java b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvSyncStrategy.java index 06b7efb1a..e0a9ed158 100644 --- a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/WechatIsvSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.wechat.service.payment.isv.WechatIsvSyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Service; /// # 微信服务商支付同步策略 /// /// 微信服务商模式(ProductEnum.WECHAT_ISV)下的支付同步策略。 -/// 从上下文容器读取通道路由参数(channelMchNo / capability), +/// 从 trade 读取通道路由参数(channelMchNo / capability), /// 组装服务商通道凭证(委托 [WechatIsvConfigAssembler]), 同步执行委托给 [WechatSyncService]。 @Slf4j @Service @@ -32,14 +31,10 @@ public class WechatIsvSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - // 从上下文容器读取通道路由参数, 用于凭证解析 - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 // 组装服务商通道调用凭证 WechatSdkCredential credential = wechatIsvConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return wechatIsvSyncService.sync(context.getTrade(), credential); } diff --git a/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectCloseStrategy.java b/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectCloseStrategy.java index b7221d781..cf1f1ebc1 100644 --- a/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectCloseStrategy.java +++ b/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectCloseStrategy.java @@ -5,7 +5,6 @@ import cn.daxpay.open.channel.yeepay.service.direct.YeepayDirectConfigAssembler; import cn.daxpay.open.channel.yeepay.service.payment.close.YeepayCloseService; import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; @@ -29,13 +28,11 @@ public class YeepayDirectCloseStrategy extends AbsPayCloseStrategy { @Override public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; + // 直接从 trade 读取路由参数, 不再需要 container 中间层 PayTrade trade = context.getTrade(); YeepaySdkCredential credential = yeepayDirectConfigAssembler.buildConfig( - trade.getMchNo(), channelMchNo, capability); + trade.getMchNo(), trade.getChannelMchNo(), trade.getCapability()); return yeepayCloseService.close(trade, credential, useCancel); } } diff --git a/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectSyncStrategy.java b/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectSyncStrategy.java index c57da2e71..18ab6c5b1 100644 --- a/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectSyncStrategy.java +++ b/daxpay-channel/daxpay-channel-yeepay/src/main/java/cn/daxpay/open/channel/yeepay/strategy/YeepayDirectSyncStrategy.java @@ -6,7 +6,6 @@ import cn.daxpay.open.channel.yeepay.service.payment.sync.YeepaySyncService; import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,12 +27,9 @@ public class YeepayDirectSyncStrategy extends AbsSyncPayOrderStrategy { @Override public PaySyncResultBo doSync(PayStrategyContext context) { - NormalPayOrder normalOrder = context.getContainer(); - String channelMchNo = normalOrder != null ? normalOrder.getChannelMchNo() : null; - String capability = normalOrder != null ? normalOrder.getCapability() : null; - + // 直接从 trade 读取路由参数, 不再需要 container 中间层 YeepaySdkCredential credential = yeepayDirectConfigAssembler.buildConfig( - context.getTrade().getMchNo(), channelMchNo, capability); + context.getTrade().getMchNo(), context.getTrade().getChannelMchNo(), context.getTrade().getCapability()); return yeepaySyncService.sync(context.getTrade(), credential); } } diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/strategy/pay/PayStrategyContext.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/strategy/pay/PayStrategyContext.java index c8d63451f..0a50210fd 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/strategy/pay/PayStrategyContext.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/strategy/pay/PayStrategyContext.java @@ -1,6 +1,5 @@ package cn.daxpay.open.payment.core.strategy.pay; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.payment.unipay.param.trade.pay.NormalPayParam; import lombok.Getter; @@ -9,8 +8,9 @@ import lombok.experimental.Accessors; /// # 支付策略执行上下文(请求级,显式传参) /// -/// 持有单笔支付策略管线的"容器(业务单) + 资金凭证 + 请求参数 + 通道配置"四要素, +/// 持有单笔支付策略管线的"资金凭证 + 请求参数 + 通道配置"三要素, /// 每次支付/同步/关闭创建新实例,显式传递,不进 ThreadLocal。 +/// 路由参数(channelMchNo / capability)已冗余到 [PayTrade],策略直接从 trade 读取。 /// /// 与线程级身份上下文严格区分: /// - 本类 = 请求级数据载体(函数传参) @@ -20,10 +20,7 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class PayStrategyContext { - /// 普通支付业务单容器(承载 bizOrderNo / 回调地址 / 通道路由等业务信息) - private NormalPayOrder container; - - /// 资金交易凭证(记录本笔资金动作的状态与通道回执) + /// 资金交易凭证(记录本笔资金动作的状态与通道回执, 含路由参数) private PayTrade trade; /// 普通支付请求参数(pay 流程必填;sync/close 流程可为空) diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/convert/PayTradeConvert.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/convert/PayTradeConvert.java index 860f31285..e28760704 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/convert/PayTradeConvert.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/convert/PayTradeConvert.java @@ -1,6 +1,5 @@ package cn.daxpay.open.payment.core.trade.convert; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPayResult; import org.mapstruct.Mapper; @@ -9,17 +8,15 @@ import org.mapstruct.factory.Mappers; /// # 支付交易转换器 /// +/// 仅从 PayTrade 映射对外支付响应;同名字段(status/bizOrderNo/payBody 等)自动映射, +/// 仅声明改名字段 @Mapper public interface PayTradeConvert { PayTradeConvert CONVERT = Mappers.getMapper(PayTradeConvert.class); - /// PayTrade + NormalPayOrder → NormalPayResult - @Mapping(target = "orderId", source = "trade.id") - @Mapping(target = "orderNo", source = "trade.tradeNo") - @Mapping(target = "status", source = "trade.status") - @Mapping(target = "bizOrderNo", source = "normalOrder.bizOrderNo") - @Mapping(target = "payBody", source = "trade.payBody") - @Mapping(target = "payBodyType", source = "trade.payBodyType") - NormalPayResult toResult(PayTrade trade, NormalPayOrder normalOrder); + /// PayTrade → NormalPayResult + @Mapping(target = "orderId", source = "id") + @Mapping(target = "orderNo", source = "tradeNo") + NormalPayResult toResult(PayTrade trade); } diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/entity/PayTrade.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/entity/PayTrade.java index ba8c0e7c4..7d9322282 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/entity/PayTrade.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/entity/PayTrade.java @@ -39,6 +39,9 @@ public class PayTrade extends MchBaseEntity { /// normal → pay_normal_order / authorize/capture → pay_auth / recurring → pay_recurring / combine_sub → pay_combine private Long containerId; + /// 商户业务单号(冗余自容器, 供同步/关闭/回调等流程直接读取, 免查容器) + private String bizOrderNo; + /// 支付产品编码,策略工厂通过此字段创建策略 /// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum private String product; @@ -125,6 +128,16 @@ public class PayTrade extends MchBaseEntity { /// 支付参数体类型(jsapi/sdk/app) private String payBodyType; + /// 通道商户号(路由回填, 冗余自容器, 供策略层直接读取) + private String channelMchNo; + + /// 支付能力编码(路由回填, 冗余自容器, 供策略层直接读取) + /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayCapabilityEnum + private String capability; + + /// 客户端 IP(冗余自容器, 供关闭/同步等策略读取) + private String clientIp; + /// 错误信息 @TableField(updateStrategy = FieldStrategy.ALWAYS) private String errorMsg; diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/NormalPayService.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/NormalPayService.java index 99e3f5cbe..bb8601ae6 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/NormalPayService.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/NormalPayService.java @@ -78,7 +78,7 @@ public class NormalPayService { return payAssistService.buildResult(context.getTrade()); } // 订单不存在则新建(填充 context) - if (Objects.isNull(context.getContainer())) { + if (Objects.isNull(context.getTrade())) { payAssistService.createOrder(payParam, context); } PayTrade trade = context.getTrade(); diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayAssistService.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayAssistService.java index 6f5cec899..5dfaefdaf 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayAssistService.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayAssistService.java @@ -87,9 +87,13 @@ public class PayAssistService { trade.setTradeNo(TradeNoGenerateUtil.pay()); trade.setTradeType(PayTradeTypeEnum.NORMAL.getCode()); trade.setContainerId(normalOrder.getId()); + trade.setBizOrderNo(payParam.getBizOrderNo()); trade.setProduct(payParam.getProduct()); trade.setChannel(channel); trade.setMethod(payParam.getMethod()); + trade.setChannelMchNo(payParam.getChannelMchNo()); + trade.setCapability(payParam.getCapability()); + trade.setClientIp(payParam.getClientIp()); trade.setLimitPay(payParam.getLimitPay() != null ? String.join(",", payParam.getLimitPay()) : null); trade.setAmount(amount); @@ -101,7 +105,7 @@ public class PayAssistService { trade.setBarCode(payParam.getAuthCode()); trade.setOpenid(payParam.getOpenId()); payTradeManager.save(trade); - context.setContainer(normalOrder).setTrade(trade); + context.setTrade(trade); // 注册超时关单延时消息(按订单过期时间定时投递) this.registerTimeoutClose(trade.getTradeNo(), normalOrder.getBizOrderNo(), expiredTime); } @@ -130,12 +134,12 @@ public class PayAssistService { return; } NormalPayOrder normalOrder = normalOrderOpt.get(); - PayTrade trade = payTradeManager.findByContainerId(normalOrder.getId()).orElse(null); + PayTrade trade = payTradeManager.findByContainerId(normalOrder.getId(), PayTradeTypeEnum.NORMAL.getCode()).orElse(null); if (trade == null) { return; } this.checkOrder(normalOrder, trade); - context.setContainer(normalOrder).setTrade(trade); + context.setTrade(trade); } /// 检查订单状态 @@ -167,8 +171,7 @@ public class PayAssistService { /// 根据 PayTrade 构建支付结果 public NormalPayResult buildResult(PayTrade trade) { - NormalPayOrder normalOrder = payNormalOrderManager.findById(trade.getContainerId()).orElse(null); - return PayTradeConvert.CONVERT.toResult(trade, normalOrder); + return PayTradeConvert.CONVERT.toResult(trade); } /// 获取支付超时时间 diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCallbackService.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCallbackService.java index 561440b30..d3f02e69c 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCallbackService.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCallbackService.java @@ -1,13 +1,10 @@ package cn.daxpay.open.payment.core.trade.service; -import cn.daxpay.open.platform.core.enums.pay.notice.CallbackStatusEnum; -import cn.daxpay.open.platform.core.exception.system.DataErrorException; import cn.daxpay.open.payment.common.callback.CallbackData; import cn.daxpay.open.payment.common.enums.PayFundStatusEnum; -import cn.daxpay.open.payment.core.trade.dao.NormalPayOrderManager; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.dao.PayTradeManager; import cn.daxpay.open.payment.core.trade.entity.PayTrade; +import cn.daxpay.open.platform.core.enums.pay.notice.CallbackStatusEnum; import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; import lombok.RequiredArgsConstructor; @@ -26,7 +23,6 @@ import java.util.Objects; public class PayCallbackService { private final PayTradeManager payTradeManager; - private final NormalPayOrderManager payNormalOrderManager; private final PayUniHandleService payUniHandleService; private final LockTemplate lockTemplate; @@ -55,12 +51,10 @@ public class PayCallbackService { if (Objects.nonNull(callbackData.getOutTradeNo())) { trade.setOutOrderNo(callbackData.getOutTradeNo()); } - NormalPayOrder normalOrder = payNormalOrderManager.findById(trade.getContainerId()) - .orElseThrow(() -> new DataErrorException("error.payment.order.payOrderNotExist")); if (Objects.equals(CallbackStatusEnum.SUCCESS.getCode(), callbackData.getTradeStatus())) { - this.success(trade, normalOrder, callbackData); + this.success(trade, callbackData); } else { - this.fail(trade, normalOrder, callbackData); + this.fail(trade, callbackData); } return trade.getProduct(); } finally { @@ -68,8 +62,7 @@ public class PayCallbackService { } } - /// 成功处理 - private void success(PayTrade trade, NormalPayOrder normalOrder, CallbackData callbackData) { + private void success(PayTrade trade, CallbackData callbackData) { trade.setStatus(PayFundStatusEnum.SUCCESS.getCode()); trade.setPayTime(callbackData.getFinishTime()); trade.setCloseTime(null); @@ -79,13 +72,12 @@ public class PayCallbackService { payUniHandleService.paySuccess(trade); } - /// 失败处理 - private void fail(PayTrade trade, NormalPayOrder normalOrder, CallbackData callbackData) { + private void fail(PayTrade trade, CallbackData callbackData) { if (!Objects.equals(trade.getStatus(), PayFundStatusEnum.PROCESSING.getCode())) { callbackData.setCallbackStatus(CallbackStatusEnum.IGNORE) .setCallbackErrorMsg("订单不是支付中状态,忽略"); return; } - payUniHandleService.payClose(trade, normalOrder, false); + payUniHandleService.payClose(trade, false); } } diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCloseService.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCloseService.java index f4d3e18e8..e00290631 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCloseService.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PayCloseService.java @@ -1,23 +1,24 @@ package cn.daxpay.open.payment.core.trade.service; -import cn.daxpay.open.platform.core.code.CommonCode; -import cn.daxpay.open.platform.core.code.CommonErrorCode; -import cn.daxpay.open.platform.core.code.DaxPayErrorCode; -import cn.daxpay.open.platform.core.exception.BizInfoException; -import cn.daxpay.open.platform.core.exception.PayFailureException; -import cn.daxpay.open.platform.core.exception.operation.OperationFailException; -import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.common.enums.PayFundStatusEnum; +import cn.daxpay.open.payment.common.enums.PayTradeTypeEnum; import cn.daxpay.open.payment.core.strategy.PaymentStrategyFactory; +import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; +import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; import cn.daxpay.open.payment.core.trade.dao.NormalPayOrderManager; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.dao.PayTradeManager; +import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; import cn.daxpay.open.payment.core.trade.entity.PayTrade; import cn.daxpay.open.payment.core.trade.record.entity.PayCloseRecord; import cn.daxpay.open.payment.core.trade.record.service.PayCloseRecordService; -import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; import cn.daxpay.open.payment.unipay.param.trade.pay.NormalPayCloseParam; +import cn.daxpay.open.platform.core.code.CommonCode; +import cn.daxpay.open.platform.core.code.CommonErrorCode; +import cn.daxpay.open.platform.core.code.DaxPayErrorCode; import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum; +import cn.daxpay.open.platform.core.exception.BizInfoException; +import cn.daxpay.open.platform.core.exception.PayFailureException; +import cn.daxpay.open.platform.core.exception.operation.OperationFailException; import cn.hutool.core.util.StrUtil; import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; @@ -29,8 +30,6 @@ import java.util.List; import java.util.Objects; /// # 支付关闭和撤销服务 -/// -/// 关闭(close): 本地置 CLOSE; 撤销(cancel): 本地置 CANCEL, 并通过 useCancel 触发通道撤销 @Slf4j @Service @RequiredArgsConstructor @@ -42,18 +41,17 @@ public class PayCloseService { private final PayCloseRecordService payCloseRecordService; private final LockTemplate lockTemplate; - /// 关闭支付 + /// 关闭支付(商户 API) public void close(NormalPayCloseParam param) { if (StrUtil.isBlank(param.getOrderNo()) && Objects.isNull(param.getBizOrderNo())) { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.orderNoRequired"); } - PayTrade trade = payTradeManager.findByTradeNo(param.getOrderNo()) - .orElse(null); + PayTrade trade = payTradeManager.findByTradeNo(param.getOrderNo()).orElse(null); if (Objects.isNull(trade) && Objects.nonNull(param.getBizOrderNo())) { NormalPayOrder normalOrder = payNormalOrderManager.findByBizOrderNo(param.getBizOrderNo()) .orElse(null); if (Objects.nonNull(normalOrder)) { - trade = payTradeManager.findByContainerId(normalOrder.getId()) + trade = payTradeManager.findByContainerId(normalOrder.getId(), PayTradeTypeEnum.NORMAL.getCode()) .orElse(null); } } @@ -74,29 +72,24 @@ public class PayCloseService { throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.closeProcessing"); } try { - NormalPayOrder normalOrder = payNormalOrderManager.findById(trade.getContainerId()) - .orElse(null); CloseTypeEnum closeType; if (Objects.equals(PayFundStatusEnum.INIT.getCode(), trade.getStatus())) { - // 待支付无通道交易, 仅本地关闭 closeType = CloseTypeEnum.CLOSE; - payUniHandleService.payClose(trade, normalOrder, false); + payUniHandleService.payClose(trade, false); } else { - // 处理中: 调用通道关闭/撤销策略 closeType = useCancel ? CloseTypeEnum.CANCEL : CloseTypeEnum.CLOSE; var context = new PayStrategyContext() - .setContainer(normalOrder) .setTrade(trade); AbsPayCloseStrategy strategy = PaymentStrategyFactory.createByProduct( trade.getProduct(), AbsPayCloseStrategy.class); strategy.doBeforeClose(context); strategy.doClose(context, useCancel); - payUniHandleService.payClose(trade, normalOrder, useCancel); + payUniHandleService.payClose(trade, useCancel); } - this.saveRecord(trade, normalOrder, closeType, null); + this.saveRecord(trade, closeType, null); } catch (Exception e) { log.error("关闭订单失败, id: {}:", trade.getId(), e); - this.saveRecord(trade, null, useCancel ? CloseTypeEnum.CANCEL : CloseTypeEnum.CLOSE, e.getMessage()); + this.saveRecord(trade, useCancel ? CloseTypeEnum.CANCEL : CloseTypeEnum.CLOSE, e.getMessage()); if (e instanceof PayFailureException) { throw e; } @@ -107,75 +100,54 @@ public class PayCloseService { } /// 超时自动关单(幂等) - /// - /// 供 MQ 延时消息消费者 [cn.daxpay.open.payment.core.trade.mq.NormalPayTimeoutConsumer] - /// 与兜底定时任务 [cn.daxpay.open.payment.core.trade.job.NormalPayTimeoutJob] 调用。 - /// - /// 与 [#closeOrder] 的区别: - /// - 仅接受 tradeNo 定位, 非 PROCESSING 状态静默返回(幂等, 不抛异常) - /// - closeType 固定 TIMEOUT, 容器态置 EXPIRED(见 [PayUniHandleService#payTimeout]) - /// - 不接受 useCancel, 超时统一走 close - /// - 通道关单失败不阻断本地关闭, 仅记录失败原因, 通道侧由后续同步兜底 public void closeForTimeout(String tradeNo) { PayTrade trade = payTradeManager.findByTradeNo(tradeNo).orElse(null); if (Objects.isNull(trade)) { - // 订单不存在, 静默返回 return; } - // 幂等校验: 仅处理中需超时关闭; 已成功/失败/关闭/撤销 直接返回 if (!Objects.equals(PayFundStatusEnum.PROCESSING.getCode(), trade.getStatus())) { return; } - // 复用与手动关单相同的锁键, 保证两条路径互斥 LockInfo lock = lockTemplate.lock("payment:close:" + trade.getId(), 10000, 50); if (Objects.isNull(lock)) { - // 并发关单进行中, 当前触发交由兜底任务后续补救 log.warn("超时关单获取锁失败(并发关单进行中), 交由兜底任务处理, tradeNo={}", tradeNo); return; } try { - // 加锁后再次校验状态(防止加锁期间已被其他路径处理) trade = payTradeManager.findByTradeNo(tradeNo).orElse(null); if (Objects.isNull(trade) || !Objects.equals(PayFundStatusEnum.PROCESSING.getCode(), trade.getStatus())) { return; } - NormalPayOrder normalOrder = payNormalOrderManager.findById(trade.getContainerId()) - .orElse(null); String errMsg = null; try { - // 处理中: 调用通道关闭策略(超时统一走 close, 不走 cancel) var context = new PayStrategyContext() - .setContainer(normalOrder) .setTrade(trade); AbsPayCloseStrategy strategy = PaymentStrategyFactory.createByProduct( trade.getProduct(), AbsPayCloseStrategy.class); strategy.doBeforeClose(context); strategy.doClose(context, false); } catch (Exception e) { - // 通道关单失败不阻断本地关闭, 通道侧状态由后续同步兜底 errMsg = e.getMessage(); log.warn("超时关单调用通道关闭失败, 仅本地关闭, tradeNo={}", tradeNo, e); } - payUniHandleService.payTimeout(trade, normalOrder); - this.saveRecord(trade, normalOrder, CloseTypeEnum.TIMEOUT, errMsg); + payUniHandleService.payTimeout(trade); + this.saveRecord(trade, CloseTypeEnum.TIMEOUT, errMsg); } finally { lockTemplate.releaseLock(lock); } } - /// 保存关闭记录 - private void saveRecord(PayTrade trade, NormalPayOrder normalOrder, CloseTypeEnum closeType, String errMsg) { + private void saveRecord(PayTrade trade, CloseTypeEnum closeType, String errMsg) { PayCloseRecord record = new PayCloseRecord() .setAppId(trade.getAppId()) .setTradeNo(trade.getTradeNo()) - .setBizTradeNo(Objects.nonNull(normalOrder) ? normalOrder.getBizOrderNo() : null) + .setBizTradeNo(trade.getBizOrderNo()) .setProduct(trade.getProduct()) .setChannel(trade.getChannel()) .setClosed(StrUtil.isBlank(errMsg)) .setCloseType(closeType.getCode()) .setErrorMsg(errMsg); - // 商户号显式赋值, 不依赖线程上下文自动填充(异步通知/定时任务等非HTTP场景上下文缺失会导致填充null) record.setMchNo(trade.getMchNo()); payCloseRecordService.saveRecord(record); } diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PaySyncService.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PaySyncService.java index 637639e4e..0664ee8de 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PaySyncService.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/core/trade/service/PaySyncService.java @@ -1,5 +1,20 @@ package cn.daxpay.open.payment.core.trade.service; +import cn.daxpay.open.payment.common.enums.PayFundStatusEnum; +import cn.daxpay.open.payment.common.enums.PayTradeTypeEnum; +import cn.daxpay.open.payment.core.strategy.PaymentStrategyFactory; +import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; +import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; +import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; +import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; +import cn.daxpay.open.payment.core.trade.dao.NormalPayOrderManager; +import cn.daxpay.open.payment.core.trade.dao.PayTradeManager; +import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; +import cn.daxpay.open.payment.core.trade.entity.PayTrade; +import cn.daxpay.open.payment.core.trade.record.entity.PaySyncRecord; +import cn.daxpay.open.payment.core.trade.record.service.PaySyncRecordService; +import cn.daxpay.open.payment.unipay.param.trade.pay.NormalPaySyncParam; +import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPaySyncResult; import cn.daxpay.open.platform.core.code.CommonErrorCode; import cn.daxpay.open.platform.core.code.DaxPayErrorCode; import cn.daxpay.open.platform.core.exception.BizInfoException; @@ -7,20 +22,6 @@ import cn.daxpay.open.platform.core.exception.PayFailureException; import cn.daxpay.open.platform.core.exception.RepetitiveOperationException; import cn.daxpay.open.platform.core.exception.system.SystemUnknownErrorException; import cn.daxpay.open.platform.core.util.DateTimeUtil; -import cn.daxpay.open.payment.core.strategy.pay.PayStrategyContext; -import cn.daxpay.open.payment.common.enums.PayFundStatusEnum; -import cn.daxpay.open.payment.core.strategy.PaymentStrategyFactory; -import cn.daxpay.open.payment.core.trade.bo.PaySyncResultBo; -import cn.daxpay.open.payment.core.trade.dao.NormalPayOrderManager; -import cn.daxpay.open.payment.core.trade.entity.NormalPayOrder; -import cn.daxpay.open.payment.core.trade.dao.PayTradeManager; -import cn.daxpay.open.payment.core.trade.entity.PayTrade; -import cn.daxpay.open.payment.core.trade.record.entity.PaySyncRecord; -import cn.daxpay.open.payment.core.trade.record.service.PaySyncRecordService; -import cn.daxpay.open.payment.core.strategy.pay.AbsPayCloseStrategy; -import cn.daxpay.open.payment.core.strategy.sync.AbsSyncPayOrderStrategy; -import cn.daxpay.open.payment.unipay.param.trade.pay.NormalPaySyncParam; -import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPaySyncResult; import cn.hutool.core.util.StrUtil; import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; @@ -36,9 +37,6 @@ import java.util.Objects; import java.util.Optional; /// # 支付同步服务 -/// -/// 通道策略层返回同步结果, 本服务负责本地资金凭证(PayTrade)与通道状态对齐, -/// 含: 状态比对、超时主动关网关、成功/失败/关闭调整, 以及同步流水记录持久化 @Slf4j @Service @RequiredArgsConstructor @@ -65,7 +63,7 @@ public class PaySyncService { NormalPayOrder normalOrder = payNormalOrderManager.findByBizOrderNo( param.getBizOrderNo()).orElse(null); if (Objects.nonNull(normalOrder)) { - trade = payTradeManager.findByContainerId(normalOrder.getId()) + trade = payTradeManager.findByContainerId(normalOrder.getId(), PayTradeTypeEnum.NORMAL.getCode()) .orElse(null); } } @@ -90,10 +88,7 @@ public class PaySyncService { throw new RepetitiveOperationException(); } try { - NormalPayOrder normalOrder = payNormalOrderManager.findById(trade.getContainerId()) - .orElse(null); var context = new PayStrategyContext() - .setContainer(normalOrder) .setTrade(trade); var syncStrategy = PaymentStrategyFactory.createByProduct( trade.getProduct(), AbsSyncPayOrderStrategy.class); @@ -105,13 +100,12 @@ public class PaySyncService { boolean statusSync = this.checkAndAdjust(syncResult, trade); if (!statusSync) { try { - this.adjustHandler(syncResult, trade, normalOrder); + this.adjustHandler(syncResult, trade); } catch (PayFailureException e) { syncResult.setSyncSuccess(false).setSyncErrorMsg(e.getMessage()); } } - // 保存同步流水记录(成功/失败均记录) - this.saveRecord(trade, normalOrder, syncResult, !statusSync); + this.saveRecord(trade, syncResult, !statusSync); return new NormalPaySyncResult() .setOrderStatus(trade.getStatus()) .setAdjust(statusSync); @@ -120,20 +114,16 @@ public class PaySyncService { } } - /// 判断本地与通道状态是否一致, 并在本地支付中且超时时标记需要远程关网关 private boolean checkAndAdjust(PaySyncResultBo syncResult, PayTrade trade) { var payStatus = Optional.ofNullable(syncResult.getPayStatus()) .orElse(PayFundStatusEnum.PROCESSING); String orderStatus = trade.getStatus(); - // 本地已失败, 直接返回需要调整 if (orderStatus.equals(PayFundStatusEnum.FAIL.getCode())) { return false; } if (orderStatus.equals(PayFundStatusEnum.PROCESSING.getCode())) { - // 通道也是处理中, 进一步判断是否超时 if (Objects.equals(PayFundStatusEnum.PROCESSING, payStatus)) { if (DateTimeUtil.le(trade.getExpiredTime(), OffsetDateTime.now(ZoneOffset.UTC))) { - // 本地超时且通道订单仍存活, 标记需要主动关闭网关交易 syncResult.setPayStatus(PayFundStatusEnum.CLOSE); syncResult.setRemoteClose(true); return false; @@ -141,36 +131,32 @@ public class PaySyncService { return true; } } else { - // 本地非处理中(已成功/已关闭/已撤销), 视为一致 return true; } return false; } - /// 根据同步结果调整资金凭证状态 - private void adjustHandler(PaySyncResultBo syncResult, PayTrade trade, NormalPayOrder normalOrder) { + private void adjustHandler(PaySyncResultBo syncResult, PayTrade trade) { var payStatus = syncResult.getPayStatus(); if (Objects.isNull(payStatus)) { return; } switch (payStatus) { case PROCESSING -> {} - case SUCCESS -> this.success(trade, normalOrder, syncResult); + case SUCCESS -> this.success(trade, syncResult); case CLOSE -> { - // 通道已关闭 → 本地关闭; 超时(remoteClose) → 主动调用通道关单后本地关闭 if (syncResult.isRemoteClose()) { - this.closeRemote(trade, normalOrder); + this.closeRemote(trade); } else { - payUniHandleService.payClose(trade, normalOrder, false); + payUniHandleService.payClose(trade, false); } } - case FAIL -> payUniHandleService.payFail(trade, normalOrder, syncResult.getSyncErrorMsg()); + case FAIL -> payUniHandleService.payFail(trade, syncResult.getSyncErrorMsg()); default -> throw new SystemUnknownErrorException(); } } - /// 同步成功后更新资金凭证与容器 - private void success(PayTrade trade, NormalPayOrder normalOrder, PaySyncResultBo syncResult) { + private void success(PayTrade trade, PaySyncResultBo syncResult) { trade.setStatus(PayFundStatusEnum.SUCCESS.getCode()); trade.setPayTime(syncResult.getFinishTime()); trade.setCloseTime(null); @@ -186,27 +172,21 @@ public class PaySyncService { payUniHandleService.paySuccess(trade); } - /// 主动关闭网关交易(超时场景), 调用通道关闭策略后置超时关闭态 - /// 资金态置 CLOSE, 容器态置 EXPIRED(见 [PayUniHandleService#payTimeout]), - /// 与 MQ 延时关单 / 兜底定时任务 三条路径统一落点。 - private void closeRemote(PayTrade trade, NormalPayOrder normalOrder) { + private void closeRemote(PayTrade trade) { AbsPayCloseStrategy strategy = PaymentStrategyFactory.createByProduct( trade.getProduct(), AbsPayCloseStrategy.class); var context = new PayStrategyContext() - .setContainer(normalOrder) .setTrade(trade); strategy.doBeforeClose(context); strategy.doClose(context, false); - // 超时关闭: 资金态置 CLOSE, 容器态置 EXPIRED(区分业务语义) - payUniHandleService.payTimeout(trade, normalOrder); + payUniHandleService.payTimeout(trade); } - /// 保存同步流水记录 - private void saveRecord(PayTrade trade, NormalPayOrder normalOrder, PaySyncResultBo syncResult, boolean adjust) { + private void saveRecord(PayTrade trade, PaySyncResultBo syncResult, boolean adjust) { PaySyncRecord record = new PaySyncRecord() .setAppId(trade.getAppId()) .setTradeNo(trade.getTradeNo()) - .setBizTradeNo(Objects.nonNull(normalOrder) ? normalOrder.getBizOrderNo() : null) + .setBizTradeNo(trade.getBizOrderNo()) .setOutTradeNo(trade.getOutOrderNo()) .setOutTradeStatus(Objects.nonNull(syncResult.getPayStatus()) ? syncResult.getPayStatus().getCode() : null) @@ -217,7 +197,6 @@ public class PaySyncService { .setAdjust(adjust) .setErrorCode(syncResult.getSyncErrorCode()) .setErrorMsg(syncResult.getSyncErrorMsg()); - // 商户号显式赋值, 不依赖线程上下文自动填充(异步通知/定时任务等非HTTP场景上下文缺失会导致填充null) record.setMchNo(trade.getMchNo()); paySyncRecordService.saveRecord(record); } diff --git a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/web/unipay/convert/UnipayNormalPayOrderConvert.java b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/web/unipay/convert/UnipayNormalPayOrderConvert.java index f48c8dae2..8393d54aa 100644 --- a/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/web/unipay/convert/UnipayNormalPayOrderConvert.java +++ b/daxpay-payment/daxpay-payment-common/src/main/java/cn/daxpay/open/payment/web/unipay/convert/UnipayNormalPayOrderConvert.java @@ -11,27 +11,26 @@ import org.mapstruct.factory.Mappers; /// /// 将 core 双表(NormalPayOrder 业务容器 + PayTrade 资金凭证)映射为对外契约 NormalPayOrderResult /// 资金态字段(status / outOrderNo / refundableBalance 等)取自 PayTrade, 业务字段取自 NormalPayOrder +/// +/// 仅声明:改名、多源同名消歧、以及目标独有字段的 ignore(由服务层后填或暂不输出) @Mapper public interface UnipayNormalPayOrderConvert { UnipayNormalPayOrderConvert CONVERT = Mappers.getMapper(UnipayNormalPayOrderConvert.class); /// NormalPayOrder + PayTrade → 对外 NormalPayOrderResult + // 改名 @Mapping(target = "orderNo", source = "trade.tradeNo") - @Mapping(target = "outOrderNo", source = "trade.outOrderNo") - @Mapping(target = "otherMethod", source = "trade.otherMethod") - @Mapping(target = "limitPay", source = "trade.limitPay") - @Mapping(target = "refundableBalance", source = "trade.refundableBalance") + // 多源同名消歧:资金态取 trade,业务容器取 order @Mapping(target = "status", source = "trade.status") - @Mapping(target = "provider", source = "trade.provider") - @Mapping(target = "buyerId", source = "trade.buyerId") - @Mapping(target = "errorMsg", source = "trade.errorMsg") + @Mapping(target = "bizOrderNo", source = "order.bizOrderNo") @Mapping(target = "channel", source = "order.channel") @Mapping(target = "method", source = "order.method") @Mapping(target = "amount", source = "order.amount") @Mapping(target = "payTime", source = "order.payTime") @Mapping(target = "closeTime", source = "order.closeTime") @Mapping(target = "expiredTime", source = "order.expiredTime") + // 目标独有字段:源无对应属性,显式 ignore 标明不在此转换 @Mapping(target = "realAmount", ignore = true) @Mapping(target = "refundStatus", ignore = true) NormalPayOrderResult toResult(NormalPayOrder order, PayTrade trade);