PAYATHON 2026

一个 APP 内多个第三方 H5 能否使用不同商户账号支付

支付阿杰

结论

可以实现,但不能在支付宝 SDK 中配置两个收款账号,也不能只根据用户当前打开的 H5 页面切换收款方。

“页面 1”和”页面 2”可以对应不同的支付宝商户。每个商户都需要具备合法、有效的支付宝支付产品签约关系。服务端使用对应的商户身份创建订单,再把完整的 APP 支付订单参数交给 APP,由 APP 调用支付宝支付 SDK 完成支付。

资金归属取决于服务端创建订单时使用的商户身份、应用身份和授权关系,与 H5 页面名称或客户端 SDK 配置无关。

如果两个第三方商户无法接入同一个 APP 支付场景,或者缺少相应的应用绑定、产品签约、服务商授权等条件,就不能靠替换 app_id、私钥或收款账号来实现。

为什么可以对应不同商户

支付宝支付 SDK 主要负责调起支付宝客户端、展示收银台和返回支付结果。交易最终归属于哪个商户,由服务端生成并签名的支付请求决定。

典型流程如下:

  1. 用户在”页面 1”提交订单。
  2. 页面通过 APP 提供的 JSBridge,将业务订单号传给原生代码。
  3. APP 请求自己的支付服务端。
  4. 服务端确认该订单属于商户 1。
  5. 服务端使用商户 1 对应的支付宝应用、签约信息或服务商授权信息调用 alipay.trade.app.pay。
  6. 服务端把生成的订单字符串返回给 APP。
  7. APP 调用支付宝 SDK 完成付款。
  8. 支付宝通过异步通知将交易结果发送给服务端。

“页面 2”采用相同流程,只是服务端会选择商户 2 的支付配置或授权上下文。

因此,一个 APP 可以作为统一的支付入口,但不能允许任意 H5 自行指定商户号、私钥、金额或回调地址。

推荐的接入方案

方案一:每个商户使用自己的支付宝应用

两个商户分别完成 APP 支付产品签约,使用各自的 app_id、应用私钥和支付宝公钥创建订单。

服务端根据订单所属商户选择配置:

页面 1订单 -> 商户 1配置 -> 生成 APP 支付订单
页面 2订单 -> 商户 2配置 -> 生成 APP 支付订单

这种方案能否直接用于同一个宿主 APP,需要结合支付宝开放平台对应用主体、APP 信息、支付产品签约和业务场景的要求来确认。不能只创建多个支付宝应用,再由客户端任意切换。

方案二:使用支付宝服务商模式

如果 APP 运营方是支付宝服务商,可以让第三方商户完成授权或进件,再由服务商应用代表对应商户发起交易。

服务端通常需要根据商户选择相应的授权信息,例如 app_auth_token。具体参数和资金结算方式取决于接入的支付产品、服务商模式及商户签约关系,应以实际开放平台配置和当前接口文档为准。

这种模式更适合平台型 APP,商户管理、权限校验和订单路由都可以集中在平台服务端处理。

H5 如何走 APP 支付流程

在 H5 中生成业务订单,不代表必须使用手机网站支付。只要服务端创建的是 APP 支付订单,并由原生 APP 调用支付宝支付 SDK,就可以走 APP 支付流程。

H5 可以通过受控的 JSBridge 请求宿主 APP 发起支付:

window.NativeBridge.requestAlipay({
  orderId: "ORDER_202609090001",
  merchantCode: "merchant_page_1"
});

建议这里只传平台内部的业务订单号。即使页面传入了 merchantCode,也只能把它作为提示信息。服务端必须根据订单记录重新确认真实商户,不能直接信任 H5 参数。

原生 APP 收到请求后,向可信服务端获取支付宝订单字符串:

fun startAlipay(orderId: String) {
    paymentApi.createAppPayOrder(orderId).enqueue { response ->
        val orderInfo = response.orderInfo

        Thread {
            val payTask = PayTask(activity)
            val result = payTask.payV2(orderInfo, true)
            handleSdkResult(result)
        }.start()
    }
}

iOS 侧的调用方式类似:

[[AlipaySDK defaultService] payOrder:orderInfo
                            fromScheme:appScheme
                              callback:^(NSDictionary *resultDic) {
    // SDK 返回结果仅用于界面提示
    // 最终支付状态仍应由服务端确认
}];

