以銀聯網站支付 - 消費類交易 為例
0. 大致邏輯
前端request->后臺封裝參數->后臺進行簽名->生成跳轉頁面(包含表單提交內容)->響應前端(將生成的html寫到瀏覽器中完成自動跳轉打開銀聯支付頁面)
復制代碼
1.acp_sdk.properties配置
- 測試環境acp_sdk.properties:
##############SDK配置文件(證書方式簽名)################
# 說明:
# 1. 使用時請刪除后綴的“.證書”,并將此文件復制到src文件夾下替換原來的acp_sdk.properties。
# 2. 具體配置項請根據注釋修改。
#
##########################################################################入網測試環境交易發送地址(線上測試需要使用生產環境交易請求地址)###############################交易請求地址
acpsdk.frontTransUrl=https://gateway.test.95516.com/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://gateway.test.95516.com/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://gateway.test.95516.com/gateway/api/queryTrans.do
acpsdk.batchTransUrl=https://gateway.test.95516.com/gateway/api/batchTrans.do
acpsdk.fileTransUrl=https://filedownload.test.95516.com/
acpsdk.appTransUrl=https://gateway.test.95516.com/gateway/api/appTransReq.do
acpsdk.cardTransUrl=https://gateway.test.95516.com/gateway/api/cardTransReq.do#以下繳費產品使用,其余產品用不到
acpsdk.jfFrontTransUrl=https://gateway.test.95516.com/jiaofei/api/frontTransReq.do
acpsdk.jfBackTransUrl=https://gateway.test.95516.com/jiaofei/api/backTransReq.do
acpsdk.jfSingleQueryUrl=https://gateway.test.95516.com/jiaofei/api/queryTrans.do
acpsdk.jfCardTransUrl=https://gateway.test.95516.com/jiaofei/api/cardTransReq.do
acpsdk.jfAppTransUrl=https://gateway.test.95516.com/jiaofei/api/appTransReq.do######################################################################### 報文版本號,固定5.1.0,請勿改動
acpsdk.version=5.1.0# 簽名方式,證書方式固定01,請勿改動
acpsdk.signMethod=01# 是否驗證驗簽證書的CN,測試環境請設置false,生產環境請設置true。非false的值默認都當true處理。
acpsdk.ifValidateCNName=false# 是否驗證https證書,測試環境請設置false,生產環境建議優先嘗試true,不行再false。非true的值默認都當false處理。
acpsdk.ifValidateRemoteCert=false#后臺通知地址,填寫接收銀聯后臺通知的地址,必須外網能訪問
acpsdk.backUrl=http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse#前臺通知地址,填寫銀聯前臺通知的地址,必須外網能訪問
acpsdk.frontUrl=http://localhost:8080/ACPSample_B2C/frontRcvResponse#########################入網測試環境簽名證書配置 ################################
# 多證書的情況證書路徑為代碼指定,可不對此塊做配置。
# 簽名證書路徑,必須使用絕對路徑,如果不想使用絕對路徑,可以自行實現相對路徑獲取證書的方法;測試證書所有商戶共用開發包中的測試簽名證書,生產環境請從cfca下載得到。
# windows樣例:
acpsdk.signCert.path=D:/certs/acp_test_sign.pfx
# linux樣例(注意:在linux下讀取證書需要保證證書有被應用讀的權限)(后續其他路徑配置也同此條說明)
#acpsdk.signCert.path=/SERVICE01/usr/ac_frnas/conf/ACPtest/acp700000000000001.pfx# 簽名證書密碼,測試環境固定000000,生產環境請修改為從cfca下載的正式證書的密碼,正式環境證書密碼位數需小于等于6位,否則上傳到商戶服務網站會失敗
acpsdk.signCert.pwd=000000
# 簽名證書類型,固定不需要修改
acpsdk.signCert.type=PKCS12##########################加密證書配置################################
# 敏感信息加密證書路徑(商戶號開通了商戶對敏感信息加密的權限,需要對 卡號accNo,pin和phoneNo,cvn2,expired加密(如果這些上送的話),對敏感信息加密使用)
acpsdk.encryptCert.path=d:/certs/acp_test_enc.cer##########################驗簽證書配置################################
# 驗簽中級證書路徑(銀聯提供)
acpsdk.middleCert.path=D:/certs/acp_test_middle.cer
# 驗簽根證書路徑(銀聯提供)
acpsdk.rootCert.path=D:/certs/acp_test_root.cer
##開發測試777290058110097
merId=
復制代碼
- 正式環境acp_sdk.properties:
acpsdk.frontTransUrl=https://gateway.95516.com/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://gateway.95516.com/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://gateway.95516.com/gateway/api/queryTrans.do
acpsdk.batchTransUrl=https://gateway.95516.com/gateway/api/batchTransReq.do
acpsdk.fileTransUrl=https://filedownload.95516.com/
acpsdk.signCert.path=D\:\\certs\\自己的私鑰.pfx
#acpsdk.signCert.path=/SERVICE01/usr/ac_frnas/conf/ACPtest/acp700000000000001.pfx
acpsdk.signCert.pwd=自己的私鑰密碼
acpsdk.signCert.type=PKCS12
acpsdk.validateCert.dir=D\:\\certs\\
#acpsdk.validateCert.dir=/SERVICE01/usr/ac_frnas/conf/ACPtest/
#acpsdk.encryptCert.path=d:\\certs\\encrypt.cer
acpsdk.singleMode=true
merId=自己的商戶號,原demo不是寫在這邊
復制代碼
2. request
- request_url:https://gateway.test.95516.com/gateway/api/frontTransReq.do
- 非測試環境:https://gateway.95516.com/gateway/api/frontTransReq.do
- parameters:詳情請求參數此處不作說明,可以直接到官網查看
3. Demo
1.獲取前端請求參數,并進行封裝請求信息
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {resp.setContentType("text/html; charset="+ DemoBase.encoding);//前臺頁面傳過來的String merId = req.getParameter("merId");String txnAmt = req.getParameter("txnAmt");String orderId = req.getParameter("orderId");String txnTime = req.getParameter("txnTime");Map<String, String> requestData = new HashMap<String, String>();/***銀聯全渠道系統,產品參數,除了encoding自行選擇外其他不需修改***/requestData.put("version", DemoBase.version); //版本號,全渠道默認值requestData.put("encoding", DemoBase.encoding); //字符集編碼,可以使用UTF-8,GBK兩種方式requestData.put("signMethod", SDKConfig.getConfig().getSignMethod()); //簽名方法requestData.put("txnType", "01"); //交易類型 ,01:消費requestData.put("txnSubType", "01"); //交易子類型, 01:自助消費requestData.put("bizType", "000201"); //業務類型,B2C網關支付,手機wap支付requestData.put("channelType", "07"); //渠道類型,這個字段區分B2C網關支付和手機wap支付;07:PC,平板 08:手機/***商戶接入參數***/requestData.put("merId", merId); //商戶號碼,請改成自己申請的正式商戶號或者open上注冊得來的777測試商戶號requestData.put("accessType", "0"); //接入類型,0:直連商戶 requestData.put("orderId",orderId); //商戶訂單號,8-40位數字字母,不能含“-”或“_”,可以自行定制規則 requestData.put("txnTime", txnTime); //訂單發送時間,取系統時間,格式為YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效requestData.put("currencyCode", "156"); //交易幣種(境內商戶一般是156 人民幣) requestData.put("txnAmt", txnAmt); //交易金額,單位分,不要帶小數點//requestData.put("reqReserved", "透傳字段"); //請求方保留域,如需使用請啟用即可;透傳字段(可以實現商戶自定義參數的追蹤)本交易的后臺通知,對本交易的交易狀態查詢交易、對賬文件中均會原樣返回,商戶可以按需上傳,長度為1-1024個字節。出現&={}[]符號時可能導致查詢接口應答報文解析失敗,建議盡量只傳字母數字并使用|分割,或者可以最外層做一次base64編碼(base64編碼之后出現的等號不會導致解析失敗可以不用管)。 requestData.put("riskRateInfo", "{commodityName=測試商品名稱}");//前臺通知地址 (需設置為外網能訪問 http https均可),支付成功后的頁面 點擊“返回商戶”按鈕的時候將異步通知報文post到該地址//如果想要實現過幾秒中自動跳轉回商戶頁面權限,需聯系銀聯業務申請開通自動返回商戶權限//異步通知參數詳見open.unionpay.com幫助中心 下載 產品接口規范 網關支付產品接口規范 消費交易 商戶通知requestData.put("frontUrl", DemoBase.frontUrl);//后臺通知地址(需設置為【外網】能訪問 http https均可),支付成功后銀聯會自動將異步通知報文post到商戶上送的該地址,失敗的交易銀聯不會發送后臺通知//后臺通知參數詳見open.unionpay.com幫助中心 下載 產品接口規范 網關支付產品接口規范 消費交易 商戶通知//注意:1.需設置為外網能訪問,否則收不到通知 2.http https均可 3.收單后臺通知后需要10秒內返回http200或302狀態碼 // 4.如果銀聯通知服務器發送通知后10秒內未收到返回狀態碼或者應答碼非http200,那么銀聯會間隔一段時間再次發送。總共發送5次,每次的間隔時間為0,1,2,4分鐘。// 5.后臺通知地址如果上送了帶有?的參數,例如:http://abc/web?a=b&c=d 在后臺通知處理程序驗證簽名之前需要編寫邏輯將這些字段去掉再驗簽,否則將會驗簽失敗requestData.put("backUrl", DemoBase.backUrl);// 訂單超時時間。// 超過此時間后,除網銀交易外,其他交易銀聯系統會拒絕受理,提示超時。 跳轉銀行網銀交易如果超時后交易成功,會自動退款,大約5個工作日金額返還到持卡人賬戶。// 此時間建議取支付時的北京時間加15分鐘。// 超過超時時間調查詢接口應答origRespCode不是A6或者00的就可以判斷為失敗。requestData.put("payTimeout", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date().getTime() + 15 * 60 * 1000));////// 報文中特殊用法請查看 PCwap網關跳轉支付特殊用法.txt/////**請求參數設置完畢,以下對請求參數進行簽名并生成html表單,將表單寫入瀏覽器跳轉打開銀聯頁面**/Map<String, String> submitFromData = AcpService.sign(requestData,DemoBase.encoding); //報文中certId,signature的值是在signData方法中獲取并自動賦值的,只要證書配置正確即可。String requestFrontUrl = SDKConfig.getConfig().getFrontRequestUrl(); //獲取請求銀聯的前臺地址:對應屬性文件acp_sdk.properties文件中的acpsdk.frontTransUrlString html = AcpService.createAutoFormHtml(requestFrontUrl, submitFromData,DemoBase.encoding); //生成自動跳轉的Html表單LogUtil.writeLog("打印請求HTML,此為請求報文,為聯調排查問題的依據:"+html);//將生成的html寫到瀏覽器中完成自動跳轉打開銀聯支付頁面;這里調用signData之后,將html寫到瀏覽器跳轉到銀聯頁面之前均不能對html中的表單項的名稱和值進行修改,如果修改會導致驗簽不通過resp.getWriter().write(html);
}
復制代碼
2.網關頁面請求頁面生成
/*** 功能:前臺交易構造HTTP POST自動提交表單<br>* @param action 表單提交地址<br>* @param hiddens 以MAP形式存儲的表單鍵值<br>* @param encoding 上送請求報文域encoding字段的值<br>* @return 構造好的HTTP POST交易表單<br>*/
public static String createAutoFormHtml(String reqUrl, Map<String, String> hiddens,String encoding) {StringBuffer sf = new StringBuffer();sf.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset="+encoding+"\"/></head><body>");sf.append("<form id = \"pay_form\" action=\"" + reqUrl+ "\" method=\"post\">");if (null != hiddens && 0 != hiddens.size()) {Set<Entry<String, String>> set = hiddens.entrySet();Iterator<Entry<String, String>> it = set.iterator();while (it.hasNext()) {Entry<String, String> ey = it.next();String key = ey.getKey();String value = ey.getValue();sf.append("<input type=\"hidden\" name=\"" + key + "\" id=\""+ key + "\" value=\"" + value + "\"/>");}}sf.append("</form>");sf.append("</body>");sf.append("<script type=\"text/javascript\">");sf.append("document.all.pay_form.submit();");sf.append("</script>");sf.append("</html>");return sf.toString();
}
復制代碼