1. 程式人生 > >銀聯無跳轉介面除錯程式碼

銀聯無跳轉介面除錯程式碼

自定義銀聯工具類

package util;
import com.unionpay.acp.sdk.SDKConstants;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class UnionPayConstantUtil {

    /**
     * 版本 5.1.0
     */
public static final String VERSION = "5.1.0";
/**
     * 預設編碼 UTF-8
     */
public static final 
String ENCODING = "UTF-8"; /** * 商戶號 */ public static final String MER_ID = "777290058156102"; /** * 商戶名稱 */ public static final String MER_NAME = ""; /** * 商戶簡稱 */ public static final String MER_ABBR = ""; /** * 交易型別 01-消費 */ public static final String TXN_TYPE_CONSUMER
= "01"; /** * 交易型別 04-退貨 */ public static final String TXN_TYPE_REFUND = "04"; /** * 交易型別 31-消費撤銷 */ public static final String TXN_TYPE_CONSUMER_UNDO = "31"; /** * 交易型別 77-傳送簡訊 */ public static final String TXN_TYPE_SMS = "77"; /** * 交易型別 78-交易查詢 */ public static final
String TXN_TYPE_QUERY = "78"; /** * 首次開通 */ public static final String TXN_TYPE_OPEN_CARD = "79"; /** * 交易型別 95 - 銀聯加密公鑰更新查詢 */ public static final String TXN_TYPE_ENCRYPTCER_UPDATE_QUERY = "95"; /** * 交易子型別 00-預設 */ public static final String TXN_SUBTYPE_DEFAULT = "00"; /** * 交易子型別 01-消費 */ public static final String TXN_SUBTYPE_CONSUMER = "01"; /** * 交易子型別 02-消費簡訊 */ public static final String TXN_SUBTYPE_CONSUMER_SMS = "02"; /** * 交易子型別 03-分期 */ public static final String TXN_SUBTYPE_FQ = "03"; /** * 業務型別 000000-預設 */ public static final String BIZ_TYPE_DEFAULT = "000000"; /** * 業務型別 000201-B2C閘道器支付 */ public static final String BIZ_TYPE_B2C = "000201"; /** * 業務型別 000301-認證支付2.0 */ public static final String BIZ_TYPE_AUTH = "000301"; /** * 業務型別 000902-TOKEN支付 */ public static final String BIZ_TYPE_TOKEN = "000902"; /** * 渠道型別 07-網際網路 */ public static final String CHANNEL_TYPE_PC = "07"; /** * 渠道型別 08-移動 */ public static final String CHANNEL_TYPE_MOBILE = "08"; /** * 商戶接入型別 0-商戶直接接入 預設為0 1-機構接入 2-平臺接入 */ public static final String ACCESS_TYPE_DEFAULT = "0"; /** * 交易幣種 預設人民幣 */ public static final String CURRENCY_CODE = "156"; /** * 賬號型別 01-銀行卡 */ public static final String ACC_TYPE_BANK_CARD = "01"; /** * 賬號類 03:IC卡 */ public static final String ACC_TYPE_IC_CARD = "03"; /** * 敏感資訊加密公鑰 01 */ public static final String CERT_TYPE = "01"; /** * 封裝資料拆解 * @param data * @return */ public static String genHtmlResult(Map<String, String> data){ TreeMap<String, String> tree = new TreeMap<String, String>(); Iterator<Map.Entry<String, String>> it = data.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> en = it.next(); tree.put(en.getKey(), en.getValue()); } it = tree.entrySet().iterator(); StringBuffer sf = new StringBuffer(); while (it.hasNext()) { Map.Entry<String, String> en = it.next(); String key = en.getKey(); String value = en.getValue(); if("respCode".equals(key)){ sf.append("<b>"+key + SDKConstants.EQUAL + value+"</br></b>"); }else sf.append(key + SDKConstants.EQUAL + value+"</br>"); } return sf.toString(); } }

銀聯介面實現

