PAYATHON 2026

Cordova 生成 iOS 后支付宝支付 SDK 方法不执行怎么办?

支付小周

结论

Cordova 生成 iOS 工程后,如果支付宝 SDK 方法没有执行,通常不是支付接口失效,而是调用链中的某个环节没有接通。常见原因包括:

  • JavaScript 调用没有正确桥接到 Cordova 原生插件;
  • 插件类名、方法名与 plugin.xml 配置不一致;
  • 支付宝 SDK 没有完整链接,或缺少必要的系统依赖;
  • Info.plist、URL Scheme 或应用回调没有配置;
  • 原生调用没有在主线程执行;
  • Cordova 重新生成 iOS 工程时覆盖了手工配置。

排查时,先确认原生插件方法是否收到调用,再检查 SDK 调用和支付结果回调。如果一开始只检查支付宝参数,很容易把桥接问题误认为支付问题。

第一步:确认 JavaScript 调用已经发出

Cordova 通常通过 cordova.exec 调用原生插件:

cordova.exec(
  function (result) {
    console.log('支付成功或已返回结果:', result);
  },
  function (error) {
    console.error('支付调用失败:', error);
  },
  'AlipayPlugin',
  'pay',
  [orderString]
);

需要核对以下内容:

  • AlipayPlugin 是否与插件注册的服务名完全一致;
  • pay 是否与原生端暴露的方法名完全一致;
  • orderString 是否为空;
  • 调用是否发生在 deviceready 之后。

建议等 deviceready 触发后再调用:

document.addEventListener('deviceready', function () {
  console.log('Cordova is ready');
}, false);

如果 cordova 未定义,或者代码在 deviceready 之前执行,原生方法可能根本不会触发。

第二步:检查 Cordova 插件注册

插件的 plugin.xml 需要同时配置 JavaScript 服务名和 iOS 原生类。例如:

<platform name="ios">
    <config-file target="config.xml" parent="/*">
        <feature name="AlipayPlugin">
            <param name="ios-package" value="AlipayPlugin" />
        </feature>
    </config-file>

    <source-file src="src/ios/AlipayPlugin.m" />
    <header-file src="src/ios/AlipayPlugin.h" />
</platform>

对应的 Objective-C 类可以这样写:

#import <Cordova/CDVPlugin.h>

@interface AlipayPlugin : CDVPlugin

- (void)pay:(CDVInvokedUrlCommand *)command;

@end

先在实现中加入日志,确认代码是否进入原生方法:

#import "AlipayPlugin.h"
#import <AlipaySDK/AlipaySDK.h>

@implementation AlipayPlugin

- (void)pay:(CDVInvokedUrlCommand *)command
{
    NSLog(@"[AlipayPlugin] pay method invoked");

    NSString *orderString = [command.arguments firstObject];

    if (orderString.length == 0) {
        CDVPluginResult *result =
            [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
                             messageAsString:@"orderString is empty"];

        [self.commandDelegate sendPluginResult:result
                                    callbackId:command.callbackId];
        return;
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [[AlipaySDK defaultService] payOrder:orderString
                                 fromScheme:@"your_app_scheme"
                                   callback:^(NSDictionary *resultDic) {
            CDVPluginResult *result =
                [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                             messageAsDictionary:resultDic];

            [self.commandDelegate sendPluginResult:result
                                        callbackId:command.callbackId];
        }];
    });
}

@end

如果 Xcode 控制台没有出现 pay method invoked,问题在 Cordova 桥接层。此时应继续检查:

  • 插件是否已安装到当前 iOS 平台;
  • config.xml 中是否有对应的 <feature>;
  • 原生类是否加入了正确的 Target;
  • 类名、服务名和方法名的大小写是否一致;
  • JavaScript 传入的 action 是否确实是 pay。

第三步:确认支付宝 SDK 已正确加入工程

如果代码已经进入原生方法,但执行支付宝 SDK 调用时没有反应,需要检查 SDK 的集成状态:

  1. 在 Xcode 的 Target Membership 中确认 SDK 文件属于当前应用 Target。
  2. 检查 Build Phases > Link Binary With Libraries,确认 SDK 及其要求的系统依赖已经加入。
  3. 如果使用 CocoaPods 管理 SDK,应打开 .xcworkspace,不要继续使用 .xcodeproj。
  4. 清理构建缓存后重新编译:
Product > Clean Build Folder

如果静态库包含 Objective-C Category,可能需要在以下位置:

Build Settings > Other Linker Flags

加入:

-ObjC

其他链接参数应以当前支付宝 SDK 的接入文档和实际链接错误为准。没有依据时,不建议加入 -all_load,否则可能产生重复符号问题。

如果控制台出现 unrecognized selector、symbol not found、Undefined symbols 或动态库加载失败,应先处理链接和依赖问题。

第四步:配置 URL Scheme

支付完成后,支付宝通过 URL Scheme 返回应用。fromScheme 的值必须与 Xcode 中配置的 Scheme 完全一致。

例如,调用时使用:

fromScheme:@"your_app_scheme"

那么 Info.plist 的 CFBundleURLTypes 中也要配置相同的值:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>alipay</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>your_app_scheme</string>
        </array>
    </dict>
</array>

Scheme 最好使用应用唯一标识的一部分,避免与其他应用冲突。不要填写 https://,也不要在 Scheme 后面添加 ://。

URL Scheme 配置错误通常不会阻止支付页面拉起,但可能导致支付完成后无法返回应用,或者应用收不到最终回调。

第五步:处理应用回调

不同版本的 Cordova、iOS 和支付宝 SDK 可能使用不同的应用生命周期接口。无论使用哪个接口,应用收到支付宝返回的 URL 后,都需要把它交给支付宝 SDK 处理。

Objective-C 示例:

#import <AlipaySDK/AlipaySDK.h>

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
    if ([url.host isEqualToString:@"safepay"]) {
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url
                                                 standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"Alipay result: %@", resultDic);
        }];
        return YES;
    }

    return NO;
}

如果工程使用 Scene 生命周期,可能还需要在 SceneDelegate 中处理 URL:

- (void)scene:(UIScene *)scene
    openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
{
    NSURL *url = URLContexts.allObjects.firstObject.URL;
    if (url == nil) {
        return;
    }

    [[AlipaySDK defaultService] processOrderWithPaymentResult:url
                                             standbyCallback:^(NSDictionary *resultDic) {
        NSLog(@"Alipay result: %@", resultDic);
    }];
}

具体使用哪个入口,要看当前工程是否启用了 UIScene,以及所用 Cordova iOS 版本如何转发应用事件。不要随意同时修改多个生命周期文件,以免影响 Cordova 自身的 URL 分发逻辑。

第六步:区分“方法没执行”和“回调没执行”

这两种情况的排查方向不同。

如果原生入口日志没有输出:

NSLog(@"[AlipayPlugin] pay method invoked");

问题多半出在 Cordova 插件注册、JavaScript 调用时机或类名映射上。

如果有入口日志,但支付宝界面没有拉起,应检查:

  • orderString 是否有效;
  • SDK 是否正确链接;
  • 调用是否在主线程执行;
  • Xcode 控制台是否出现运行时异常;
  • 真机是否安装了可用的支付宝客户端;
  • 当前 SDK 是否支持所用的模拟器架构。

如果支付宝能够拉起,但结果没有返回,应检查:

  • URL Scheme 是否一致;
  • AppDelegate 或 SceneDelegate 是否收到了 URL;
  • URL 是否传给了 processOrderWithPaymentResult;
  • Cordova 是否拦截或覆盖了 URL 回调。

Cordova 工程的特殊注意事项

不要只在 platforms/ios 生成目录中手工添加 SDK 或修改配置。执行以下命令后,目录可能重新生成,手工修改也可能被覆盖:

cordova platform remove ios
cordova platform add ios
cordova prepare ios

更稳妥的方式是把这些内容写入 Cordova 插件:

  • SDK 文件声明;
  • Framework 和系统库依赖;
  • Info.plist 修改;
  • URL Scheme;
  • -ObjC 等构建参数;
  • 原生源文件和资源文件。

如果目前只能手工集成,应记录每一项 Xcode 配置,并在重新生成 iOS 平台后逐项核对。

推荐的最短排查顺序

沿着调用链逐层添加日志:

deviceready
    ↓
cordova.exec
    ↓
原生插件 pay 方法
    ↓
支付宝 SDK payOrder
    ↓
支付宝客户端或支付页面
    ↓
AppDelegate / SceneDelegate 收到 URL
    ↓
processOrderWithPaymentResult
    ↓
Cordova JavaScript 成功或失败回调

最后出现日志的位置,通常就是正常环节与故障环节的分界点。按这个顺序检查,可以判断问题出在 Cordova 桥接、SDK 集成、支付参数还是应用回调配置,不必反复更换 SDK 或订单参数。

备注:内容仅供参考。