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

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

结论

下单创建 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 小时前
MySQL 如何提高查询速度:从索引、SQL、表结构到实战调优
android·sql·mysql
我是人✓1 小时前
Spring框架的事务管理
java·后端·spring
kimnoic1 小时前
Python操作MySQL数据库的两种方式实例分析【pymysql和pandas】
开发语言·python
苏辰澈1 小时前
C++独属于自己的变身:多态
c语言·开发语言·c++·visualstudio·编辑器
谢亮_vipxieliang1 小时前
PHP 异常处理全解析:try-catch、自定义异常与全局异常处理器
开发语言·php
外收内放1 小时前
Python基础语法练习题(65)
开发语言·python
data analyse 4561 小时前
前端自建访问统计,访客标识怎么设计才稳?Cookie、本地存储与设备指纹的取舍
前端·数据分析
浅尝辄止;1 小时前
设计模式在HIS/LIS医疗系统中的完整实践指南(C#版)
开发语言·设计模式·c#
终端安全笔记1 小时前
配置锁状态那一栏查的是什么:报告里几项各自指向什么风险
android·前端·安全·ios