Android 集成支付宝第三方登录

前言:

在集成支付宝支付的时候遇到一点小麻烦,先在此记录供大家参考

1.授权

支付宝第三方登录需要在后台进行授权,在查看授权的时候我们一定要看清楚时候真的已经获得了权限(我在没有获取权限的情况下集成的效果是提示系统繁忙),进入支付宝开放平台的后台管理中心,点击应用,
点击这里
这里写图片描述
未签约的需要填写一些信息。

2,代码集成

其实相对于微信而言,支付宝的代码集成一般都是比较简单的。下载其官网的demo。
点击进入demo页面
然后我们重点来看下PayDemoActivity这里类的相关方法:

/**
 *  重要说明:
 *  
 *  这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
 *  真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
 *  防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; 
 */
public class PayDemoActivity extends FragmentActivity {

    /** 支付宝支付业务:入参app_id */
    public static final String APPID = "";

    /** 支付宝账户登录授权业务:入参pid值 */
    public static final String PID = "";
    /** 支付宝账户登录授权业务:入参target_id值 */
    public static final String TARGET_ID = "";

    /** 商户私钥,pkcs8格式 */
    /** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */
    /** 如果商户两个都设置了,优先使用 RSA2_PRIVATE */
    /** RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE */
    /** 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成, */
    /** 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1 */
    public static final String RSA2_PRIVATE = "";
    public static final String RSA_PRIVATE = "";

    private static final int SDK_PAY_FLAG = 1;
    private static final int SDK_AUTH_FLAG = 2;

    @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 为9000则代表支付成功
                if (TextUtils.equals(resultStatus, "9000")) {
                    // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
                    Toast.makeText(PayDemoActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                } else {
                    // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                    Toast.makeText(PayDemoActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
                }
                break;
            }
            case SDK_AUTH_FLAG: {
                @SuppressWarnings("unchecked")
                AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);
                String resultStatus = authResult.getResultStatus();

                // 判断resultStatus 为“9000”且result_code
                // 为“200”则代表授权成功,具体状态码代表含义可参考授权接口文档
                if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                    // 获取alipay_open_id,调支付时作为参数extern_token 的value
                    // 传入,则支付账户为该授权账户
                    Toast.makeText(PayDemoActivity.this,
                            "授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                            .show();
                } else {
                    // 其他状态值则为授权失败
                    Toast.makeText(PayDemoActivity.this,
                            "授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

                }
                break;
            }
            default:
                break;
            }
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay_main);
    }

    /**
     * 支付宝支付业务
     * 
     * @param v
     */
    public void payV2(View v) {
        if (TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))) {
            new AlertDialog.Builder(this).setTitle("警告").setMessage("需要配置APPID | RSA_PRIVATE")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            //
                            finish();
                        }
                    }).show();
            return;
        }

        /**
         * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
         * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
         * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; 
         * 
         * orderInfo的获取必须来自服务端;
         */
        boolean rsa2 = (RSA2_PRIVATE.length() > 0);
        Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);
        String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

        String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
        String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);
        final String orderInfo = orderParam + "&" + sign;

        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(PayDemoActivity.this);
                Map<String, String> result = alipay.payV2(orderInfo, true);
                Log.i("msp", result.toString());

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

        Thread payThread = new Thread(payRunnable);
        payThread.start();
    }

    /**
     * 支付宝账户授权业务
     * 
     * @param v
     */
    public void authV2(View v) {
        if (TextUtils.isEmpty(PID) || TextUtils.isEmpty(APPID)
                || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))
                || TextUtils.isEmpty(TARGET_ID)) {
            new AlertDialog.Builder(this).setTitle("警告").setMessage("需要配置PARTNER |APP_ID| RSA_PRIVATE| TARGET_ID")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                        }
                    }).show();
            return;
        }

        /**
         * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
         * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
         * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; 
         * 
         * authInfo的获取必须来自服务端;
         */
        boolean rsa2 = (RSA2_PRIVATE.length() > 0);
        Map<String, String> authInfoMap = OrderInfoUtil2_0.buildAuthInfoMap(PID, APPID, TARGET_ID, rsa2);
        String info = OrderInfoUtil2_0.buildOrderParam(authInfoMap);

        String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
        String sign = OrderInfoUtil2_0.getSign(authInfoMap, privateKey, rsa2);
        final String authInfo = info + "&" + sign;
        Runnable authRunnable = new Runnable() {

            @Override
            public void run() {
                // 构造AuthTask 对象
                AuthTask authTask = new AuthTask(PayDemoActivity.this);
                // 调用授权接口,获取授权结果

                Map<String, String> result = authTask.authV2(authInfo, true);

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

        // 必须异步调用
        Thread authThread = new Thread(authRunnable);
        authThread.start();
    }

    /**
     * get the sdk version. 获取SDK版本号
     * 
     */
    public void getSDKVersion() {
        PayTask payTask = new PayTask(this);
        String version = payTask.getVersion();
        Toast.makeText(this, version, Toast.LENGTH_SHORT).show();
    }

    /**
     * 原生的H5(手机网页版支付切natvie支付) 【对应页面网页支付按钮】
     * 
     * @param v
     */
    public void h5Pay(View v) {
        Intent intent = new Intent(this, H5PayDemoActivity.class);
        Bundle extras = new Bundle();
        /**
         * url是测试的网站,在app内部打开页面是基于webview打开的,demo中的webview是H5PayDemoActivity,
         * demo中拦截url进行支付的逻辑是在H5PayDemoActivity中shouldOverrideUrlLoading方法实现,
         * 商户可以根据自己的需求来实现
         */
        String url = "http://m.taobao.com";
        // url可以是一号店或者淘宝等第三方的购物wap站点,在该网站的支付过程中,支付宝sdk完成拦截支付
        extras.putString("url", url);
        intent.putExtras(extras);
        startActivity(intent);
    }

}

