Flutter中实现支付宝支付流程

1. 支付宝支付流程

上面的图来自官方的文档,看起来比较繁琐,下面的图是流程的简化版。

简单解释一下流程步骤:

1. 当用户点击支付宝支付的时候,客户端请求App的服务端接口,此时,App的服务端会请求支付宝的服务器获得生成的签名信息返回给客户端;

2. 客户端获取生成的签名信息以后,调用Flutter提供的支付宝SDK,传入签名信息,调起支付宝支付, 用户输入完密码完成支付以后,支付宝的服务器首先会给App返回支付结果,同时,支付宝的服务器还会异步通知App的服务器进行订单更新。

参考:https://opendocs.alipay.com/open/59/103658/

2. Flutter支付插件

参考:https://pub.dev/packages/sy_flutter_alipay

安装插件。

dependencies:
  sy_flutter_alipay: ^0.2.1

在pubspec.yaml中配置保存后,在VS Code环境中会自动下载依赖包。

如果无法正常下载,执行 flutter pub get 。

插件安装完成以后,如果是IOS平台,还需要提前添加urlScheme,步骤如下:

1. 用Xcode打开Flutter项目的IOS端;

2. 添加urlScheme;

注意:urlScheme填写必须要有一定的标识度,最好与App有定的关联,以免支付失败。

3. 服务端调用支付宝SDK生成订单信息

根据服务端所采用的语言,下载对应的SDK。

地址:https://opendocs.alipay.com/open/54/103419/

以PHP为例,以下是参考代码,请注意代码中的注释说明。

<?php 

ini_set('date.timezone','Asia/Shanghai');
header("Access-Control-Allow-Origin: *");
require_once('AopSdk.php');
$aop = new AopClient;
$aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";