package web;
import com.unionpay.acp.sdk.AcpService;
import com.unionpay.acp.sdk.LogUtil;
import com.unionpay.acp.sdk.SDKConfig;
import com.unionpay.acp.sdk.SDKConstants;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import util.UnionPayConstantUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/api/commons/pay")
public class UnionPayController {

    /**
     * 交易查詢
     *
     * @param sessionId
* @param accNo
* @param orderId
* @param txnTime
* @param response
* @return
*/
@RequestMapping("/unionPayQuery.do")
    public @ResponseBody
Map<String, Object> unionPay(String sessionId, String accNo, String orderId, String txnTime, HttpServletResponse response) {
        //判斷引數
        //判斷是否符合條件
Map<String, String> contentData = new HashMap<String, String>();
//配置銀聯全渠道資訊
contentData.put(SDKConstants.param_version, UnionPayConstantUtil.VERSION);                  //版本號
contentData.put(SDKConstants.param_encoding, UnionPayConstantUtil.ENCODING);                //字符集編碼 可以使用UTF-8,GBK兩種方式
contentData.put(SDKConstants.param_signMethod, SDKConfig.getConfig().getSignMethod()); //簽名方法
contentData.put(SDKConstants.param_txnType, UnionPayConstantUtil.TXN_TYPE_QUERY);                              //交易型別 78-開通查詢
contentData.put(SDKConstants.param_txnSubType, UnionPayConstantUtil.TXN_SUBTYPE_DEFAULT);                           //交易子型別 00-根據賬號accNo查詢(預設)
contentData.put(SDKConstants.param_bizType, UnionPayConstantUtil.BIZ_TYPE_AUTH);                          //業務型別 認證支付2.0
contentData.put(SDKConstants.param_channelType, UnionPayConstantUtil.CHANNEL_TYPE_PC);                          //渠道型別07-PC
        //商戶資訊
contentData.put(SDKConstants.param_merId, UnionPayConstantUtil.MER_ID);
contentData.put(SDKConstants.param_orderId, orderId);
contentData.put(SDKConstants.param_txnTime, txnTime);
contentData.put(SDKConstants.param_accessType, UnionPayConstantUtil.ACCESS_TYPE_DEFAULT);
//買家賬戶資訊
        ////////////如果商戶號開通了【商戶對敏感資訊加密】的許可權那麼需要對 accNo,phoneNo加密使用:
String accNo1 = AcpService.encryptData(accNo, UnionPayConstantUtil.ENCODING);            //這裡測試的時候使用的是測試卡號,正式環境請使用真實卡號
contentData.put(SDKConstants.param_accNo, accNo1);
contentData.put(SDKConstants.param_encryptCertId, AcpService.getEncryptCertId());   //加密證書的certId,配置在acp_sdk.properties檔案 acpsdk.encryptCert.path屬性下
        //與銀聯通訊
try {
            Map<String, String> reqData = AcpService.sign(contentData, UnionPayConstantUtil.ENCODING);              //報文中certId,signature的值是在signData方法中獲取並自動賦值的,只要證書配置正確即可。
String requestBackUrl = SDKConfig.getConfig().getBackRequestUrl();                          //交易請求url從配置檔案讀取對應屬性檔案acp_sdk.properties中的 acpsdk.backTransUrl
Map<String, String> rspData = AcpService.post(reqData, requestBackUrl, UnionPayConstantUtil.ENCODING); //傳送請求報文並接受同步應答(預設連線超時時間30秒,讀取返回結果超時時間30秒);這裡呼叫signData之後,呼叫submitUrl之前不能對submitFromData中的鍵值對做任何修改,如果修改會導致驗籤不通過
StringBuffer parseStr = new StringBuffer("");
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, UnionPayConstantUtil.ENCODING)) {
                    LogUtil.writeLog("驗證簽名成功");
String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //成功
parseStr.append("<br>解析敏感資訊加密資訊如下(如果有):<br>");
String customerInfo = rspData.get("customerInfo");
                        if (null != customerInfo) {
                            Map<String, String> cm = AcpService.parseCustomerInfo(customerInfo, UnionPayConstantUtil.ENCODING);
parseStr.append("customerInfo明文: " + cm + "<br>");
}
                        String an = rspData.get("accNo");
                        if (null != an) {
                            an = AcpService.decryptData(an, UnionPayConstantUtil.ENCODING);
parseStr.append("accNo明文: " + an);
}
                        //TODO
} else {
                        //其他應答碼為失敗請排查原因或做失敗處理
                        //TODO
}
                } else {
                    LogUtil.writeErrorLog("驗證簽名失敗");
//TODO 檢查驗證簽名失敗的原因
}
            } else {
                //未返回正確的http狀態
LogUtil.writeErrorLog("未獲取到返回報文或返回http狀態碼非200");
}
            String reqMessage = UnionPayConstantUtil.genHtmlResult(reqData);
