前言,梦想是需要坚持的,在路上,一路前行。加油。
这两天软件需要集成支付宝了,第一次集成,过程还是挺简单的,不过由于支付宝官方文档写的不够清晰,也是走了一些弯路,下面把过程写出来分享给大家
一、申请移动支付权限
首先登录【支付宝开放平台】http://open.alipay.com/platform/home.htm,添加应用,申请移动支付权限。申请开通支付,是需要公司文件的,个人是不允许开始支付的。
具体细节就不再详聊了,下面就讲讲如何将阿里给出的demo运行起来。
二、阿里支付DEMO
1、概述
(1)支付调用页面及测试
支付宝在调用时,会首先看本地是不是存在支付宝客户端,如果有的话,就直接调用客户端进行支付,如果没有,则调用jar包中的H5页面支付。
所以在测试时,需要有测试两种情境:有支付宝客户端和没有支付宝客户端的情况。
(2)、客户端与服务器
在demo中大家可以看到,有客户端的demo也有服务端的demo,大家可能觉得需要服务端写好之后,客户端才能集成,其实并不是。整个流程是这样的:1,APP客户端通过SDK发送支付请求 (客户端处理)
2,SDK支付成功并同步返回支付结果(客户端处理)
3,支付宝服务器向我们的服务器发送支付结果字符串(服务端处理)
客户端:从上面的流程可以看出,服务端只是用来接出异步返回的支付结果的。而支付与同步结果返回都是在客户端可以直接看得到的。所以在集成支付宝支付接口时,主要功能是在客户端,即便服务端没有做集成,也是可能付款成功的。
服务端:服务端只需要添加一个功能:接口支付结果返回
下面几张图显示了整个demo的运行过程,由于没办法在真机上录制gif,所以只能用图片来代替了。
初始化界面:
点击支付后,跳出确认付款界面:
点击确认付款后,跳出输入密码界面:
最后是支付成功界面:
在看DEMO的代码之前,我们需要先配置几个变量:
2、配置几个变量
这部分会对代码中用到的几个变量的找到方法或生成方法进行讲述,部分资料引自支付宝开放平台。(1)PID
合作者身份ID(PID)是商户与支付宝签约后,商户获得的支付宝商户唯一识别码。当商户把支付宝功能接入商户网站时会用到PID,以便让支付宝认证商户。
查看PID步骤如下:
1、登录支付宝官方网站b.alipay.com
2、点击导航栏中“商家服务”
3、点击“查询PID、Key”
(2)、APPID、APP SECRET和支付宝公钥
在https://openhome.alipay.com/platform/createApp.htm页面,创建一个应用完成之后:在我的应用中是可以看得到的:
然后转到帐户基本信息页面:https://openhome.alipay.com/platform/keyManage.htm
在开放平台密钥栏,可以找到APPID,APP SECRET,和支付宝密钥
这三个数据,都是在应用创建后,支付宝为我们生成好的,无法更改!
(3)、生成商户私钥【windows生成方法】
(有关mac的生成方法,下面会再补充)1、下载DEMO及SDK
到文档中心,查看移动支付对应的文档,文档地址:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1
然后,点击(SDK&DEMO下载)下载代码
2、得到原始私钥
在代码中的DEMO/openssl/bin目录下,有openssl.exe文件
打开openssl.exe
输入
- genrsa -out rsa_private_key.pem 1024
此时,我们可以在bin文件夹中看到一个文件名为rsa_private_key.pem的文件
用记事本方式打开它,可以看到-----BEGIN RSA PRIVATE KEY-----开头,-----END RSA PRIVATE KEY-----结尾的没有换行的字符串,这个就是原始的私钥。
但这段原始私钥代码中是用不到的,我们需要将它转化为PKCS8格式
3、转换为PKCS8格式
在openssl.exe中输入:并回车
- pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
注意,私钥是红框包括的那部分,是不包含BEGIN PRIVATE KEY和END PRIVATE KEY这两行的。
右键点击openssl窗口上边边缘,选择编辑→标记,选中要复制的文字(如上图),
此时继续右键点击openssl窗口上边边缘,选择编辑→复制,
把复制的内容粘土进一个新的记事本中,可随便命名,只要知道这个是PKCS8格式的私钥即可。
(4)、生成商户私钥【MAC生成方法】
这里来讲一下mac端如何生成用户私钥的,由于mac系统是自带openssl的,所以只需要打开终端,利用cd 命令切到任意一个想存放生成Key的文件夹下:
比如,切到下载目录下
然后运行下面的命令来生成私钥原始密钥
- openssl genrsa -out rsa_private_key.pem 1024
- openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
从上面的命令可以看出,与windows相比,mac上需要在前面添加openssl指定运行的是openssl命令。其它命令是完全一致的。
(5)、生成用户公钥及网页填充
1、生成公钥同样对于windows用户而言,直接在openssl.exe中输入下面的命令:
- rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
- openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
此时,我们可以在bin文件夹中看到一个文件名为rsa_public_key.pem的文件,用记事本方式打开它,可以看到-----BEGIN PUBLIC KEY-----开头,
-----END PUBLIC KEY-----结尾的没有换行的字符串,这个就是公钥。
在生成网页以后,复制----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----之间的部分,即那段纯代码,不要把----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----给复制进去了。中间的这部分就是公钥。
2、网页填充
然后到https://openhome.alipay.com/platform/keyManage.htm?keyType=partner(需要登录)中,左侧找到合作伙伴密钥栏,再到右侧的RSA加密中,将公钥粘贴进去。由于,我们已经粘贴进去了,所以这里显示查看开发者公钥,在没填之前写的是“添加开发者公钥”
到这里,所有的准备工作都已经结束了。下面就是配置DEMO的过程了
3、配置DEMO
在刚才下载的sdk&demo的源码中,打开DEMO/客户端demo/支付宝Android 15.0.1/alipay_demo工程路径如下:
在PayDemoActivity中配置几个变量:
- //PID
- public static final String PARTNER = "";
- // 商户收款账号
- public static final String SELLER = "76949XXXX@qq.com";
- // 支付宝公钥
- public static final String RSA_PUBLIC ="";
- // 商户私钥,pkcs8格式
- public static final String RSA_PRIVATE = "";
私钥这部分,注意是----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----之间的部分,即那段纯代码,不要把----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----给复制进去了。中间的这部分就是公钥。
现在运行demo就直接可以支付了。
本文中对应的DEMO在文章底部给出。4、代码讲解
通过上面的配置,demo应该就直接可以运行了,但这里所涉及的代码,我们再仔细看看主要的支付与结果返回就是pay()这个函数,这里完成了支付所需要的所有功能。代码如下:
- public void pay(View v) {
- …………
- // 订单信息
- String orderInfo = getOrderInfo("测试的商品", "该测试商品的详细描述", "0.01");
- // 对订单做RSA 签名
- String sign = sign(orderInfo);
- try {
- // 仅需对sign 做URL编码
- sign = URLEncoder.encode(sign, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- // 完整的符合支付宝参数规范的订单信息
- final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"
- + getSignType();
- Runnable payRunnable = new Runnable() {
- @Override
- public void run() {
- // 构造PayTask 对象
- PayTask alipay = new PayTask(PayDemoActivity.this);
- // 调用支付接口,获取支付结果
- String result = alipay.pay(payInfo);
- Message msg = new Message();
- msg.what = SDK_PAY_FLAG;
- msg.obj = result;
- mHandler.sendMessage(msg);
- }
- };
- // 必须异步调用
- Thread payThread = new Thread(payRunnable);
- payThread.start();
- }
这里总是分了四步来完成支付与结果接收。
第一步:构造定单信息:
- String orderInfo = getOrderInfo("测试的商品", "该测试商品的详细描述", "0.01");
有关paymethod的方法使用,参考:https://cshall.alipay.com/support/help_detail.htm?help_id=476935
各个字段的意义及取值参考:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103663&docType=1
- public String getOrderInfo(String subject, String body, String price) {
- // 签约合作者身份ID
- String orderInfo = "partner=" + "\"" + PARTNER + "\"";
- // 签约卖家支付宝账号
- orderInfo += "&seller_id=" + "\"" + SELLER + "\"";
- // 商户网站唯一订单号
- orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";
- // 商品名称
- orderInfo += "&subject=" + "\"" + subject + "\"";
- // 商品详情
- orderInfo += "&body=" + "\"" + body + "\"";
- // 商品金额
- orderInfo += "&total_fee=" + "\"" + price + "\"";
- // 服务器异步通知页面路径
- orderInfo += "¬ify_url=" + "\"" + "http://notify.msp.hk/notify.htm"
- + "\"";
- …………
- return orderInfo;
- }
- // 服务器异步通知页面路径
- orderInfo += "&noify_url=" + "\"" + "http://notify.msp.hk/notify.htm"
- + "\"";
其它的就不讲了,通过看源码都能看得懂,比如构造订单号啥的。
第二步:对订单字符串做RSA签名
为什么要签名呢?当然是防止传输出错了,这可是跟钱相关的,如果orderInfo传输过程中出错了,那怎么样来校验它是不是出错了呢,只有通过签名算法来了。所以这里就需要对订单字符串做签名。具体签名算法就不讲了,直接应用到项目中就行,不需要理解,如果想看看怎么实现的,里面有对应的源码,可以去研究一下。
- // 对订单做RSA 签名
- String sign = sign(orderInfo);
- try {
- // 仅需对sign 做URL编码
- sign = URLEncoder.encode(sign, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
第三步:构造完成的请求字符串
在订单字符串和签名做完以后,就可以用他们来构造完整的请求字符串了:- // 完整的符合支付宝参数规范的订单信息
- final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"
- + getSignType();
第四步:请求与结果返回
最后是发送请求,代码如下:- Runnable payRunnable = new Runnable() {
- @Override
- public void run() {
- // 构造PayTask 对象
- PayTask alipay = new PayTask(PayDemoActivity.this);
- // 调用支付接口,获取支付结果
- String result = alipay.pay(payInfo);
- Message msg = new Message();
- msg.what = SDK_PAY_FLAG;
- msg.obj = result;
- mHandler.sendMessage(msg);
- }
- };
- // 必须异步调用
- Thread payThread = new Thread(payRunnable);
- payThread.start();
- PayTask alipay = new PayTask(PayDemoActivity.this);
- // 调用支付接口,获取支付结果
- String result = alipay.pay(payInfo);
- Message msg = new Message();
- msg.what = SDK_PAY_FLAG;
- msg.obj = result;
- mHandler.sendMessage(msg);
然后通过handler将结果发送出去。
这就是同步的方式获取支付结果的方式。
好了,有关支付宝对接的方法全部都在这了。至于getOrderInfo函数里,使用的调用银行卡支付,我觉得也没啥用,在我们程序里也没接上。
本文所使用的DEMO源码下载地址:http://download.csdn.net/detail/harvic880925/9261363