PAYATHON 2026

境外网站接入支付宝支付时API是否通用?

支付老李

结论

境内版支付宝与面向境外商户的国际支付产品使用的支付 API 并不通用。

两者的签名机制、请求结构或支付流程可能相似,但产品权限、接口名称、网关地址、商户号体系、币种与结算方式、参数要求、异步通知和 SDK 配置都可能不同。境内接口代码通常不能只替换商户号,就直接用于境外网站。

国际版 API 应以支付宝国际业务的官方开发者中心为准,可从以下入口查找:

  • 支付宝全球商户平台:https://global.alipay.com/
  • Alipay+ 开发者文档:https://docs.alipayplus.com/

具体使用哪个入口,要看签约主体、收单机构和已开通的产品。如果服务商提供了专属接入门户或文档,应优先使用签约渠道提供的资料。

为什么不能直接共用

境内版与国际版主要有以下区别:

  1. 商户体系不同

    境内接口通常面向中国境内的支付宝商户。国际业务可能使用全球商户账号、合作伙伴账号,或者由收单机构分配的商户标识。

  2. 支付产品不同

    境内网站常用电脑网站支付、手机网站支付等产品。境外商户接入的可能是支付宝跨境支付或 Alipay+ 产品。即便用户最终通过支付宝付款,服务端调用的接口也未必相同。

  3. 网关与认证配置可能不同

    接口域名、客户端 ID、商户私钥、平台公钥、证书和签名算法都要以对应产品文档为准,不能直接沿用境内环境的配置。

  4. 交易参数不同

    国际业务通常还会涉及交易币种、结算币种、汇率、地区、收单市场和合规信息。境内接口中的某些参数,在国际产品中可能不存在,也可能有不同的含义。

  5. 退款和通知规则不同

    支付查询、退款、撤销、关闭交易及异步通知的接口名称、状态值和验签方式也可能不同。

接入步骤

1. 先确认签约主体和目标市场

首先需要明确:

  • 商户主体注册在哪个国家或地区;
  • 网站主要面向哪些国家或地区;
  • 用户使用支付宝还是其他 Alipay+ 钱包;
  • 交易币种和结算币种;
  • 由支付宝直接收单,还是通过第三方支付服务商收单。

这些条件决定了应该申请哪种产品,不能只看网站是否部署在境外。服务器位于境外,不代表一定要使用国际版。更重要的是商户主体、签约关系和实际业务场景。

2. 确认已经开通的支付产品

登录签约所用的商户平台,在产品列表或开发者配置中核对:

  • 产品名称;
  • API 文档入口;
  • 测试环境和生产环境;
  • 商户标识或客户端 ID;
  • 支持的币种、国家和支付方式;
  • SDK 及其版本要求。

如果还没有签约,应先联系支付宝国际业务或有资质的收单服务商,确认准入条件。

3. 按国际版文档创建应用

通常需要完成以下配置:

  • 创建应用或商户接入项目;
  • 获取商户标识;
  • 配置密钥或证书;
  • 设置支付结果通知地址;
  • 设置支付完成后的跳转地址;
  • 开通测试环境;
  • 完成上线审核或申请生产权限。

不同产品的字段名称和操作流程可能不同,应以商户后台的实际页面为准。

4. 分别实现支付和回调验签

典型流程如下:

用户提交订单
    ↓
商户服务端创建支付请求
    ↓
跳转至收银台或调用支付组件
    ↓
用户完成付款
    ↓
支付平台向商户发送异步通知
    ↓
商户验签并主动查询交易状态
    ↓
更新订单并执行发货

不要只根据浏览器的跳转结果把订单标记为已支付。订单的最终状态应通过验签成功的异步通知确认,必要时还要调用交易查询接口核实。

代码示例

不同国际支付产品的接口名称和请求字段不完全一致。下面的代码只用于说明推荐的服务端结构。API_ENDPOINT、请求参数和签名规则必须替换成所签约产品文档中的实际值。

import crypto from "node:crypto";

function signPayload(payload, privateKey) {
  const content = JSON.stringify(payload);

  return crypto
    .sign("RSA-SHA256", Buffer.from(content, "utf8"), privateKey)
    .toString("base64");
}

async function createPayment(order, config) {
  const payload = {
    merchantOrderId: order.id,
    orderAmount: {
      currency: order.currency,
      value: order.amount
    },
    paymentRedirectUrl: config.returnUrl,
    paymentNotifyUrl: config.notifyUrl
  };

  const signature = signPayload(payload, config.privateKey);

  const response = await fetch(config.apiEndpoint, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Client-Id": config.clientId,
      "Signature": signature
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    throw new Error(`Payment API returned HTTP ${response.status}`);
  }

  return response.json();
}

代码中的 merchantOrderId、orderAmount、Client-Id 和 Signature 仅用于展示结构,不能据此判断它们适用于所有支付宝国际产品。开发时应直接使用官方 SDK,或者严格按照对应的 API 文档构造请求。

回调处理还需要完成验签、金额校验和幂等控制:

async function handlePaymentNotification(req, config) {
  const rawBody = req.rawBody;
  const signature = req.headers["signature"];

  if (!verifySignature(rawBody, signature, config.alipayPublicKey)) {
    throw new Error("Invalid payment notification signature");
  }

  const notification = JSON.parse(rawBody);

  const order = await findOrder(notification.merchantOrderId);
  if (!order) {
    throw new Error("Order not found");
  }

  if (
    notification.orderAmount.currency !== order.currency ||
    notification.orderAmount.value !== order.amount
  ) {
    throw new Error("Payment amount mismatch");
  }

  if (order.status === "PAID") {
    return;
  }

  const payment = await queryPaymentFromProvider(notification.paymentId);

  if (payment.status === "SUCCESS") {
    await markOrderAsPaid(order.id, payment);
  }
}

回调报文必须按照平台规定的方法验签。是否需要使用原始请求体、请求头的具体名称,以及代表交易成功的状态值,都应以实际产品文档为准。

注意事项

  • 不要混用境内开放平台和国际商户平台生成的密钥、证书或商户号。
  • 接口名称相似,不代表两套 API 可以互换。
  • 金额应按文档规定的单位和精度处理,避免使用浮点数直接计算货币。
  • 必须校验商户订单号、支付状态、金额和币种。
  • 回调处理必须具备幂等性,避免重复通知导致重复发货。
  • 测试环境与生产环境的网关、账号和密钥通常需要单独配置。
  • 网站还要符合目标市场对隐私、税务、反洗钱和消费者保护的要求。
  • 如果通过第三方收单机构接入,应使用该机构提供的 API,此时未必会直接调用支付宝官方接口。

接入时不应直接把境内版支付代码迁移到境外网站。应先确认签约产品,再根据对应的国际商户后台和官方开发者文档完成开发。

备注:内容仅供参考。