String rspMessage = UnionPayConstantUtil.genHtmlResult(rspData);
response.getWriter().write("請求報文:<br/>" + reqMessage + "<br/>" + "應答報文:</br>" + rspMessage + parseStr);
} catch (Exception e) {
            e.printStackTrace();
            return null;
}

        return null;
}

    /**
     * 首次使用開通
     *
     * @param sessionId
* @param orderId
* @param accNo
* @param phoneNo
* @param cvn2
* @param expired
* @param response
* @return
*/
@RequestMapping("/unionPayOpenCardBack.do")
    public @ResponseBody
Map<String, Object> unionPayOpenCardBack(String sessionId, String orderId, String accNo, String phoneNo, String cvn2,
String expired, HttpServletResponse response) {
        //判斷引數是否合法
        //判斷使用者是否存在
        //判斷訂單是否存在 訂單狀態是否合法
        //判斷銀行卡號 手機號
        //封裝資料
Map<String, String> contentData = new HashMap<String, String>();
//銀聯全渠道預設引數
contentData.put(SDKConstants.param_version, UnionPayConstantUtil.VERSION);                  //版本號
contentData.put(SDKConstants.param_encoding, UnionPayConstantUtil.ENCODING);           //字符集編碼 可以使用UTF-8,GBK兩種方式
contentData.put(SDKConstants.param_signMethod, SDKConfig.getConfig().getSignMethod()); //簽名方法
contentData.put(SDKConstants.param_txnType, UnionPayConstantUtil.TXN_TYPE_OPEN_CARD);                     //交易型別 79-開通
contentData.put(SDKConstants.param_txnSubType, UnionPayConstantUtil.TXN_SUBTYPE_DEFAULT);                      //交易子型別 00
contentData.put(SDKConstants.param_bizType, UnionPayConstantUtil.BIZ_TYPE_AUTH);                          //業務型別 認證支付2.0
contentData.put(SDKConstants.param_channelType, UnionPayConstantUtil.CHANNEL_TYPE_PC);               //渠道型別07-PC
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String txnTime = sdf.format(date);
//商戶接入引數   商戶訂單內容的補充
contentData.put(SDKConstants.param_merId, UnionPayConstantUtil.MER_ID);
contentData.put(SDKConstants.param_accessType, UnionPayConstantUtil.ACCESS_TYPE_DEFAULT);                            //接入型別,商戶接入固定填0,不需修改
contentData.put(SDKConstants.param_orderId, orderId);                           //商戶訂單號,8-40位數字字母,不能含“-”或“_”,可以自行定製規則
contentData.put(SDKConstants.param_txnTime, txnTime);                           //訂單傳送時間,格式為YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效
contentData.put(SDKConstants.param_accType, UnionPayConstantUtil.ACC_TYPE_BANK_CARD);                              //賬號型別
        //商戶需要開通對銀行卡進行開通的許可權  否則商戶不能再自己的站點開通
        //消費交易要素  買家交易的賬號進行補充   買家個人資訊
Map<String, String> customInfoData = new HashMap<String, String>();
//商戶號要是開啟了對銀行卡號進行加密  就需要這一步驟
customInfoData.put(SDKConstants.param_phoneNo, phoneNo);
customInfoData.put(SDKConstants.param_cvn2, cvn2);
customInfoData.put(SDKConstants.param_expired, expired);
String customerInfoWithEncrypt = AcpService.getCustomerInfoWithEncrypt(customInfoData, null, UnionPayConstantUtil.ENCODING);
contentData.put(SDKConstants.param_customerInfo, customerInfoWithEncrypt);
//根據商戶是否開啟加密而設定
String accNo1 = AcpService.encryptData(accNo, UnionPayConstantUtil.ENCODING);
contentData.put(SDKConstants.param_accNo, accNo1);
contentData.put(SDKConstants.param_encryptCertId, AcpService.getEncryptCertId());   //獲取加密證書的id
        //後臺通知地址
contentData.put(SDKConstants.param_backUrl, SDKConfig.getConfig().getBackUrl());
//進行交易簽名   並應答
try {
            Map<String, String> signData = AcpService.sign(contentData, UnionPayConstantUtil.ENCODING);
String backRequestUrl = SDKConfig.getConfig().getBackRequestUrl();
//響應回來的資料   這裡只能證明與銀聯連線是否接通  正真的完成交易是在銀聯給後臺地址傳送資料  才能證明交易完成
Map<String, String> resposeData = AcpService.post(signData, backRequestUrl, UnionPayConstantUtil.ENCODING);
String reqMessage = UnionPayConstantUtil.genHtmlResult(signData);
String rspMessage = UnionPayConstantUtil.genHtmlResult(resposeData);
response.getWriter().write("請求報文:<br/>" + reqMessage + "<br/>" + "應答報文:</br>" + rspMessage);
            if (resposeData == null) {
                return null;
}
            if (AcpService.validate(resposeData, UnionPayConstantUtil.ENCODING)) {
                String respCode = resposeData.get("respCode");
                if ("00".equals(respCode)) {
                    //處理業務 交易以受理
                    //儲存訂單日誌 PayRequestLog
} else if (("03").equals(respCode) ||
                        ("04").equals(respCode) ||
                        ("05").equals(respCode)) {
                    //處理沒有受理 情況
} else {
                    //這裡處理錯誤  返回給前臺提示使用者
}
            } else {
                return null;
}
        } catch (Exception e) {
            e.printStackTrace();
}


        return null;
}


    /**
     * 銀聯支付介面
     *
     * @param sessionId
* @param orderId
* @param smsCode
* @param accNo
* @param fq_num
* @return
*/
@RequestMapping("/unionPay.do")
    public @ResponseBody
