• 调用中行接口针对返回报文(xml形式)做相关处理


    最近在对接中行银行接口,在获取返回报文的时候遇到一些问题,现在在这里做个总结
    TIP:
    在返回报文之前,要对前置机的URL请求,在这期间遇到一个坑,还是通过查看日志才发现问题
    在填写转账信息的时候要求输入转账公司名称,但是银行接口又不会强制对转账公司名称校验,而且转账操作也会显示成功,只是在查询交易状态的时候才会显示
    交易失败被银行退回/收款人账号和收款人名称不一致的错误
    当时有点懵逼,还仔细检查到底有没有输错信息 = =
    后来使用Postman把我要发送的报文粘贴进去,发现成功!这时候才发现是编码问题
    原来
    最开始使用下面方法设置字符集

    // 设置文件字符集:
          conn.setRequestProperty("Charset", "UTF-8");

    发现这样不会把字符设置为UTF-8的编码,所以系统就取了默认的编码格式
    原来是要在转换为字节数组的时候给它设置字符编码

    //转换为字节数组
          byte[] data = xml.getBytes("UTF-8");

    1.普通报文

    <?xml version="1.0" encoding="UTF-8"?>
    <bocb2e version="120" locale="zh_CN">
        <head>
            <termid>E192168000105</termid>
            <trnid>20060704001</trnid>
            <custid>133724203</custid>
            <cusopr>135989127</cusopr>
            <trncod>b2e0001</trncod>
            <token>SyX3PnpuNdIQm6FDj1SgZn8</token>
        </head>
        <trans>
            <trn-b2e0001-rs>
                <status>
                    <rspcod>B001</rspcod>
                    <rspmsg>ok</rspmsg>
                </status>
                <serverdt>20180126105944</serverdt>
                <token>SyX3PnpuNdIQm6FDj1SgZn8</token>
            </trn-b2e0001-rs>
        </trans>
    </bocb2e>

    上面是调用银行接口成功签到的报文,类似于这样的特征就比较明显,不需要做任何处理,就能通过下面Dom4j提供的基础方法对每个节点进行操作

    Document document = DocumentHelper.parseText("传入的报文");
    //获取文档根节点
    Element root = document.getRootElement();

    上面方法就已经获取到返回报文的根节点了,这个时候你就能获取到任何你想要的节点参数了
    例如:
    获取b2e0001-rs节点下面status的值

    Element rspcodElem = root.element("trans").element("trn-b2e0001-rs").element("status")
            .element("rspcod");
    rspcodElem.getStringValue()//节点的值
    rspcodElem.getName()//节点名称

    想要获取其他节点值也与上面方法一样
    2.报文中含有规律重复节点处理
    例如接口中的历史余额查询返回的报文

    <?xml version="1.0" encoding="UTF-8"?>
    <bocb2e version="120" locale="zh_CN">
        <head>
            <termid>E192168000105</termid>
            <trnid>04051003128</trnid>
            <custid>133724203</custid>
            <cusopr>135989127</cusopr>
            <trncod>b2e0012</trncod>
            <token>PCxkDXIhAPRtlBhuqF-6A-V</token>
        </head>
        <trans>
            <trn-b2e0012-rs>
                <status>
                    <rspcod>B001</rspcod>
                    <rspmsg>ok</rspmsg>
                </status>
                <b2e0012-rs>
                    <status>
                        <rspcod>B001</rspcod>
                        <rspmsg>ok</rspmsg>
                    </status>
                    <account>
                        <ibknum>47504</ibknum>
                        <actacn>726357720234</actacn>
                        <curcde>CNY</curcde>
                    </account>
                    <balance>
                        <bokbal>199799896.54</bokbal>
                        <avabal>199799871.54</avabal>
                    </balance>
                    <baldat>20180102</baldat>
                </b2e0012-rs>
                <b2e0012-rs>
                    <status>
                        <rspcod>B001</rspcod>
                        <rspmsg>ok</rspmsg>
                    </status>
                    <account>
                        <ibknum>47504</ibknum>
                        <actacn>726357720234</actacn>
                        <curcde>CNY</curcde>
                    </account>
                    <balance>
                        <bokbal>199799871.54</bokbal>
                        <avabal>199799871.54</avabal>
                    </balance>
                    <baldat>20180103</baldat>
                </b2e0012-rs>
             </trn-b2e0012-rs>
        </trans>
    </bocb2e>

    上面返回的报文中就有多个b2e0012-rs节点,这种情况就不能像上面简单的去获取,要特殊处理
    1.使用递归去遍历每个节点,在遍历到b2e0012-rs时候,操作就和普通的一样

    private static void   getHistoryBalanceChildNodes(Element elem){
        HistoryBalanceBank historyBalanceBank=new HistoryBalanceBank();
        if (("b2e0012-rs").equals(elem.getName())){
          historyBalanceBank.setRspcod(elem.element("status").element("rspcod").getStringValue());
          historyBalanceBank.setRspmsg(elem.element("status").element("rspmsg").getStringValue());
          if (("B001").equals(elem.element("status").element("rspcod").getStringValue())){
            historyBalanceBank.setIbknum(elem.element("account").element("ibknum").getStringValue());
            historyBalanceBank.setActacn(elem.element("account").element("actacn").getStringValue());
            historyBalanceBank.setCurcde(elem.element("account").element("curcde").getStringValue());
            historyBalanceBank.setBokbal(elem.element("balance").element("bokbal").getStringValue());
            historyBalanceBank.setAvabal(elem.element("balance").element("avabal").getStringValue());
            historyBalanceBank.setBaldat(elem.element("baldat").getStringValue());
          }
          historyBalanceBanks.add(historyBalanceBank);
        }
        Iterator<Node> it=    elem.nodeIterator();
        while (it.hasNext()){
          Node node = it.next();
          if (node instanceof Element){
            Element e1 = (Element)node;
            getHistoryBalanceChildNodes(e1);
          }
        }
      }

    2.上面的historyBalanceBanks是定义了一个全局静态变量

     //历史余额List
      private static List<HistoryBalanceBank> historyBalanceBanks=new ArrayList<HistoryBalanceBank>();

    在调用递归方法之后将historyBalanceBanks塞入到返回的实体类中,大功告成

  • 相关阅读:
    Java集合知识点小结
    集合类说明及区别
    微信翻译机器人实战
    细说:域名与SEO存在什么关系
    我为PHP摇旗呐喊!
    每个程序员都该知道的10大编码原则
    浏览器加载模式:window.onload和$(document).ready()
    修改Mysql编码集
    java实现LIS算法,出操队形问题
    [笔记]: 前向星 标签: 数据结构存储 2017-05-25 09:13 35人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/jpfss/p/9287466.html
Copyright © 2020-2023  润新知