1. 概述 最近工作中用到了招商銀行的銀企直聯絡統,作為資金支出渠道。招行系統提供兩種方式與企業財務系統對接:一種是
前置機式;一種是
嵌入式。而“嵌入式直聯方式僅作向下相容支援,新增客戶請使用前置機式直聯”。因此使用了前置機方式。 使用到的介面文檔為《招商銀行銀企直串連口說明書version 5.21.0》和《網銀互聯結口說明書Version 1.0》。針對前者,使用了其3.6節“直接支付”介面進行招行內支付,並使用3.3節“查詢支付結果”介面進行結果查詢;針對後者,使用其第2章節“網銀貸記”介面進行跨行支付,並使用1.2節的“交易查詢”介面進行支付結果查詢。 前置機的安裝參照了文檔《銀企直聯安裝流程(測試環境專用)》及《招商銀行直聯絡統開發指南version 3.9.0》,文中講解得十分詳細,並且提供了範例程式碼。 開發使用語言為JAVA。
2.開發中遇到的問題及解決
存在許多問題,在使用測試環境帳號、參數時無法發現,直到上了生產環境才出現。在此將遇到的一個個問題彙集如下,以期對後來開發人員提供借鑒。 2.1 測試
關於調用查詢介面,查詢支付結果,使用的時間段的問題:
(1).測試時使用本地的前置機,且一直使用招行商務人員提供的測試帳號,發現支付時能夠即時返回請求被受理的結果,卻查詢不到支付記錄。經過詢問銀行技術人員,得知銀行測試伺服器時間不是目前時間,需要用一個工具軟體查詢測試伺服器日期。使用此日期後查詢到了支付結果。
(2).查詢交易記錄時需要注意,”起始日期和結束日期的間隔不能超過100天”。並且查詢時間段應該至少包含支付日期的前一天及後一天,因為在0點附近的交易可能會處於前一天,也可能屬於後一天。
另外,使用前置機,不需要報文格式轉換外掛程式,因為採用demo中所示的程式,我們使用的已經是格式三的報文了。 2.2 程式
使用HTTP方式向前置機發送請求,在處理支付及查詢的返回報文時,對樣本程式作出少許修改,對多條結果處理的方式如下(以直接支付為例):
/** * 處理返回的報文 * @param result 前置機返回的報文 */ private List<NTQPAYRQZ> processResult(String result) { List<NTQPAYRQZ> ntqpayrqzs = null; if (result != null && result.length() > 0) { XmlPacket pktRsp = XmlPacket.valueOf(result); if (pktRsp != null) { String sRetCod = pktRsp.getRETCOD(); if (sRetCod.equals("0")) { /*start 批量支付封裝返回的報文開始*/ Vector<Map> vector = pktRsp.getProperty("NTQPAYRQZ"); ntqpayrqzs = new ArrayList<NTQPAYRQZ>(); if(vector!=null){ for (Map map : vector) { NTQPAYRQZ ntqpayrqz = new NTQPAYRQZ(); ntqpayrqz=(NTQPAYRQZ) DataUtil.transMap2Bean(map,ntqpayrqz); ntqpayrqzs.add(ntqpayrqz); } } /*end 批量支付封裝返回的報文結束*/ /* 此處應為對多比交易返回結果的處理 */ //下面為單筆時的處理 int sectionSize = pktRsp.getSectionSize("NTQPAYRQZ"); Map propPayResult = pktRsp.getProperty("NTQPAYRQZ", 0);//由於本人在項目中是單筆支付的,所以最多會返回一條記錄,故此處取0。 String sREQSTS = (String) propPayResult.get("REQSTS"); String sRTNFLG = (String) propPayResult.get("RTNFLG"); if (sREQSTS.equals("FIN") && sRTNFLG.equals("F")) { logger.info("支付失敗:" + propPayResult.get("ERRTXT")); } else { logger.info("支付已被銀行受理(支付狀態:" + sREQSTS + ")"); } } else if (sRetCod.equals("-9")) { logger.info("支付未知異常,請查詢支付結果確認支付狀態,錯誤資訊:" + pktRsp.getERRMSG()); } else { logger.info("支付失敗:" + pktRsp.getERRMSG()); } } else { logger.info("響應報文解析失敗"); } } return ntqpayrqzs; } 備忘:NTQPAYRQZ 為以返回報文的節點構造的類,以節點NTQPAYRQZ下的各個欄位作為類的屬性。
其中,用到的工具方法如下:
/** * 取得指定介面的資料記錄 * @param sSectionName * @param index 索引,從0開始 * @return Map<String,String> */ public Map getProperty(String sSectionName, int index){ if(data.containsKey(sSectionName)){ return (Map)((Vector)data.get(sSectionName)).get(index); }else{ return null; } } /** * 取得指定介面的所有資料記錄 * @param sSectionName * @return Map<String,String> */ public Vector getProperty(String sSectionName){ if(data.containsKey(sSectionName)){ return (Vector)data.get(sSectionName); }else{ return null; } } // Map --> Bean 1: 利用Introspector,PropertyDescriptor實現 Map --> Bean public static Object transMap2Bean(Map<String, Object> map, Object obj) { try { BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName(); if (map.containsKey(key)) { Object value = map.get(key); // 得到property對應的setter方法 Method setter = property.getWriteMethod(); setter.invoke(obj, value); } } } catch (Exception e) { logger.error("transMap2Bean Error:",e); } return obj; } 2.3 生產
(1).生產環境應用伺服器串連不上前置機伺服器
營運人員對於串連前置機的伺服器IP進行了限制;另外,還需要財務人員遠程登入前置機伺服器,開啟前置機;
(2).返回錯誤資訊:有審批業務,不可直接經辦
編寫程式時忽略了介面文檔中的BUSMOD欄位值,採用了文檔中的樣本BUSMOD= 00001。對比參照之前生產環境前置機的報文,發現支付成功的報文中此欄位值為00002,修改程式後成功。此欄位表示“支付結算業務所採用的業務審批模式”。
而報文中的另外一個值:“業務類型”欄位BUSCOD,指的是“支付、集團支付或內部轉帳等”,如BUSCOD=N02031。這兩個欄位容易混淆,需特別注意,並且它們的長度也不一樣。
(3).行內支付使用直接支付介面,返回錯誤資訊:收方必須為商戶賬戶
諮詢招行技術人員得知是因為我們公司在招行的賬戶受到限制,收款方必須加入白名單才能打款。詢問財務人員,確實如此,經加入白名單後,打款成功。
跨行未受到限制,估計是因為走的是央行的超級網銀渠道,所以沒有限制。
(4).跨行支付收款方行號的問題
跨行支付時需要輸入收款行行號(網銀貸記介面中的CDTBRD欄位),只能輸入總行的行號,輸入支行的行號報錯。諮詢招行技術人員,回複是系統中沒有支行的行號。與招行對接時商務人員會提供“人行網銀互聯(跨行清算系統)聯行號資訊.txt”,其中有各銀行及對應的聯行號。
2.4 關於並發請求的問題
在文檔《招商銀行直聯絡統開發指南version 3.9.0》的3.4及3.5節,有調用頻率及並發效能的說明。
摘錄如下:
3.4調用頻率 請求調用間隔:本次請求調用與上次請求調用之間的時間差; 調用頻率控制按介面種類區別控制: 經辦類請求:兩次經辦類請求最小調用間隔為1秒; 查詢類請求:兩次查詢類請求最小調用間隔為2秒; 通知類請求:兩次通知類請求最小調用間隔為5秒。 當調用頻率沒有滿足以上條件時(實際調用間隔小於最小調用間隔),系統預設會內部等待,等待時間為:最小調用間隔 — 實際調用間隔,等待完成後再處理該請求。 當調用頻率滿足以上條件時(實際調用間隔大於或等於最小調用間隔),系統立即處理該請求並轉寄到銀行後台系統。 調用頻率控制以登陸使用者為單位,不同登陸使用者之間不受影響。
3.5 並發效能 本系統支援多使用者並發請求,同一使用者的多個請求按照優先隊列排隊處理,為了避免請求等待時間過長,建議同一使用者並發請求不要超過50個,登陸使用者數沒有限制。備忘:一台電腦只能安裝一個招行前置機,多台電腦允許安裝多個招行前置機。
開發、測試、上線此通道,前後經曆約一個月,與銀行商務及技術人員保持了電話及QQ溝通。感謝銀行技術人員耐心的講解及熱情的協助。