前言
这里开篇讲解一系列的Android相关的移动支付。移动支付也称为手机支付,用户使用移动的设备,完成对所购买商品或者服务的支付功能。包括远程支付(网上支付、短信支付),近场支付(刷卡、滴卡、pos机)。
国内的移动支付方式:
支付宝,微信,银联,百度钱包,QQ钱包,财付通,京东支付
易宝支付,快钱支付,还有一些第三方的支付什么连连支付之类的
*的移动支付方式(这里直说一个) :paypal
流程
我们这里主要是来学习一下支付宝,微信支付,银联支付和paypal支付
现实生活中的支付就是:去商店浏览商品->把商品加入购物车->把购物车中的商品拿到收银台付款
上面的支付流程细化下来就是:
1.浏览商品
2.把要买的商品加入购物车
3.把商品拿到收银台,收银人员处理商品信息
4.告诉收银员支付方式
5.选择支付方式进行支付
6.处理支付结果(成功、失败、取消)
程序中的支付流程中:
1.浏览商品
2.把要买的商品加入购物车
3.把购物车中的商品信息和用户信息和支付方式等信息发送到自己服务器,服务器处理商品信息生成订单,并返回”支付串”给客户端
4.客户端拿着“支付串”,调用第三方服务(支付宝、微信、银联、paypal等)完成支付
5.处理支付结果(成功、失败、取消)
l 同步返回:支付后通知我们的客户端
l 异步通知:支付后通知我们的服务端
以上就是一般的移动支付的基本流程了,下面看这几个支付平台的详细介绍
android移动支付——支付宝支付
android移动支付——微信支付
android移动支付——银联支付
android移动支付——PayPal支付
银联支付
1.概述
银联支付有很多种类型,我们这里主要说的是手机控件支付
银联手机支付控件主要应用于各类手机电子商务平台的支付应用。银联控件合作商户的手机客户端(或网站)内集成(或调用)银联支付控件后,持卡人在合作商户上即可使用银联手机支付安全控件进行安全的、便捷的即时支付,同时,保障用户银行卡信息的安全。
2.支付流程
流程图说明:
(1)用户在客户端中点击购买商品,客户端发起订单生成请求到商户后台;
(2)商户后台收到订单生成请求后,按照《手机控件支付产品接口规范》组织并推送订单信息至银联后台;
(3)银联后台接收订单信息并检查通过后,生成对应交易流水号(即TN),并回复交易流水号至商户后台(应答要素:交易流水号等);
(4)商户后台接收到交易流水号,将交易流水号返回给客户端;
(5)客户端通过交易流水号(TN)调用支付控件;
(6)用户在支付控件中输入相关支付信息后,由支付控件向银联后台发起支付请求;
(7)支付成功后,银联后台将支付结果通知给商户后台;
(8)银联将支付结果通知支付控件;
(9)支付控件显示支付结果并将支付结果返回给客户端;
注: 本文档主要关注上述流程中(5)、(9)部分的实现
目前各个平台支持的设备情况如下:
Android平台SDK主要适用于Android 2.3及以上版本的终端设备;
3.测试账号
提供测试使用卡号、手机号信息(此类信息仅供测试,不会发生正式交易)
招商银行借记卡:6226090000000048
手机号:18100000000
密码:111101
短信验证码:123456(先点获取验证码之后再输入)
证件类型:01身份证
证件号:510265790128303
姓名:张三
华夏银行贷记卡:6226388000000095
手机号:18100000000
cvn2:248
有效期:1219
短信验证码:123456(先点获取验证码之后再输入)
证件类型:01身份证
证件号:510265790128303
姓名:张三
4.接入SDK和一些文档的说明
技术支持和业务说明的一些东西
手机控件支付SDK下载demo还有相关的接入文档之类的jar包
因为下载下来的银联手机控件支付开发包里面的demo工程都还没配好的,还有是用eclipse的,一些说明也在下载回来的控件使用指南的文档中有了,这里也会列出来,现在我改用Androidstudio来完成这个demo,如下:
4.1 SDK包说明
商户开发者在获取到银联提供的开发包后请检查SDK文件所在目录upmp_android/sdkProSDK,以下部分提及的文件均在该目录中:
apk目录下包括了支付控件的apk:UPPayPluginExPro.apk
jar目录下包括了商户集成所需要的jar包、so文件(支持arm,armv7,x86,x86_64和arm64-v8a平台)和资源文件。
UPPayAssistEx.jar定义了调用支付控件所需要的接口。
4.2接口说明
1、 支付接口
upmp_android/UPPayAssistEx.jar中定义了启动支付控件的接口,接口定义如下:
public static int startPay(Activity activity, String spId, String sysProvider, String orderInfo, String mode)
参数说明:
activity —— 用于启动支付控件的活动对象
spId —— 保留使用,这里输入null
sysProvider —— 保留使用,这里输入null
orderInfo —— 订单信息为交易流水号,即TN,为商户后台从银联后台获取。
mode —— 银联后台环境标识,“00”将在银联正式环境发起交易,“01”将在银联测试环境发起交易
返回值:
UPPayAssistEx.PLUGIN_VALID —— 该终端已经安装控件,并启动控件
UPPayAssistEx.PLUGIN_NOT_FOUND — 手机终端尚未安装支付控件,需要先安装支付控件
2、检查是否安装银联Apk的接口
upmp_android/UPPayAssistEx.jar中定义了检测银联apk是否安装的接口,接口定义如下:
public static boolean checkInstalled (Context context)
参数说明:
activity —— 用于启动支付控件的context环境
返回值:
true —— 该终端已经安装控件apk
false — 该终端未安装控件apk
4.3 添加SDK包
(1)可以自己新建一个工程来写demo,也可以利用Androidstudio导入eclipse的demo
生成Androidstudio的工程
(2)在appàsrcàmain新建一个assets文件夹,拷贝upmp_android/sdkPro/jar/data.bin到工程的assets/目录下;
(3)在main目录下新建一个jniLibs,然后再拷贝upmp_android/sdkPro/jar/xxx/libentryexpro.so和upmp_android/sdkPro/jar/xxx/libuptsmaddon.so到工程的libs/xxx/目录下,其中xxx为 armeabi-v7a、armeabi、arm64-v8a、x86、x86_64之一。
arm64-v8a(x86_64)是针对arm64(x86 64)架构优化的库文件,引入工程后在arm64(x86 64)机型上性能会提升,但是最终生成的程序包将变大。注意: 如果工程中使用了其他的.so库,那么需要所有.so库都有arm64-v8a(x86_64)的版本。
(4)app目录下新建libs,拷贝upmp_android/sdkPro/UPPayAssistEx.jar到工程的libs/目录下;
拷贝upmp_android/sdkPro/jar/UPPayPluginExPro.jar到工程的libs/目录下,然后进行依赖jar包;
效果如下图:
(5)在工程的AndroidManifest.xml文件中注册支付插件使用的Activity。添加如下
<uses-libraryandroid:name="org.simalliance.openmobileapi" android:required="false"/>
<activity
android:name="com.unionpay.uppayplugin.demo.JARActivity"
android:label="@string/jar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="com.unionpay.uppay.PayActivity"
android:configChanges="orientation|keyboardHidden|keyboard"
android:screenOrientation="portrait">
</activity>
<activity
android:name="com.unionpay.UPPayWapActivity"
android:configChanges="orientation|keyboardHidden|fontScale"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" >
</activity>
同时添加权限:
<uses-permissionandroid:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD"/>
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce"/>
注意:版本编译时的target应选用OpenMobile API,建议level19以上
(6)调用支付控件
1、支付接口调用
a) 在调用支付控件的代码文件中引入UPPayAssistEx类如:
import com.unionpay.UPPayAssistEx;
b) 接着可以通过以下方式调用支付控件:
// “00” – 银联正式环境
// “01” – 银联测试环境,该环境中不发生真实交易
String serverMode = "01";
UPPayAssistEx.startPay (activity, null,null, tn, serverMode);
支付完成后,获取支付控件支付结果,并添加相应处理逻辑,只需实现调用Activity中的onActivityResult()方法即可,支付成功时会返回商户客户端支付结果的签名信息。
对于新增的签名信息需注意以下几点:
1. 前台返回的支付结果中包含银联签名,要在商户后台对签名进行校验后才能展示结果。
2. 前台签名使用的密钥和算法与后台结果中的签名一致。
3. 如果商户APP在客户端内进行签名验证,要自行实现签名密钥更新的机制,否则更换密钥后会导致验签失败。(不推荐)
4. 商户订单是否成功支付应该以商户后台收到全渠道返回的支付结果为准,此处支付控件返回的结果仅作为参考。
示例代码如下:
protected void onActivityResult( int requestCode,
int resultCode,
Intent data)
{undefined
if( data ==null ){undefined
return;
}
String str = data.getExtras().getString("pay_result");
if( str.equalsIgnoreCase(R_SUCCESS) ){undefined
// 支付成功后,extra中如果存在result_data,取出校验
// result_data结构见c)result_data参数说明
if(data.hasExtra("result_data")) {undefined
String sign = data.getExtras().getString("result_data");
// 验签证书同后台验签证书
// 此处的verify,商户需送去商户后台做验签
if(verify(sign)) {undefined
//验证通过后,显示支付结果
showResultDialog(" 支付成功! ");
} else {undefined
// 验证不通过后的处理
// 建议通过商户后台查询支付结果
}
} else {undefined
// 未收到签名信息
// 建议通过商户后台查询支付结果
}
}else if( str.equalsIgnoreCase(R_FAIL) ){undefined
showResultDialog(" 支付失败! ");
}else if( str.equalsIgnoreCase(R_CANCEL) ){undefined
showResultDialog(" 你已取消了本次订单的支付! ");
}
}
c) result_data参数说明:
参数说明:
sign —— 签名后做Base64的数据
data —— 用于签名的原始数据
data中原始数据结构:
pay_result —— 支付结果success,fail,cancel
tn —— 订单号
result_data示例如下:
"{"sign":"ZnZY4nqFGu/ugcXNIhniJh6UDVriWANlHtIDRzV9w120E6tUgpL9Z7jIFzWrSV73hmrkk8BZMXMc/9b8u3Ex1ugnZn0OZtWfMZk2I979dxp2MmOB+1N+Zxf8iHr7KNhf9xb+VZdEydn3Wc/xX/B4jncg0AwDJO/0pezhSZqdhSivTEoxq7KQTq2KaHJmNotPzBatWI5Ta7Ka2l/fKUv8zr6DGu3/5UaPqHhnUq1IwgxEWOYxGWQgtyTMo/tDIRx0OlXOm4iOEcnA9DWGT5hXTT3nONkRFuOSyqS5Rzc26gQE6boD+wkdUZTy55ns8cDCdaPajMrnuEByZCs70yvSgA==","data":"pay_result=success&tn=201512151321481233778"}"
2、检测是否已安装银联Apk接口调用
if(UPPayAssistEx.checkInstalled(context))
{undefined
//当判断用户手机上已安装银联Apk,商户客户端可以做相应个性化处理
}
(7)老版SDK商户修改说明
对于原有sdk接入商户,可在原有修改的基础上更新对应文件后,还需增加如下修改:
1. 增加upmp_android/sdkPro/jar/xxx/libuptsmaddon.so
2. 在工程的AndroidManifest.xml文件增加UPPayWapActivity。添加如下:
<application>
<!--工程其它配置此处省略…-->
<activity
android:name="com.unionpay.UPPayWapActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
</application>
3. 调用接口改为4.2节中支付接口startPay,但原有的startPayByJAR接口仍保留,如下所示:
public static int startPayByJAR (Activity activity, Class<?> payCls, String spId, String sysProvider, String orderInfo, String mode)
参数说明:
activity —— 用于启动支付控件的活动对象
payCls ——支付插件代表的类,填入“PayActivty.class”即可
spId —— 保留使用,这里输入null
sysProvider —— 保留使用,这里输入null
orderInfo —— 订单信息为交易流水号,即TN,为商户后台从银联后台获取。
mode —— 银联后台环境标识,“00”将在银联正式环境发起交易,“01”将在银联测试环境发起交易
5.常见问题总结
更多请参见https://open.unionpay.com帮助中心-FAQ
1. java.lang.ClassNotFoundException:org.simalliance.openmobileapi.SEService
此条异常仅会打印异常栈,而不会引起控件崩溃,无视即可。
2.java.io.FileNotFoundException: UPPayPluginExPro.apk
请将开发包中的UPPayPluginExPro.apk更改文件名为 UPPayPluginEx.apk后再放到assets文件夹下,可参考控件指南。
3.demo代码UPPayAssistEx.installPlugin调用后无反应/“完成购买需要安装银联支付控件,是否安装?”的确定按钮点击后无反应
同上一问。
4.java.lang.NoClassDefFoundError:com.unionpay.UPPayAssistEx
1. 工程里看看jar包是不是放对。
2. Jar包是不是加到build path里。
3. eclipse等工具里,工程上右键java build path-order andexport里需要勾上jar包。
5.Unable to start activity ComponentInfo(…): java.lang.NullPointerException《=UPPayEngine.a报的空指针
如:
比较大的可能:传进控件的tn参数不能为空或空值。
Jar方式接入也有可能:data.bin文件没有放对位置,请参照控件指南放。
6. Permission异常
如:
java.lang.RuntimeException: Unable to start activityComponentInfo{com.unionpay.uppayplugin.demo/com.unionpay.uppay.PayActivity}:java.lang.SecurityException: Requires READ_PHONE_STATE: Neither user 10065 norcurrent process has android.permission.READ_PHONE_STATE.
请检查一下权限是否在AndroidManifest文件中定义:
<uses-permissionandroid:name=""android.permission.INTERNET"" />
<uses-permission android:name=""android.permission.ACCESS_NETWORK_STATE""/>
<uses-permissionandroid:name=""android.permission.CHANGE_NETWORK_STATE""/>
<uses-permissionandroid:name=""android.permission.WRITE_EXTERNAL_STORAGE""/>
<uses-permissionandroid:name=""android.permission.READ_PHONE_STATE"" />
<uses-permissionandroid:name=""android.permission.ACCESS_WIFI_STATE"" />
7.java.lang.UnsatisfiedLinkErrror: Couldn’t load entryexpro: findLibrary return null或java.lang.UnsatisfiedLinkErrror: Library entryex not found
libentryexpro.so文件应放置到libs/CPU名比如armeabi目录下。2.1.2及以下控件的.so文件直接放libs目录下的,升级2.1.3及以上控件时,请务必注意目录层级多了CPU名的文件夹。
8.java.lang.NoClassDefFoundError: com.unionpay.uppay.PayActivity
请将相关的jar包拷贝至libs目录下,然后再add to build path。
9.can’t find reference class org.openmobileapi.SEService
如:
出现该错误是由于target未设置为openmobile API导致的,具体设置请参加4.3(5)节。
以上一部分是直接copy银联支付的文档的,因为很详细了,再加上一些Androidstudio的东西,跑出来的demo如图:
6.实际项目开发
完成所有的配置运行出来的Demo可以完全支付了说明Demo就已经完全配置好了银联的开发环境了,我们只需要参照这个Demo去配置我们自己的项目即可。