最近在作一個項目,裏面涉及到了支付功能,使用的是銀聯的在線支付功能(網關跳轉支付)。銀聯給的例子很坑爹,簡單的代碼註釋了一大堆,關鍵的部分一點兒註釋都沒有,不少工具類尚未源碼。因此學習起來比較吃力。而網上這方面的資料有相對比較少,僅有的一些資料也比較陳舊。因此我打算記錄一下個人學習記錄,說不定會對別人也有一些幫助。javascript
我作的是銀聯的網關跳轉支付功能,用戶在個人網頁上點擊跳轉按鈕之後會跳轉到銀聯在線支付頁面,支付完用戶能夠點擊返回商家回到咱們的網站(可是他能夠不點,直接關閉頁面),而後咱們的服務器後臺會接受銀聯的用戶付款的通知,再更新本身數據庫的功能。html
銀聯技術服務的首頁地址是https://open.unionpay.com/ajweb/index 不少資料能夠在這裏找到。前端
我下載的Demo在這裏https://open.unionpay.com/ajweb/help/file/techFile?cateLog=Sample_code 這裏有不少資料均可以選擇。可是其實不少是重複的,不少是用不到的(對於我作的功能來講)。因此選擇本身須要的就能夠了。我選擇的是 下載資源類別裏的開發包菜單(左側菜單) 下面的 跳轉網關支付產品技術開發包。java
我寫這個項目的時候銀聯版本是2015-07-29的1.11版本(夠新了吧(⊙﹏⊙))web
裏面亂糟糟的一大堆東西。。。。。PHP啊Java啊ASP啊啥都有。。。。數據庫
我選擇Java版本的。json
而後把示例代碼下面的src目錄下面的東西所有導入到本身建的web項目下。(是所有導入,因此除了.java之外還要導入acp_sdk.properties)api
而後把依賴包下面的jar和upacp_sdk-1.0.0-20150703140550.jar導入到lib目錄下(我沒有導入json可選包)瀏覽器
給張圖說明一切問題服務器
而後項目就搭建好了。。是否是超級容易呀。。而後我會將如何配置項目。。
而後我來講下如何配置properties文件。
properties文件打開註釋所有是unicode編碼。。。簡直坑爹。。看不懂能夠去網上把unicode轉成中文看看註釋。。其實也沒有必要。後面我會介紹比較有用的幾個配置項。。其餘沒啥用處。
acp_sdk.properties這個文件你們不要重命名。
由於這個文件名是銀聯寫死在配置類中的。改了名字會讀取不到。
前面各類Url配置你們不須要去改動,下載下來都是配好的測試地址。只有到了正式上線了才須要去配置成正式的地址(可是個人項目也沒上線。。因此我也不知道正式地址是啥。。可是銀聯官網上我看到是有資料寫的。你們能夠去本身搜搜看)
後面的配置是和證書相關的,另外插一句。properties裏少了幾行配置。。。坑了我幾天時間。。
把證書Cert文件夾裏的入網測試環境的3個文件夾所有拷到桌面上。由於會用到。(我放桌面上是爲了方便配置)
修改properties裏的acpsdk.signCert.path的值爲C:\\Users\\Administrator\\desktop\\入網測試環境\\商戶私鑰證書(簽名)PM_700000000000001_acp.pfx
你們對照路徑能夠本身改,注意這裏700000000000001這個數字。後面會用到(又被坑了幾天。。。)
這個證書在正式上線之後須要改成正式的證書,這個證書是測試使用。
acpsdk.signCert.pwd並不須要改,由於測試證書的密碼就是6個0。
同理,正式上線以後要修改爲本身的密碼
acpsdk.signCert.type不須要修改,就是PKCS12
acpsdk.validateCert.dir的值修改成C:\\Users\\Administrator\\desktop\\入網測試環境\\銀聯公鑰證書(驗籤)
validateCert是用在銀聯給你發消息的時候判斷真僞用的(別人可能會僞造銀聯的信息,因此須要用這個證書驗證信息真僞),因此對於建立訂單付款來講沒有什麼用處。可是後面銀聯通知你用戶付款的時候你要用這個證書驗證消息是否是真的來自銀聯。
增長acpsdk.encryptCert.path這個key,value爲C:\\Users\\Administrator\\desktop\\入網測試環境\\加密證書 (根據業務需求選用)\\encrypt.cer
銀聯竟然默認沒有這個配置。。坑爹啊。。。這個是你給銀聯發消息的時候銀聯要判斷這個訂單是否是指定商戶(你)發過來的。也是驗證真僞用的(加密)
完成這些配置就能夠愉快(剁手)的和銀聯作交易了。
建立訂單方面其實能夠直接參考Form_6_2_FrontConsume這個類。
SDKConfig.getConfig().loadPropertiesFromSrc();是去加載properties配置文件,可是要求配置文件放在.class的根目錄。就是和包文件com同級。
這個方法並很差用,由於你本身測試的時候和項目部署上去位置可能會常常變化。因此可使用更好用的方法SDKConfig.getConfig().loadPropertiesFromPath("C:/Users/Administrator/desktop");
loadPropertiesFromPath的參數是properties文件所在的目錄,不用寫properties的文件名,緣由我前面已經說了,名字被寫死在銀聯工具類裏了。
另外銀聯的工具包都沒有源碼,你們能夠反編譯一下看看源代碼,我記得還有一個讀取properties文件的方法可使用。可是我是使用loadPropertiesFromPath這個方法的。
後面各類put參數我就說幾個重要的。
frontUrl是前端通知地址,就是客戶付完款之後銀聯會給一個返回商戶的按鈕,用戶點擊按鈕之後就到了你配置的這個url映射的網頁。同時會提交不少訂單數據給你。
backUrl是後臺通知地址,客戶付完款之後銀聯會給你配置的這個後臺url對應的Action發扣款的消息過來。數據和前端通知發送過來的消息是同樣的。
我以爲前端通知地址就用來展現訂單數據給用戶看就好了,用戶不必定會去點那個按鈕。
後臺通知用來更新本身數據庫裏的訂單數據。
而後是merId這個不是隨便寫的,由於你前面的證書是PM_700000000000001_acp.pfx。因此這裏必須寫700000000000001。就是證書對應的商戶號,這點很重要。銀聯下載來的demo默認是888888888888888。坑爹哪這是。
而後就沒啥好說的了,運行Form_6_2_FrontConsume類之後會生成一段html代碼。好比:
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 4 </head> 5 <body> 6 <form id="pay_form" 7 action="https://101.231.204.80:5000/gateway/api/frontTransReq.do" 8 method="post"> 9 <input type="hidden" name="txnType" id="txnType" value="01" /><input 10 type="hidden" name="frontUrl" id="frontUrl" 11 value="http://localhost:8080/ACPTest/acp_front_url.do" /><input 12 type="hidden" name="currencyCode" id="currencyCode" value="156" /><input 13 type="hidden" name="channelType" id="channelType" value="08" /><input 14 type="hidden" name="merId" id="merId" value="700000000000001" /><input 15 type="hidden" name="txnSubType" id="txnSubType" value="01" /><input 16 type="hidden" name="txnAmt" id="txnAmt" value="1" /><input 17 type="hidden" name="version" id="version" value="5.0.0" /><input 18 type="hidden" name="signMethod" id="signMethod" value="01" /><input 19 type="hidden" name="backUrl" id="backUrl" 20 value="http://222.222.222.222:8080/ACPTest/acp_back_url.do" /><input 21 type="hidden" name="certId" id="certId" 22 value="124876885185794726986301355951670452718" /><input 23 type="hidden" name="encoding" id="encoding" value="UTF-8" /><input 24 type="hidden" name="bizType" id="bizType" value="000201" /><input 25 type="hidden" name="signature" id="signature" 26 value="UfR4EHEma3rnwsQPIQOsdzEiVgEyT/tEza6vXiy1AjnlSS5C2qVVeV1TWClTXVA6OPh5Y9E7OyOwQYbWeuK+a4hCreY/R7oESNiF9gZs7KCphGp54daKOjRV1zNRcL2pDT2YhleBGQPgH/dwdhrOuprrFtvJBhi0TbRxFX2LSBU=" /><input 27 type="hidden" name="orderId" id="orderId" value="20150829171948" /><input 28 type="hidden" name="accessType" id="accessType" value="0" /><input 29 type="hidden" name="txnTime" id="txnTime" value="20150829171948" /> 30 </form> 31 </body> 32 <script type="text/javascript"> 33 document.all.pay_form.submit(); 34 </script> 35 </html>
把這段代碼刷到用戶瀏覽器上用戶就會跳轉到銀聯界面上去了。
而後測試付款可使用demo裏readMe.txt裏的銀行卡號和密碼。
用戶付完款點了返回商戶按鈕之後會跳轉到你寫的前臺通知地址上去。
我以爲原理和你讓客戶跳轉到銀聯去的方法差很少,可能也是銀聯刷了一個html在客戶機器上,而後客戶提交了一個post請求到你的前臺通知地址。(不過我知道銀聯是怎麼實現的,我以爲也是這個原理)
而後就完成付款了。
值得注意的是銀聯給你後臺的通知可能有N次。。。反正我常常受到不僅一次的同一訂單付款了的提醒。
至於通知會返回什麼數據。你們本身試一次就OK了,數據仍是不少的。
有朋友可能會想:要是壞人給我後臺通知的地址發假冒的銀聯信息怎麼辦呢。這個不用擔憂,銀聯發送回來的數據也是用證書加密過的,你也須要先驗證真僞,是真的再更新數據庫。假的就無視好啦。
至於怎麼驗證真僞,BackRcvResponse這個類,這個類就是模擬後臺接受銀聯信息用的。
有時候可能本身服務器有問題或者網絡很差,會收不到銀聯後臺通知地址。而前臺通知地址又不可靠,由於用戶可能會不去點擊它。
這種狀況下你也要去更新訂單的狀況,那麼可使用主動去銀聯查詢訂單狀況的方法。
能夠參考Form_6_5_Query這個類。
put的大部分數據你們不要更改,只須要更改merId,orderId,txnTime爲前面提交時候的信息就能夠完成查詢工做啦。
我這裏就貼出一個我前面完成的訂單的查詢結果好了(就是前面那段html對應的訂單)
打印返回報文:accNo=6216***********0018&accessType=0&bizType=000000¤cyCode=156&encoding=UTF-8&issuerIdentifyMode=0&merId=700000000000001&orderId=20150829171948&origRespCode=00&origRespMsg=成功[0000000]&queryId=201508291719485608648&respCode=00&respMsg=成功[0000000]&settleAmt=1&settleCurrencyCode=156&settleDate=0829&signMethod=01&traceNo=560864&traceTime=0829171948&txnAmt=1&txnSubType=01&txnTime=20150829171948&txnType=01&version=5.0.0&certId=3474813271258769001041842579301293446&signature=VREVdo+eEtKaNY2HpVsGiEVab711cxwfjx6OHbb6wX3XdisIyftVRz1DAlboN34G/OhsDMFfy1HHKZvpSb8A+dVbVe58VKm1ZWpa6VaXTssBtNBj9WNozatJKk7Df7CmodEcBmye7oUaB8diYc0yqqdODBllWDdw6GlEzKe3rerheo92p9Q7RxmfV6CEXsCeNhlWL550OMKE1cvJYV/lBLqEMVQ6ec5ED2QglVBasGZO+ehFKKAb7TzgY6y9D/MWGhgLegDN7Sl7TSkTsjqbYGbA31dsZX3YcsdTLSqCbhOdC+yD9buFMM9Y29XehSEhyAp/7J5PQu5mi71E6LvUDQ== 請求報文=[{txnType=00, channelType=08, merId=700000000000001, txnSubType=00, version=5.0.0, signMethod=01, certId=124876885185794726986301355951670452718, encoding=UTF-8, bizType=000000, signature=PuT1JKdoa2NXxAC4LSVeSdQLJy5ZIo7OfBVDDIR3NxtACsK3KBkjrwcuM0JyZA8AOegFSwWv9gMWuIuyBpSjusc1GTXKTd3uJy9whun3QIYSJKSNNj9Zoe+m088+N6QjzQ7CCx4ncIdaMlo3rcdaDnIxEKW/Dji2OFRZroT3v9k=, orderId=20150829171948, txnTime=20150829171948, accessType=0}] 應答報文=[{respCode=00, origRespMsg=成功[0000000], origRespCode=00, txnSubType=01, txnAmt=1, version=5.0.0, signMethod=01, settleAmt=1, encoding=UTF-8, traceTime=0829171948, respMsg=成功[0000000], queryId=201508291719485608648, signature=VREVdo+eEtKaNY2HpVsGiEVab711cxwfjx6OHbb6wX3XdisIyftVRz1DAlboN34G/OhsDMFfy1HHKZvpSb8A+dVbVe58VKm1ZWpa6VaXTssBtNBj9WNozatJKk7Df7CmodEcBmye7oUaB8diYc0yqqdODBllWDdw6GlEzKe3rerheo92p9Q7RxmfV6CEXsCeNhlWL550OMKE1cvJYV/lBLqEMVQ6ec5ED2QglVBasGZO+ehFKKAb7TzgY6y9D/MWGhgLegDN7Sl7TSkTsjqbYGbA31dsZX3YcsdTLSqCbhOdC+yD9buFMM9Y29XehSEhyAp/7J5PQu5mi71E6LvUDQ==, orderId=20150829171948, txnType=01, currencyCode=156, merId=700000000000001, settleDate=0829, accNo=6216***********0018, certId=3474813271258769001041842579301293446, settleCurrencyCode=156, bizType=000000, traceNo=560864, issuerIdentifyMode=0, accessType=0, txnTime=20150829171948}]
研究一下應答報文就知道哪些功能是能作的那些是不能作的了。好比就不能知道客戶的完整付款帳戶號,其中多的位數被打*了。
差很少這些就是我在這個項目中對銀聯跳轉網關支付功能的理解啦。