• 一功能描述
  • 二实现过程
    • 1下载银联支付SDK和Demo

      • 1银联商家服务地址httpsopenunionpaycomajwebindex
      • 2下载的文件如下
    • 2集成过程
      • 1先试官方Demo
      • 2集成到自己的工程里
  • 2016年5月6日补充
    • 3后台通知接收处理配置

      • 1修改DemoBasejava中的backUrl
      • 2后台通知处理部分

2016年5月6日有更新,请参考第三部分。

一.功能描述

因为是自己开发了一个app应用,没资格去申请微信支付和支付宝支付,于是就采用了银联支付功能,银联支付分为了两种环境:测试环境和生产环境,一般前期开发的时候都是使用测试环境,数据都是测试数据,不会发生真实交易。第一次做Android项目+IDE为Android Studio+第一次集成支付功能,所以个人觉得整个集成过程可能有点复杂,而且银联支付产品众多:网关支付产品、手机控件支付、手机网页支付等等,第一次看的时候真是云里雾里,不知道选哪个,不知道他们的区别,最后自己选择了手机控件支付,先试试,光看没有用。自己做了多少写多少,好记性不如烂笔头,就怕后面想记录的时候忘记了前面的过程。

二.实现过程

2.1下载银联支付SDK和Demo

(1)银联商家服务地址:https://open.unionpay.com/ajweb/index

第一步:注册;

第二步:然后在帮助中心界面的产品分类下载里选择手机控件支付;

第三步:下载安卓版的开发包。

(2)下载的文件如下

2.2集成过程

个人建议可以先把服务器端的工程跑一下,这样结合代码的时候就很容易明白怎么集成到自己的工程里了。所以这一小部分内容是官方Demo的运行情况,需要修改的配置很少,但是还是有小地方需要调整一下。

(1)先试官方Demo

  • 将工程导入

  • 修改acp_sdk_properties的配置

将这三个路径修改为测试环境证书的路径(证书在assets文件夹下),可以使用相对路径或者绝对路径都行,下面图中是绝对路径,我把assets/测试环境证书下的三个文件移动到了C盘。

我的测试环境证书地址:

  • Run一个试试

启动tomcat过程中比较关键的一处就是

  • 首页

  • 获取tn


最后打印的报文

(2)集成到自己的工程里

先讲服务器端,因为自己也才完成了这部分工作。运行了官方Demo以及相关说明文档后,整体思路其实就有了。
首先试试配置!!!

  • jar包

将Demo工程lib中的jar包复制到自己工程的lib里(如果已经有jar包了,就不需要复制了)

  • 修改acp_sdk_propertise和log4j.properties
    (主要是一些路径的修改,因为我的服务器上只有C盘,所以我必须得改,acp_sdk_properties的修改见(1)运行Demo部分)

  • 导入相关java文件

之所以写用import的方式是为了少出现乱码的问题,见下图

第一部分 controller对应于Demo中的ACPSample_AppServer\src\com\unionpay\acp\demo,其中PayController是我自己写的Controller。
第二部分model对应于Demo中的ACPSample_AppServer\src\com\unionpay\acp\sdk
第三部分的两个java文件对应于Demo中的\ACPSample_AppServer\src\web中的两个java文件

  • web.xml配置
    增加
<servlet><servlet-name>autoLoadServlet</servlet-name><servlet-class>com.XXX.component.pay.AutoLoadServlet</servlet-class><load-on-startup>0</load-on-startup></servlet><servlet-mapping><servlet-name>autoLoadServlet</servlet-name><url-pattern>/autoLoadServlet</url-pattern></servlet-mapping>

ok,配置过程就算完事了,现在就该写PayController来接受请求了。

  • PayController控制器
    其实就是Form05_6_2_AppConsume.java中的代码,因为使用是SSM架构,就改了改架构而已。
