一、關於支付:
最近用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包見附件。
- HttpClient client = new HttpClient();
- HttpMethod method = new PostMethod(url);
- method.setRequestHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)");
- method.setRequestHeader("Content-Encoding","text/html");
- method.setRequestHeader("Content-Type","text/xml; charset=UTF-8");
- method.setRequestHeader("Accept-Language", "zh-cn");
- method.setRequestHeader("Connection","close");
- client.executeMethod(method);
- byte[] bytes = method.getResponseBody();
- String xmlString = new String(bytes);
- System.out.println(xmlString.trim());
由於返回的xml開頭空了4行,所以需要setRequestHeader來設置后才可以獲取。
解析此xml,我選擇jdom方式,不過處理前還是需要處理下,如下:
- String tempString = "";
- InputStream is = new ByteArrayInputStream(xmlString.getBytes());
- BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
- for (String temp = br.readLine(); temp != null;
- tempString += temp, temp = br.readLine()
- );
- logger.info("銀行返回的xml字符串:"+tempString);
- InputStream stream = new ByteArrayInputStream(tempString.getBytes());
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document doc = builder.parse(stream);
繼續
- //看是否能返回正確的xml格式數據
- NodeList nodeList = doc.getElementsByTagName("DOCUMENT");
- for (int i = 0; i < nodeList.getLength(); i++) {
- Element be = (Element) nodeList.item(i);
- NodeList childNodes = be.getChildNodes();
- for (int j = 0; j < childNodes.getLength(); j++) {
- if("RETURN_CODE".equals(childNodes.item(j).getNodeName())){
- if("000000".equals(childNodes.item(j).getTextContent())){ //000000表示返回的是正確的對賬數據
- logger.info("返回正確的數據格式!");
- //讀取 QUERYORDER 內容
- readXML(doc);
- }else{
- logger.error("返回數據格式錯誤!");
- }
- }
- }
- //循環結束
- stream.close();
- }
- NodeList nlCurrent = doc.getElementsByTagName("QUERYORDER");
- for (int j = 0; j < nlCurrent.getLength(); j++) {
- Element elmtLesson = (Element) nlCurrent.item(j);
- NodeList nlLesson = elmtLesson.getElementsByTagName("ORDERID");
- System.out.println(nlLesson.item(0).getFirstChild().getNodeValue());
- NodeList code = elmtLesson.getElementsByTagName("STATUSCODE");
- String ORDERID = nlLesson.item(0).getFirstChild().getNodeValue();
- String STATUSCODE = code.item(0).getFirstChild().getNodeValue();
- }
ORDERID 即是訂單號,接下來就是處理訂單對象了,此處省略200字 。。。。
還有,程序要每天執行一次,可以用java.util下的Timer來設定調用,方法不難,網上例子很多。
這里我用了spring的quartz來調用,代碼如下:
- <bean name="quartzQueryBean"
- class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
- <property name="targetObject" ref="CCBBankQueryService" />
- <!-- 調用CCBBankQueryService類的autoQuery方法 -->
- <property name="targetMethod" value="autoQuery" />
- <property name="concurrent" value="false" />
- </bean>
- <bean name="quartzAutoQuery" class="org.springframework.scheduling.quartz.CronTriggerBean">
- <property name="jobDetail" ref="quartzQueryBean" />
- <property name="cronExpression">
- <!-- 每天晚上1點30分 執行一次 > -->
- <value>0 30 1 * * ?</value>
- </property>
- </bean>
- <!-- quartz觸發管理器 -->
- <bean name="quartzScheduler"
- class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="triggers">
- <list>
- <ref bean="quartzAutoQuery" />
- </list>
- </property>
- </bean>
時間關系,說的不很詳細,如果有疑問處或想深入交流的童鞋們,可以加我QQ:361570665.

