PAYATHON 2026

已入驻服务商账号如何签约并集成支付宝 APP 支付 SDK?

支付小周

结论

如果已入驻为支付宝服务商的账号无法直接签约商户收款产品,需要改用具备商户身份、且与实际收款主体一致的支付宝账号签约 APP 支付。

签约通过后,在支付宝开放平台创建或配置应用,并将应用与签约商户绑定。商户服务端通过支付宝开放平台接口生成支付订单,再由商户 APP 调用支付宝 APP 支付 SDK 拉起支付宝完成付款。

支付完成后,SDK 会把同步结果返回商户 APP,但这个结果不能作为支付成功的最终依据。最终支付状态必须以商户服务端的查询结果或支付宝异步通知为准。

为什么服务商账号无法直接签约

服务商账号主要用于帮助其他商户开发、代运营或提供技术服务,不等同于实际收款商户。APP 支付涉及商户主体认证、收款产品签约和资金结算,通常需要由实际收款主体对应的商户账号签约。

系统提示“需要更换账号签约”,一般表示当前账号的身份或主体不符合该收款产品的签约条件。修改 SDK 参数无法解决这个问题,因为 SDK 只负责拉起支付,不能代替商户签约或应用授权。

如果服务商需要为多个商户提供支付能力,应根据实际业务模式选择普通商户直连或服务商代商户接入。这两种模式的应用关系、授权方式、资金结算和接口参数不同,不能混用。

接入流程

1. 使用实际收款商户账号签约

退出当前服务商账号,改用符合以下条件的支付宝账号登录并签约:

  • 账号已经完成企业或个体工商户认证。
  • 认证主体与实际收款、结算主体一致。
  • 账号具备对应收款产品的签约资格。
  • APP 业务、经营类目和提交资料符合签约要求。

如果目前没有符合条件的账号,应由实际经营主体注册并认证商户账号。签约入口的名称和所需审核材料可能随开放平台调整,请以签约页面的实际展示为准。

2. 创建并配置开放平台应用

在完成签约的主体下创建移动应用,取得 app_id,并完成以下配置:

  • 应用公钥或支付宝公钥模式;
  • 应用私钥,由商户安全保存;
  • 支付宝公钥或支付宝公钥证书;
  • 应用包名、签名或 Bundle Identifier 等客户端信息;
  • 服务端异步通知地址 notify_url;
  • APP 支付产品能力。

应用还需要按平台要求提交审核并上线。签约成功不代表任意应用都能立即发起正式支付,应用主体、产品签约关系和应用配置必须相互对应。

3. 在服务端创建支付订单

支付参数和签名必须由商户服务端生成。应用私钥、订单金额计算逻辑和签名过程都不能放进 APP。

下面的 Java 示例展示了服务端生成 APP 支付订单字符串的基本结构。具体的 SDK 版本、证书模式和初始化方式,应以项目实际使用的支付宝开放平台 SDK 为准。

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi.alipay.com/gateway.do",
    APP_ID,
    APP_PRIVATE_KEY,
    "json",
    "UTF-8",
    ALIPAY_PUBLIC_KEY,
    "RSA2"
);

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl("https://example.com/api/alipay/notify");

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject("订单商品名称");
model.setOutTradeNo("ORDER_202609130001");
model.setTotalAmount("99.00");
model.setProductCode("QUICK_MSECURITY_PAY");

request.setBizModel(model);

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (!response.isSuccess()) {
    throw new IllegalStateException(
        "创建支付宝支付订单失败:" + response.getSubMsg()
    );
}

String orderString = response.getBody();

需要注意:

  • out_trade_no 在商户系统内必须唯一。
  • total_amount 应由服务端根据订单计算,不能直接采用客户端上传的金额。
  • notify_url 必须是支付宝服务器可以访问的 HTTPS 地址。
  • orderString 是已经签名的支付参数。服务端应将它返回给商户 APP,再交由 APP 支付 SDK 使用。
  • 正式环境使用 https://openapi.alipay.com/gateway.do。沙箱环境有不同的网关和账号体系,不能与正式环境的配置混用。

4. APP 使用 SDK 发起支付

Android 端取得服务端返回的 orderString 后,可以调用 APP 支付 SDK:

Runnable payRunnable = () -> {
    PayTask payTask = new PayTask(activity);
    Map<String, String> result = payTask.payV2(orderString, true);

    activity.runOnUiThread(() -> {
        String resultStatus = result.get("resultStatus");

        if ("9000".equals(resultStatus)) {
            // 仅表示客户端返回成功状态,仍需向商户服务端查询最终结果
            queryOrderFromMerchantServer();
        } else {
            // 取消、处理中或失败等情况,也建议由服务端核实订单状态
            showPaymentPendingOrFailed(resultStatus);
        }
    });
};

Thread payThread = new Thread(payRunnable);
payThread.start();

iOS 端通常这样调用:

[[AlipaySDK defaultService]
    payOrder:orderString
    fromScheme:@"merchantAppScheme"
    callback:^(NSDictionary *resultDic) {
        NSString *resultStatus = resultDic[@"resultStatus"];

        if ([resultStatus isEqualToString:@"9000"]) {
            // 客户端结果不能作为最终入账依据
            [self queryOrderFromMerchantServer];
        } else {
            [self showPaymentPendingOrFailed:resultStatus];
        }
    }];

fromScheme 必须与 iOS 工程中注册的 URL Scheme 一致,否则用户从支付宝返回商户 APP 时可能失败。SDK 的具体引入方式、平台权限和回跳配置,应按照所用 SDK 版本的接入说明处理。

5. 服务端接收异步通知

支付宝会向 notify_url 发送支付状态通知。商户服务端收到通知后,应按以下顺序检查:

  1. 使用支付宝公钥或证书验证签名。
  2. 检查 app_id 是否属于当前应用。
  3. 检查 out_trade_no 是否存在,并确认它对应正确的订单。
  4. 核对 total_amount、币种和商户身份是否与本地订单一致。
  5. 判断交易状态是否符合业务定义的支付成功条件。
  6. 以幂等方式更新订单,避免重复通知导致重复发货。
  7. 按接口要求返回成功响应。

示意代码如下:

Map<String, String> params = parseRequestParams(request);

boolean valid = AlipaySignature.rsaCheckV1(
    params,
    ALIPAY_PUBLIC_KEY,
    "UTF-8",
    "RSA2"
);

if (!valid) {
    response.getWriter().print("failure");
    return;
}

String outTradeNo = params.get("out_trade_no");
String tradeStatus = params.get("trade_status");
String totalAmount = params.get("total_amount");
String appId = params.get("app_id");

if (!APP_ID.equals(appId)) {
    response.getWriter().print("failure");
    return;
}

Order order = orderService.findByOrderNo(outTradeNo);
if (order == null || !order.getAmount().toPlainString().equals(totalAmount)) {
    response.getWriter().print("failure");
    return;
}

if ("TRADE_SUCCESS".equals(tradeStatus)
        || "TRADE_FINISHED".equals(tradeStatus)) {
    orderService.markPaidIdempotently(outTradeNo);
}

response.getWriter().print("success");

这段代码只说明处理顺序。实际项目还需要检查通知中的商户身份、交易号等重要字段,并使用与项目 SDK 相匹配的验签方法。使用证书模式时,验签的初始化方式和参数也会不同。

6. APP 展示最终结果

用户从支付宝返回 APP 后,可以先显示“支付结果确认中”,再调用商户自己的订单查询接口:

GET /api/orders/ORDER_202609130001/payment-status

商户服务端根据本地订单状态返回结果。如果异步通知还没有到达,服务端可在必要时调用支付宝交易查询接口核实,然后向 APP 返回以下状态之一:

  • 支付成功;
  • 支付处理中;
  • 支付失败或订单已关闭。

即使遇到网络中断、用户未正常回跳、客户端结果被篡改或异步通知延迟,商户仍可通过服务端确认并维护可靠的订单状态。

服务商参与开发时如何处理账号关系

服务商可以承担 SDK 集成和服务端开发工作,但收款能力必须归属于正确的商户主体。常见接入方式有两种:

  • 商户直连:由商户账号签约并创建应用,服务商取得必要的开发权限后为商户完成接入。
  • 服务商代商户接入:由服务商创建第三方应用,商户完成授权后,服务商根据授权信息代商户调用接口。

服务商代商户接入需要相应的平台能力和商户授权,不能简单地把服务商账号的 app_id 与商户账号的密钥组合使用。app_id、应用私钥、支付宝公钥或证书以及商户授权关系,必须属于同一套有效配置。

注意事项

  • 客户端返回的 resultStatus=9000 不能单独作为发货或记账依据。
  • 私钥只能保存在服务端,不能写入 Android 或 iOS 安装包。
  • 不要让客户端生成 out_trade_no、决定订单金额或拼接签名参数。
  • 同一订单的支付通知可能重复到达,订单更新和发货操作必须保证幂等。
  • 用户取消支付不代表订单一定没有支付,最终仍应以服务端订单状态为准。
  • 正式环境与沙箱环境的应用、密钥、账号和网关必须配套使用。
  • 更换签约账号后,需要重新核对应用所属主体、产品签约关系和密钥配置,不能继续使用原服务商账号下与新主体不匹配的参数。
  • 如果页面允许提交签约,但审核未通过,应根据页面提示的主体、类目或材料问题进行处理。如果页面明确提示服务商身份不受支持,则需要改用实际收款商户账号,或申请符合业务模式的服务商代商户能力。

备注:内容仅供参考。