orderInfo 必须由服务端生成并签名,不能把商户私钥保存在 H5 或 APP 中,也不能在客户端完成签名。

服务端订单路由示例

下面是一段简化的 Java 伪代码,主要展示如何选择多商户配置:

public String createAppPayOrder(String userId, String orderId) {
    BusinessOrder order = orderRepository.findByOrderId(orderId);

    if (order == null || !order.getUserId().equals(userId)) {
        throw new IllegalArgumentException("Invalid order");
    }

    if (order.getStatus() != OrderStatus.UNPAID) {
        throw new IllegalStateException("Order cannot be paid");
    }

    MerchantConfig config =
        merchantConfigService.getByMerchantId(order.getMerchantId());

    AlipayClient alipayClient = new DefaultAlipayClient(
        config.getGatewayUrl(),
        config.getAppId(),
        config.getMerchantPrivateKey(),
        "json",
        "UTF-8",
        config.getAlipayPublicKey(),
        "RSA2"
    );

    AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
    request.setNotifyUrl(config.getNotifyUrl());

    AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
    model.setOutTradeNo(order.getOrderId());
    model.setSubject(order.getSubject());
    model.setTotalAmount(order.getAmount().toPlainString());
    model.setProductCode("QUICK_MSECURITY_PAY");

    request.setBizModel(model);

    AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

    if (!response.isSuccess()) {
        throw new IllegalStateException("Failed to create Alipay order");
    }

    return response.getBody();
}

如果采用服务商模式,请求中还需要加入目标商户对应的授权信息。具体写法应以所用的支付宝 SDK 版本和接口文档为准。

必须注意的问题

不要让第三方 H5 直接提供支付参数

第三方页面不能直接决定以下内容:

  • app_id
  • 商户身份或授权令牌
  • 支付金额
  • 支付标题
  • out_trade_no
  • notify_url
  • 签名内容
  • 支付宝订单字符串

否则可能导致金额被篡改、商户身份被冒用、重复支付,或订单被转向其他收款方。

H5 应该只提交业务订单号,由服务端根据数据库中的订单信息确定金额和商户。

私钥只能保存在服务端

商户私钥不能写入 H5、JavaScript、Android APK 或 iOS 安装包。客户端代码可以被反编译,H5 内容也能被查看或修改。

订单参数的组装和 RSA2 签名都应在受控服务端完成。

SDK 返回成功不等于最终支付成功

即使客户端收到 resultStatus=9000,也不能立即把业务订单标记为已支付。最终结果应以支付宝异步通知为主,必要时由服务端主动查询交易状态。

处理异步通知时,至少需要校验:

  • 通知签名是否合法;
  • app_id 是否属于预期应用;
  • out_trade_no 是否存在;
  • 订单金额是否一致;
  • 交易对应的商户是否正确;
  • 订单是否已经处理,防止重复入账或重复发货。

“支付到账”和”资金结算”不是同一概念

用户付款后,交易归属于哪个商户,取决于创建交易时使用的商户身份和授权关系。资金何时进入可用余额、何时结算到银行卡,以及是否涉及分账,则取决于支付宝产品规则和商户协议。

如果业务目标是先由用户向平台付款,再按比例分给多个第三方商户,就不能用”切换商户账号”代替分账方案。此时应评估支付宝提供的服务商、分账或资金结算类产品。

WebView 需要限制调用权限

APP 不应允许任意网页调用支付桥接接口。建议校验:

  • 页面域名是否在白名单中;
  • 当前登录用户是否拥有该订单;
  • 订单所属商户是否已启用;
  • 订单金额是否由服务端保存;
  • 同一订单是否正在支付或已经支付;
  • JSBridge 请求是否带有有效的登录态和防重放信息。

最终判断

多个第三方 H5 可以分别对应不同的支付宝商户,也可以通过宿主 APP 已集成的支付宝 SDK 完成 APP 支付。实现方式不是在客户端切换”收款账号”,而是由服务端根据订单所属商户,使用合规的支付宝应用、签约关系或服务商授权创建 alipay.trade.app.pay 订单。

能否正式上线,还要确认两个商户是否都满足支付宝 APP 支付的签约、应用绑定、授权和业务合规要求。如果第三方页面只是随意传入另一个商户的订单信息,却没有相应的平台关系和服务端校验,就不应接入。

备注:内容仅供参考。