这个demo里有支付和授权两个功能介绍,我们可以重点看其授权代码:

        boolean rsa2 = (RSA2_PRIVATE.length() > 0);
        Map<String, String> authInfoMap = OrderInfoUtil2_0.buildAuthInfoMap(PID, APPID, TARGET_ID, rsa2);
        String info = OrderInfoUtil2_0.buildOrderParam(authInfoMap);

        String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
        String sign = OrderInfoUtil2_0.getSign(authInfoMap, privateKey, rsa2);
        final String authInfo = info + "&" + sign;

简单理解为:拼接authinfo,其实这应该是服务器端拼接返回给我们客户端,但是我们不妨来看看这其中需要的参数:

PID:

支付宝支付业务参数,这个东西不好找,具体为:“首页”-》“右上角个人中心”-》“左边mapi网关产品秘钥”可查看。

APPID:

应用的appid。

TARGET_ID:

不重复的一个数即可,可用时间戳。

rsa2:

推荐用RSA加密参数,此时rsa2=true;

RSA2_PRIVATE:

商户私钥。私钥需要通过官方提供的工具生成。
点击查看,下载对应版本的工具后,点击生成的2048位参数就是私钥,同时记得需要将该私钥的文件上传到支付宝开放平台的开发者中心的具体应用中,这样才能生效。

