开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
需求:
flutter App 跳转支付宝小程序,完成支付。
背景
插件tobias可以完成的功能是,app支付的时候,打开支付宝app进行支付(需要再支付宝开放平台注册,签名信息后台开发回返回的),使用小程序支付,可以在提现的时候,降低费率,处于这一需求,需要完成app跳转支付宝小程序进行支付,打开小程序后的支付,属于小程序的内部功能,我们今天的研究点,就是完成app跳转支付宝小程序。
准备工作
支付宝
URL 格式
alipays://platformapi/startapp?appId=[appId]&page=[page]&query=[query]
相关参数的具体含义,请参考官方文档。 以上分析,支付宝小程序是支持外部app打开的。
跳转到调试中未上架的小程序版本
支付宝调试的时候,可跳转任意状态(测试,体验,发布)的版本,需要点击联调版本右上角胶囊的三个点,选择 联调设置,然后打开跳转开关即可。官方文档
代码编写
由于本次要实现的功能比较少,所以没有专门开发一个插件,集成这个功能,直接在项目里定义并调用了。 定义渠道,目的是跳转支付宝小程序:
flutter 代码
import 'package:flutter/services.dart';
// 渠道名称可自己定义,唯一就好
final MethodChannel _channel = const MethodChannel('flutterChannel');
// 跳转至支付宝
Future jumpToAliMini(String path) async {
// 调用各平台对应的jumpToAliMini方法
return await _channel.invokeMethod("jumpToAliMini", {"path":path});
}
ios端
我们直接在AppDelegate.swift中编写对应的代码
private func flutterCallNative(){
// 注册渠道
let controller:FlutterViewController = window.rootViewController as! FlutterViewController
// flutterCallNative 为Flutter中的声明的渠道名
let channel = FlutterMethodChannel(name: "flutterChannel", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { (call, res) in
print("正在执行原生方法,传入的参数是:" + call.method)
// 根据函数名做不同的处理
switch(call.method) {
// 这里就是Flutter中声名的方法名
case "jumpToAliMini":
// 这里为了减少方法里的内容又创建了一个新得方法,其实完全可以下面方法的完全的放入到此处
self.jumpToAliMini(call: call, result: res)
default:
res(nil)
}
}
}
private func jumpToAliMini(call: FlutterMethodCall, result: FlutterResult ) {
// 获取传入的参数字典
let params = call.arguments as? NSDictionary
var msg = ""
if (params != nil) {
// 获取具体的参数值
msg = params!["path"] as? String ?? ""
let url = URL(string: msg)
if UIApplication.shared.canOpenURL(url!) {
UIApplication.shared.openURL(url!)
}
}
// 打印日志
print("正在执行原生方法,传入的参数是:" + msg)
// 通知结束
result("调用成功了")
}
上面完成了,渠道的声明,和方法的定义,我们需要在程序启动的时候,执行
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// flutter 调用原生方法
flutterCallNative()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
android 端代码
MainActivity.kt 文件中编写代码,各种包也贴上,避免报错,不是写kt,导入包也找了好一阵😭
import android.os.Bundle
import androidx.annotation.NonNull;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import com.jarvan.fluwx.handlers.FluwxRequestHandler
import com.jarvan.fluwx.handlers.WXAPiHandler
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
val messenger = flutterEngine.dartExecutor.binaryMessenger
// 新建一个 Channel 对象
val channel = MethodChannel(messenger, "flutterChannel")
// 为 channel 设置回调
channel.setMethodCallHandler { call, res ->
// 根据方法名,分发不同的方法
when (call.method) {
// Flutter中声明的方法名
"jumpToAliMini" -> {
val url = call.argument<String>("path")
var intent = Intent(Intent.ACTION_VIEW,Uri.parse(url));
startActivity(intent);
res.success("这是执行的结果")
}
else -> {
// 如未识别,通知执行失败
res.error("error_code", "error_message", null)
}
}
}
}
至此代码部分已经完成,
使用
在需要得地方,导入对应的flutter文件,使用即可
jumpToAliMini("alipays://platformapi/startapp?appId=${appId}&page=pages/index/index}&query=${Uri.encodeComponent('orderNo=12345')}");