Map<String, Object> unionPay(String sessionId, String orderId, String smsCode, String accNo, String fq_num, HttpServletResponse response, String prize) {
        //判斷當前使用者
        //判斷引數是否符合要求
        //判斷訂單是否存在  判斷訂單狀態
        //判斷accno銀行卡號是否符合規格   並判斷是否是合作的銀行所屬的卡號
Map<String, String> contentData = new HashMap<String, String>();
//銀聯全渠道預設引數
contentData.put(SDKConstants.param_version, UnionPayConstantUtil.VERSION);                  //版本號
contentData.put(SDKConstants.param_encoding, UnionPayConstantUtil.ENCODING);           //字符集編碼 可以使用UTF-8,GBK兩種方式
contentData.put(SDKConstants.param_signMethod, SDKConfig.getConfig().getSignMethod()); //簽名方法
        //txnSubType 01-消費 03-分期
contentData.put(SDKConstants.param_txnType, UnionPayConstantUtil.TXN_TYPE_CONSUMER);                     //交易型別 01-消費
contentData.put(SDKConstants.param_txnSubType, UnionPayConstantUtil.TXN_SUBTYPE_CONSUMER);                      //交易子型別 01-消費  03-分期
        //numberOfInstallments分期期數03 06 12  instalRate分期期率  mchntFeeSubsidy 商戶補貼
        //contentData.put("instalTransInfo", "{numberOfInstallments=" + fq_num + "}");
contentData.put(SDKConstants.param_bizType, UnionPayConstantUtil.BIZ_TYPE_AUTH);                          //業務型別 認證支付2.0
contentData.put(SDKConstants.param_channelType, UnionPayConstantUtil.CHANNEL_TYPE_PC);               //渠道型別07-PC
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String txnTime = sdf.format(date);
//商戶接入引數   商戶訂單內容的補充
contentData.put(SDKConstants.param_merId, UnionPayConstantUtil.MER_ID);
contentData.put(SDKConstants.param_accessType, UnionPayConstantUtil.ACCESS_TYPE_DEFAULT);                            //接入型別,商戶接入固定填0,不需修改
contentData.put(SDKConstants.param_orderId, orderId);                           //商戶訂單號,8-40位數字字母,不能含“-”或“_”,可以自行定製規則
contentData.put(SDKConstants.param_txnTime, txnTime);                           //訂單傳送時間,格式為yyyyMMddHHmmss,必須取當前時間,否則會報txnTime無效
contentData.put(SDKConstants.param_currencyCode, UnionPayConstantUtil.CURRENCY_CODE);    //交易幣種(境內商戶一般是156 人民幣)
contentData.put(SDKConstants.param_txnAmt, prize);                               //交易金額,單位分,不要帶小數點
contentData.put(SDKConstants.param_accType, UnionPayConstantUtil.ACC_TYPE_BANK_CARD);                              //賬號型別
        //contentData.put("orderDesc", "訂單描述");
contentData.put(SDKConstants.param_reqReserved, "orderDesc=訂單描述;remark=備註"); //請求保留域
        //消費交易要素  買家交易的賬號進行補充
Map<String, String> customInfoData = new HashMap<String, String>();
customInfoData.put(SDKConstants.param_smsCode, smsCode);
//商戶號要是開啟了對銀行卡號進行加密  就需要這一步驟
String customerInfoWithEncrypt = AcpService.getCustomerInfoWithEncrypt(customInfoData, accNo, UnionPayConstantUtil.ENCODING);
String accNo1 = AcpService.encryptData(accNo, UnionPayConstantUtil.ENCODING);
contentData.put(SDKConstants.param_accNo, accNo1);
contentData.put(SDKConstants.param_encryptCertId, AcpService.getEncryptCertId());   //獲取加密證書的id
contentData.put(SDKConstants.param_customerInfo, customerInfoWithEncrypt);
//後臺通知地址
contentData.put(SDKConstants.param_backUrl, SDKConfig.getConfig().getBackUrl());
//進行交易簽名   並應答
try {
            Map<String, String> signData = AcpService.sign(contentData, UnionPayConstantUtil.ENCODING);
String backRequestUrl = SDKConfig.getConfig().getBackRequestUrl();
//響應回來的資料   這裡只能證明與銀聯連線是否接通  正真的完成交易是在銀聯給後臺地址傳送資料  才能證明交易完成
Map<String, String> resposeData = AcpService.post(signData, backRequestUrl, UnionPayConstantUtil.ENCODING);
String reqMessage = UnionPayConstantUtil.genHtmlResult(signData);
String rspMessage = UnionPayConstantUtil.genHtmlResult(resposeData);
response.getWriter().write("請求報文:<br/>" + reqMessage + "<br/>" + "應答報文:</br>" + rspMessage);
            if (resposeData == null) {
                return null;
}
            if (AcpService.validate(resposeData, UnionPayConstantUtil.ENCODING)) {
                String respCode = resposeData.get("respCode");
                if ("00".equals(respCode)) {
                    //處理業務 交易以受理
                    //儲存訂單日誌 PayRequestLog
LogUtil.writeLog("consume=======》OK");
} else if (("03").equals(respCode) ||
                        ("04").equals(respCode) ||
                        ("05").equals(respCode)) {
                    //處理沒有受理 情況
} else {
                    //這裡處理錯誤  返回給前臺提示使用者
}
            } else {
                return null;
}
        } catch (Exception e) {
            e.printStackTrace();
            return null;
}
        return null;
}

    /**
     * 銀聯消費簡訊
     */
