flutter App 跳转支付宝小程序

944 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

需求:

flutter App 跳转支付宝小程序,完成支付。

背景

插件tobias可以完成的功能是,app支付的时候,打开支付宝app进行支付(需要再支付宝开放平台注册,签名信息后台开发回返回的),使用小程序支付,可以在提现的时候,降低费率,处于这一需求,需要完成app跳转支付宝小程序进行支付,打开小程序后的支付,属于小程序的内部功能,我们今天的研究点,就是完成app跳转支付宝小程序。

准备工作

支付宝

# 外部跳转到小程序

image.png

scheme实现方式

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')}");