JavaEE 銀聯支付之手機控制元件支付-消費類交易

weixin_34162695發表於2018-04-05

0. workflow

app端request->後臺封裝引數->後臺進行簽名->請求銀聯平臺->解析響應->響應需求資訊
複製程式碼

1. 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_AppServer/backRcvResponse

#前臺通知地址,填寫處理銀聯前臺通知的地址,必須外網能訪問
acpsdk.frontUrl=http://localhost:8080/ACPSample_AppServer/frontRcvResponse

#########################入網測試環境簽名證照配置 ################################
# 多證照的情況證照路徑為程式碼指定,可不對此塊做配置。
# 簽名證照路徑,必須使用絕對路徑,如果不想使用絕對路徑,可以自行實現相對路徑獲取證照的方法;測試證照所有商戶共用開發包中的測試簽名證照,生產環境請從cfca下載得到。
# windows樣例:
acpsdk.signCert.path=D:/certs/acp_test_sign.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
複製程式碼

2. Request

  • request_url:https://gateway.test.95516.com/gateway/api/appTransReq.do
    • 非測試環境:https://gateway.95516.com/gateway/api/appTransReq.do
  • parameters:詳情請求引數此處不作說明,可以直接到官網檢視

3. Demo

1.獲取前端請求引數,並進行封裝請求資訊

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		String merId = req.getParameter("merId");
		String txnAmt = req.getParameter("txnAmt");
		String orderId = req.getParameter("orderId");
		String txnTime = req.getParameter("txnTime");
		
		Map<String, String> contentData = new HashMap<String, String>();
		
		/***銀聯全渠道系統,產品引數,除了encoding自行選擇外其他不需修改***/
		contentData.put("version", DemoBase.version);            //版本號 全渠道預設值
		contentData.put("encoding", DemoBase.encoding);     //字符集編碼 可以使用UTF-8,GBK兩種方式
		contentData.put("signMethod", SDKConfig.getConfig().getSignMethod()); //簽名方法
		contentData.put("txnType", "01");              		 	//交易型別 01:消費
		contentData.put("txnSubType", "01");           		 	//交易子類 01:消費
		contentData.put("bizType", "000201");          		 	//填寫000201
		contentData.put("channelType", "08");          		 	//渠道型別 08手機

		/***商戶接入引數***/
		contentData.put("merId", merId);   		 				//商戶號碼,請改成自己申請的商戶號或者open上註冊得來的777商戶號測試
		contentData.put("accessType", "0");            		 	//接入型別,商戶接入填0 ,不需修改(0:直連商戶, 1: 收單機構 2:平臺商戶)
		contentData.put("orderId", orderId);        	 	    //商戶訂單號,8-40位數字字母,不能含“-”或“_”,可以自行定製規則	
		contentData.put("txnTime", txnTime);		 		    //訂單傳送時間,取系統時間,格式為YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效
		contentData.put("accType", "01");					 	//賬號型別 01:銀行卡02:存摺03:IC卡帳號型別(卡介質)
		contentData.put("txnAmt", txnAmt);						//交易金額 單位為分,不能帶小數點
		contentData.put("currencyCode", "156");                 //境內商戶固定 156 人民幣

		// 請求方保留域,
        // 透傳欄位,查詢、通知、對賬檔案中均會原樣出現,如有需要請啟用並修改自己希望透傳的資料。
        // 出現部分特殊字元時可能影響解析,請按下面建議的方式填寫:
        // 1. 如果能確定內容不會出現&={}[]"'等符號時,可以直接填寫資料,建議的方法如下。
//		contentData.put("reqReserved", "透傳資訊1|透傳資訊2|透傳資訊3");
        // 2. 內容可能出現&={}[]"'符號時:
        // 1) 如果需要對賬檔案裡能顯示,可將字元替換成全形&={}【】“‘字元(自己寫程式碼,此處不演示);
        // 2) 如果對賬檔案沒有顯示要求,可做一下base64(如下)。
        //    注意控制資料長度,實際傳輸的資料長度不能超過1024位。
        //    查詢、通知等介面解析時使用new String(Base64.decodeBase64(reqReserved), DemoBase.encoding);解base64後再對資料做後續解析。