// 应用ID(需要配置)
$aop->appId = "2017122101048570";
// 应用私钥(需要配置)
// 请填写开发者私钥去头去尾去回车,一行字符串
$aop->rsaPrivateKey = 'MIIEowIBAAKCAQEA2YqSo7uX27Fdi32MEx2hAmfZUWl19KNovLLEm3P6mlQYkD7+ThVE8468n8meyTBl2QC8YXQVbGANbFdwdcxldDnOUKv7f9VFiaXn+jT0t9hJ00t5HLJ2yY85hMWFhuO+wxIjZdJ82u4dekY7F2T32wC7qIx4dsncPVfCvW4nB8Co6+eVi+PBEkp92HiBk/b4HbjhZxBCe9urbiN9syO5ZlVzAPUDcDvlRVSICv0S9BzWCQPjzxO8sd6jvJ/EFBmbz9VjvFbOkwSoibElY7kShDtAR2Ae/PTzEF2hvOUKVI/hW7T2p7VewgYF1kcPxlLoZJ8Zljxn7EYhMmsfukbPHQIDAQABAoIBAHPUS9XwWaA5ZTSTiZTYDtXoE5c8jvjOVUM78GFRNJsdseKEGAXdX1RLqPVvdiNrqJ8NvEArfgixcBRCznd6eH6VFNxxZj0fgqIS+1yG+9Iz0MM3iWoVQBh8MUUXosw60WSucLiThbVQWdO0N1xyf2JVlpXdDXs6ahEjfGY+k3uVR0No0qIBgwirM2Ofyk3orgBFxXgEbjpoAindpglrqhw2LlMMNb9wwNkjzB/guiYhRu3xOoodstPqcR/FXy0WLRc6W+pxF83E7lPJ22U3DLM2yIc4NQjGxa8Kfkhm0fQUQz5M1akRfk0nj6w8sIjd5XJKgw+Cjosh4EubHVptpyUCgYEA8DzEleQo01hdZqHLeYBghbuEuoFm+N80Xk/7i4Dxlny2R4ZO/sCH3ZURbwcI4kA2WvdScB2Lir9NI10HJNW3xJRjVpumPzfrNxLoYZb+2h0eSS6peIlMAidZyspwGEwLE+jelnMQu8IVbKQ0aTN8tjpKolbpII95Tlq58Ijf8ksCgYEA59CVDkNU+dCufVnLHkOASrd0AGmXMccKeBZfpNlZIdmH9/KBRbXiUec8TWgDwfZg8e//FMCA7r4Y4pj2XZhb+G0M3FfBf2hjKjkqVDEv9+3zYK4zI07ts2WRvkLgY+SvzFYwSEo/U72zka1ocWdDZtiNdXqqAC5DTTc6zIIsozcCgYBPDdAq+v+sPIHPyiIpA2O/3isZLIf0EY8sEenWyEG3oaZh9wJ7tmN/ORSZkpkLytGYMZbBKhfHOphpsK0vI9zrJWFjGKkmWIJghypNIuEOaVKUBnTiI1wNwWE86Ezm0e87SAAnRgoVnxJpw8czbyv0003ICg2BF3V1oUlaq8/17QKBgAD+cvUpsr6Td3wQG3/YuD8ZxESQL1bGTLQxHF3flLNBdITKpGVBH2RMgoSucn2tacL/zW8wWB0t8XtfPocuNQ6+oPR859Z9AxfWQOk1gMgmXAnJFW0MVJaVU+el78Jd46cTo4db0iOwx4lTXgRGdhKF0S10xi/UAvPczcK8uCZHAoGBAN+74UouDYmZaAfzj5O0857ZVHBiXtJ5AasYqbBALZ17EqTjscYcD3nlvWhoX7JtGAyU09fuH23NK6hpi3yk67KUBuJOab+wjjDUIIAveFqjmiaV+Ra727v39d2ide534ikOfz04RDiAUVA43V+a3kdaAXuvTfhF+mczjN3joFtm' ;
$aop->format = "json";
$aop->charset = "UTF-8";
$aop->signType = "RSA2";
// 支付宝公钥
// 请填写支付宝公钥,一行字符串
$aop->alipayrsaPublicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhb/KlxYfhRE8KRp92MQM8ZB8NVjoM9LYFOnPIuNtcMZVA8ld7ybDP2FiA+QEE7wLGqMImwl1Y4xzkrTLCjHVC8fdR8ZvzZR2I3ZOrARerI9+RbkCfT+7YLv55+A+WTHEyiB+v7PfXVTT28s0CHNLPXMyQD1u8UVEQEpbMSs8hH3pJF55Li7kc5VvJpV3RVO9TXZTVAA5mSp9FvO3u+47IJDgFVLnqqHh6ETL1nHVpxiAY2LGer+RWpVYD8v+We+VWsrfJP7bO0xr2pwizldepo8YNYPgcIAIwd7KiveypL1pA0xWgSjUHzrkVh1j/nSnvJgKSdydU/VRcaVt/Mt8wwIDAQAB';//对应填写

// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
$request = new AlipayTradeAppPayRequest();
// SDK已经封装掉了公共参数,这里只需要传入业务参数
$date=date("YmdHis");
// 注意:下面除了body描述不是必填,其他必须有,否则失败
$bizcontent = json_encode(array(
    // 以下数据根据实际项目而定,此处写死了
    'body'=>'我是测试数据',
    // 支付的标题
    'subject' => 'App支付测试111',
    // 支付宝订单号必须是唯一的,不能在支付宝再次使用,必须重新生成,哪怕是同一个订单,不能重复
    // 否则二次支付时候会失败,订单号可以在自己订单那里保持一致,但支付宝那里必须要唯一,具体处理自己操作
    'out_trade_no' => $date.'st11',
    // 过期時間(分钟)
    'timeout_express' => '30m',
    // 金額最好能要保留小数点后两位数
    'total_amount' => '0.01',
    'product_code' => 'QUICK_MSECURITY_PAY'
));

