参看支付宝官方文档《安全支付服务 Android 应用开发指南》
一、安全支付服务简介:
(一)、安全支付服务介绍
安全支付服务是安装在本地 Android 操作系统上的一个组件,主要用来向其它的应用程 序提供便捷、安全以及可靠的支付服务。正如平常系统上所提供的其它服务,如电子邮件和电话服务一样。
(二)、安全支付业务流程图
(三)、调用安全支付数据的流程
二、安全支付接入流程
(一)接入前期准备
接入前期准备工作包括商户签约和密钥配置。
1、商户签约
首先,商户需要在 https://ms.alipay.com 进行注册,并签约安全支付服务。签约成功后可获取支付宝分配的合作商户 ID(PartnerID),账户 ID(SellerID),如图:
2、密钥配置
签约成功后,商户可登陆 https://ms.alipay.com 获取商户账号对应的支付宝公钥,具体获取步骤请见 “RSA 密钥详解”。接着,商户生成商户公钥和商户私钥(具体生成步骤请见 “ RSA 密钥详解”),并登陆https://ms.alipay.com,上传商户公钥(具体上传步骤请见 “ RSA 密钥详解”)。至此,接入前期准备工作完成,下一节将使用 demo 测试准备工作是否正确。
(二)、 Demo
【注意:请勿在模拟器下测试 demo,否则可能导致付款账户被锁定!】
1、Demo 配置运行
步骤 1: Demo 导入
步骤 2:
打开“PartnerConfig.java”文件,按照注释添加商户账号信息,具体包括:合作商户 ID、账户 ID、支付宝公钥(即服务器公钥)、商户公钥、商户私钥。
示例代码:
// 合作身份者id,以2088开头的16位纯数字
public static final String PARTNER = "2088112738535023";
// 收款支付宝账号
public static final String SELLER = "[email protected]";
// 商户私钥,自助生成
public static final String RSA_PRIVATE = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAM99AHDnDbybtO/z/XqieV1Y1jHH3Y5m9XCGNXPMBSkIU5nzc/jLmrl034GnlaoB5q3OH2Ze99Tet816OmWfDqmCoZZIZ8g3cw8ntgM92lxwAd97Lh76NtwDQ5KN1slBw2ZUkszyvNq/VGyjqiE/270JwQWslo9qMHaPldpL/Z2tAgMBAAECgYBAYujtIDYaDjOCtrM1CBAjUHr/bacqFncZmPwjV+9OAWB4CJ03Wm9EF6l4AXonDHn5+1mxGc1MSGS/JavTdx1EG0uPyDc16BpSWbvlmKsPQgUKyAs6Fugyl11PowIDvf29geukQcKLVwhgLYHPd5hH1GO1UAF+cj/IsjIWFaGhoQJBAPtIjh8p3DBvAbgvh5fBEwjX0b6q95jkbbfdQZS4YgWFdoaP70Zq3KYw3dHVGgLJxWGxCSW2wEwoHuLzZjNwyeUCQQDTYgGOJYM0PcMkJVnEhy4S2/+mQb7WBU+mBWooUK61lUpajZuBj8xBZggrHkPU4iQB/wWOVCc8XdPaq9ctw6gpAkBH6Sya6HzV836XeiqgmCVdW33vxbeTrpNjkdMJv3Z1xAr2WUyNZ1l7yfJA8W4/LATrfyFyBImlgbnNEwDFadqtAkAr6EakbRxUxKN9JZkA3odueW4f7bYjJJVHygYj+6Zep3T7XEC559Gon/YAZtf2J0cNdxiDWO2Rd3fjCyC2K9cJAkBEQP43KekFeDdADP0QDNhG/bWfqWHfVim46EOxgJr8yw8Kr9SfinQfQZvPKPEFBvorK90/jtsukmwvEaaK+WZj";
// 支付宝公钥
public static final String RSA_PUBLIC = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB";
步骤 3:
在真机或者模拟器上运行项目(下图以模拟器为例),首次启动时,由于系统未安装安全支付服务,将出现以下提示:
图:安全支付安装确定
此时,可以选择“确定”进行安装,安装后该提示不会再出现。此时点击任意商品进行购买,即启动安全支付:
图: 安全支付启动
首次运行安全支付服务,会进行安全认证,此时选择“支付宝账户”付款(注意:付款用的账户应为某一真实账户,交易金额也是真实的!),输入账户信息,按照提示一步步进行:
图: 安全认证
完成安全认证后,若出现如下提示,说明密钥配置有误,请仔细阅读 “RSA 密钥详解”
图:验签错误-支付失败
若出现“确认支付”页面,说明密钥配置无误,接入前期准备工作全部正确完成。接下来将正式进行安全支付的接入集成。
2、Demo 结构说明
类名 | 说明 |
AlixDemo | 主 Activity |
Base64 |
Base64 编码类,签名及验签,必须 |
MobileSecurePayer |
封装了对安全支付的调用,可参考性较强 |
MobileSecurePayHelper |
实现安全支付插件的检测,更新下载,安装,可参考性较强 |
Networkmanager | 网络连接管理 |
PartnerConfig |
商户账户信息配置 |
ResultChecker |
AlixPay 返回结果的解析处理,可参考性较强 |
Rsa |
RSA 签名验签类,必须 |
(三)、安全支付集成
本节指导在商户APP项目中集成安全支付,关键代码以 Demo 为例。
1、步骤 1:添加 jar 文件
添加 demo 中的 alipay_msp.jar 包添加工程中。
2、步骤 2:初始化安全支付服务
在调用安全支付进行支付前,需要先初始化安全支付服务。
3、步骤 3:订单数据生成
在调用安全支付时,需要提交订单信息 orderInfo 其中参数以“key=value”形式呈现,参数之间以“&”分割,所有参数不可缺。
partner="2088002007260245"&seller="2088002007260245"&out_trade_no="500000000006548"&subject=" 商 品 名 称 "&body=" 这 是 商 品 描 述"&total_fee="30"¬ify_url="http://notify.java.jpxx.org/index.jsp"&sign="kU2Fa3x6V985g8ayTozI1eJ5fHtm8%2FJGeJQf9in%2BcVmRJjHaExbirnGGKJ%2F7B63drqc4Kjlk%2FSg6vtSIkOtdvVBrRDpYaKxXVqkJTzRYgUwrrpMudbIj9aMS2O3dHG0GPyL4Zb6jKDYXHabGG0aBJY3QA7JuTJ23t6SqV%2B5f1xg%3D"&signtype="RSA"
其中 sign 值的生成,需要特别注意的是:对数据签名后得到的 sign值必须进行 URLEncode,之后才可作为参数。
4、步骤 4:调用安全支付
准备好参数后,即可调用安全支付进入支付流程并获得调用结果,代码如下:
result = mAlixPay.pay(orderInfo);
AliXPay 函数具体说明请见 AlixPay 方法描述。
5、步骤 5:支付结果获取和处理
调用安全支付后,将通过两种途径获得支付结果:
1)、 AliXpay.pay()方法的返回。该方法将返回表示支付结果的字符串
2)、支付宝服务器通知。商户需要提供一个 http 协议的接口,包含在参数里传递给安全支付,即 notify_url。支付宝服务器在支付完成后,会用 POST 方法调用 notufy_url,以 xml 为数据格式传输支付结果。
(四)、应用发布
目前,我们为第三方应用客户端提供了两种集成安全支付服务的方式。第一种是运行时安装,即将安全支付服务安装包 apk 与第三方应用客户端整合在一起,在恰当的时机,由第三方应用客户端释放并安装安全支付服务安装包 apk。另一种则称为动态下载安装,在此种情况下,安全支付服务安装包 apk 是预先存放在约定的远程服务器中,第三方应用客户端可以从此处下载 apk 并进行安装。
为了提升用户体验,避免捆绑安装旧版本的安全支付服务之后,接着又需要重新升级并安装成最新版本,我们目前推荐结合使用以上两种集成方式。在最新的 demo 中,会首先连接支付宝服务器,检测并判断捆绑在第三方客户端中的 alipay_plugin.apk 是否为最新版本,如果是,则直接安装。如果捆绑在第三方客户端中的 alipay_plugin.apk 不是最新版本,则从服务器中下载最新版本的安装包,然后进行安装。
1、运行时安装
运行时安装的具体步骤如下所示:
1) 将 alipay_plugin.apk 作为资源复制到第三方应用工程中的 assets 目录。
2) 第三方应用在需要付款时(或者其它恰当时机),先检测安全支付服务是否已经安装。如果尚未安装,则从 assets 目录中提取 alipay_plugin.apk 到手机存储。
3) 安装手机存储中的安全支付服务 apk。
2、动态下载安装
动态下载安装的具体步骤如下所示:
1) 由支付宝预先将安全支付服务 apk 放置到约定的远程下载服务器。
2) 第三方应用在需要付款时(或者其它恰当时机),先检测安全支付服务是否已经安装。如果尚未安装,则从约定的远程下载服务器提取 alipay_plugin.apk 到手机存储。
3) 安装手机存储中的安全支付服务 apk。
三、RSA 详解
(一)、RSA 和 OpenSSL 介绍
1、什么是 RSA?
RSA 是一种非对称的签名算法,即签名密钥(私钥)与验签密钥(公钥)是不一样的,私钥用于签名,公钥用于验签。在与支付宝交易中,会有 2 对公私钥,即商户公私钥,支付宝公钥。
2、为什么要用 RSA?
使用这种算法可以起到防止数据被篡改的功能,保证支付订单和支付结果不可抵赖(商户私钥只有商户知道)。
3、什么是 OpenSSL
一句话概括:OpenSSL 是基于众多的密码算法、公钥基础设施标准以及 SSL 协议安全开发包。
4、为什么要用 OpenSSL?
通过 OpenSSL 生成的签名和内置的算法可以做到跨平台,这样在不同的开发语言中均可以签名和验签。
(二)、RSA 密钥详解【重要】
1、找到生成 RSA 密钥工具
(1)下载开发指南和集成资料,您能看到此文档说明指南和集成包已经下载了。
(2)解压下载的压缩包(WS_SECURE_PAY),找到并解压 openssl-0.9.8k_WIN32(RSA 密钥生成工具).zip 工具包
2、生成商户密钥并获取支付宝公钥
(1) 生成原始 RSA 商户私钥文件
假设解压后的目录为 c:\alipay,命令行进入目录 C:\alipay\bin,执行“openssl genrsa -out rsa_private_key.pem 1024”,在 C:\alipay\bin 下会生成文件 rsa_private_key.pem,其内容为原始的商户私钥(请妥善保存该文件),以下为命令正确执行截图:
图 3- 3 生成原始 RSA 商户私钥文件
(2) 将原始 RSA 商户私钥转换为 pkcs8 格式
命令行执行“ openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt”得到转换为 pkcs8 格式的私钥。复制下图红框内的内容至新建 txt 文档,去掉换行,最后另存为“private_key.txt”(请妥善保存,签名时使用)。
图 3- 4 转换私钥格式
(3) 生成 RSA 商户公钥
命令行执行“ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem”,在 C:\alipay\bin 文件夹下生成文件 rsa_public_key.pem。接着用记事本打开rsa_public_key.pem,复制全部内容至新建的 txt 文档,删除文件头“-----BEGIN PUBLIC KEY-----”与文件尾“-----END PUBLIC KEY-----”及空格、换行,如下图。最后得到一行字符串并保存该 txt 文件为“public_key.txt”。
图 3- 5 生成公钥
(4) 上传商户公钥至支付宝
浏览器访问 https://ms.alipay.com/index.htm 并用签约帐号登录,点击菜单栏“我的产品”,右侧点击“密钥管理”,见下图红色框内图 3- 6 商户公钥上传。点击“上传”,选择步骤(3)生成的“public_key.txt”并完成上传。
(5) 获取 RSA 支付宝公钥
成功上传公钥至支付宝后,页面显示如下:
图 3- 7 支付宝公钥获取
其中红色框内部分即支付宝公钥,请复制至新建 txt 文档,去掉换行和空格,妥善保存(用于验签收到的支付宝通知)。
(三)、RSA 签名和验签【重要】
【建议:签名和验签尽量在商户服务器端进行,同时一些敏感数据(如公私钥等)也应存储在服务器端,避免可能的安全隐患。】
1、RSA 签名
(1) 在项目中添加下面的类:
(2) 生成商品订单:
可参考 Demo 中 AlixDemo.java 的方法:
private String getOrderInfo()
例子:出售商品(subject)“Iphone4”,价格(total_fee)“1”元,外部交易号(out_trade_no)“zzzz”,商品描述(body)为“秒杀”,订单支付完成通知 URL(notify_url)为 http://notify.java.jpxx.org/index.jsp
则生成如下商品信息字串:
partner="xxxx"&seller="yyyy"&out_trade_no="zzzz"&subject="Ipone4"&body="秒杀"&total_fee="1"¬ify_url="http://notify.java.jpxx.org/index.jsp"
(4) 对商品信息进行 RSA 签名
可使用 Demo 中 Rsa.java 的方法:
public static String sign(String content, String privateKey)
String content:待签名字符串
String privateKey:商户私钥(pkcs8 转换后的商户私钥)
返回值:签名值(传递给安全支付前需要 URL 编码,样例中未编码)
partner="xxxx"&seller="yyyy"&out_trade_no="zzzz"&subject="Ipone4"&body="秒杀"&total_fee="1"¬ify_url="http://notify.java.jpxx.org/index.jsp"&sign_type="RSA"&sign="O0I1APPVQcK5bbSgdeFx9HB3Yu/U2+akTZ3T0/P7v3g7XD7TsQCprb6O9Nybr8CDIrztdUseQN/TCXuEvCU2cvCt1xX9UUyI6fOxXxQFlDWx7IE2S7Zo5wOeVWmMBnCQCV8iDjcNxGHwhtCT09bVVf0wbaOiHXvAYzWlvPhyR+0="
2、RSA 验签
(1) 使用 RSA 类进行验签:
public static boolean doCheck(String content, String sign, String publicKey)
String content:待验签的字符串(红色部分)
String sign:签名值(蓝色部分)
String publicKey:支付宝公钥
返回值:验签成功则返回true,反之返回false.
以下是一个订单支付成功完整信息的示例:
resultStatus={9000};
result={partner="2088002007260245"&seller="2088002007260245"&out_trade_no="600000000006891"&subject="商品名称"&body="这是商品描述"&total_fee="1"¬ify_url="http%3A%2F%2Fnotify.java.jpxx.org%2Findex.jsp"&success="true"&sign_type="RSA"&sign="O0I1APPVQcK5bbSgdeFx9HB3Yu/U2+akTZ3T0/P7v3g7XD7TsQCprb6O9Nybr8CDIrztdUseQN/TCXuEvCU2cvCt1xX9UUyI6fOxXxQFlDWx7IE2S7Zo5wOeVWmMBnCQCV8iDjcNxGHwhtCT09bVVf0wbaOiHXvAYzWlvPhyR+0="}
备注:result返回的json字串需要处理转义字符(可参考Demo中checkSign函数的处理方式)否则可能导致验签无法通过。
(2) 为了方便商户接入安全支付服务,我们将签名和验签的方法封装成 Rsa.java 提供给大家使用,可从 demo 中提取。
四、通知结果
(一)、AlixPay 方法返回的结果
支付结果的处理可以参考 Demo 中的类 ResultChecker.java。
结果信息详细描述如下:
结果判断说明:
需要通过 resultStatus 以及 result 字段的值来综合判断并确定支付结果。在resultStatus=9000,并且 success="true"以及 sign="xxx"校验通过的情况下,证明支付成功。其它情况归为失败。较低安全级别的场合,也可以只通过检查 resultStatus 以及success="true"来判定支付结果。以下为订单支付成功的完成信息示例:
partner=""&seller=""&out_trade_no=""&subject=""&body=""&total_fee="30"¬ify_url=""&success="true"&sign_type="RSA"&sign="xxx"
(二)、notify_url 通知说明
1、什么是 Notify_url
支付宝通过访问商户提供的地址的形式,将交易状态信息发送给商户服务器。商户通过支付宝的通知判断交易是否成功,具体如下:
商户地址:提供一个 http 的 URL(例:http://www.partnertest.com/servlet/NotifyReceiver),支付宝将以 POST 方式调用该地址。
通知触发条件:交易状态发生改变,如交易从“创建”到“成功”或“关闭”。
商户返回信息:商户服务器收到通知后需返回纯字符串“success”,不能包含其他任何HTML 等语言的文本。
通知重发:若支付宝没有收到商户返回的“success”,将对同一笔订单的通知进行周期性重发 (间隔时间为:2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时,15 小时共 7 次)。
交易判断条件:收到 trade_status=TRADE_FINISHED(如果签有高级即时到帐协议则trade_status=TRADE_SUCCESS)的请求后才可判定交易成功(其它 trade_status 状态请求可以不作处理)
2、Notify_url 接收数据示例
Notify_data 参数说明
参数名 | 说明 |
trade_status | 用于判断交易状态,值有: TRADE_FINISHED:表示交易成功完成 WAIT_BUYER_PAY:表示等待付款 TRADE_SUCCESS:表示交易成功(高级即时到帐) |
total_fee |
交易金额 |
subject |
商品名称 |
out_trade_no |
外部交易号(商户交易号) |
trade_no | 支付宝交易号 |
gmt_create |
交易创建时间 |
gmt_payment |
交易付款时间 若交易状态是“WAIT_BUYER_PAY”则无此参数 |
五、常见问答
1、客户端验签,报“订单信息被篡改”是什么问题?
可能有以下2种情况
a) 有可能数据在传输过程中被黑客截取和篡改
b) 检查plaintext(待签名的字符串)中是否有以下四个符号,如果参数当中包含了这四个字符也会报“订单信息被篡改”:
2、客户端调用安全支付时对 body 和 subject 进行 URLEncode 会报签名错误,到底哪些需要URLEncode?
调用安全支付接口时,只需要对参数sign进行URLEncode,其他参数都不能URLEncode,安全支付服务插件会对所有参数进行URLEncode,所以不用担心中文乱码。
3、上传商户公钥报格式错误怎么办?
首先确认上传的位置是否是RSA的下面,注意不要是DSA,无线目前不支持DSA加密;另外请检查上传的文件中是否去除注释、空格、换行等,必须是一行的字符串。
4、 错误代码列表
错误编号 | 说明 |
9000 | 操作成功 |
4000 |
系统异常 |
4001 |
数据格式不正确 |
4003 |
该用户绑定的支付宝账户被冻结或不允许支付 |
4004 | 该用户已解除绑定 |
4005 |
订单支付失败 |
4006 |
AlixPay 返回结果的解析处理,可参考性较强 |
4010 |
重新绑定账户 |
6000 |
支付服务正在进行升级操作 |
6001 |
用户中途取消支付操作 |
6002 |
网络连接异常 |
5、AlixPay 主要方法描述
主要包含外部商户的订单信息,key="value"形式,以&连接。支付参数示例如下:
partner="2088101568358171"&seller_id="[email protected]"&out_trade_no=
"0819145412-6177"&subject="《暗黑破坏神 3:凯恩之书》"&body="暴雪唯一官方授权
中文版!玩家必藏!附赠暗黑精致手绘地图!绝不仅仅是一本暗黑的故事或画册,而是一个
栩栩如生的游戏再现。是游戏玩家珍藏的首选。
"&total_fee="0.01"¬ify_url="http%3A%2F%2Fnotify.msp.hk%2Fnotify.htm"&servic
e="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30
m"&show_url="m.alipay.com"&sign="lBBK%2F0w5LOajrMrji7DUgEqNjIhQbidR13Gov
A5r3TgIbNqv231yC1NksLdw%2Ba3JnfHXoXuet6XNNHtn7VE%2BeCoRO1O%2BR1
KugLrQEZMtG5jmJIe2pbjm%2F3kb%2FuGkpG%2BwYQYI51%2BhA3YBbvZHVQBY
veBqK%2Bh8mUyb7GM1HxWs9k4%3D"&sign_type="RSA"
例如:
resultStatus={9000};memo={};result={partner="2088101568358171"&seller_id="alipa
[email protected]"&out_trade_no="0819145412-6177"&subject="《暗黑破坏神 3:
凯恩之书》"&body="暴雪唯一官方授权中文版!玩家必藏!附赠暗黑精致手绘地图!绝不仅
仅是一本暗黑的故事或画册,而是一个栩栩如生的游戏再现。是游戏玩家珍藏的首选。
"&total_fee="0.01"¬ify_url="http%3A%2F%2Fnotify.msp.hk%2Fnotify.htm"&servic
e="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30
m"&show_url="m.alipay.com"&success="true"&sign_type="RSA"&sign="hkFZr+zE94
99nuqDNLZEF7W75RFFPsly876QuRSeN8WMaUgcdR00IKy5ZyBJ4eldhoJ/2zghqrD
4E2G2mNjs3aE+HCLiBXrPDNdLKCZgSOIqmv46TfPTEqopYfhs+o5fZzXxt34fwdrzN4
mX6S13cr3UwmEV4L3Ffir/02RBVtU="}