//		contentData.put("reqReserved", Base64.encodeBase64String("任意格式的資訊都可以".toString().getBytes(DemoBase.encoding)));
					
		//後臺通知地址(需設定為外網能訪問 http https均可),支付成功後銀聯會自動將非同步通知報文post到商戶上送的該地址,【支付失敗的交易銀聯不會傳送後臺通知】
		//後臺通知引數詳見open.unionpay.com幫助中心 下載  產品介面規範  閘道器支付產品介面規範 消費交易 商戶通知
		//注意:1.需設定為外網能訪問,否則收不到通知    2.http https均可  3.收單後臺通知後需要10秒內返回http200或302狀態碼 
		//    4.如果銀聯通知伺服器傳送通知後10秒內未收到返回狀態碼或者應答碼非http200或302,那麼銀聯會間隔一段時間再次傳送。總共傳送5次,銀聯後續間隔1、2、4、5 分鐘後會再次通知。
		//    5.後臺通知地址如果上送了帶有?的引數,例如:http://abc/web?a=b&c=d 在後臺通知處理程式驗證簽名之前需要編寫邏輯將這些欄位去掉再驗籤,否則將會驗籤失敗
		contentData.put("backUrl", DemoBase.backUrl);
		
		/**對請求引數進行簽名併傳送http post請求,接收同步應答報文**/
		Map<String, String> reqData = AcpService.sign(contentData,DemoBase.encoding);			 //報文中certId,signature的值是在signData方法中獲取並自動賦值的,只要證照配置正確即可。
		String requestAppUrl = SDKConfig.getConfig().getAppRequestUrl();								 //交易請求url從配置檔案讀取對應屬性檔案acp_sdk.properties中的 acpsdk.backTransUrl
		Map<String, String> rspData = AcpService.post(reqData,requestAppUrl,DemoBase.encoding);  //傳送請求報文並接受同步應答(預設連線超時時間30秒,讀取返回結果超時時間30秒);這裡呼叫signData之後,呼叫submitUrl之前不能對submitFromData中的鍵值對做任何修改,如果修改會導致驗籤不通過
		
		/**對應答碼的處理,請根據您的業務邏輯來編寫程式,以下應答碼處理邏輯僅供參考------------->**/
		//應答碼規範參考open.unionpay.com幫助中心 下載  產品介面規範  《平臺接入介面規範-第5部分-附錄》
		if(!rspData.isEmpty()){
			if(AcpService.validate(rspData, DemoBase.encoding)){
				LogUtil.writeLog("驗證簽名成功");
				String respCode = rspData.get("respCode") ;
				if(("00").equals(respCode)){
					//成功,獲取tn號
					//String tn = resmap.get("tn");
					//TODO
				}else{
					//其他應答碼為失敗請排查原因或做失敗處理
					//TODO
				}
			}else{
				LogUtil.writeErrorLog("驗證簽名失敗");
				//TODO 檢查驗證簽名失敗的原因
			}
		}else{
			//未返回正確的http狀態
			LogUtil.writeErrorLog("未獲取到返回報文或返回http狀態碼非200");
		}
		String reqMessage = DemoBase.genHtmlResult(reqData);
		String rspMessage = DemoBase.genHtmlResult(rspData);
		resp.getWriter().write("請求報文:<br/>"+reqMessage+"<br/>" + "應答報文:</br>"+rspMessage+"");
}
複製程式碼

2.請求銀聯平臺獲取資料


	/**
	 * 功能:後臺交易提交請求報文並接收同步應答報文<br>
	 * @param reqData 請求報文<br>
	 * @param rspData 應答報文<br>
	 * @param reqUrl  請求地址<br>
	 * @param encoding<br>
	 * @return 應答http 200返回true ,其他false<br>
	 */
	public static Map<String,String> post(
			Map<String, String> reqData,String reqUrl,String encoding) {
		Map<String, String> rspData = new HashMap<String,String>();
		LogUtil.writeLog("請求銀聯地址:" + reqUrl);
		//傳送後臺請求資料
		HttpClient hc = new HttpClient(reqUrl, 30000, 30000);//連線超時時間,讀超時時間(可自行判斷,修改)
		try {
			int status = hc.send(reqData, encoding);
			if (200 == status) {
				String resultString = hc.getResult();
				if (null != resultString && !"".equals(resultString)) {
					// 將返回結果轉換為map
					Map<String,String> tmpRspData  = SDKUtil.convertResultStringToMap(resultString);
					rspData.putAll(tmpRspData);
				}
			}else{
				LogUtil.writeLog("返回http狀態碼["+status+"],請檢查請求報文或者請求地址是否正確");
			}
		} catch (Exception e) {
			LogUtil.writeErrorLog(e.getMessage(), e);
		}
		return rspData;
	}
複製程式碼

相關文章