银联手机控件支付,java后台开发(避坑)。

今天研究了一下银联的支付系统,关于银联的支付集成,我真的也是醉了,官方文档写的和屎一样,主要里面还有坑,官方页面展示的文档和官方下载的代码Demo在参数的解释上有明显不同(关于后台回调地址字段),里面还有错别字,还有注释写错的,我真是无言以对,不知道银联怎么想的~~~~

正题

银联开放的接口主要分两类,一类是针对pc端的,一类是针对移动端的。

类型

简单解释下上面的几种类型

PC端

网关支付:主要针对B2C电商网站,用户发起支付需要跳转到银联页面完成支付。
无跳转支付:是银联为一些大型电商网站开的小灶,不需要跳转页面。
企业网银支付:多家银行企业网银统一支付(这个我没仔细看,有兴趣的可以自行研究)。

移动端

手机控件支付:类似APP集成支付宝SDK那种模式。
手机网页支付(wap):类似于PC端的网关支付。
银联云闪和Apple Pay我也没仔细看........

下面我们以 “手机控件支付”为例简单说下流程,然后看个小例子,
先看个流程图,

流程图

这时银联官网的流程图,我怀疑他是用word画的.....

交易步骤:

1、 用户通过商户App终端购买商品;

2、 商户后台接收商品购买请求,生成订单发送订单推送请求(签名)至银联;

3、 银联 同步返回对应该订单的交易流水号至商户后台(验签);

4、 商户后台转发交易流水号至商户App,并跳转至银联安全支付控件页面;

5、 用户输入支付相关支付信息(如密码),完成支付操作;

6、 支付成功完成后,控件通过前台通知的方式向商户系统发送交易结果;

7、 银联交易成功后,主动将支付结果以post方式通知商户后台,银联采用通知重发机制告知商户后台(需要验签)。

基本和集成支付宝和微信类似,但是银联比较烦的一点就是他有各种证书,签名和验签时都需要用到证书。

现在我们可以去银联的官网下载一个demo示例运行感受下。
地址:https://open.unionpay.com/ajweb/help/file/techFile?productId=3

导入eclipse后大概是这个样子,不知道为啥有个红叉,请忽略,懒得去解决了,只是看个源码而已。

Paste_Image.png

其中 sdk 包下存放的是精华,是银联为我们封装好的一些工具类,比如签名和验签等方法,其余的大部分是示例代码,
assets文件夹下存放的是一些配置文件和相关证书,不一一解释了,在代码注释中有详细的解释。

现在看下支付的调用过程

    @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");                   //填写000201
        contentData.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 人民币

        // 请求方保留域,
        // 透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据。
        // 出现部分特殊字符时可能影响解析,请按下面建议的方式填写:
        // 1. 如果能确定内容不会出现&={}[]"'等符号时,可以直接填写数据,建议的方法如下。
//      contentData.put("reqReserved", "透传信息1|透传信息2|透传信息3");
        // 2. 内容可能出现&={}[]"'符号时:
        // 1) 如果需要对账文件里能显示,可将字符替换成全角&={}【】“‘字符(自己写代码,此处不演示);
        // 2) 如果对账文件没有显示要求,可做一下base64(如下)。
        //    注意控制数据长度,实际传输的数据长度不能超过1024位。
        //    查询、通知等接口解析时使用new String(Base64.decodeBase64(reqReserved), DemoBase.encoding);解base64后再对数据做后续解析。
//      contentData.put("reqReserved", Base64.encodeBase64String("任意格式的信息都可以".toString().getBytes(DemoBase.encoding)));
                    
        //后台通知地址(需设置为外网能访问 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);            //报文中certId,signature的值是在signData方法中获取并自动赋值的,只要证书配置正确即可。
        String requestAppUrl = SDKConfig.getConfig().getAppRequestUrl();                                 //交易请求url从配置文件读取对应属性文件acp_sdk.properties中的 acpsdk.backTransUrl
        Map<String, String> rspData = AcpService.post(reqData,requestAppUrl,DemoBase.encoding);  //发送请求报文并接受同步应答(默认连接超时时间30秒,读取返回结果超时时间30秒);这里调用signData之后,调用submitUrl之前不能对submitFromData中的键值对做任何修改,如果修改会导致验签不通过
        
        /**对应答码的处理,请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考------------->**/
        //应答码规范参考open.unionpay.com帮助中心 下载  产品接口规范  《平台接入接口规范-第5部分-附录》
        if(!rspData.isEmpty()){
            if(AcpService.validate(rspData, DemoBase.encoding)){
                LogUtil.writeLog("验证签名成功");
                String respCode = rspData.get("respCode") ;
                if(("00").equals(respCode)){
                    //成功,获取tn号
                    //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+"");
    }

详细解释代码中都有,

注意!!这里面说下遇到的一个比较严重的坑,,,,

在从官方下载的demo中,就是上面看的那个代码,有如下配置文件

Paste_Image.png

这里面有两个参数,他的解释分别是

前台通知地址backUrl(流程图 6) 和 后台通知地址frontUrl(流程图7)

但是官方网页文档上有如下解释

地址:http://open.unionpay.com/

Paste_Image.png

backUrl 代码中说他是前台通知地址,,网页文档说他是后台通知地址,不知道银联在想什么。。。

我搞了2个小时,终于找到的银联的官方 pdf版文档,有如下解释

Paste_Image.png

说因为兼容控件第一期未采用 frontUrl 方式来做 支付控件给 商户APP返回结果,

我个人觉得还是这个比较靠谱一点,这两个参数正确的解释是

后台通知地址backUrl(对应流程图 7)
前台通知地址frontUrl(对应流程图6)

代码中的注释是错误的,真是太坑了,
现在把项目跑起来看看吧

Paste_Image.png

点击消费

Paste_Image.png

成功,nice!

还有个后台异步通知,就不演示了,可以去官网下代码搞一搞,里面有配置好的测试环境,还算好用,就是注释有些错的,切记以官网pdf版为准!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容