1. 程式人生 > >易寶支付Demo,生產中封裝成簡潔的代付接口,不用request如何獲取項目運行時的真實路徑(轉)

易寶支付Demo,生產中封裝成簡潔的代付接口,不用request如何獲取項目運行時的真實路徑(轉)

工作文件夾 自己 png code 代碼 但是 import 其中 image

最近項目在做融360引流,涉及到了易寶支付的代扣和代付。易寶官方給出的demo只能簡單運行,而且都是通過form表單的形式提交,返回XML格式。同時接口代碼都寫在了JSP中看起來不友好。項目在生成中想要用,必須修改整合到自己的項目工程中(文末附我修改的源碼下載地址)。

首先說明易寶的版本號:易寶支付-代付代發-商戶接入包-V3.3

言歸正傳,相信易寶官方的demo大家都能獲取到,所以這裏不再贅述demo的難看點。在這裏直接截圖給大家說明我修改後的代碼。有不好的地方請大家看了代碼後及時在下方評論

技術分享圖片

上圖是通過request獲取項目的真實路徑,以便下面用於獲取證書地址,但是實際我們在封裝成自己的代碼時,傳入request是不太好的,因為有可能在我們用的時候,無法獲取到request對象。而且這裏的功能單一,所以我用下面的方法進行了修改,以便獲取到證書真實路徑(urlss這裏需要替換成自己的當前類全限定名稱,TransferParamResolver這個都要替換。下面有可Cp代碼)

技術分享圖片

這裏代替為用靜態代碼塊獲取證書的真實路徑,這裏的System.Properties功能還是很多的

?
12345678910111213141516171819202122232425// System.err.println(sysPath);// Properties props = System.getProperties();// propertis = props.getProperty("user.dir")+"文件分隔符:" + //props.getProperty("file.separator"); // System.out.println("操作系統的名稱:" + props.getProperty("os.name"));
// System.out.println("操作系統的構架:" + props.getProperty("os.arch"));// System.out.println("操作系統的版本號:" + props.getProperty("os.version"));// System.out.println("文件分隔符:" + props.getProperty("file.separator"));// //在 unix 系統中是"/"// System.out.println("路徑分隔符:" + props.getProperty("path.separator"));
// //在 unix 系統中是":"// System.out.println("行分隔符:" + props.getProperty("line.separator"));// //在 unix 系統中是"/n"// System.out.println("用戶的賬戶名稱:" + props.getProperty("user.name"));// System.out.println("用戶的主文件夾:" + props.getProperty("user.home"));// System.out.println("用戶的當前工作文件夾:" + props.getProperty("user.dir")); // 操作系統的名稱:Windows 8.1// 操作系統的構架:amd64// 操作系統的版本號:6.3// 文件分隔符:\// 路徑分隔符:;// 行分隔符:// 用戶的賬戶名稱:雷神// 用戶的主文件夾:C:\Users\雷神// 用戶的當前工作文件夾:D:\JAVAInstall\intelIdeaWorkSpace\TestProject1

  剩下的就是傳參和返回值的獲取,這裏直接放入所有代碼

技術分享圖片
package com.ssm.yibaoPay.yeepay.common.transfer;

import com.cfca.util.pki.api.CertUtil;
import com.cfca.util.pki.api.KeyUtil;
import com.cfca.util.pki.api.SignatureUtil;
import com.cfca.util.pki.cert.X509Cert;
import com.cfca.util.pki.cipher.JCrypto;
import com.cfca.util.pki.cipher.JKey;
import com.cfca.util.pki.cipher.Session;
import com.ssm.yibaoPay.yeepay.common.securityplatform.Digest;
import com.ssm.yibaoPay.yeepay.common.utils.CallbackUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * com.fastx.cooperate.threeInterface.yeepay.common.transfer;
 * 功能:;
 *
 * @author 李冉 Email:[email protected]
 * Time:2018/7/11 10:56
 */
public class TransferParamResolver {

    private static String sysPath;

    static {
        String urlss = "com.fastx.cooperate.threeInterface.yeepay.common.transfer.TransferParamResolver";
        urlss = "classes/" + urlss.substring(0, urlss.indexOf("TransferParamResolver")).replace(".", "/");
        java.net.URL url = TransferParamResolver.class.getResource("");
        sysPath = (System.getProperties().getProperty("os.name").toUpperCase().startsWith("WIN") ? "" :
                System.getProperties().getProperty("file.separator"))
                + String.valueOf(url).substring(String.valueOf(url).indexOf("file:/")
                + 6, String.valueOf(url).indexOf(urlss)) + "lib/";
    }

    //protected final static Log log = Log.getLog(TransferParamResolver.class); //添加日誌