// 在应用那里设置的异步回调地址
$request->setNotifyUrl("http://agent.itying.com/alipay/notify_url.php");

$request->setBizContent($bizcontent);

// 这里和普通的接口调用不同,使用的是sdkExecute
$response = $aop->sdkExecute($request);
echo $response;

// 输出结果
// echo htmlspecialchars($response);

?>

4. 客户端支付的实现

import 'package:flutter/material.dart';
import 'package:sy_flutter_alipay/sy_flutter_alipay.dart';
import 'package:dio/dio.dart';

class AliPay extends StatefulWidget {
    AliPay({Key key}) : super(key: key);
    _AliPayState createState() => _AliPayState();
}

class _AliPayState extends State<AliPay> {
    // 执行支付宝支付
    _doAliPay() async {
        // App服务端的地址(根据业务需要传入对应的参数,此处省略了)
        var serverApi = "http://agent.itying.com/alipay/";

        var serverData = await Dio().get(serverApi);

        var payInfo = serverData.data;
        var result = await SyFlutterAlipay.pay(

            // 请求App服务端获取的签名信息
            payInfo,

            // 前面配置的urlScheme,只对IOS有效
            // urlScheme: '你的ios urlScheme', 

            // 是否是沙箱环境,只对Android有效
            // isSandbox: true  

        );
        // 获取信息以后,跳转到订单列表
        print(result);
    }

    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text('支付宝支付'),
            ),
            body: Center(
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                        RaisedButton(
                            child: Text('支付宝支付'),
                            onPressed: _doAliPay,
                        )
                    ],
                )
            )
        );
    }
}

5. 服务器端异步回调更新订单信息

<?php 

ini_set('date.timezone','Asia/Shanghai');
header("Access-Control-Allow-Origin: *");
require_once('AopSdk.php');
$aop = new AopClient;

// 请填写支付宝公钥,一行字符串;
$aop->alipayrsaPublicKey='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhb/KlxYfhRE8KRp92MQM8ZB8NVjoM9LYFOnPIuNtcMZVA8ld7ybDP2FiA+QEE7wLGqMImwl1Y4xzkrTLCjHVC8fdR8ZvzZR2I3ZOrARerI9+RbkCfT+7YLv55+A+WTHEyiB+v7PfXVTT28s0CHNLPXMyQD1u8UVEQEpbMSs8hH3pJF55Li7kc5VvJpV3RVO9TXZTVAA5mSp9FvO3u+47IJDgFVLnqqHh6ETL1nHVpxiAY2LGer+RWpVYD8v+We+VWsrfJP7bO0xr2pwizldepo8YNYPgcIAIwd7KiveypL1pA0xWgSjUHzrkVh1j/nSnvJgKSdydU/VRcaVt/Mt8wwIDAQAB';
$flag = $aop->rsaCheckV1($_POST, NULL, "RSA2");

file_put_contents('post.txt',json_encode($_POST));
// $flag返回是的布尔值,可以根据这个判断是否支付成功
if($flag){
    // 验证成功
    // 这里可以做一下你自己的订单逻辑处理
    file_put_contents('success.txt',json_encode($_POST));
    // 这个必须返回给支付宝,
    echo 'success';
} else {
    // 验证失败
    file_put_contents('fail.txt','失败');
    echo "fail";
}

?>

当支付成功后,支付宝会异步给服务器发送数据,所以要在支付宝后台提前配置好授权回调地址。

6. 编译错误解决

项目配置成功后,建议首先在Flutter中执行 flutter run , 以便下载相关的依赖。

Xcode上编译打包时可能会提示 :Target 'Runner': script phase “ [CP] Embed Pods Frameworks”。

解决方法:打开Xcode,点击File菜单,选择Workspace Settings,将Build System修改成如下所示的选项。

猜你喜欢

转载自blog.csdn.net/weixin_40629244/article/details/113749005
今日推荐