出海外卖平台:支付对接为什么要和下单收款分开

出海外卖平台 集成当地支付时,若下单写入口与回调处理耦死在同一分支,沙箱未通就会阻塞整单状态机。宜拆「订单领域」与「支付适配层」,各国通道按需插件化。

结论

下单创建 order 不依赖 payment_provider;支付成功事件异步推进 status,未配置通道时 front 展示明确不可用。

typescript 复制代码
interface PaymentAdapter {
  createSession(orderId: string): Promise<PaySession>;
  verifyWebhook(body: string, headers: Headers): PaymentEvent;
}

PaymentAdapter 注册表按 country 注入;订单服务仅依赖 adapter 接口,不 import 具体 SDK。

实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。

一、订单状态机独立验收

mock_pay 模式下,用户提交订单 → 待支付 → 模拟支付 → 已支付 → 商家可见。全程不调用真实网关。回归用例固定 order_id golden 集。

mock_pay profile 走内存 adapter,回归用例不触网。

实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。

二、回调 idempotent

同一 gateway_tx_id 重复回调只处理一次。验签失败记 dead letter,不 silently 丢弃。

java 复制代码
if (paymentRepo.existsByGatewayTxId(txId)) {
  return Response.ok();
}
orderService.applyPaymentSuccess(orderId, txId);

webhook 验签失败入 DLQ,监控告警。

实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。

三、多国家 profile

配置中心按 country_code 加载 adapter bean。沙箱 merchant_id 与生产分离,环境变量打标,防止试跑写入生产。

config namespace payment.* 与 i18n.* 权限分离。

实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。

四、语言包与支付解耦

i18n key 变更不触发支付重测;但币种展示变更需回归 amount 格式化与导出列。

amount format 变更需回归 export 列。

实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。

五、导出与对账

export 含 currency、pay_channel、gateway_tx_id 列,财务按国别 pivot。各国规则不同,列映射宜配置化而非硬编码。

export 含 currency、channel、gateway_tx_id。

实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。

六、光合同城边界

海外版成品含下单链路与支付底座;具体通道按国定制。商务结算规则由客户确定,系统侧不抽成客户平台订单;不写全球统一自动分账。

各国税务展示字段配置化,不写死默认国。

七、组合验收顺序

阶段 A:mock 支付下跑通下单→paid→商家可见→finished→export。阶段 B:sandbox adapter 小额支付,验签 webhook,重复 notify 幂等。阶段 C:换目标语言 bundle,只回归 UI 与 export_locale,不重测支付。阶段 D:生产 profile 小额单三处留证。禁止在 A 未绿时启动 D,否则问题混杂难排查。

各国 payment adapter 实现统一接口,禁止在 orderService 内 import 某国 SDK。配置中心变更 payment profile 需 audit;回滚 profile 不应回滚语言 bundle 指针。退款 consumer 与支付 success consumer 分 topic,避免乱序覆盖状态。

八、小结

先 golden 单走状态,再挂各国 adapter 沙箱,最后生产小额。下单与收款分开验收,缩短阻塞面。

未接通道时 front 宜 disable 按钮并提示,而非点击后 500。退款走独立事件,避免与支付成功竞态覆盖状态。

退款事件独立 consumer,避免覆盖 paid 状态。

相关推荐
开开心心就好1 分钟前
音频降噪剪辑工具,音量裁剪一键处理
运维·服务器·前端·spring·ocr·音视频·1024程序员节
jarvisuni2 分钟前
白嫖Tripo3D ?Kimi 3D Make可以玩起来!
人工智能·ai编程
梦影_7 分钟前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
考虑考虑7 分钟前
mariadb数据库
数据库·后端·mariadb
niucloud-admin11 分钟前
NIUCLOUD PHP SAAS上门家政使用文档--服务订单:订单列表
开发语言·php
一枕槐安48713 分钟前
大模型限流、重试、超时处理:API 调用健壮性方案
linux·服务器·php·大模型api·指数退避·限流控制·超时预算
西索斯coding19 分钟前
gpt-image-2.5-sunburst 和 gemini-3.1-flash-image 差多少?60 组项目素材的成功成本评测框架
java·linux·gpt·ai
明月_清风30 分钟前
用自然语言操控真机:Google Artemis 移动端 AI Agent 上手与实践
人工智能·后端
怪我冷i32 分钟前
Rust 的impl语法详解
开发语言·后端·rust
李纲明44 分钟前
WordPress 白屏或提示「出现了严重错误」:先开 WP_DEBUG 抓致命错误,再二分插件与主题
运维·php·debug·wordpress·白屏·插件冲突·devdiy