    /**
     * 單筆打款xml請求報文
     *
     * @param transferSingle
     * @return
     * @throws Exception
     */
    public static Map transferSingle(TransferSingle transferSingle) throws Exception {
//TranferSingle 這個實體類 是傳參的實體,對應文檔自己查看,生產中把下面amount對應修改成自己的實際金額即可 String xml
= "<data>\n" + "\t<cmd>TransferSingle</cmd>\n" + "\t<version>1.1</version>\n" + "\t<mer_Id>10022581269</mer_Id>\n" + "\t<group_Id>10022581269</group_Id>\n" + "\t<batch_No>" + transferSingle.getBatch_no() + "</batch_No>\n" + "\t<order_Id>" + transferSingle.getOrder_id() + "</order_Id>\n" + "\t<bank_Code>" + transferSingle.getBank_code() + "</bank_Code>\n" + "\t<cnaps>100123123123</cnaps>\n" + "\t<bank_Name>" + transferSingle.getBank_name() + "</bank_Name>\n" + "\t<branch_Bank_Name>農業銀行北京市朝陽支行</branch_Bank_Name>\n" + "\t<amount>" + "0.01" + "</amount>\n" + "\t<account_Name>" + transferSingle.getAccount_name() + "</account_Name>\n" + "\t<account_Number>" + transferSingle.getAccount_number() + "</account_Number>\n" + "\t<province>110000</province>\n" + "\t<city>110000</city>\n" + "\t<fee_Type>SOURCE</fee_Type>\n" + "\t<payee_Email></payee_Email>\n" + "\t<payee_Mobile></payee_Mobile>\n" + "\t<leave_Word></leave_Word>\n" + "\t<abstractInfo></abstractInfo>\n" + "\t<remarksInfo></remarksInfo>\n" + "\t<urgency>0</urgency>\n" + "\t<hmac></hmac>\n" + "</data>"; //需要參加簽名的參數:其中(hmacKey)指的是商戶自己的密鑰 String todigestValues = "cmd,mer_Id,batch_No,order_Id,amount,account_Number,hmacKey"; //驗證返回參數簽名的參數:其中(hmacKey)指的是商戶自己的密鑰 String tobackDigestValues = "cmd,ret_Code,mer_Id,batch_No,total_Amt,total_Num,r1_Code,hmacKey"; try { return DoTransferSingle(xml, todigestValues, tobackDigestValues); } catch (Exception e) { e.printStackTrace(); // log.info("單筆打款異常---------------->" + e.getMessage()); // log.info("異常輸入的參數---------------->" + transferSingle.toString()); throw e; } } /** * 打款明細查詢xml請求報文 * * @param betchNo 訂單批次號 * @param orderId 訂單ID號 * @return * @throws Exception */ public static Map singlePayQuery(String betchNo, String orderId) throws Exception { String xml = "<data>\n" + "\t<cmd>BatchDetailQuery</cmd>\n" + "\t<version>1.1</version>\n" + "\t<group_Id>10022581269</group_Id>\n" + "\t<mer_Id>10022581269</mer_Id>\n" + "\t<query_Mode>1</query_Mode>\n" + "\t<batch_No>" + betchNo + "</batch_No>\n" + "\t<order_Id>" + orderId + "</order_Id>\n" + "\t<page_No>1</page_No>\n" + "\t<hmac></hmac>\n" + "</data>"; //需要參加簽名的參數:其中(hmacKey)指的是商戶自己的密鑰 String todigestValues = "cmd,mer_Id,batch_No,order_Id,page_No,hmacKey"; //驗證返回參數簽名的參數:其中(hmacKey)指的是商戶自己的密鑰 String tobackDigestValues = "cmd,ret_Code,batch_No,total_Num,end_Flag,hmacKey"; try { return DoTransferSingle(xml, todigestValues, tobackDigestValues); } catch (Exception e) { e.printStackTrace(); //log.info("單筆打款查詢異常---------------->" + e.getMessage()); // log.info("異常輸入的參數---------------->" + "betchNo" + betchNo + "orderId" + orderId); throw e; } } private static Map DoTransferSingle(String xml, String todigestValues, String tobackDigestValues) throws Exception { //商戶密鑰 String hmacKey = "02Ji5At46r9BwZ8TVW7aFHox1pNm9N0n8c7DsA8e5813IEu74T50i901F762"; Map result = new LinkedHashMap(); Map xmlMap = new LinkedHashMap(); Map xmlBackMap = new LinkedHashMap(); //需要參加簽名的參數:其中(hmacKey)指的是商戶自己的密鑰 String[] digestValues = todigestValues.split(","); //驗證返回參數簽名的參數:其中(hmacKey)指的是商戶自己的密鑰 String[] backDigestValues = tobackDigestValues.split(","); //String xml = request.getParameter("xml"); //第一步:將請求的數據和商戶自己的密鑰拼成一個字符串, Document document = null; try { document = DocumentHelper.parseText(xml); } catch (DocumentException e) { } Element rootEle = document.getRootElement(); String cmdValue = rootEle.elementText("cmd"); List list = rootEle.elements(); for (int i = 0; i < list.size(); i++) { Element ele = (Element) list.get(i); String eleName = ele.getName(); if (!eleName.equals("list")) { xmlMap.put(eleName, ele.getText().trim()); } else { continue; } } String hmacStr = ""; for (int i = 0; i < digestValues.length; i++) { if (digestValues[i].equals("hmacKey")) { hmacStr = hmacStr + hmacKey; continue; } hmacStr = hmacStr + xmlMap.get(digestValues[i]); } System.out.println("簽名之前的源數據為---||" + hmacStr + "||"); //下面用數字證書進行簽名 Session tempsession = null; String ALGORITHM = SignatureUtil.SHA1_RSA; JCrypto jcrypto = null; if (tempsession == null) { try { //初始化加密庫,獲得會話session //多線程的應用可以共享一個session,不需要重復,只需初始化一次 //初始化加密庫並獲得session。 //系統退出後要jcrypto.finalize(),釋放加密庫 jcrypto = JCrypto.getInstance(); jcrypto.initialize(JCrypto.JSOFT_LIB, null); tempsession = jcrypto.openSession(JCrypto.JSOFT_LIB); } catch (Exception ex) { System.out.println(ex.toString()); } } String sysPath = TransferParamResolver.sysPath; System.out.println("------" + sysPath + "------" + File.separator + "------"); JKey jkey = KeyUtil.getPriKey(sysPath + File.separator + "7.3.pfx", "123456"); X509Cert cert = CertUtil.getCert(sysPath + File.separator + "7.3.pfx", "123456"); System.out.println(cert.getSubject()); X509Cert[] cs = new X509Cert[1]; cs[0] = cert; String signMessage = ""; SignatureUtil signUtil = null; try { // 第二步:對請求的串進行MD5對數據進行簽名 String yphs = Digest.hmacSign(hmacStr); signUtil = new SignatureUtil(); byte[] b64SignData; // 第三步:對MD5簽名之後數據調用CFCA提供的api方法用商戶自己的數字證書進行簽名 b64SignData = signUtil.p7SignMessage(true, yphs.getBytes(), ALGORITHM, jkey, cs, tempsession); if (jcrypto != null) { jcrypto.finalize(JCrypto.JSOFT_LIB, null); } signMessage = new String(b64SignData, "UTF-8"); } catch (Exception e) { } System.out.println("經過md5和數字證書簽名之後的數據為---||" + signMessage + "||"); Element r = rootEle.element("hmac"); r.setText(signMessage); result.put("xml", xml); document.setXMLEncoding("GBK"); System.out.println("完整xml請求報文:" + document.asXML()); String textHost = "http://cha.yeepay.com/app-merchant-proxy/groupTransferController.action"; System.out.println("請求地址為:" + textHost); //第四步:發送https請求 String responseMsg = CallbackUtils.httpRequest(textHost, document.asXML(), "POST", "gbk", "text/xml ;charset=gbk", false); // out.println( // "<html><body><textarea rows=\"23\" cols=\"120\" name=\"xml\" id=\"xml\">" + // responseMsg + // "</textarea></body></html>"); // System.out.println("服務器響應xml報文:" + responseMsg); try { document = DocumentHelper.parseText(responseMsg); } catch (DocumentException e) { } rootEle = document.getRootElement(); cmdValue = rootEle.elementText("hmac"); //第五步:對服務器響應報文進行驗證簽名 boolean sigerCertFlag = false; if (cmdValue != null) { sigerCertFlag = signUtil.p7VerifySignMessage(cmdValue.getBytes(), tempsession); String backmd5hmac = xmlBackMap.get("hmac") + ""; if (sigerCertFlag) { System.out.println("證書驗簽成功"); backmd5hmac = new String(signUtil.getSignedContent()); System.out.println("證書驗簽獲得的MD5簽名數據為----" + backmd5hmac); System.out.println("證書驗簽獲得的證書dn為----" + new String(signUtil.getSigerCert()[0].getSubject())); //第六步.將驗簽出來的結果數據與自己針對響應數據做MD5簽名之後的數據進行比較是否相等 Document backDocument = null; try { backDocument = DocumentHelper.parseText(responseMsg); } catch (DocumentException e) { System.out.println(e); } Element backRootEle = backDocument.getRootElement(); List backlist = backRootEle.elements(); for (int i = 0; i < backlist.size(); i++) { Element ele = (Element) backlist.get(i); String eleName = ele.getName(); if (!eleName.equals("list")) { xmlBackMap.put(eleName, ele.getText().trim()); } else { continue; } } String backHmacStr = ""; for (int i = 0; i < backDigestValues.length; i++) { if (backDigestValues[i].equals("hmacKey")) { backHmacStr = backHmacStr + hmacKey; continue; } String tempStr = (String) xmlBackMap.get(backDigestValues[i]); backHmacStr = backHmacStr + ((tempStr == null) ? "" : tempStr); } String newmd5hmac = Digest.hmacSign(backHmacStr); System.out.println("提交返回源數據為---||" + backHmacStr + "||"); System.out.println("經過md5簽名後的驗證返回hmac為---||" + newmd5hmac + "||"); System.out.println("提交返回的hmac為---||" + backmd5hmac + "||"); if (newmd5hmac.equals(backmd5hmac)) { System.out.println("md5驗簽成功"); //第七步:判斷該證書DN是否為易寶 if (signUtil.getSigerCert()[0].getSubject().toUpperCase().indexOf("OU=YEEPAY,") > 0) { System.out.println("證書DN是易寶的"); if (todigestValues.equals("cmd,mer_Id,batch_No,order_Id,page_No,hmacKey")) { return resolve(responseMsg); } return xmlBackMap; } else { System.out.println("證書DN不是易寶的"); } // } else { System.out.println("md5驗簽失敗"); } } else { System.out.println("證書驗簽失敗...."); } } return null; } private static Map resolve(String responseMsg) { Map xmlBackMap = new LinkedHashMap(); Map listBackMap = new LinkedHashMap(); Document backDocument; try { backDocument = DocumentHelper.parseText(responseMsg); Element backRootEle = backDocument.getRootElement(); List backlist = backRootEle.elements(); for (int i = 0; i < backlist.size(); i++) { Element ele = (Element) backlist.get(i); String eleName = ele.getName(); if (!eleName.equals("list")) { xmlBackMap.put(eleName, ele.getText().trim()); } else { List backList = ((Element) (((Element) (((Element) backlist.get(i)).elements().get(0))).elements().get(0))).elements(); for (int j = 0; j < backList.size(); j++) { Element e1111 = (Element) backList.get(j); listBackMap.put(e1111.getName(), e1111.getText().trim()); } } } xmlBackMap.put("listBackMap", listBackMap); return xmlBackMap; } catch (DocumentException e) { //log.info("易寶解析返回XML參數錯誤----->" + e.getMessage()); return null; } } /** * 根據易寶代付訂單批次號和訂單號查詢支付狀態 * * @param betch_no * @param order_Id * @return */ public static Integer getPayStatus(String betch_no, String order_Id) { //代付狀態/1 代付中 /2 代付成功/ 3 代付失敗 try { Map transferMap = TransferParamResolver.singlePayQuery(betch_no, order_Id); if (transferMap == null || transferMap.get("listBackMap") == null) { return 3; } Map listBackMap = (Map) transferMap.get("listBackMap"); if (transferMap.get("ret_Code") != null && listBackMap.get("r1_Code") != null && listBackMap.get("bank_Status") != null) { if ("1".equals(String.valueOf(transferMap.get("ret_Code"))) && "0026".equals(String.valueOf(listBackMap.get("r1_Code"))) && "S".equals(String.valueOf(listBackMap.get("bank_Status")))) { return 2; } //失敗情況 if ("1".equals(String.valueOf(transferMap.get("ret_Code"))) && ("0026".equals(String.valueOf(listBackMap.get("r1_Code"))) || "0027".equals(String.valueOf(listBackMap.get("r1_Code")))) && "F".equals(String.valueOf(listBackMap.get("bank_Status")))) { return 3; } //正在進行中 if ("1".equals(String.valueOf(transferMap.get("ret_Code"))) && ("0026".equals(String.valueOf(listBackMap.get("r1_Code")))) || "0025".equals(String.valueOf(listBackMap.get("r1_Code")))) { return 1; } } else { return 3; } } catch (Exception e) { e.printStackTrace(); //log部分 } return 3; } }
技術分享圖片

 這裏附上源碼下載地址(源碼在TestProject中):鏈接:https://pan.baidu.com/s/1UVUCG4zNYDJmJl9q5twrkw 密碼:32gw

易寶支付Demo,生產中封裝成簡潔的代付接口,不用request如何獲取項目運行時的真實路徑(轉)