安卓支付宝支付功能的集成,全网最详细教程(2019年8更新)

前言

支付宝最新版本SDK (从 15.5.7 开始)引入方式由以前的JAR包引入更换为 AAR包引入,并且在新的集成方式下我们无需再手动在 AndroidManifest.xml 清单文件中额外配置activity,具体而言支付宝的集成相比微信支付还是比较简洁的,下面我们会从实际项目出发,具体讲解集成过程:

<!-- AAR方式不必再配置以下内容 -->
<activity
    android:name="com.alipay.sdk.app.H5PayActivity"
    android:configChanges="orientation|keyboardHidden|navigation|screenSize"
    android:exported="false"
    android:screenOrientation="behind"
    android:windowSoftInputMode="adjustResize|stateHidden" >
</activity>
 <activity
    android:name="com.alipay.sdk.app.H5AuthActivity"
    android:configChanges="orientation|keyboardHidden|navigation"
    android:exported="false"
    android:screenOrientation="behind"
    android:windowSoftInputMode="adjustResize|stateHidden" >
</activity>
<!-- AAR方式不必再配置以上内容 -->

首先是创建应用获取appkey,签约APP支付,公私钥的配置等准备工作,都很简单,交给运营去搞就行了,需要什么东西我们配合一下即可,本篇我们着重讲下准备工作完成之后的支付功能集成方法,步骤如下:

添加依赖

1,首先下载最新的 AAR 的 SDK 包:https://docs.open.alipay.com/54/104509
2,将下载的 AAR 包拷贝到应用工程的 libs 目录下,然后在 Project 的 build.gradle中添加下面的内容,将 libs 目录作为依赖仓库:

allprojects {
    repositories {

        // 添加下面的内容
        flatDir {
            dirs 'libs'
        }

        // ... jcenter() 等其他仓库
        jcenter()
        maven { url 'https://dl.bintray.com/umsdk/release' }
        maven { url "https://jitpack.io" }
        maven { url "https://maven.google.com"}
    }
}

3,接着在 App 的 build.gradle 中,添加下面的内容,将支付宝 SDK 作为项目依赖:
(注意修改name值和libs下拷贝的AAR文件的名字保持一致)

dependencies {
    // 添加下面的内容
    compile (name: 'alipaySdk-15.5.7-20181023110917', ext: 'aar')
}

至此SDK集成就完成了。
4,添加需要的权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

您需要在 AndroidManifest 里配置以上 3 个权限,支付宝 SDK 在运行时需要进行网络连接,并在必要的时候判断网络连接的状态(4G/Wi-Fi)等来进行支付体验的优化。

API调用

支付宝支付交互流程如下图所示:
在这里插入图片描述
1,从上图我们可以看到,当用户在app点击了支付宝支付按钮之后,首先会向我们自己的后台服务器发送一个请求,获取服务器端经过签名的订单信息,发送请求时可能需要传递商品id和用户身份表示token,然后服务器端根据商品的id和用户身份去实际计算所要支付的费用并生成订单号等信息然后进行签名,最后将结果返回发给客户端,我们的后台返回的信息如下:

{
    "code": 200,
    "msg": "成功",
    "orderinfo": "alipay_sdk=alay-sdk-php-2005&app_id=20190335010&biz_content=%7B%22body%22%3A3D"
    }
}

如上其中orderinfo即为经过服务端签名后的订单信息。
2,客户端app获取到服务端签名之后的订单信息之后,就可以利用支付宝客户端SDK提供的支付对象 PayTask去调起支付宝客户端收银台,支付宝客户端 SDK 将会按照商户客户端提供的请求参数发送支付请求,如下:

final Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(RechargeActivity.this);
                Map<String, String> result = alipay.payV2(orderInfo, true);

//                Logger.d(result.toString());

                Message msg = new Message();
                msg.what = SDK_PAY_FLAG;
                msg.obj = result;
                mHandler.sendMessage(msg);
            }
        };

        // 必须异步调用
        new Thread(payRunnable).start();

其中payV2方法中:参数1orderInfo即为第一步服务端返回的签名后的订单信息,参数2表示:用户在商户app内部点击付款,是否需要一个 loading 做为在钱包唤起之前的过渡,这个值设置为 true,将会在调用 pay 接口的时候直接唤起一个 loading,直到唤起H5支付页面或者唤起外部的钱包付款页面 loading 才消失。(建议将该值设置为 true,优化点击付款到支付唤起支付页面的过渡过程。)