@Controller
public class PayController extends BasicController{@RequestMapping(value = "/pay/pay")@ResponseBodypublic void pay(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {request.setCharacterEncoding(DemoBase.encoding_UTF8);//response.setContentType("text/html; charset="+ DemoBase.encoding_UTF8);//这两句是我临时加的,因为出现了乱码Map<String, String> contentData = new HashMap<String, String>();/***银联全渠道系统,产品参数,除了encoding自行选择外其他不需修改***/contentData.put("version", DemoBase.version);            //版本号 全渠道默认值contentData.put("encoding", DemoBase.encoding_UTF8);     //字符集编码 可以使用UTF-8,GBK两种方式contentData.put("signMethod", "01");                    //签名方法 目前只支持01:RSA方式证书加密contentData.put("txnType", "01");                       //交易类型 01:消费contentData.put("txnSubType", "01");                    //交易子类 01:消费contentData.put("bizType", "000201");                   //填写000201contentData.put("channelType", "08");                   //渠道类型 08手机String merId = request.getParameter("merId");String txnAmt = request.getParameter("txnAmt");String orderId = request.getParameter("orderId");String txnTime = request.getParameter("txnTime");/***商户接入参数***/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("reqReserved", "透传字段");              //商户自定义保留域,交易应答时会原样返回//后台通知地址(需设置为外网能访问 http https均可),支付成功后银联会自动将异步通知报文post到商户上送的该地址,【支付失败的交易银联不会发送后台通知】//后台通知参数详见open.unionpay.com帮助中心 下载  产品接口规范  网关支付产品接口规范 消费交易 商户通知//注意:1.需设置为外网能访问,否则收不到通知    2.http https均可  3.收单后台通知后需要10秒内返回http200或302状态码 //    4.如果银联通知服务器发送通知后10秒内未收到返回状态码或者应答码非http200或302,那么银联会间隔一段时间再次发送。总共发送5次,银联后续间隔1、2、4、5 分钟后会再次通知。//    5.后台通知地址如果上送了带有?的参数,例如:http://abc/web?a=b&c=d 在后台通知处理程序验证签名之前需要编写逻辑将这些字段去掉再验签,否则将会验签失败contentData.put("backUrl", DemoBase.backUrl);//[其实还没搞明白这个地址的作用]/**对请求参数进行签名并发送http post请求,接收同步应答报文**/Map<String, String> reqData = AcpService.sign(contentData,DemoBase.encoding_UTF8);           //报文中certId,signature的值是在signData方法中获取并自动赋值的,只要证书配置正确即可。String requestAppUrl = SDKConfig.getConfig().getAppRequestUrl();                                 //交易请求url从配置文件读取对应属性文件acp_sdk.properties中的 acpsdk.backTransUrlMap<String, String> rspData = AcpService.post(reqData,requestAppUrl,DemoBase.encoding_UTF8);  //发送请求报文并接受同步应答(默认连接超时时间30秒,读取返回结果超时时间30秒);这里调用signData之后,调用submitUrl之前不能对submitFromData中的键值对做任何修改,如果修改会导致验签不通过/**对应答码的处理,请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考------------->**///应答码规范参考open.unionpay.com帮助中心 下载  产品接口规范  《平台接入接口规范-第5部分-附录》if(!rspData.isEmpty()){if(AcpService.validate(rspData, DemoBase.encoding_UTF8)){LogUtil.writeLog("验证签名成功");String respCode = rspData.get("respCode") ;if(("00").equals(respCode)){//成功,获取tn号//String tn = resmap.get("tn");//这里应该是rspData.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);try {response.getWriter().write("请求报文:<br/>"+reqMessage+"<br/>" + "应答报文:</br>"+rspMessage+"");//response.getOutputStream().write(("请求报文:<br/>"+reqMessage+"<br/>" + "应答报文:</br>"+rspMessage+"").getBytes("UTF-8"));} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
  • 运行

然后浏览器输入(get方式,在Form05_6_2_AppConsume.java中get和post方式是一样的,我的PayController因为没有指定请求方式,所以两种方式也是兼容的,而且只是为了测试采用的get,后面把客户端搭好,就用post方式)
:http://123.XX.XXX.127:8080/intveh/pay/pay?merId=777290058110048&txnTime=20160505092851&orderId=20160505092851&txnAmt=5
效果和官方Demo一样:

目前就把服务器端的tn获取搭好了,还有退款退货等等以及客户端的搭建,接着搞~~

2016年5月6日补充

服务器端还应该有“后台通知接收处理”部分。可参见Demo中ACPSample_AppServer\src\com\unionpay\acp\demo\BackRcvResponse.java。这部分的功能很重要:见下图所示(银联支付流程图)

第七步是银联后台将支付结果返回给我们的服务器端,我们将根据返回结果更新订单的状态,请注意:虽然第八步是将客户端的支付控件也会支付结果,但是能作为订单支付结果的只有后台的通知,官方文档中有一处说的有歧义,客服是这样说的:

关于客户端支付结果+验签,在下一篇文档中说明。

3.3后台通知接收处理配置

(1)修改DemoBase.java中的backUrl

请注意:这个backUrl必须填写真实ip地址,回路地址不行、localhost不行,银联后台返回通知必须能post到你的backUrl。

(2)后台通知处理部分

/*** 后台通知处理* @param sign* @param request* @param response*/@RequestMapping(value = "/pay/backRcvResponse")@ResponseBodypublic void backRcvResponse(HttpServletRequest request, HttpServletResponse response) {System.out.println("后台通知验签开始");//return AcpService.validateAppResponse(sign, DemoBase.encoding_UTF8);//System.out.println("验签开始");String encoding = request.getParameter(SDKConstants.param_encoding);// 获取银联通知服务器发送的后台通知参数Map<String, String> reqParam = Tool.getAllRequestParam(request);LogUtil.printRequestLog(reqParam);Map<String, String> valideData = null;try{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();value = new String(value.getBytes(encoding), encoding);valideData.put(key, value);}}//重要!验证签名前不要修改reqParam中的键值对的内容,否则会验签不过if (!AcpService.validate(valideData, encoding)) {LogUtil.writeLog("验证签名结果[失败].");//验签失败,需解决验签问题} else {LogUtil.writeLog("验证签名结果[成功].");//【注:为了安全验签成功才应该写商户的成功处理逻辑】交易成功,更新商户订单状态//valideData里封装了很多数据,可参考官方文档,做相应后续处理}}LogUtil.writeLog("BackRcvResponse接收后台通知结束");//返回给银联服务器http 200  状态码response.getWriter().print("ok");}catch(Exception e){}}

ok,backUrl配置正确,那么进行支付后,商户后台就会得到银联后台的支付通知,如下图:

这部分工作不能少,一定要记住后台通知处理的作用:真正作为接收订单支付结果的地方。

Android开发:app工程集成银联支付功能(服务器端)相关推荐

  1. Android开发:app工程集成银联支付功能(客户端)

    Android开发:app工程集成银联支付功能(客户端) email:chentravelling@163.com 上一篇博文完成了服务器端的集成,可参考: Android开发:app工程集成银联支付 ...

  2. Android 开发 | App 工程目录结构

    包括两个分类:app 和 Gradle Scripts. app 目录包括: manifests 子目录,只有一个 AndroidManifest.xml 文件,它是 App 的运行配置文件. jav ...

  3. Android开发app实现发送短信功能

    程序使用手机发短信的方法 短信收发: ◆发送短信只需要几行代码,如下: SmsManager sms = SmsManager.getDefault(); PendingIntent pi = Pen ...

  4. Android集成银联支付最新版3.8.5(银联真NM坑)

    Android集成银联支付(银联真N&M坑) 1.这是银联Android 开发包的下载地址开发包下载地址 2.下载完里面的内容是这样的 3.其实调起来银联支付(云闪付),就一句代码,其他的都是 ...

  5. PHP 集成银联支付

    现如今支付系统几乎成了许多网站必不可少的东西,那么常见的几种支付方式:支付宝.微信:关于 支付宝 .微信 的实现方式在 世界上最好用的 Alipay 和 WeChat 的支付 SDK 这篇文章有介绍, ...

  6. APP中的第三方“支付”功能该如何测试

    经过最近几个项目的测试,APP中带有支付功能的产品有很多,那么APP中带有第三方支付功能的产品在这一模块该如何测试才尽可能的测试完整. 正常流程: 正常使用支付宝.微信.银行卡(目前使用最多的第三方支 ...

  7. android微信风格,Android开发实现模仿微信小窗口功能【Dialog对话框风格窗口】

    本文实例讲述了Android开发实现模仿微信小窗口功能.分享给大家供大家参考,具体如下: 运用方法: 将显示窗口的风格 设置为对话框风格即可 具体效果: 具体实现: 首先我们先定义布局文件: andr ...

  8. Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题

    Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题 1.调用相机,兼容7.0 AndroidManifest配置 <providera ...

  9. android 文字选中朗读,Android开发之文本内容自动朗读功能实现方法

    本文实例讲述了Android开发之文本内容自动朗读功能实现方法.分享给大家供大家参考,具体如下: Android提供了自动朗读支持.自动朗读支持可以对指定文本内容进行朗读,从而发生声音:不仅如此,An ...

最新文章

  1. 振动力学基础与matlab应用_【日文好书推荐】振动与噪声控制技术for机械设计者...
  2. 企业 SOA 设计(1)–ESB 设计
  3. Python之web开发(六):python使用django框架搭建网站之登陆页搭建不同页面之间跳转
  4. 方法 | 机器学习(深度学习)通用工作流程
  5. Mybatis源码分析之(一)搭建一个mybatis框架(写一个mybatis的Demo)
  6. leetcode —— 965. 单值二叉树
  7. FlashBuilder 4.5 安装图解
  8. 启动报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
  9. 移动端媒体尺寸_网络推广外包浅析提升移动端网站建设效率有哪些网络推广外包技巧-企服...
  10. vue-element-admin 设置默认语言
  11. [转载] python字符串只留数字_Python工匠:数字与字符串(下)
  12. ZXing开发彩色二维码
  13. Java反编译生成java文件
  14. 人工智能白皮书(2022年) 附下载
  15. win10相机计算机无法使用,win10相机无法使用完美解决方法
  16. 单片机加减法C语言,单片机的加减法原理
  17. element表格样式修改
  18. 云原生|kubernetes|etcd集群详细介绍+安装部署+调优
  19. ERROR: Cannot uninstall ‘PyYAML‘. It is a distutils installed project and thus we cannot...
  20. 游戏原画之组合画法-张聪-专题视频课程

热门文章

  1. Residual Networks(吴恩达课程)
  2. 电子计算机的基本结构基于存储程序,计算机考试理论
  3. 空间说说转发显示服务器繁忙,发QQ日志的说说
  4. 圆桌会议一 -象牙塔内外精英的对话
  5. CSS超链接里的“love hate“
  6. 算法图解part7:狄克斯特拉算法
  7. 现代饭店中主要有哪些计算机应用系统,酒店信息管理系统习题
  8. 暴雪的hash算法[翻译]
  9. 关于360N6 Lite的Root教程
  10. access订单明细表怎么做_快速开发平台(进销存教程)--必须在字段采购订单明细表.完成数量中输入一个值...