PAYATHON 2026

客户端SDK支付API传入alipays协议链接为何不跳转?

支付小周

结论

客户端 SDK 的支付 API 通常不能接收 alipays:// 协议链接。它需要的是服务端生成并签名的支付订单字符串,而不是用于唤起支付宝客户端的 URL Scheme。

把 alipays://... 直接传给支付 API,无法跳转到带有 alipay_sdk=alipay-sdk-php-20161101&app_id=xxx 等参数的页面。具体应按业务目标选择处理方式:

  • 如果要使用支付宝 App 支付,由服务端创建订单并完成签名,再把返回的 orderString 交给客户端 SDK 的支付 API。
  • 如果要打开 alipays:// 链接,应使用操作系统或容器提供的 URL 跳转能力,而不是支付 API。

原因

支付 API 和协议链接用途不同:

  1. 支付 API 接收支付宝 App 支付订单参数,也就是由 app_id、method、biz_content、sign 等参数组成的已签名字符串。
  2. alipays:// 是支付宝客户端的私有协议,用于尝试唤起支付宝并打开指定功能。
  3. 支付 SDK 不会把传入的内容当作普通 URL 解析,也不会自动把协议链接转换为支付订单。

alipay_sdk=alipay-sdk-php-20161101 只是请求参数之一,不能说明传入的内容就是客户端支付 API 可以执行的订单。支付 API 要求订单字符串合法、完整,并且签名正确。

推荐解决方案:使用标准 App 支付流程

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

服务端调用支付宝 App 支付接口,设置业务参数后使用应用私钥签名。下面的 PHP 代码只展示典型结构,具体类名和配置方式应以项目实际使用的支付宝 SDK 为准:

<?php

$aop = new AopClient();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = 'your_app_id';
$aop->rsaPrivateKey = 'your_application_private_key';
$aop->alipayrsaPublicKey = 'your_alipay_public_key';
$aop->signType = 'RSA2';
$aop->format = 'json';
$aop->charset = 'UTF-8';

$request = new AlipayTradeAppPayRequest();

$bizContent = [
    'subject' => '订单标题',
    'out_trade_no' => 'your_unique_order_no',
    'total_amount' => '0.01',
    'product_code' => 'QUICK_MSECURITY_PAY',
];

$request->setBizContent(
    json_encode($bizContent, JSON_UNESCAPED_UNICODE)
);
$request->setNotifyUrl('https://example.com/alipay/notify');

$response = $aop->sdkExecute($request);

// 将 $response 原样返回给客户端,不要再次拼接或重新编码。
echo $response;

私钥必须保存在服务端,不能写入客户端代码。

2. 将订单字符串传给客户端 SDK

以 Android 支付 SDK 的常见调用方式为例:

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

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

        // 客户端结果只能用于界面提示,
        // 最终支付状态应由服务端异步通知或主动查询确认。
    });
};

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

这里的 orderString 必须是服务端 SDK 生成的完整签名结果,不能换成 alipays://... 链接。

如果确实需要打开 alipays:// 链接

这类链接应交给系统的 URL 打开能力处理。

Android 示例:

try {
    Intent intent = new Intent(
        Intent.ACTION_VIEW,
        Uri.parse(alipaysUrl)
    );
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // 未安装支付宝,或当前系统无法处理该协议。
}

iOS 示例:

NSURL *url = [NSURL URLWithString:alipaysURL];

if ([[UIApplication sharedApplication] canOpenURL:url]) {
    [[UIApplication sharedApplication] openURL:url
                                       options:@{}
                             completionHandler:nil];
} else {
    // 未安装支付宝,或当前应用配置不允许查询、打开该协议。
}

如果代码运行在 WebView、小程序或其他应用容器中,还要确认容器是否允许打开自定义 Scheme。出于安全考虑,部分环境会拦截 alipays://。

注意事项

  • 不要在客户端生成支付签名。应用私钥只能保存在服务端。
  • 不要随意对服务端返回的订单字符串进行 URL 解码、重新编码或参数重排,否则可能导致验签失败。
  • alipays:// 能否打开,取决于操作系统、设备是否安装支付宝,以及宿主应用或容器的安全策略。
  • iOS 使用 canOpenURL: 时,可能需要在 Info.plist 中配置相应 Scheme。具体要求取决于系统版本和应用实现。
  • Android 某些版本在查询目标应用时可能涉及包可见性配置,但直接打开与查询能力的要求并不完全相同,需要按实际调用方式检查。
  • 客户端返回 支付成功 只能用于界面提示,不能作为最终入账依据。最终状态应以支付宝异步通知的验签结果为主,必要时由服务端调用订单查询接口确认。
  • 如果这里的客户端 SDK 不是支付宝官方 App 支付 SDK,而是第三方框架的封装,还需核对其支付 API 参数定义,并确认它是否提供独立的 URL Scheme 跳转接口。

备注:内容仅供参考。