• 中国建设银行网上支付接口以及自动对账


    一、关于支付:

         最近用java语言做了一个建行网上支付的系统,和建行做的接口。现在整理一下发布出来。

         开发之前,参考了同道中人苏飞同学的一篇文章,他写的非常好,非常完善和细致。用.net语言所写,见链接:

         http://www.cnblogs.com/sufei/archive/2010/07/22/1783168.html,我呢,用java来改善补充了一下。

              MD5算法,在.net中,有框架自带可以直接调用。在java中调用java.security.MessageDigest即可。

          当然也可以网上找,很多。

              把银行所需要的参数和值拼成sql串,加密后传送。链接上建行的网站。支付后会有成功或失败的返回结果。

          这个结果需要用来接收。商户下载证书后生成的密钥和银行处理完返回的sign签名需要一致,才更改订单。

    二、关于自动对账:

                银行会在晚上处理当天的流水账,所以第二天可以进行已支付流水的查询和对账。我们可以以操作员的身份

          下载对账文件,也可以完全交给程序来自动完成。

                在银行提供的 “一点接入网上支付商户批量查询接口技术文档V1.2.doc”中,我选择了返回xml方式来获取。

                原理是,提供文档中所需要的参数和值传入指定URL,然后银行处理完毕会返回xml以网页形式,

           我们用 HttpClient 程序来读取其中的内容即可。该jar包见附件。

        

    Java代码  收藏代码
    1. HttpClient client = new HttpClient();  
    2. HttpMethod method = new PostMethod(url);  
    3.       
    4. method.setRequestHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)");  
    5. method.setRequestHeader("Content-Encoding","text/html");  
    6. method.setRequestHeader("Content-Type","text/xml; charset=UTF-8");  
    7. method.setRequestHeader("Accept-Language", "zh-cn");  
    8. method.setRequestHeader("Connection","close");  
    9.       
    10. client.executeMethod(method);  
    11. byte[] bytes = method.getResponseBody();  
    12. String xmlString = new String(bytes);  
    13. System.out.println(xmlString.trim());  

           由于返回的xml开头空了4行,所以需要setRequestHeader来设置后才可以获取。

           解析此xml,我选择jdom方式,不过处理前还是需要处理下,如下:

    Java代码  收藏代码
    1.     String tempString = "";  
    2. InputStream is = new ByteArrayInputStream(xmlString.getBytes());   
    3. BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));  
    4. for (String temp = br.readLine(); temp != null;   
    5.         tempString += temp, temp = br.readLine()  
    6. );  
    7. logger.info("银行返回的xml字符串:"+tempString);  
    8.      
    9. InputStream stream = new ByteArrayInputStream(tempString.getBytes());  
    10. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
    11. DocumentBuilder builder = factory.newDocumentBuilder();  
    12. Document doc = builder.parse(stream);  

          继续

      

    Java代码  收藏代码
    1. //看是否能返回正确的xml格式数据  
    2. NodeList nodeList = doc.getElementsByTagName("DOCUMENT");  
    3. for (int i = 0; i < nodeList.getLength(); i++) {  
    4.     Element be = (Element) nodeList.item(i);  
    5.     NodeList childNodes = be.getChildNodes();  
    6.     for (int j = 0; j < childNodes.getLength(); j++) {  
    7.         if("RETURN_CODE".equals(childNodes.item(j).getNodeName())){  
    8.             if("000000".equals(childNodes.item(j).getTextContent())){       //000000表示返回的是正确的对账数据  
    9.                 logger.info("返回正确的数据格式!");    
    10.                 //读取 QUERYORDER 内容  
    11.                 readXML(doc);  
    12.             }else{  
    13.                 logger.error("返回数据格式错误!");  
    14.             }  
    15.         }  
    16.     }  
    17.     //循环结束  
    18.     stream.close();  
    19.    }  
    Java代码  收藏代码
    1. NodeList nlCurrent = doc.getElementsByTagName("QUERYORDER");  
    2.     for (int j = 0; j < nlCurrent.getLength(); j++) {  
    3.         Element elmtLesson = (Element) nlCurrent.item(j);  
    4.         NodeList nlLesson = elmtLesson.getElementsByTagName("ORDERID");  
    5.         System.out.println(nlLesson.item(0).getFirstChild().getNodeValue());  
    6.   
    7.         NodeList code = elmtLesson.getElementsByTagName("STATUSCODE");  
    8.         String ORDERID = nlLesson.item(0).getFirstChild().getNodeValue();  
    9.         String STATUSCODE = code.item(0).getFirstChild().getNodeValue();  
    10.     }  

          ORDERID  即是订单号,接下来就是处理订单对象了,此处省略200字 。。。。

          还有,程序要每天执行一次,可以用java.util下的Timer来设定调用,方法不难,网上例子很多。

     这里我用了spring的quartz来调用,代码如下:

    Java代码  收藏代码
    1. <bean name="quartzQueryBean"  
    2.     class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
    3.     <property name="targetObject" ref="CCBBankQueryService" />  
    4.     <!-- 调用CCBBankQueryService类的autoQuery方法 -->  
    5.     <property name="targetMethod" value="autoQuery" />  
    6.     <property name="concurrent" value="false" />  
    7. </bean>  
    8.   
    9. <bean name="quartzAutoQuery" class="org.springframework.scheduling.quartz.CronTriggerBean">  
    10.     <property name="jobDetail" ref="quartzQueryBean" />  
    11.     <property name="cronExpression">  
    12.         <!-- 每天晚上1点30分 执行一次 > -->  
    13.         <value>30 1 * * ?</value>  
    14.     </property>  
    15. </bean>  
    16. <!-- quartz触发管理器 -->  
    17. <bean name="quartzScheduler"  
    18.     class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    19.     <property name="triggers">  
    20.         <list>  
    21.             <ref bean="quartzAutoQuery" />  
    22.         </list>  
    23.     </property>  
    24. </bean>  

       时间关系,说的不很详细,如果有疑问处或想深入交流的童鞋们,可以加我QQ:361570665.

  • 相关阅读:
    常见的等待事件如何处理
    oracle常见的等待事件
    12c建立物化视图出现ORA-23319错误
    ORA-07445: exception encountered: core dump [qsmmixGetIdxKeyStats()+231] [SIGSEGV] [ADDR:0x8] [PC:0x58AE44F] [Address not mapped to object] []
    Idea的Debug调试快捷键
    C# 程序禁止重复启动
    C#.Net与SQLServer时间范围的最小值最大值
    MySQL-8.0.20
    Flask框架
    Docker常用命令
  • 原文地址:https://www.cnblogs.com/liangjq/p/3967687.html
Copyright © 2020-2023  润新知