上面的 payV2 方法返回的 result 对于 Android 平台而言是一个 map 集合,其结构如下:

{
    "memo" : "xxxxx",
    "result" : "{
                    \"alipay_trade_app_pay_response\":{
                        \"code\":\"10000\",
                        \"msg\":\"Success\",
                        \"app_id\":\"2014072300007148\",
                        \"out_trade_no\":\"081622560194853\",
                        \"trade_no\":\"2016081621001004400236957647\",
                        \"total_amount\":\"0.01\",
                        \"seller_id\":\"2088702849871851\",
                        \"charset\":\"utf-8\",
                        \"timestamp\":\"2016-10-11 17:43:36\"
                    },
                    \"sign\":\"NGfStJf3i3ooWBuCDIQSumOpaGBcQz+aoAqyGh3W6EqA/gmyPYwLJ2REFijY9XPTApI9YglZyMw+ZMhd3kb0mh4RAXMrb6mekX4Zu8Nf6geOwIa9kLOnw0IMCjxi4abDIfXhxrXyj********\",
                    \"sign_type\":\"RSA2\"
                }",
    "resultStatus" : "9000"
}

里面有三个key,其中 memo 是描述信息(类型为字符串);result 是处理结果(类型为 json 结构字符串);resultStatus 是结果码(类型为字符串)。

关于处理结果result中各参数的说明和resultStatus结果码的说明见官方文档:https://docs.open.alipay.com/204/105301/
3,调用上面的payV2方法完成支付后,将通过2种途径获得支付结果,分别对应客户端同步获得支付结果和服务端异步获得支付结果:

途径1~同步通知:商户应用客户端通过当前调用支付的Activity的Handler对象,通过它的回调函数获取支付结果。

    private static final int SDK_PAY_FLAG = 1;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @SuppressWarnings("unused")
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SDK_PAY_FLAG: {
                    @SuppressWarnings("unchecked")
                    PayResult payResult = new PayResult((Map<String, String>) msg.obj);  
                    String resultInfo = payResult.getResult();// 同步返回需要验签的信息,对应map集合中key为result对应的value值。
                    Logger.d("resultInfo"+resultInfo);
                    String resultStatus = payResult.getResultStatus();
                    if (TextUtils.equals(resultStatus, "9000")) {
                        // 同步通知验证,在返回数据resultStatus为9000的情况下,继续解析resultInfo字符串,进行验签
                        ToastUtil.showShort(RechargeActivity.this, "验签通过后才能证明支付成功:" + payResult);
                    }else if(TextUtils.equals(resultStatus, "6001")){
                        ToastUtil.showShort(HuiyuanActivity.this, "支付取消");
                    }else { 
                        ToastUtil.showShort(RechargeActivity.this, "支付失败:" + payResult);
                    }
                    break;
                }
                default:
                    break;
            }
        }

    };

4,同步通知验签(客户端验证)
在同步通知返回数据 resultStatus 为9000的情况下,还需要解析resultInfo 结果进行验签操作,resultInfo的值即为上述map集合的result对应的value值,验签通过后并对返回的参数做合法性效验,都通过后才能确定该笔订单是真的支付成功了,具体的客户端同步通知验证验签操作见官方文档:https://docs.open.alipay.com/204/105301/ ,中同步通知验证部分的描述。

途径2~异步通知:对于App支付产生的交易,支付宝会根据原始支付 API 中传入的异步通知地址 notify_url,通过 POST 请求的形式将支付结果作为参数通知到商户后台。

5,异步通知验签(服务端验证)
例如某商户设置的通知地址为 https://api.xx.com/receive_notify.htm ,客户端支付成功后,对应接收到异步通知的示例如下:

https://api.xx.com/receive_notify.htm?total_amount=2.00&buyer_id=2088102116773037&body=大乐透2.1&trade_no=2016071921001003030200089909&refund_fee=0.00&notify_time=2016-07-19 14:10:49&subject=大乐透2.1&sign_type=RSA2&charset=utf-8&notify_type=trade_status_sync&out_trade_no=0719141034-6418&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47&trade_status=TRADE_SUCCESS&version=1.0&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=&gmt_create=2016-07-19 14:10:44&app_id=2015102700040153&seller_id=2088102119685838&notify_id=4a91b7a78a503640467525113fb7d8bg8e

