最近在使用小程序多端框架做一个 APP,业务上除了要接入微信支付,还需要接入支付宝支付。通过研究了解到多端框架支持原生插件,也就是说支付宝接入的部分可以用原生来实现,都到这了,收拾收拾开搞了。
考虑到要同时在 iOS 和 Android 两个平台接,这就需要写两个原生插件,一个个的来。
一、 iOS 接入过程
参考多端应用插件使用指引,先创建一个空白的多端插件项目
这个项目是个自带的插件开发模板
按照模拟器中的步骤操作,第 1 是安全设置要打开「多端插件服务端口」
自己的mac 电脑要安装 xcode(必须的,要不然你怎么原生开发?),在工具栏顶部选择「iOS-运行」,应该会拉起 Xcode打开项目
什么也不用管,直接点击播放按钮
会拉起一个iphone 模拟器
点按钮「点击加载多端插件」,然后点击「点击调用多端插件」,可以正常互动,这个示例模板运行很正常。
研究一下这里的代码,在 Xcode 里,MyPlugin 目录中会写一些开放的方法,比如mySyncFunc
然后在开发者工具里,可以看到在调用这个声明的函数
这就完成了一个调用,而声明的 myAsyncFuncwithCallback 则是一个异步的方法,基本的情况都考虑到了。
简单的示例能够跑通,接下来开始做支付宝接入,支付宝这个 SDK 依赖我们用 CocoaPods 来管理,在开发者工具里 iOS 目录搞一个新文件,名字叫「Podfile」
然后粘贴一下代码:
platform :ios, '11.0'
target 'wx换成插件id' do
pod "MyPlugin", :path => "."
pod 'WechatOpenSDK'
end
插件 id 需要自己替换,这个插件申请可以在「微信开发者平台」自己小程序的多端应用中申请,获得插件 ID 后就可以拿来用了。
然后再新建一个「MyPlugin.podspec」文件,粘贴下面的代码
Pod::Spec.new do |spec|
spec.name = 'MyPlugin'
spec.version = '1.0.0'
spec.summary = 'Summary of MyPlugin'
spec.homepage = 'https://your-framework-website.com'
spec.author = { 'Your Name' => 'your@email.com' }
spec.source = { :git => 'https://github.com/your/repo.git', :tag => "#{spec.version}" }
# Set your deployment target
spec.ios.deployment_target = '11.0'
# 引入 Open SDK
spec.dependency 'WechatOpenSDK-XCFramework'
# 引入 支付宝 SDK
spec.dependency 'AlipaySDK-iOS', '~> 15.8.16'
end
在 iOS 目录右键打开终端,运行命令「pod install」,发现有很多告警,基本都是配置被覆盖了
关闭 Xcode,点击 NativePlugin.xcworkspace 来打开项目
可按照使用 CocoaPods 开发 iOS 插件 | 微信开放文档这个文档来操作消掉告警
消掉之后就这样子了
支付宝 SDK 依赖引入进来了,接下来就开始写支付宝插件的代码,在 Xcode 的「MyPlugin.mm」文件中写就可以。
这里我把代码示例写了一下,大家可以自己取用
#import
#import
#import "WeAppNativePlugin.framework/WeAppNativePlugin.h"
#import "MyPlugin.h"
# import
__attribute__((constructor))
static void initPlugin() {
[MyPlugin registerPluginAndInit:[[MyPlugin alloc] init]];
};
@implementation MyPlugin
// 声明插件ID
WEAPP_DEFINE_PLUGIN_ID(wx9a790b5a7ff816c6)
// 声明插件同步方法
WEAPP_EXPORT_PLUGIN_METHOD_SYNC(mySyncFunc, @selector(mySyncFunc:))
// 声明插件异步方法
WEAPP_EXPORT_PLUGIN_METHOD_ASYNC(myAsyncFuncwithCallback, @selector(myAsyncFunc:withCallback:))
// 声明插件异步方法
WEAPP_EXPORT_PLUGIN_METHOD_ASYNC(doAliPayOrderwithCallback, @selector(doAliPayOrder:withCallback:))
- (id)mySyncFunc:(NSDictionary *)param {
NSLog(@"mySyncFunc %@", param);
return @"mySyncFunc";
}
- (void)myAsyncFunc:(NSDictionary *)param withCallback:(WeAppNativePluginCallback)callback {
NSLog(@"myAsyncFunc %@", param);
callback(@{ @"a": @"1", @"b": @[@1, @2], @"c": @3 });
}
- (void)doAliPayOrder:(NSDictionary *)param withCallback:(WeAppNativePluginCallback)callback {
// 获取支付相关参数
NSLog(@"doAliPayOrder %@", param);
NSString *orderString = [param objectForKey:@"orderString"];
NSString *appScheme = [param objectForKey:@"appScheme"];
NSString *universalLink = [param objectForKey:@"universalLink"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme
fromUniversalLink:universalLink callback:^(NSDictionary *resultDic) {
NSLog(@"reslut = %@", resultDic);
}];
}
// 插件初始化方法,在注册插件后会被自动调用
- (void)initPlugin {
NSLog(@"initPlugin");
[self registerAppDelegateMethod:@selector(application:openURL:options:)];
[self registerAppDelegateMethod:@selector(application:continueUserActivity:restorationHandler:)];
}
// 处理支付宝 URL Scheme 回调
- (void)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {
if ([url.host isEqualToString:@"safepay"]) {
//跳转支付宝客户端进行支付,处理支付结果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@", resultDic);
}];
}
}
// 处理支付宝 Universal Link 回调
- (void)application:(UIApplication *)application continueUserActivity:
(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> *__nullable restorableObjects))restorationHandler {
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
[[AlipaySDK defaultService] handleOpenUniversalLink:userActivity standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@", resultDic);
}];
}
}
@end
还是点击 Xcode 的播放按钮,顺利的话还是会 build success
在 iPhone 的模拟器里再试一下加载和使用,还是可以运行(我保留了示例的代码)
下面我们可以在开发者工具里,ios 的 page 页面尝试调用一下我们写的支付宝方法
这个使用还是看自己实现,
涉及到的 Universal Links 文档可参考:
插件项目: 小程序文档 - 支付宝文档中心
多端项目:Universal Link 配置 | 微信开放文档
appScheme 的设置路径:
插件项目: xcode -> 项目名称 -> info -> URL Types。
多端项目:默认已配置「移动应用id」,自定义要在「project.miniapp.json -> ios -> 应用配置(info.plist 相关)-> URL Types -> URL Schemes」中
原生到多端的通信差不多就搞定了,接下来就需要融入自己的业务了,这个就不继续分享了,大家继续!
二、 Android 接入过程
Android 插件的过程,可参考Android 原生插件开发指引 | 微信开放文档用示例项目先跑一遍,跑通了之后再替换支付宝支付
这里粘贴 PluginManager.kt 文件的关键代码(插件ID的获取方式看 iOS 的步骤)
package com.donut.wx替换你自己的插件ID
import android.app.Activity
import com.alipay.sdk.app.PayTask
import com.tencent.luggage.wxa.SaaA.plugin.AsyncJsApi
import com.tencent.luggage.wxa.SaaA.plugin.NativePluginBase
import com.tencent.luggage.wxa.SaaA.plugin.NativePluginInterface
import com.tencent.luggage.wxa.SaaA.plugin.SyncJsApi
import org.json.JSONObject
class TestNativePlugin: NativePluginBase(), NativePluginInterface {
private val TAG = "TestNativePlugin"
override fun getPluginID(): String {
android.util.Log.e(TAG, "getPluginID")
return BuildConfig.PLUGIN_ID
}
@SyncJsApi(methodName = "mySyncFunc")
fun test(data: JSONObject?, activity: Activity): String {
android.util.Log.i(TAG, data.toString())
// 从 data 中获取 orderInfo
val orderInfo = data?.getString("orderInfo")
// 创建一个 Runnable 来处理支付
val payRunnable = Runnable {
val alipay = PayTask(activity)
val result = alipay.payV2(orderInfo, true)
// 处理支付结果
handlePayResult(result.toString())
}
val payThread = Thread(payRunnable)
payThread.start()
return "Payment initiated"
}
@AsyncJsApi(methodName = "myAsyncFuncwithCallback")
fun testAsync(data: JSONObject?, callback: (data: Any) -> Unit, activity: Activity) {
android.util.Log.i(TAG, data.toString())
// 从 data 中获取 orderInfo
val orderInfo = data?.getString("orderInfo")
// 创建一个 Runnable 来处理支付
val payRunnable = Runnable {
val alipay = PayTask(activity)
val result = alipay.payV2(orderInfo, true)
// 发送状态消息到 JS
val values1 = HashMap()
values1["status"] = "testAsync start"
this.sendMiniPluginEvent(values1)
// 处理支付结果并通过回调返回
val resultMessage = handlePayResult(result.toString())
callback(resultMessage)
}
// 启动支付线程
val payThread = Thread(payRunnable)
payThread.start()
}
private fun handlePayResult(result: String): String {
// 处理支付结果
android.util.Log.i(TAG, "支付结果: $result")
// 这里可以解析 result 字符串并根据支付结果进行相应的处理
// 返回处理后的结果
return result // 或者根据需要返回更具体的信息
}
}
另外在 plugin 目录的build.gradle中,需要导入支付宝 sdk,然后build和asyc
dependencies {
implementation "androidx.exifinterface:exifinterface:1.1.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api "androidx.constraintlayout:constraintlayout:1.1.3"
api 'com.google.android.material:material:1.0.0'
api 'com.alipay.sdk:alipaysdk-android:+@aar'
compileOnly("com.tencent.luggage:wxa-standalone-open-runtime-SaaA-plugin-sdk:$saaaSDKVersionDepend") {}
}
开发者工具里的插件加载和方法调用和 iOS 的差不多,不展示了
Android的插件重点就是:先跑通官方给的示例插件项目,然后自己再换支付宝的代码,因为 CPU 类型和系统类型大家都不太一致,所以没有分享的很详细,只是给个大概。所以如果遇到报错或与文档描述不一致,就专注于解决报错就可以了。