@RequestMapping("/unionPayConsumeSMS.do")
    public @ResponseBody
Map<String, Object> unionPayConsumeSMS(String sessionId, String orderId, String accNo, String phoneNo, HttpServletResponse response, String prize) {
        //判斷引數是否合法
        //檢視使用者是否存在
        //查詢訂單  判斷訂單狀態
        //判斷電話是否符合要求
        //封裝資料
Map<String, String> contentData = new HashMap<String, String>();
//銀聯全渠道預設引數
contentData.put(SDKConstants.param_version, UnionPayConstantUtil.VERSION);                  //版本號
contentData.put(SDKConstants.param_encoding, UnionPayConstantUtil.ENCODING);           //字符集編碼 可以使用UTF-8,GBK兩種方式
contentData.put(SDKConstants.param_signMethod, SDKConfig.getConfig().getSignMethod()); //簽名方法
contentData.put(SDKConstants.param_txnType, UnionPayConstantUtil.TXN_TYPE_SMS);                     //交易型別 77簡訊
contentData.put(SDKConstants.param_txnSubType, UnionPayConstantUtil.TXN_SUBTYPE_CONSUMER_SMS);                      //交易子型別 01-消費  03-分期
contentData.put(SDKConstants.param_bizType, UnionPayConstantUtil.BIZ_TYPE_AUTH);                          //業務型別 認證支付2.0
contentData.put(SDKConstants.param_channelType, UnionPayConstantUtil.CHANNEL_TYPE_PC);               //渠道型別07-PC
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String txnTime = sdf.format(date);
//商戶接入引數   商戶訂單內容的補充
contentData.put(SDKConstants.param_merId, UnionPayConstantUtil.MER_ID);
contentData.put(SDKConstants.param_accessType, UnionPayConstantUtil.ACCESS_TYPE_DEFAULT);                            //接入型別,商戶接入固定填0,不需修改
contentData.put(SDKConstants.param_orderId, orderId);                           //商戶訂單號,8-40位數字字母,不能含“-”或“_”,可以自行定製規則
contentData.put(SDKConstants.param_txnTime, txnTime);                           //訂單傳送時間,格式為YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效
contentData.put(SDKConstants.param_currencyCode, UnionPayConstantUtil.CURRENCY_CODE);    //交易幣種(境內商戶一般是156 人民幣)
contentData.put(SDKConstants.param_txnAmt, prize);                               //交易金額,單位分,不要帶小數點
contentData.put(SDKConstants.param_accType, UnionPayConstantUtil.ACC_TYPE_BANK_CARD);                              //賬號型別
        //contentData.put("orderDesc", "訂單描述");
contentData.put(SDKConstants.param_reqReserved, "orderDesc=訂單描述;remark=備註"); //請求保留域
        //消費交易要素  買家交易的賬號進行補充
Map<String, String> customInfoData = new HashMap<String, String>();
//新增手機號碼
customInfoData.put(SDKConstants.param_phoneNo, phoneNo);
String customerInfoWithEncrypt = AcpService.getCustomerInfoWithEncrypt(customInfoData, null, UnionPayConstantUtil.ENCODING);
//商戶號要是開啟了對銀行卡號進行加密  就需要這一步驟
String accNo1 = AcpService.encryptData(accNo, UnionPayConstantUtil.ENCODING);
contentData.put(SDKConstants.param_accNo, accNo1);
contentData.put(SDKConstants.param_encryptCertId, AcpService.getEncryptCertId());   //獲取加密證書的id
contentData.put(SDKConstants.param_customerInfo, customerInfoWithEncrypt);
//後臺通知地址
contentData.put(SDKConstants.param_backUrl, SDKConfig.getConfig().getBackUrl());
//進行交易簽名   並應答
try {
            Map<String, String> signData = AcpService.sign(contentData, UnionPayConstantUtil.ENCODING);
String backRequestUrl = SDKConfig.getConfig().getBackRequestUrl();
//響應回來的資料   這裡只能證明與銀聯連線是否接通  正真的完成交易是在銀聯給後臺地址傳送資料  才能證明交易完成
Map<St