银联支付接口研究(Android端和Java服务端)
先来一张官方文档中的流程图
同样的,我们会严格按照流程走,会将私钥等安全相关信息放在后台,以前写过的微信,支付宝也是一样,有兴趣可以看一下。
第一步,android端选中购买商品,直接将后台需要的参数传过去。对应于步骤1
String merId = req.getParameter("merId");String txnAmt = req.getParameter("txnAmt");String orderId = req.getParameter("orderId");String txnTime = req.getParameter("txnTime");
这几个参数将会和接下来的第二步一起说明。
第二步,商户后台向银联全渠道平台发送订单推送请求,并获得交易流水号tn。对应于步骤2,3。
官方demo点我(包括了android端和Java端,我就是依照这个讲的)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String merId = req.getParameter("merId");String txnAmt = req.getParameter("txnAmt");String orderId = req.getParameter("orderId");String txnTime = req.getParameter("txnTime");Map<String, String> contentData = new HashMap<String, String>();/***银联全渠道系统,产品参数,除了encoding自行选择外其他不需修改***/contentData.put("version", DemoBase.version); //版本号 全渠道默认值contentData.put("encoding", DemoBase.encoding); //字符集编码 可以使用UTF-8,GBK两种方式contentData.put("signMethod", SDKConfig.getConfig().getSignMethod()); //签名方法contentData.put("txnType", "01"); //交易类型 01:消费contentData.put("txnSubType", "01"); //交易子类 01:消费contentData.put("bizType", "000201"); //填写000201contentData.put("channelType", "08"); //渠道类型 08手机/***商户接入参数***/contentData.put("merId", merId); //商户号码,请改成自己申请的商户号或者open上注册得来的777商户号测试contentData.put("accessType", "0"); //接入类型,商户接入填0 ,不需修改(0:直连商户, 1: 收单机构 2:平台商户)contentData.put("orderId", orderId); //商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则 contentData.put("txnTime", txnTime); //订单发送时间,取系统时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效contentData.put("accType", "01"); //账号类型 01:银行卡02:存折03:IC卡帐号类型(卡介质)contentData.put("txnAmt", txnAmt); //交易金额 单位为分,不能带小数点contentData.put("currencyCode", "156"); //境内商户固定 156 人民币contentData.put("backUrl", DemoBase.backUrl);//参数certId在生成signature前在AcpService.sign方法中获取并自动赋值,只要证书配置正确即可。/**对请求参数进行签名并发送http post请求,接收同步应答报文**/Map<String, String> reqData = AcpService.sign(contentData,DemoBase.encoding); // 将除了signature外所有必须的参数放在contentData中,然后将所有参数用SHA算法生成[消息摘要](https://open.unionpay.com/ajweb/product/detail?id=3),然后用商户的私钥对消息摘要进行加密生成了signature,然后将signature也加入到contentData中。String requestAppUrl = SDKConfig.getConfig().getAppRequestUrl();//交易的URL是常数即为:https://gateway.95516.com/gateway/api/appTransReq.do Map<String, String> rspData = AcpService.post(reqData,requestAppUrl,DemoBase.encoding); //封装网络通信,将回复的数据转化到Map中,方便后面操作。/**对应答码的处理,请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考------------->**///应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》if(!rspData.isEmpty()){if(AcpService.validate(rspData, DemoBase.encoding)){//根据返回数据rspData中的signMethod加密方法的不同,RSA或SHA或其他进行分类验签。//如果是RSA则要用银联的公钥对signature摘要值进行解密然并和除signature外的所有参数进行SHA加密生成的摘要进行效验;主要代码为:
/**
public static boolean validateSignBySoft(PublicKey publicKey,byte[] signData, byte[] srcData) throws Exception {Signature st = Signature.getInstance(BC_PROV_ALGORITHM_SHA1RSA, "BC");st.initVerify(publicKey);st.update(srcData);return st.verify(signData);
}*///如果是SHA256则signature摘要值和除signature外的所有参数进行SHA加密生成的摘要进行equal比较,和shangRSA的区别是signature值没有进行私钥加密,可以直接比较。//此处涉及到加密的许多知识可以参考如下资料: [安全体系(零)—— 加解密算法、消息摘要、消息认证技术、数字签名与公钥证书](http://blog.csdn.net/fengyuzhiren/article/details/61201447)LogUtil.writeLog("验证签名成功");String respCode = rspData.get("respCode") ;if(("00").equals(respCode)){//成功,获取tn号,返回给android端即可。//String tn = resmap.get("tn");//TODO}else{//其他应答码为失败请排查原因或做失败处理//TODO}}else{LogUtil.writeErrorLog("验证签名失败");//TODO 检查验证签名失败的原因}}else{//未返回正确的http状态LogUtil.writeErrorLog("未获取到返回报文或返回http状态码非200");}String reqMessage = DemoBase.genHtmlResult(reqData);String rspMessage = DemoBase.genHtmlResult(rspData);resp.getWriter().write("请求报文:<br/>"+reqMessage+"<br/>" + "应答报文:</br>"+rspMessage+"");
}
基本信息,以下域必送
NS5:长度为5字节定长的数字字符和/或特殊字符;
M:必须填写的域、O:受理方和发卡方自选填写的域;
ANS1..20:长度为1到20字节的变长字母、数字和/或特殊符号字符
官方参数文档点我
第三步,android获得交易流水号后通过方法 UPPayAssistEx.startPay(this, null, null, tn, mode);跳到支付控件进行订单支付,然后提示支付是否完成。对应步骤4、5、6
①调用startPay方法,根据返回结果判断如果没有安装支付控件,就先安装,然后才能跳到支付控件进行支付。
@Override
public void doStartUnionPayPlugin(Activity activity, String tn, String mode) {// mMode参数解释:// 0 - 启动银联正式环境// 1 - 连接银联测试环境int ret = UPPayAssistEx.startPay(this, null, null, tn, mode);if (ret == PLUGIN_NEED_UPGRADE || ret == PLUGIN_NOT_INSTALLED) {// 需要重新安装控件Log.e(LOG_TAG, " plugin not found or need upgrade!!!");AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("提示");builder.setMessage("完成购买需要安装银联支付控件,是否安装?");builder.setNegativeButton("确定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {UPPayAssistEx.installUPPayPlugin(APKActivity.this);dialog.dismiss();}});builder.setPositiveButton("取消",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});builder.create().show();}Log.e(LOG_TAG, "" + ret);
}
②返回结果处理如下:
@Override
protected 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")) {// 如果想对结果数据验签,可使用下面这段代码,但建议不验签,直接去商户后台查询交易结果// result_data结构见c)result_data参数说明if (data.hasExtra("result_data")) {String result = data.getExtras().getString("result_data");try {JSONObject resultJson = new JSONObject(result);String sign = resultJson.getString("sign");String dataOrg = resultJson.getString("data");// 此处的verify建议送去商户后台做验签// 如要放在手机端验,则代码必须支持更新证书 boolean ret = verify(dataOrg, sign, mMode);if (ret) {// 验签成功,显示支付结果msg = "支付成功!";} else {// 验签失败msg = "支付失败!";}} catch (JSONException e) {}} // 结果result_data为成功时,去商户后台查询一下再展示成功msg = "支付成功!";} else if (str.equalsIgnoreCase("fail")) {msg = "支付失败!";} else if (str.equalsIgnoreCase("cancel")) {msg = "用户取消了支付";}
官方文档提醒:控件返回的结果信息仅作为参考,商户订单是否成功支付应该以商户后台主动到全渠道查询的结果或者收到全渠道支付结果通知为准。
第四步,银联服务端将支付状态通过backUrl设置的路径通知给商户后台,然后进行验签,通过后处理业务逻辑,并给银联服务端回复确认应答,验签过程和第一步中的验签过程一样,是同一个验签函数。
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {LogUtil.writeLog("BackRcvResponse接收后台通知开始");String encoding = req.getParameter(SDKConstants.param_encoding);// 获取银联通知服务器发送的后台通知参数Map<String, String> reqParam = getAllRequestParam(req);LogUtil.printRequestLog(reqParam);Map<String, String> valideData = null;if (null != reqParam && !reqParam.isEmpty()) {Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();valideData = new HashMap<String, String>(reqParam.size());while (it.hasNext()) {Entry<String, String> e = it.next();String key = (String) e.getKey();String value = (String) e.getValue();valideData.put(key, value);}}//重要!验证签名前不要修改reqParam中的键值对的内容,否则会验签不过if (!AcpService.validate(valideData, encoding)) {LogUtil.writeLog("验证签名结果[失败].");//验签失败,需解决验签问题} else {LogUtil.writeLog("验证签名结果[成功].");//【注:为了安全验签成功才应该写商户的成功处理逻辑】交易成功,更新商户订单状态String orderId =valideData.get("orderId"); //获取后台通知的数据,其他字段也可用类似方式获取String respCode = valideData.get("respCode");//判断respCode=00、A6后,对涉及资金类的交易,请再发起查询接口查询,确定交易成功后更新数据库。}LogUtil.writeLog("BackRcvResponse接收后台通知结束");//返回给银联服务器http 200 状态码resp.getWriter().print("ok");
}
可选:商户在30分钟内未收到中国银联全渠道平台的支付结果通知时,建议应该主动向全渠道平台发起交易信息查询交易(该步骤可选),查询该交易是否成功,可查询一次或多次。下载官方demo后可通过readme.txt选择其他操作。
最后提醒支付交易中的生成摘要信息、公钥加密、签名证书,验签这些概念是比较重要的,建议一定要弄清楚,看起官方文档才能游刃有余。
银联支付接口研究(Android端和Java服务端)相关推荐
- java 加密服务器_Javascript端加密java服务端解密
通常我们会通过htts来保证传输安全,但如果我们不用https,如何通过javascript来保证浏览器端发送的参数进行加密,并且通过RSA算法来处理. 这里我们可以利用jquery的一个加密插件jc ...
- 谷歌支付(Java服务端)
Google Pay主要支付流程 1.手机端向Java服务端发起支付,生成预订单,给手机端返回生成的订单号 2.手机端向Google发起支付(传入本地服务器生成的订单号) 3.Google服务器将支付 ...
- 支付宝APP支付Java服务端
支付宝APP支付Java服务端: 公司项目要求对接支付宝进行支付功能,这边做出整理方便以后使用(支付宝的支付对接还是很简单的). 1):去支付宝开放平台,-1.注册账号,2.创建应用 3.配置应用 4 ...
- django2.0调用银联支付接口实现银联支付
准备工作: 1.银联技术开放平台注册:https://open.unionpay.com/tjweb/acproduct/list?apiservId=448 2.点击网关支付 --> 我要测试 ...
- php银联支付接口 demo,php版银联支付接口开发简单实例详解
这篇文章主要介绍了php版银联支付接口开发的方法,结合实例形式分析了php银联支付接口开发的具体流程与相关操作技巧,需要的朋友可以参考下 支付接口现在有第三方的支付接口也有银行的支付接口.这里就来介绍 ...
- Chinapay 银联支付接口
银联开发必须要开启mcrypt 和 bcmath 两个PHP扩展库的支持 如果没有就没有办法进行开发,先确认数据库是否开启扩展 关于银联支付接口 最主要的是银行提供的秘钥和私钥, netpayclie ...
- Android端+Java服务端+servlet+MySQL二手商城设计
项目地址: Android端+Java服务端+servlet+MySQL二手商城设计.zip-Android文档类资源-CSDN下载 项目简介及内容截图如下: 本系统适用于计算机专业作为期末课程设计. ...
- 基于TCP/IP协议的Java服务端与Android客户端的Socket通信及数据交互
基于TCP/IP协议的Java服务端与Android客户端的Socket通信及数据交互 一.前言 1.Java服务端程序代码的项目名为TcpSocketServerOfJava,包名为com.exam ...
- android+okhttp+java服务端(tomcat)+mysql实现登录注册
先上代码(文章结尾有遇到的问题和对应解决方案) android客户端 >android:app-build.gradle 1.添加okhttp依赖,具体根据自己的okhttp包来决定 depen ...
- 那些年,我们见过的 Java 服务端“问题”
导读 明代著名的心学集大成者王阳明先生在<传习录>中有云: 道无精粗,人之所见有精粗.如这一间房,人初进来,只见一个大规模如此.处久,便柱壁之类,一一看得明白.再久,如柱上有些文藻,细细都 ...
最新文章
- 【Netty】Netty为什么要手动释放ByteBuf资源?
- Kafka解惑之Old Producer(2)——Sync Analysis
- 初学者对python的认识_Python初学者列表,python,初识
- Java Servlet总结
- 图片不显示问题 图片url监测改变问题
- Oracle 数据库-分组函数总结
- VS封装给Unity使用的DLL
- 当你写爬虫抓不到APP请求包的时候该怎么办?【高级篇-混淆导致通用Hook工具失效】...
- 使用 Java API 操作 HBase
- c语言 入字符要中文状态吗,常见的HTTP状态码深入理解
- qt 获取本地文件夹、文件路径
- JavaScript实现 网页倒计时
- 手把手教你虚拟机安装(VMware)、Linux操作系统安装
- Python 读取mgf文件
- NFS服务器搭建与autofs自动挂载
- 趣聊51之串口通信(实现篇)
- 【生活】年化收益率、七日年化收益率这些事
- kali上的一些密码破解工具
- 运用arcGIS ArcPy推求管网节点高程
- 新浪微博验证码接口短信轰炸的防护攻略
热门文章
- centos 7.5 安装ruby -bash: ruby: command not found
- linux monitor工具,5 款 Ubuntu 系统监控工具
- 恶意代码防范技术原理-恶意代码概述
- 修改PDF文件软件中文问题,福昕软件Foxit PDF Editor
- ut红种状态解决办法汇总
- mysql中哪一个储存逻辑型_《VisualFoxPro》2018秋华东年季学期在线作业(一)二三...
- QQ连连看6.0 逆向分析
- 折腾手机与平板的心得体会
- 电脑telnet失败的解决方法
- jmail邮件服务器,jmail.smtpmail的核心代码: