接入了一個比較冷萌的第三方環迅h5網關支付,發起訂單以及同步/異步回調(文檔中也有官方微信支付寶接入代碼資源哦)

雖然之前對於接入第三方支付有比較多的經驗,但是這次接入環迅h5支付還是花了2天半的時間才整入到項目中,遇到了一個坑耽擱了一天半,下面講一下接入注意事項

 

  1. 可能大家一般都是接入微信支付寶等官方支付(微信支付寶官方支付全部已調通更換參數即可,下面會有下載資源鏈接),下面是環迅支付接入流程
  2. 環迅支付文檔請看IPS接口定義技術規範-綜合網關-V2.0.2,裏面自帶demo,demo並不是Javaweb項目,需要使用tomcat運行

 

demo啓動效果訪問地址:http://localhost:8080/accentry/

 

h5發起支付後會返回html代碼,該代碼可以在瀏覽器直接加載---------手機號登錄------------------添加銀行卡------------開通快捷支付-----------再次發送驗證碼進行付款-------付款成功後環迅服務器會同步回調以及異步回調

 

 

 

 

這會直接上接入代碼了:發起h5網關支付類

AccEntryConfig/CollBackResponse/FunctionUtils/MerVerify/Request/SSLClient/SynchronousResponse/Utils這些類在demo中直接複製過來





package com.api.ips;

import java.net.URLEncoder;
import java.util.LinkedHashMap;

import org.junit.Test;

import com.alibaba.fastjson.JSONObject;

/**
 * 環迅支付工具
 *
 * @author leehao
 * @date 2019-09-25
 */
public class IpsPayUtils {

	/***
	 * 環迅h5支付
	 * 
	 * @param commodity  商品
	 * @param describe   描述
	 * @param payCode    訂單號
	 * @param orderPrice 金額(以元爲單位)
	 * @return
	 */
	public static String hxPay(String commodity, String describe, String payCode, String orderPrice) {
		String ts = AccEntryConfig.date;// AccEntryConfig.date;//時間戳
		String nonceStr = Utils.getRandomString(32);// 隨機字符串
		String trxDtTm = AccEntryConfig.date;// 商戶日期
		// 1.加密data
		JSONObject dt = new JSONObject(new LinkedHashMap());
		dt.put("platCode", "");// 平臺編碼默認1001
		dt.put("account", AccEntryConfig.accCode);// 賬戶號
		dt.put("trxId", payCode);// 商戶訂單號
		dt.put("trxDtTm", ts);// 訂單日期
		dt.put("expireDtTm", "");// 訂單截止時間
		dt.put("trxCcyCd", "156");// 幣種枚舉,默認 156
		dt.put("trxAmt", orderPrice);// 單位元
		dt.put("productType", "");// 產品類型
		dt.put("limitPayType", "");// 限制支付方式
		dt.put("lang", AccEntryConfig.lang);// 默認爲zh
		dt.put("pageUrl", AccEntryConfig.successURL);// 頁面回調地址
		dt.put("notifyUrl", AccEntryConfig.s2sURL);// 後臺回調地址
		dt.put("attach", commodity);// 商品介紹
		dt.put("goodsDesc", describe);// 商品內容
		String ds = dt.toString();
		// 1
		// System.out.println("加密前data: " + ds);
		String signData = MerVerify.encryptAES(AccEntryConfig.AES_KEY, ds);
		// System.out.println("加密後signData: " + signData);
		// 2
		Request accEntryRequest = new Request(AccEntryConfig.version, AccEntryConfig.date, AccEntryConfig.merCode,
				nonceStr, AccEntryConfig.format, AccEntryConfig.encryptType, signData, AccEntryConfig.signType);
		String object = Utils.getParamStr(Utils.objectToMap(accEntryRequest));
		// System.out.println("加密前object: " + object);
		String signObject = MerVerify.signSHA256withRSA(AccEntryConfig.SHA256_PRIVATE_KEY, object);
		// System.out.println("加密後signObject: " + signObject);

		JSONObject retObj = new JSONObject();
		retObj.put("version", AccEntryConfig.version);
		retObj.put("ts", ts);
		retObj.put("merCode", AccEntryConfig.merCode);
		retObj.put("nonceStr", nonceStr);
		retObj.put("format", AccEntryConfig.format);
		retObj.put("encryptType", AccEntryConfig.encryptType);
		retObj.put("signType", AccEntryConfig.signType);
		retObj.put("account", AccEntryConfig.accCode);
		retObj.put("trxId", payCode);
		retObj.put("trxDtTm", trxDtTm);
		retObj.put("trxAmt", orderPrice);
		retObj.put("data", signData);
		retObj.put("sign", signObject);
		String response = null;
		try {
			response = Utils.postSubmit(AccEntryConfig.ipsURL, retObj);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "10001";
		}
		return response;

	}
  • 這裏是發起請求接口以及支付回調(同步-異步 驗籤解析data中的數據)
    確認交易成功後必須響應環迅支付服務器"ipscheckok"否則會多次回調接口
    
    
    package com.api.ips;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.alibaba.fastjson.JSONObject;
    
    @RestController
    public class pay {
    
    	@GetMapping("pay")
    	public String payh() {
    		String hxPay = IpsPayUtils.hxPay("蘋果", "蝦皮蘋果", "798484848444474", "0.01");
    		System.out.println(hxPay);
    		return hxPay;
    	}
    
    	/**
    	 * 同步回調
    	 * 
    	 * @param request
    	 * @param response
    	 * @throws UnsupportedEncodingException
    	 */
    	@RequestMapping("asynchroHuanxin")
    	public void asynchroHuanxin(HttpServletRequest request, HttpServletResponse response)
    			throws UnsupportedEncodingException {
    		JSONObject map = Utils.getJsonParam(request);
    		System.out.println("同步回調:" + map.toString());
    		String data = map.getString("data");
    	    String version = map.getString("version");
    	    String merCode = map.getString("merCode");
    	    String ts = map.getString("ts");
    	    String nonceStr = map.getString("nonceStr");
    	    String format = map.getString("format");
    	    String encryptType = map.getString("encryptType");
    	    String signType = map.getString("signType");
    	    String notifyType = map.getString("notifyType");
    	    String sign = map.getString("sign");
    	    String verifyObject = null;
    	    String decryptData = null;
    	    boolean verifyResult = false;
    		try {
    	        if (!Utils.isBlank(sign)) {
    	            CollBackResponse backResponse = new CollBackResponse(version,ts,merCode,nonceStr,
    	                    format,encryptType,data,signType,notifyType);
    	            verifyObject = Utils.getParamStr(Utils.objectToMap(backResponse));
    	            verifyResult = MerVerify.verifySHA256withRSA(AccEntryConfig.SHA256_PUBLIC_KEY,
    	                    verifyObject, sign);
    	            if (verifyResult) {
    	                decryptData = MerVerify.decryptAES(AccEntryConfig.AES_KEY, data);
    	                System.out.println("----:"+decryptData);
    	                JSONObject jo = JSONObject.parseObject(new String(decryptData));
    	                String trxId = jo.getString("trxId");//商戶訂單號
    	                String trxStatus = jo.getString("trxStatus");//訂單狀態
    	                String trxResultMsg = jo.getString("trxResultMsg");//訂單消息
    	                String ipsTrxId = jo.getString("ipsTrxId");//IPS訂單流水號
    	                if (trxStatus.equals("SUCCESS")) {
    						//交易成功
    	                	System.out.println("交易成功");
    					}
    	                if (trxStatus.equals("FAIL")) {
    						//交易失敗
    	                	System.out.println("交易失敗");
    					}
    	                if (trxStatus.equals("PROCESSING")) {
    						//交易處理中
    	                	System.out.println("交易處理中");
    					}
    	            }
    	        }
    	    } catch (Throwable ex) {
    	        ex.printStackTrace();
    	    }
    	}
    
    	/**
    	 * 異步回調
    	 * 
    	 * @param request
    	 * @param response
    	 */
    	@RequestMapping("synchroHuanxin")
    	public String synchroHuanxin(HttpServletRequest request, HttpServletResponse response) {
    		JSONObject map = Utils.getJsonParam(request);
    		System.out.println("異步回調:" + map.toString());
    		String data = map.getString("data");
    	    String version = map.getString("version");
    	    String merCode = map.getString("merCode");
    	    String ts = map.getString("ts");
    	    String nonceStr = map.getString("nonceStr");
    	    String format = map.getString("format");
    	    String encryptType = map.getString("encryptType");
    	    String signType = map.getString("signType");
    	    String notifyType = map.getString("notifyType");
    	    String sign = map.getString("sign");
    	    String verifyObject = null;
    	    String decryptData = null;
    	    boolean verifyResult = false;
    		try {
    	        if (!Utils.isBlank(sign)) {
    	            CollBackResponse backResponse = new CollBackResponse(version,ts,merCode,nonceStr,
    	                    format,encryptType,data,signType,notifyType);
    	            verifyObject = Utils.getParamStr(Utils.objectToMap(backResponse));
    	            verifyResult = MerVerify.verifySHA256withRSA(AccEntryConfig.SHA256_PUBLIC_KEY,
    	                    verifyObject, sign);
    	            if (verifyResult) {
    	                decryptData = MerVerify.decryptAES(AccEntryConfig.AES_KEY, data);
    	                System.out.println("----:"+decryptData);
    	                JSONObject jo = JSONObject.parseObject(new String(decryptData));
    	                String trxId = jo.getString("trxId");//商戶訂單號
    	                String trxStatus = jo.getString("trxStatus");//訂單狀態
    	                String trxResultMsg = jo.getString("trxResultMsg");//訂單消息
    	                String ipsTrxId = jo.getString("ipsTrxId");//IPS訂單流水號
    	                if (trxStatus.equals("SUCCESS")) {
    						//交易成功
    	                	System.out.println("交易成功");
    	                	return "ipscheckok";
    					}
    	                if (trxStatus.equals("FAIL")) {
    						//交易失敗
    	                	System.out.println("交易失敗");
    					}
    	                if (trxStatus.equals("PROCESSING")) {
    						//交易處理中
    	                	System.out.println("交易處理中");
    					}
    	            }
    	        }
    	    } catch (Throwable ex) {
    	        ex.printStackTrace();
    	    }
    		return null;
    	}
    	}
    
    