Runnable authRunnable = new Runnable() {

            @Override
            public void run() {
                // 构造AuthTask 对象
                AuthTask authTask = new AuthTask(PayDemoActivity.this);
                // 调用授权接口,获取授权结果

                Map<String, String> result = authTask.authV2(authInfo, true);

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

        // 必须异步调用
        Thread authThread = new Thread(authRunnable);
        authThread.start();

在runnable中直接调用支付宝的sdk方法authV2即可。然后在handle中进行回调即可,不懂的同学可以文章下方留言。
同时也可参考下集成支付宝支付

最近搞了个Android技术分享的公众号,欢迎关注投稿。
这里写图片描述

本门课程共有6个章节,通过4个项目,让您掌握Springboot和SpringCloud作为服务端的工作机制,Angular框架作为前端开发框架的使用方法,以及应用于网站制作和作为移动端用户界面;Spring Security+JWT作为安全框架,对网站和移动端,进行用户认证、角色访问控制;掌握Hybird开发技术在Android和iOS移动客户端中的应用;云服务器配置技术,包括java运行环境安装、Nginx作为web服务器和前后端分离的实现、SSL证书的申请与配置等内容; 第一章介绍了前后端开发环境的搭建和开发工具的安装,包括Java JDK的安装、Maven依赖管理工具的安装、NodeJS开发环境的安装、Angular开发环境的安装、Git版本管理工具的使用 第二章通过体脂计算器(BMI)项目,掌握使用Maven生成Springboot工程,Angular与Springboot的协作机制、从而理解前后端分别架构的实现方法。 第三章通过开发一个CMS系统,既网站内容管理系统,来掌握Springboot操作数据库、Angular框架与NG-BootStrap框架作为前端框架,并与Springboot服务端交互的协作机制;其中还包含了程序员的必备技能,既增、删、查、改、数据分页、文件上传、Web在线编辑器的集成与使用等内容。通过本章节的学习,你可以做出一个能自动适应各种屏幕尺寸网站项目。 第四章我们通过开发CMS系统的移动端版本,来掌握ionic框架的使用;首先我们我们将第三章的网站内容无缝衔接的显示在移动端上,并通过一个仿微信朋友圈的模块,来掌握ionic capacitor框架调用手机的摄像头,以及图片的编码转换等内容, 第五章我们通过使用Spring Security+Jwt技术来保护我们的CMS网站版和移动端,来学习Spring boot+JWT的运行机制。然后我们通过将服务端和Web端部署到云服务器上,来学习网络系统的上云步骤,其中包括域名申请、服务器采购、服务器配置,其中包括,Java运行环境的安装、Springboot运行环境部署,Nginx通过代理实现前后端分离,以及SSL证书的申请与配置等内容,服务器操作系统我们使用Cent OS,你还能学到使用XShell和XFTP进行网站管理;除此之外,我们还介绍了,android开发环境的配置以及签名发布、iOS开发环境的配置,并最终实现在真机设备上可以运行CMS移动端项目。 第六章我们通过一个网上花店电商项目作为实训项目,这个项目,服务端部分我们使用Spring Cloud,通过用户认证模块、花店模块、支付中心模块之间的相互协作,让您掌握在Spring Cloud框架中Eureka、Zuul、Feign的使用方法;客户端部分,在这个项目中我们采用运行在云服务器上的ionic作为用户界面,并通过Ionic与Android和iOS原生代码的交互过程,来学习JS Bridge技术,从而掌握Hybird移动端开发技术,这种技术可以有效地解决App上架缓慢、更新不及时的问题。同时平衡使用Web与原生开发的性能问题。花店项目是一个电商项目,自然少不了支付功能,我们在课程中可以学到如何集成微信和支付宝,并使用他们进行登录验证和支付。  为什么我要上这门课 现在的网络应用,一般都在网站、Android、iOS和微信四平台同时发布,为了适应这一趋势,我们必须把自己打造成“全栈工程师”,能独立开发“一网三平台”网络应用才能在目前的市场环境中生存。而这四个平台,以往至少需要四名程序员才能完成,面对浩如烟海的知识,本门课程采取弱水三千尺,只取一瓢饮的办法,从开发工作的实际需要出发,将工作中最常用的20%提炼出来,并在实际应用中,反复演练,让你通过,每门技术这最常用的20%,来应付80%的工作。 谁应该报名上这门课如果你是一名计算机专业的学生,那么本门课程可以作为你的实训课程,让你体验到软件企业开发工作中的实际需要,并在本门课程的学习过程中,快速度过计算机专业学生普遍存在的“断奶期”问题 如果您是一名渴望丰富自身技能的程序员,并且对Springboot、Spring Security+JWT、Spring Cloud、Angular、Ionic、Hybird移动端开发技术,有着浓厚的兴趣,但对于瀚如烟海的知识点,又让您望洋兴叹,那么在本门课程中,将会为您抛砖引玉,让您茅塞顿开。 
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值