长话短说,本文根据银联官方说明文档,简单总结下,并且说明下中途碰到问题该如何解决。
一、开发前的准备工作
1. 打开https://open.unionpay.com/,后续说的文档下载、FAQ查询等都在这个平台操作。
2. 下载规范和开发包。帮助中心-下载-产品接口规范-手机控件支付产品接口规范,帮助中心-下载-产品接口规范-手机控件支付产品技术开发包。
3. 开发人员都请先看下6.2的消费的交易流程。
流程图说明:
(1)用户在客户端中点击购买商品,客户端发起订单生成请求到商户后台;
(2)商户后台收到订单生成请求后,按照《手机控件支付产品接口规范》组织并推送订单信息至银联后台;
(3)银联后台接收订单信息并检查通过后,生成对应交易流水号(即TN),并回复交易流水号至商户后台(应答要素:交易流水号等);
(4)商户后台接收到交易流水号,将交易流水号返回给客户端;
(5)客户端通过交易流水号(TN)调用支付控件;
(6)用户在支付控件中输入相关支付信息后,由支付控件向银联后台发起支付请求;
(7)支付成功后,银联后台将支付结果通知给商户后台;
(8)银联将支付结果通知支付控件;
(9)支付控件显示支付结果并将支付结果返回给客户端;
注: 本文档主要关注上述流程中(5)、(9)部分的实现
目前各个平台支持的设备情况如下:
Android平台SDK主要适用于Android 2.1及以上版本的终端设备;
iOS版本支付控件适用iOS 6.0及以上版本终端设备。
4. 相关测试参数:
如果已签约,有自己的测试商户,则直接用自己的商户号测试,测试证书开发包里都有。* 尽量用真实商户号测试,防止有时候参数配错能尽早发现。
如果没有签约,或者商户号尚未分配,请在平台里自行获取商户并且开交易权限,方法为:
a) 左上角注册;
b) 登陆后右上角我的测试-测试参数
c) 我的测试-产品-选下自己集成的。
测试卡号信息:(此类信息仅供测试,不会发生正式交易)
借记卡:6226090000000048
手机号:18100000000
密码:111101
短信验证码:123456
(短信验证码记得点下获取验证码之后再输入)--如果提示短信验证码错误[8100201],要看下是测试环境还是生产环境,另外控件版本是否是最新的
贷记卡:6226388000000095;
手机号:18100000000;
cvn2:248;
有效期:1219;
短信验证码:123456
(短信验证码记得点下获取验证码之后再输入)
二、客户端开发步骤
1. 参考文档《中国银联手机支付控件使用指南》(该文档位于前台开发包的doc目录下),建立一下工程。
2. 在后台开发实现消费(获取tn)请求前,App开发可以看看demo代码怎么调起控件的,demo里默认由银联的一个商户仿真获取tn(http://202.101.25.178:8080/sim/gettn或http://101.231.204.84:8091/sim/getacptn),之后需要改从商户自己的后台那里获取tn的。
3. 后台开发完成消费请求后,与后台开发商讨一下后台和app间传递tn的方式。
4. 改为从自己后台tn做测试。
5. 自行增加其他业务逻辑。
这里介绍下,客户端整合jar包的方式,如下图,一目了然
控件的调用(BYbrid插件方式):
public class PayPlugin extends CordovaPlugin { @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { String tn = args.getString(0); if(action.equals("unionPay")) { UPPayAssistEx.startPayByJAR(cordova.getActivity(), PayActivity.class, null, null, tn, "00"); } return super.execute(action, args, callbackContext); } }
返回结果处理(在MainActivity里面处理):
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { /************************************************* * 步骤3:处理银联手机支付控件返回的支付结果 ************************************************/ if (data == null) { return; } String msg = ""; /* * 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消 */ String str = data.getExtras().getString("pay_result"); if (str.equalsIgnoreCase("success")) { msg = "支付成功!"; } else if (str.equalsIgnoreCase("fail")) { msg = "支付失败!"; } else if (str.equalsIgnoreCase("cancel")) { msg = "用户取消了支付"; } Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show(); }
集成方式说明:
安卓分为静态库集成和apk接入两种方式:Apk接入方式、静态库集成。
Apk接入方式:调用startPay方法,调起手机中单独安装的控件。
静态库集成:调用startPayByJar方法,调起内置在商户app里的控件。
2种方式对比:
Apk接入方式:控件为独立安装。把demo代码中未安装控件时的代码修改为从银联官网下载控件apk后,商户就可以不用关心控件的版本了。控件apk下载地址:http://mobile.unionpay.com/getclient?platform=android&type=securepayplugin。
静态库集成:安装完商户app之后不需要再安装一次控件,但是商户需关心控件版本是否升级。另外iOS也是静态库集成,同时需要集成iOS的推荐用此方法,2边一致。
* 遇到问题可到https://open.unionpay.com/先自行看看能否解决: 1) 如果是代码异常:帮助中心-FAQ中把异常拷贝一小段搜索;或可以到FAQ的开发问题类别下,搜“安卓”或“iOS”可搜到对应的全量开发问题。 2) 如果是控件出错,报错信息有7位数字:技术集成-应答码,输入7位数字搜索。 3) 如果是控件出错,没有报错信息或没有7位数字:帮助中心-FAQ-测试问题,搜“app”可搜到控件的全量测试问题。 * 开发包中有pro和不带pro的,请使用不带pro的开发包,pro的开发包因包含一般接入方不使用的特殊功能,有些代码需要特殊处理。 * 安卓用startPay还是用startPayByJar的问题参考FAQ“apk方式和jar方式有何区别”。
三、后台开发步骤
1. 打开后台开发包,找到对应语言\示例代码文件夹,看下readme.txt,按步骤部署、修改配置文件等。
2. 其中Form_6_2_AppConsume的接口可获取tn,请跟客户端开发确定一下后台和app间传递tn的方式,最简单的方法就是直接在页面打印tn,不过部分语言直接仅打印tn的时候会带换行符,建议手机开发在收到tn的时候trim一下。
3. 后续参考readme完成。
简单介绍下后台获取tn的方法:
/** * 组装请求报文 */ Map<String, String> data = new HashMap<String, String>(); // 版本号 data.put("version", "5.0.0"); // 字符集编码 默认"UTF-8" data.put("encoding", "UTF-8"); // 签名方法 01 RSA data.put("signMethod", "01"); // 交易类型 01-消费 data.put("txnType", "01"); // 交易子类型 01:自助消费 02:订购 03:分期付款 data.put("txnSubType", "01"); // 业务类型 data.put("bizType", "000201"); // 渠道类型,07-PC,08-手机 data.put("channelType", "08"); // 前台通知地址 ,控件接入方式无作用 data.put("frontUrl", "http://localhost:8080/ACPTest/acp_front_url.do"); // 后台通知地址 data.put("backUrl", "http://222.222.222.222:8080/ACPTest/acp_back_url.do"); // 接入类型,商户接入填0 0- 商户 , 1: 收单, 2:平台商户 data.put("accessType", "0"); // 商户号码,请改成自己的商户号 data.put("merId", "888888888888888"); // 商户订单号,8-40位数字字母 data.put("orderId", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); // 订单发送时间,取系统时间 data.put("txnTime", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); // 交易金额,单位分 data.put("txnAmt", "1"); // 交易币种 data.put("currencyCode", "156"); // 请求方保留域,透传字段,查询、通知、对账文件中均会原样出现 // data.put("reqReserved", "透传信息"); // 订单描述,可不上送,上送时控件中会显示该信息 // data.put("orderDesc", "订单描述"); data = signData(data); // 交易请求url 从配置文件读取 String requestAppUrl = SDKConfig.getConfig().getAppRequestUrl(); Map<String, String> resmap = submitUrl(data, requestAppUrl); System.out.println("请求报文=["+data.toString()+"]"); System.out.println("应答报文=["+resmap.toString()+"]");
如上 resmap.get("tn"); 就是我们所需要的交易流水号。
* 遇到问题可到https://open.unionpay.com/先自行看看能否解决: 1) 如果是代码异常:帮助中心-FAQ中把异常拷贝一小段搜索;或可以到FAQ的开发问题类别下,搜“java”、“c#”、“php”可搜到对应的全量开发问题。 2) 如果是正常收到应答respcode非00,可以看一下respMsg,里面的7位数字在平台上技术集成-应答码搜索。 3) 如果是其他错,在FAQ的测试问题类别下看看是否有自己遇到的问题。
最重要的一点:
开发过程中难免碰到一些难点无法独立解决,这时可以联系银联的客服:
https://open.unionpay.com/ajweb/help?id=291
入网流程问题
业务申请和咨询,可发送邮件至[email protected]或电话021-50362428,银联有专门的人员进行处理。其他专项服务:请见《业务运营服务指引(商户) 》日常业务运营服务。
入网测试问题
您可发送邮件到[email protected]邮箱,(邮件标题为:商户号+商户名称+联系QQ),提供商户号和联系QQ,银联测试服务专员会将商户接口人的联系QQ加入到银联统一服务QQ中提供支持服务(商户也可以通过服务电话021-38929999-2049,来提供自己的商户号和联系QQ)
代收、订购、无跳转支付产品暂不支持自助测试,请见谅。
人工服务时间:工作日9:00-11:30,13:00-17:00