    所需的jar包在demo全部複製過來即可,但是不支持maven從網上倉庫引入依賴,會導致無法加載私鑰。目前我是直接把jar包添加到項目中,大家可以嘗試本地安裝jar再引入依賴

這裏是支付成功後環迅服務器回調接口傳過來的參數值,訂單狀態以及訂單信息都在data中。需要解密
驗籤需要把所有參數通過文檔方式加密一遍與sign相對比

同步回調:

{"merCode":"178767",
"notifyType":"1",
"data":"83b8203f20b6a9aabb79a9c3735ae75f8a3bd1c1b99e8972b4146297ccd2ed17a0948434480fd47f270a41093800b02e6bf426bacd846bc88b4671a89a51af3e8c0bf611d7e744d0b8b293e47aeae983597d02a98f8b90a0c5f9c738906d625c27fd52b39d7bcf05171c960ad535a26569d2579bd1ee6f921395e6258064067298694b8d80269276459cf4703c4c21a22d5fe9803fa7ce38d650cba8131504c0e3e965de980ba8525d452507b735db5f91ec6ac9ffbcd5555d22ddcdfbed1a2e486493de9bac03367857923f6effa9fbffe6d26dde4cdb7e818ab4dd3020c1acab938d42811e81c606ef2f462015f03b89e4f805eb0df182407bc68ed12e5f510785e1c5d324e756ef4c85b4ba63635773782a75d3559ec519e59a4a7814c942b09757c8f6d07d9c21c6bf67c92f13387a481410cc28a6208f3d5e5996fa0195a822abe5c6303e2439a56a4e443a19c72a9f652eb97112c3551a87e38741e5edf36f3fdbdf94222b52be63ad81e075da898700e380e5d44509a7ba59305ec995c8e61c3746fa1b7cd8ba1b3ba72969a9",
"sign":"3ff5680aed7a5667a19015567efd86d9b6734191746be3e31c095c629ee9763e63e58acccbe01c706f2e6d431f20d9fcca6b9bb3e58afb621a0bc53300ba0523b35b745d1fb414eeab7202f7de786ad6a8d8ad3a229f00db78eefe5de43d15a68df5291a681264384733c6bd71dfee53fafdec9f5eace2104d5aa7c34de0eba412fe5b6ad803442a85009f510494f6430645f1ec42a31500979f0fa610f042c4c5af3020472c970cc2a362dcc55afb2bf5fd2418f86a8288714d238df6a166d8a339f2f8e17ea2bbaf8a2e171efc71001256858e48bce7140101e3ebfde0485dd2f3eb22df94528af9fa0be390bb0b7e5c5987088324b3e6ac6f6a93b806e268",
"signType":"RSA2",
"version":"2.0.0",
"encryptType":"AES",
"nonceStr":"5668d6f03c6b4e0c8f3e28acc86473ef",
"ts":"20191024115045"}



----:{"account":"1787670106","trxId":"88988998989444","trxDtTm":"20191024","trxCcyCd":"156","trxAmt":"0.01","payAmt":"0.01","payFee":"0","feeWho":"2","payType":"1501","cardType":"1","trxStatus":"SUCCESS","trxResultMsg":"支付成功","attach":"蘋果","ipsTrxId":"BO20191024115016004120","bkTrxId":"2019102442104710419284230202905","ipsTrxDtTm":"20191024115045","thdTrxId":"","extInfo":"thrPayInfo="}




----:蘋果
異步回調:{
"merCode":"178767",
"notifyType":"1",
"data":"83b8203f20b6a9aabb79a9c3735ae75f8a3bd1c1b99e8972b4146297ccd2ed17a0948434480fd47f270a41093800b02e6bf426bacd846bc88b4671a89a51af3e8c0bf611d7e744d0b8b293e47aeae983597d02a98f8b90a0c5f9c738906d625c27fd52b39d7bcf05171c960ad535a26569d2579bd1ee6f921395e6258064067298694b8d80269276459cf4703c4c21a22d5fe9803fa7ce38d650cba8131504c0e3e965de980ba8525d452507b735db5f91ec6ac9ffbcd5555d22ddcdfbed1a2e486493de9bac03367857923f6effa9fbffe6d26dde4cdb7e818ab4dd3020c1acab938d42811e81c606ef2f462015f03b89e4f805eb0df182407bc68ed12e5f510785e1c5d324e756ef4c85b4ba63635773782a75d3559ec519e59a4a7814c942b09757c8f6d07d9c21c6bf67c92f13387a481410cc28a6208f3d5e5996fa0195a822abe5c6303e2439a56a4e443a19c72a9f652eb97112c3551a87e38741e5edf36f3fdbdf94222b52be63ad81e075da898700e380e5d44509a7ba59305ec995c8e61c3746fa1b7cd8ba1b3ba72969a9",
"sign":"29f4050533302b29cd5d13e85e89390cdb8bab95d84c77cfe2ee1fcb4c0d5d0948431460afa98e36875a406af212328c79f1c054f5d000ea579b7959e7933cf5e01fca7245bfa1d1ecefe6f30350e25870329a435c4e9828fca71e6f66949e831bee93c1cd6bbc3583a206996dfbb0e1e8bc0f3a78ff94589cc8e8db009e3a597a457b17a74e63a387bbfdb93c3e7624f0cfc313c0a307a7fdba1af7ec199c49fe9c54e811d50ce111de22fa9de86f1ea4c36e8de152cb8d2351fbd97fdb1494e7295b92a285adb1c9716fc8d3d66d45cdcaa98174801ce6bb3267e16a00a05181145e7c58d933e5be0ab880977acba63a7e1ee61cc5b836da92f0e5e363e177",
"signType":"RSA2",
"version":"2.0.0",
"nonceStr":"889df20d9ccd4b3385d7cc139da36f52",
"encryptType":"AES",
"ts":"20191024115045"}

支付回調必須要做域名穿透,大家可是用花生殼或者https://natapp.cn/member/dashborad這兩者,花生殼前期可以免費試用,但是得實名認證,域名不會發生改變,natapp可以一直使用但是每次使用的時候分配的域名都不一致

 

說實話,環迅支付文檔是我遇到最難搞的了。像個gui一樣~~~~~

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章