其中参数部分的trade_status参数代表交易状态,值为TRADE_SUCCESS时代表交易成功,同样的服务端在交易成功的前提下也需要对通知返回回来的参数进行验签操作,验签通过后并对返回的部分参数做合法性效验,都通过后才能确定该笔订单是真的支付成功了。


支付宝官方建议:

同步返回的数据,商户可以按照上面描述的方式在服务端验证,验证通过后,可以即可认为本次用户付款成功。但有些时候会出现商户App在支付宝付款阶段被关闭导致无法正确收到同步结果,此时支付结果可以完全依赖服务端的异步通知。

由于同步通知和异步通知都可以作为支付完成的凭证,且异步通知支付宝一定会确保发送给商户服务端。为了简化集成流程,商户可以将同步结果仅仅作为一个支付结束的通知(忽略执行校验),实际支付是否成功,完全依赖服务端异步通知。

其实意思就是:对于支付结果的判断,必须依赖服务端的异步通知结果,同步通知结果仅用作支付结束的通知,上面简化集成流程的意思是如果以服务器端异步通知的结果作为最终判断的话,就可以省略在客户端进行同步通知验签的过程即上面的第4步,因为在服务器端也有类似的异步验签操作,代码示例如下:

    private static final int SDK_PAY_FLAG = 1;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @SuppressWarnings("unused")
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SDK_PAY_FLAG: {
                    @SuppressWarnings("unchecked")
                    PayResult payResult = new PayResult((Map<String, String>) msg.obj);
                    /**
                     * 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
                     */
                    String resultInfo = payResult.getResult();
                    String resultStatus = payResult.getResultStatus();
                    // 判断resultStatus,
                    if (TextUtils.equals(resultStatus, "9000") || TextUtils.equals(resultStatus, "8000") || TextUtils.equals(resultStatus, "6004")) {
                        // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
                        Bundle data = msg.getData();
                        String orderno = data.getString("orderno");
                        checkOrder(orderno);
                    }else if(TextUtils.equals(resultStatus, "6001")){
                        ToastUtil.showShort(RechargeActivity.this, "支付取消");
                    } else {
                        // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                        ToastUtil.showShort(RechargeActivity.this, "支付失败");
                    }
                    break;
                }
                default:
                    break;
            }
        }

    };

在这里插入图片描述
可以看到在上面resultStatus值为9000等值的情况下,继续调用了checkOrder(orderno);方法,该方法就是对后台自己新增的一个根据订单号查询实际订单状态的一个接口,参数为本次交易的订单号,该订单号的获取我们可以通过解析 resultInfo 字符串中out_trade_no对应的值来获取,当然了你如果嫌解析out_trade_no获取订单号的方式比较麻烦的话,可以在第一步通过接口获取签名后的订单信息的时候让后台新增一个字段,把订单号设置进返回的结果中,如下:

{
    "code": 200,
    "msg": "成功",
    "data": {
        "orderno": "G806572813565727",
        "orderinfo": "alipay_sdk=alay-sdk-php-2005&app_id=20190335010&biz_content=%7B%22body%22%3A3D"
    }
}

然后在调起支付宝app的时候将订单号信息通过msg进行传递,最后在Handle中进行处理即可:

final Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(RechargeActivity.this);
                Map<String, String> result = alipay.payV2(orderInfo, true);

                Logger.d("map"+result);

//                Logger.d(result.toString());

                Message msg = new Message();
                msg.what = SDK_PAY_FLAG;
                msg.obj = result;
                //利用bundle对象来传递订单号
                Bundle b = new Bundle();
                b.putString("orderno", orderno);
                msg.setData(b);

                mHandler.sendMessage(msg);
            }
        };

        // 必须异步调用
        new Thread(payRunnable).start();

ok,支付宝支付集成到这里就讲完了,相比于微信支付虽然两者差不多,但是因为微信支付会回调一个默认的Activity,给人感觉没有支付宝支付简洁,关于微信支付可以参见另一篇文章,谢谢支持!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智玲君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值