商城app如何对接国际版支付宝并向国外商户付款?
结论
不能只在国内支付宝后台配置一个境外商户账号,就让现有 app支付 订单自动结算给该商户。也不建议境外商户将私钥交给商城,再由 App 根据店铺切换 CLIENT_ID 或密钥。
这类业务属于“跨境收单+境外商户入驻及结算”。如果商城内有多个商户,还会涉及平台型或 marketplace 型支付。商城应先请支付宝、Antom(具体品牌和产品名称以签约地区为准)或具备跨境资质的支付服务商确认资金链路,再选择合适的模式:
- 平台收款后向境外商户结算:用户先向商城平台付款,平台再依法向境外商户结算。这会涉及跨境结算、外汇、税务和平台资质,不能仅靠支付接口完成。
- 平台型收单或分账结算:境外商户先以子商户身份入驻支付机构。创建订单时,平台传入对应的商户或分账信息,由支付机构按照合同结算。
- 境外商户独立收款:每家商户分别签约并使用自己的收款配置,商城只负责技术接入。平台能否统一代接,需要支付机构明确授权。
具体选择哪种方案,取决于商城主体注册地、消费者所在地、境外商户所在国家或地区、交易币种、商品类型,以及平台是否参与资金结算。
为什么现有国内支付宝支付不能直接复用
国内支付宝 app支付 的商户号、应用、公私钥和签约产品都与特定签约主体绑定。订单最终进入哪个收款主体,通常由商户签约关系和支付产品决定,不能由前端随意填写一个支付宝账号来指定。
因此,下面两种理解都不准确:
- 在国内支付宝后台添加境外商户账号:普通商户后台通常不能将任意境外账号配置为订单收款方。
- 让境外商户提供私钥,商城重新开发一套支付代码:取得密钥并不代表商城拥有跨境收款、代接入或结算资格,而且私钥原则上不应交给无关主体。
即使境外商户使用某种“国际版支付宝”,也不能只凭名称判断应该接入哪个接口。它可能指支付宝面向境外用户的版本、支付宝合作钱包,也可能指 Antom/Alipay+ 体系下的商户服务。这几类产品的接入方式和资金结算方式并不相同。
推荐的实施步骤
1. 先说明完整的业务模式
联系支付宝、Antom 或支付服务商时,应提供完整的交易链路:
消费者所在地区:
商城运营主体及注册地:
境外商户所在国家或地区:
商品类型:
支付币种:
境外商户希望收到的币种:
退款和拒付责任方:
商城是否收取佣金:
商城是否接触或暂存交易资金:
预计月交易额和客单价:
其中要明确消费者是中国内地用户还是境外用户。用户钱包、收单主体和结算对象不同,对应的支付产品也会不同。
2. 申请平台或跨境收单方案
如果商城内有多家境外商户,应优先确认支付机构是否支持以下能力:
- 平台商户和子商户入驻;
- 境外商户 KYC/KYB 审核;
- 多币种计价与结算;
- 按订单指定子商户;
- 分账、佣金和结算;
- 退款、部分退款及拒付处理;
- 对账单和结算单下载;
- 境外商户没有开发能力时的平台代接入模式。
不要先根据某个接口名称自行开发。只有完成商务审核并确定产品,才能确认订单字段、签名方式和结算规则。
3. 让境外商户完成入驻审核
常见资料可能包括:
- 公司注册证明、商业登记证或同类主体证明;
- 法定代表人及最终受益人信息;
- 董事和联系人身份证明;
- 经营地址和联系方式;
- 网站、店铺页面或商品说明;
- 业务模式及交易场景说明;
- 境外收款银行账户证明;
- 预计交易规模、交易币种及结算币种;
- 退款、隐私、配送和消费者争议政策;
- 特殊行业所需的许可证;
- 平台与境外商户之间的合作协议。
不同国家、地区、行业和签约主体的要求各不相同,最终资料清单应以收单机构的 KYC/KYB 要求为准。仅有一个“国际支付宝账号”,通常不足以完成商户入驻。
4. 按签约模式设计凭证管理
常见的凭证管理方式有两种。
平台模式
商城使用平台的 CLIENT_ID 或应用身份调用 API,境外商户则作为子商户存在。创建订单时,后端传入 subMerchantId、merchantAccountId 或含义相同的字段。
商户直连模式
每家境外商户拥有独立的商户身份,并授权商城代为接入。不同商户的配置应相互隔离并保存在服务端。平台是否可以保存和使用这些配置,必须符合支付机构的授权规则。
无论采用哪种模式,都应遵守以下要求:
- 私钥和 API 密钥不能存放在 App 中;
- 商户私钥不应通过聊天工具或邮件传输;
- App 只能接收当前订单生成的支付凭证或跳转链接;
- 后端必须验证异步通知签名和订单金额;
- 收款主体不能由客户端提交的参数决定。
参考技术架构
商城 App
│ 创建订单
▼
商城业务后端
│ 校验商品、商户、币种和金额
│ 查询已审核的境外商户配置
▼
支付接入服务
│ 使用平台服务端凭证签名
│ 创建跨境支付订单
▼
支付机构 / 收单机构
│
├─ 返回 paymentUrl、paymentToken 或 SDK 参数
▼
商城 App 完成付款
支付机构 ──异步通知──> 商城后端
商城后端 ──主动查询──> 支付机构
支付机构 ──按合同约定──> 境外商户结算账户
境外商户没有开发能力,并不影响采用这种模式。商城可以负责订单系统和支付接口开发,境外商户则负责签约、完成入驻审核、提供结算账户,以及处理履约和售后。
服务端示例
下面的代码仅用于说明如何在订单中绑定已经通过审核的境外商户,不对应某个确定的支付宝或 Antom 接口。实际 API 地址、字段名称、签名算法和必填参数,应以签约后取得的官方文档为准。
public PaymentResponse createPayment(CreateOrderRequest request) {
Order order = orderService.get(request.getOrderId());
Merchant merchant = merchantService.get(order.getMerchantId());
if (!merchant.isPaymentApproved()) {
throw new IllegalStateException("Merchant is not approved for cross-border payment");
}
if (!order.getAmount().equals(request.getAmount())) {
throw new IllegalArgumentException("Invalid order amount");
}
CrossBorderPaymentRequest payment = new CrossBorderPaymentRequest();
payment.setRequestId(order.getPaymentRequestId());
payment.setOrderId(order.getOrderNo());
payment.setAmount(order.getAmount());
payment.setCurrency(order.getCurrency());
// 只能取服务端保存并通过审核的商户标识
payment.setSubMerchantId(merchant.getProviderMerchantId());
payment.setDescription(order.getDescription());
payment.setNotifyUrl(config.getPaymentNotifyUrl());
payment.setReturnUrl(config.getPaymentReturnUrl());
return paymentGateway.createPayment(payment);
}
处理异步通知时,至少要核验签名、金额、币种、商户归属和订单状态:
public void handlePaymentNotification(
String body,
Map<String, String> headers) {
if (!paymentGateway.verifyNotification(body, headers)) {
throw new SecurityException("Invalid notification signature");
}
PaymentNotification notification =
paymentGateway.parseNotification(body);
Order order = orderService.get(notification.getOrderId());
if (!order.getAmount().equals(notification.getAmount())
|| !order.getCurrency().equals(notification.getCurrency())
|| !order.getMerchantId().equals(
merchantService.findByProviderMerchantId(
notification.getSubMerchantId()).getId())) {
throw new IllegalStateException("Payment notification mismatch");
}
// 必须保证重复通知不会重复入账或发货
orderService.markPaidIdempotently(
order.getId(),
notification.getPaymentId());
}
前端不能接受任意收款方参数,再将其原样传给支付接口。例如,下面的设计存在越权收款风险:
{
"orderId": "ORDER_10001",
"payeeAccount": "user_input_account@example.com"
}
前端只应提交订单标识。后端再根据商品与店铺的绑定关系确定收款商户:
{
"orderId": "ORDER_10001"
}
关于 CLIENT_ID、公钥和私钥
境外商户是否需要提供 CLIENT_ID,取决于最终的签约模式,不能在商务方案确定前一概而论。
- 如果商城以平台身份接入,通常使用平台自己的服务端凭证。境外商户提供入驻资料,以及审核通过后的子商户标识。
- 如果境外商户独立签约,支付机构可能会为其生成相应的应用或接口身份,但商城必须获得明确授权后才能代为使用。
- 公钥可用于验签,通常不属于敏感秘密。私钥和 API Secret 是敏感凭证,不应要求商户直接发送给开发人员。
- App 包内不能存放私钥,否则私钥可能在反编译后被提取,进而造成伪造订单或资金损失。
- 不应让 App 根据商品动态切换多套商户密钥。多商户路由必须由后端按照已经审核的绑定关系完成。
还需要重点确认的问题
-
结算不等于支付成功
支付成功只表示消费者已经付款。境外商户何时收到款项、收到哪种币种,还取决于结算周期、汇率、手续费和风险准备金。
-
不要自行代收代付
如果商城先收款,再私下向境外商户转账,可能涉及跨境资金、外汇和支付业务合规问题。实施前应取得支付机构以及法律、财税顾问的确认。
-
退款链路必须完整
需要确认由谁发起退款、退款资金从哪里扣除、跨币种退款使用什么汇率,以及商户余额不足时如何处理。
-
订单与商户的绑定关系不能被篡改
商品、店铺、境外商户标识和收款关系应由服务端维护。支付订单创建后,不能只修改前端参数就更换收款方。
-
国内支付与跨境支付应分别建模
两者可以共用商城订单系统,但支付渠道、商户配置、币种、退款、通知和对账逻辑应相互隔离,避免直接在原有国内
app支付代码中堆叠大量条件分支。
实际落地前,应先让支付机构根据完整的资金流,确认可以签约的产品和主体关系,而不是先向境外商户索取密钥。产品确定后,再按照支付机构的平台商户、子商户或商户代接入规范进行开发。
备注:内容仅供参考。
