一、下載銀聯sdk;
二、將所需的jar包導入項目中;
三、將示例代碼拷貝到項目中來;
四、修改SDKConfig.java中加載公鑰和私鑰的位置,用動態加載的方式:
path.substring(0,path.indexOf("WEB-INF")) + File.separator + "WEB-INF" + File.separator + "pub.key";
/**
*
* Licensed Property to China UnionPay Co., Ltd.
*
* (C) Copyright of China UnionPay Co., Ltd. 2010
* All Rights Reserved.
*
*
* Modification History:
* =============================================================================
* Author Date Description
* ------------ ---------- ---------------------------------------------------
* xshu 2014-05-28 MPI基本參數工具類
* =============================================================================
*/
package com.unionpay.acp.sdk;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
/**
*
* @ClassName SDKConfig
* @Description acpsdk配置文件acp_sdk.properties配置信息類
* @date 2016-7-22 下午4:04:55
* 聲明:以下代碼只是爲了方便商戶測試而提供的樣例代碼,商戶可以根據自己需要,按照技術文檔編寫。該代碼僅供參考,不提供編碼,性能,規範性等方面的保障<br>
*/
public class SDKConfig {
public static final String FILE_NAME = "acp_sdk.properties";
/** 前臺請求URL. */
private String frontRequestUrl;
/** 後臺請求URL. */
private String backRequestUrl;
/** 單筆查詢 */
private String singleQueryUrl;
/** 批量查詢 */
private String batchQueryUrl;
/** 批量交易 */
private String batchTransUrl;
/** 文件傳輸 */
private String fileTransUrl;
/** 簽名證書路徑. */
private String signCertPath;
/** 簽名證書密碼. */
private String signCertPwd;
/** 簽名證書類型. */
private String signCertType;
/** 加密公鑰證書路徑. */
private String encryptCertPath;
/** 驗證簽名公鑰證書目錄. */
private String validateCertDir;
/** 按照商戶代碼讀取指定簽名證書目錄. */
private String signCertDir;
/** 磁道加密證書路徑. */
private String encryptTrackCertPath;
/** 磁道加密公鑰模數. */
private String encryptTrackKeyModulus;
/** 磁道加密公鑰指數. */
private String encryptTrackKeyExponent;
/** 有卡交易. */
private String cardRequestUrl;
/** app交易 */
private String appRequestUrl;
/** 證書使用模式(單證書/多證書) */
private String singleMode;
/** 安全密鑰(SHA256和SM3計算時使用) */
private String secureKey;
/** 中級證書路徑 */
private String middleCertPath;
/** 根證書路徑 */
private String rootCertPath;
/** 是否驗證驗簽證書CN,除了false都驗 */
private boolean ifValidateCNName = true;
/** 是否驗證https證書,默認都不驗 */
private boolean ifValidateRemoteCert = false;
/** signMethod,沒配按01吧 */
private String signMethod = "01";
/** version,沒配按5.0.0 */
private String version = "5.0.0";
/** frontUrl */
private String frontUrl;
/** backUrl */
private String backUrl;
/*繳費相關地址*/
private String jfFrontRequestUrl;
private String jfBackRequestUrl;
private String jfSingleQueryUrl;
private String jfCardRequestUrl;
private String jfAppRequestUrl;
private String qrcBackTransUrl;
private String qrcB2cIssBackTransUrl;
private String qrcB2cMerBackTransUrl;
/** 配置文件中的前臺URL常量. */
public static final String SDK_FRONT_URL = "acpsdk.frontTransUrl";
/** 配置文件中的後臺URL常量. */
public static final String SDK_BACK_URL = "acpsdk.backTransUrl";
/** 配置文件中的單筆交易查詢URL常量. */
public static final String SDK_SIGNQ_URL = "acpsdk.singleQueryUrl";
/** 配置文件中的批量交易查詢URL常量. */
public static final String SDK_BATQ_URL = "acpsdk.batchQueryUrl";
/** 配置文件中的批量交易URL常量. */
public static final String SDK_BATTRANS_URL = "acpsdk.batchTransUrl";
/** 配置文件中的文件類交易URL常量. */
public static final String SDK_FILETRANS_URL = "acpsdk.fileTransUrl";
/** 配置文件中的有卡交易URL常量. */
public static final String SDK_CARD_URL = "acpsdk.cardTransUrl";
/** 配置文件中的app交易URL常量. */
public static final String SDK_APP_URL = "acpsdk.appTransUrl";
/** 以下繳費產品使用,其餘產品用不到,無視即可 */
// 前臺請求地址
public static final String JF_SDK_FRONT_TRANS_URL= "acpsdk.jfFrontTransUrl";
// 後臺請求地址
public static final String JF_SDK_BACK_TRANS_URL="acpsdk.jfBackTransUrl";
// 單筆查詢請求地址
public static final String JF_SDK_SINGLE_QUERY_URL="acpsdk.jfSingleQueryUrl";
// 有卡交易地址
public static final String JF_SDK_CARD_TRANS_URL="acpsdk.jfCardTransUrl";
// App交易地址
public static final String JF_SDK_APP_TRANS_URL="acpsdk.jfAppTransUrl";
// 人到人
public static final String QRC_BACK_TRANS_URL="acpsdk.qrcBackTransUrl";
// 人到人
public static final String QRC_B2C_ISS_BACK_TRANS_URL="acpsdk.qrcB2cIssBackTransUrl";
// 人到人
public static final String QRC_B2C_MER_BACK_TRANS_URL="acpsdk.qrcB2cMerBackTransUrl";
/** 配置文件中籤名證書路徑常量. */
public static final String SDK_SIGNCERT_PATH = "acpsdk.signCert.path";
/** 配置文件中籤名證書密碼常量. */
public static final String SDK_SIGNCERT_PWD = "acpsdk.signCert.pwd";
/** 配置文件中籤名證書類型常量. */
public static final String SDK_SIGNCERT_TYPE = "acpsdk.signCert.type";
/** 配置文件中密碼加密證書路徑常量. */
public static final String SDK_ENCRYPTCERT_PATH = "acpsdk.encryptCert.path";
/** 配置文件中磁道加密證書路徑常量. */
public static final String SDK_ENCRYPTTRACKCERT_PATH = "acpsdk.encryptTrackCert.path";
/** 配置文件中磁道加密公鑰模數常量. */
public static final String SDK_ENCRYPTTRACKKEY_MODULUS = "acpsdk.encryptTrackKey.modulus";
/** 配置文件中磁道加密公鑰指數常量. */
public static final String SDK_ENCRYPTTRACKKEY_EXPONENT = "acpsdk.encryptTrackKey.exponent";
/** 配置文件中驗證簽名證書目錄常量. */
public static final String SDK_VALIDATECERT_DIR = "acpsdk.validateCert.dir";
/** 配置文件中是否加密cvn2常量. */
public static final String SDK_CVN_ENC = "acpsdk.cvn2.enc";
/** 配置文件中是否加密cvn2有效期常量. */
public static final String SDK_DATE_ENC = "acpsdk.date.enc";
/** 配置文件中是否加密卡號常量. */
public static final String SDK_PAN_ENC = "acpsdk.pan.enc";
/** 配置文件中證書使用模式 */
public static final String SDK_SINGLEMODE = "acpsdk.singleMode";
/** 配置文件中安全密鑰 */
public static final String SDK_SECURITYKEY = "acpsdk.secureKey";
/** 配置文件中根證書路徑常量 */
public static final String SDK_ROOTCERT_PATH = "acpsdk.rootCert.path";
/** 配置文件中根證書路徑常量 */
public static final String SDK_MIDDLECERT_PATH = "acpsdk.middleCert.path";
/** 配置是否需要驗證驗簽證書CN,除了false之外的值都當true處理 */
public static final String SDK_IF_VALIDATE_CN_NAME = "acpsdk.ifValidateCNName";
/** 配置是否需要驗證https證書,除了true之外的值都當false處理 */
public static final String SDK_IF_VALIDATE_REMOTE_CERT = "acpsdk.ifValidateRemoteCert";
/** signmethod */
public static final String SDK_SIGN_METHOD ="acpsdk.signMethod";
/** version */
public static final String SDK_VERSION = "acpsdk.version";
/** 後臺通知地址 */
public static final String SDK_BACKURL = "acpsdk.backUrl";
/** 前臺通知地址 */
public static final String SDK_FRONTURL = "acpsdk.frontUrl";
/** 操作對象. */
private static SDKConfig config = new SDKConfig();
/** 屬性文件對象. */
private Properties properties;
private SDKConfig() {
super();
}
/**
* 獲取config對象.
* @return
*/
public static SDKConfig getConfig() {
return config;
}
/**
* 從properties文件加載
*
* @param rootPath
* 不包含文件名的目錄.
*/
public void loadPropertiesFromPath(String rootPath) {
if (StringUtils.isNotBlank(rootPath)) {
LogUtil.writeLog("從路徑讀取配置文件: " + rootPath+File.separator+FILE_NAME);
File file = new File(rootPath + File.separator + FILE_NAME);
InputStream in = null;
if (file.exists()) {
try {
in = new FileInputStream(file);
properties = new Properties();
properties.load(in);
loadProperties(properties);
} catch (FileNotFoundException e) {
LogUtil.writeErrorLog(e.getMessage(), e);
} catch (IOException e) {
LogUtil.writeErrorLog(e.getMessage(), e);
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
LogUtil.writeErrorLog(e.getMessage(), e);
}
}
}
} else {
// 由於此時可能還沒有完成LOG的加載,因此採用標準輸出來打印日誌信息
LogUtil.writeErrorLog(rootPath + FILE_NAME + "不存在,加載參數失敗");
}
} else {
loadPropertiesFromSrc();
}
}
/**
* 從classpath路徑下加載配置參數
*/
public void loadPropertiesFromSrc() {
InputStream in = null;
try {
LogUtil.writeLog("從classpath: " +SDKConfig.class.getClassLoader().getResource("").getPath()+" 獲取屬性文件"+FILE_NAME);
in = SDKConfig.class.getClassLoader().getResourceAsStream(FILE_NAME);
if (null != in) {
properties = new Properties();
try {
properties.load(in);
} catch (IOException e) {
throw e;
}
} else {
LogUtil.writeErrorLog(FILE_NAME + "屬性文件未能在classpath指定的目錄下 "+SDKConfig.class.getClassLoader().getResource("").getPath()+" 找到!");
return;
}
loadProperties(properties);
} catch (IOException e) {
LogUtil.writeErrorLog(e.getMessage(), e);
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
LogUtil.writeErrorLog(e.getMessage(), e);
}
}
}
}
/**
* 根據傳入的 {@link #load(java.util.Properties)}對象設置配置參數
*
* @param pro
*/
public void loadProperties(Properties pro) {
LogUtil.writeLog("開始從屬性文件中加載配置項");
String value = null;
value = pro.getProperty(SDK_SIGNCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.signCertPath = value.trim();
LogUtil.writeLog("配置項:私鑰簽名證書路徑==>"+SDK_SIGNCERT_PATH +"==>"+ value+" 已加載");
}
value = pro.getProperty(SDK_SIGNCERT_PWD);
if (!SDKUtil.isEmpty(value)) {
this.signCertPwd = value.trim();
LogUtil.writeLog("配置項:私鑰簽名證書密碼==>"+SDK_SIGNCERT_PWD +" 已加載");
}
value = pro.getProperty(SDK_SIGNCERT_TYPE);
if (!SDKUtil.isEmpty(value)) {
this.signCertType = value.trim();
LogUtil.writeLog("配置項:私鑰簽名證書類型==>"+SDK_SIGNCERT_TYPE +"==>"+ value+" 已加載");
}
value = pro.getProperty(SDK_ENCRYPTCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.encryptCertPath = value.trim();
LogUtil.writeLog("配置項:敏感信息加密證書==>"+SDK_ENCRYPTCERT_PATH +"==>"+ value+" 已加載");
}
value = pro.getProperty(SDK_VALIDATECERT_DIR);
if (!SDKUtil.isEmpty(value)) {
this.validateCertDir = value.trim();
LogUtil.writeLog("配置項:驗證簽名證書路徑(這裏配置的是目錄,不要指定到公鑰文件)==>"+SDK_VALIDATECERT_DIR +"==>"+ value+" 已加載");
}
value = pro.getProperty(SDK_FRONT_URL);
if (!SDKUtil.isEmpty(value)) {
this.frontRequestUrl = value.trim();
}
value = pro.getProperty(SDK_BACK_URL);
if (!SDKUtil.isEmpty(value)) {
this.backRequestUrl = value.trim();
}
value = pro.getProperty(SDK_BATQ_URL);
if (!SDKUtil.isEmpty(value)) {
this.batchQueryUrl = value.trim();
}
value = pro.getProperty(SDK_BATTRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.batchTransUrl = value.trim();
}
value = pro.getProperty(SDK_FILETRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.fileTransUrl = value.trim();
}
value = pro.getProperty(SDK_SIGNQ_URL);
if (!SDKUtil.isEmpty(value)) {
this.singleQueryUrl = value.trim();
}
value = pro.getProperty(SDK_CARD_URL);
if (!SDKUtil.isEmpty(value)) {
this.cardRequestUrl = value.trim();
}
value = pro.getProperty(SDK_APP_URL);
if (!SDKUtil.isEmpty(value)) {
this.appRequestUrl = value.trim();
}
value = pro.getProperty(SDK_ENCRYPTTRACKCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.encryptTrackCertPath = value.trim();
}
value = pro.getProperty(SDK_SECURITYKEY);
if (!SDKUtil.isEmpty(value)) {
this.secureKey = value.trim();
}
value = pro.getProperty(SDK_ROOTCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.rootCertPath = value.trim();
}
value = pro.getProperty(SDK_MIDDLECERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.middleCertPath = value.trim();
}
/**繳費部分**/
value = pro.getProperty(JF_SDK_FRONT_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfFrontRequestUrl = value.trim();
}
value = pro.getProperty(JF_SDK_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfBackRequestUrl = value.trim();
}
value = pro.getProperty(JF_SDK_SINGLE_QUERY_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfSingleQueryUrl = value.trim();
}
value = pro.getProperty(JF_SDK_CARD_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfCardRequestUrl = value.trim();
}
value = pro.getProperty(JF_SDK_APP_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfAppRequestUrl = value.trim();
}
value = pro.getProperty(QRC_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcBackTransUrl = value.trim();
}
value = pro.getProperty(QRC_B2C_ISS_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcB2cIssBackTransUrl = value.trim();
}
value = pro.getProperty(QRC_B2C_MER_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcB2cMerBackTransUrl = value.trim();
}
value = pro.getProperty(SDK_ENCRYPTTRACKKEY_EXPONENT);
if (!SDKUtil.isEmpty(value)) {
this.encryptTrackKeyExponent = value.trim();
}
value = pro.getProperty(SDK_ENCRYPTTRACKKEY_MODULUS);
if (!SDKUtil.isEmpty(value)) {
this.encryptTrackKeyModulus = value.trim();
}
value = pro.getProperty(SDK_IF_VALIDATE_CN_NAME);
if (!SDKUtil.isEmpty(value)) {
if( SDKConstants.FALSE_STRING.equals(value.trim()))
this.ifValidateCNName = false;
}
value = pro.getProperty(SDK_IF_VALIDATE_REMOTE_CERT);
if (!SDKUtil.isEmpty(value)) {
if( SDKConstants.TRUE_STRING.equals(value.trim()))
this.ifValidateRemoteCert = true;
}
value = pro.getProperty(SDK_SIGN_METHOD);
if (!SDKUtil.isEmpty(value)) {
this.signMethod = value.trim();
}
value = pro.getProperty(SDK_SIGN_METHOD);
if (!SDKUtil.isEmpty(value)) {
this.signMethod = value.trim();
}
value = pro.getProperty(SDK_VERSION);
if (!SDKUtil.isEmpty(value)) {
this.version = value.trim();
}
value = pro.getProperty(SDK_FRONTURL);
if (!SDKUtil.isEmpty(value)) {
this.frontUrl = value.trim();
}
value = pro.getProperty(SDK_BACKURL);
if (!SDKUtil.isEmpty(value)) {
this.backUrl = value.trim();
}
}
public String getFrontRequestUrl() {
return frontRequestUrl;
}
public void setFrontRequestUrl(String frontRequestUrl) {
this.frontRequestUrl = frontRequestUrl;
}
public String getBackRequestUrl() {
return backRequestUrl;
}
public void setBackRequestUrl(String backRequestUrl) {
this.backRequestUrl = backRequestUrl;
}
public String getSignCertPath() {
return signCertPath;
}
public void setSignCertPath(String signCertPath) {
this.signCertPath = signCertPath;
}
public String getSignCertPwd() {
return signCertPwd;
}
public void setSignCertPwd(String signCertPwd) {
this.signCertPwd = signCertPwd;
}
public String getSignCertType() {
return signCertType;
}
public void setSignCertType(String signCertType) {
this.signCertType = signCertType;
}
public String getEncryptCertPath() {
return encryptCertPath;
}
public void setEncryptCertPath(String encryptCertPath) {
this.encryptCertPath = encryptCertPath;
}
public String getValidateCertDir() {
return validateCertDir;
}
public void setValidateCertDir(String validateCertDir) {
this.validateCertDir = validateCertDir;
}
public String getSingleQueryUrl() {
return singleQueryUrl;
}
public void setSingleQueryUrl(String singleQueryUrl) {
this.singleQueryUrl = singleQueryUrl;
}
public String getBatchQueryUrl() {
return batchQueryUrl;
}
public void setBatchQueryUrl(String batchQueryUrl) {
this.batchQueryUrl = batchQueryUrl;
}
public String getBatchTransUrl() {
return batchTransUrl;
}
public void setBatchTransUrl(String batchTransUrl) {
this.batchTransUrl = batchTransUrl;
}
public String getFileTransUrl() {
return fileTransUrl;
}
public void setFileTransUrl(String fileTransUrl) {
this.fileTransUrl = fileTransUrl;
}
public String getSignCertDir() {
return signCertDir;
}
public void setSignCertDir(String signCertDir) {
this.signCertDir = signCertDir;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public String getCardRequestUrl() {
return cardRequestUrl;
}
public void setCardRequestUrl(String cardRequestUrl) {
this.cardRequestUrl = cardRequestUrl;
}
public String getAppRequestUrl() {
return appRequestUrl;
}
public void setAppRequestUrl(String appRequestUrl) {
this.appRequestUrl = appRequestUrl;
}
public String getEncryptTrackCertPath() {
return encryptTrackCertPath;
}
public void setEncryptTrackCertPath(String encryptTrackCertPath) {
this.encryptTrackCertPath = encryptTrackCertPath;
}
public String getJfFrontRequestUrl() {
return jfFrontRequestUrl;
}
public void setJfFrontRequestUrl(String jfFrontRequestUrl) {
this.jfFrontRequestUrl = jfFrontRequestUrl;
}
public String getJfBackRequestUrl() {
return jfBackRequestUrl;
}
public void setJfBackRequestUrl(String jfBackRequestUrl) {
this.jfBackRequestUrl = jfBackRequestUrl;
}
public String getJfSingleQueryUrl() {
return jfSingleQueryUrl;
}
public void setJfSingleQueryUrl(String jfSingleQueryUrl) {
this.jfSingleQueryUrl = jfSingleQueryUrl;
}
public String getJfCardRequestUrl() {
return jfCardRequestUrl;
}
public void setJfCardRequestUrl(String jfCardRequestUrl) {
this.jfCardRequestUrl = jfCardRequestUrl;
}
public String getJfAppRequestUrl() {
return jfAppRequestUrl;
}
public void setJfAppRequestUrl(String jfAppRequestUrl) {
this.jfAppRequestUrl = jfAppRequestUrl;
}
public String getSingleMode() {
return singleMode;
}
public void setSingleMode(String singleMode) {
this.singleMode = singleMode;
}
public String getEncryptTrackKeyExponent() {
return encryptTrackKeyExponent;
}
public void setEncryptTrackKeyExponent(String encryptTrackKeyExponent) {
this.encryptTrackKeyExponent = encryptTrackKeyExponent;
}
public String getEncryptTrackKeyModulus() {
return encryptTrackKeyModulus;
}
public void setEncryptTrackKeyModulus(String encryptTrackKeyModulus) {
this.encryptTrackKeyModulus = encryptTrackKeyModulus;
}
public String getSecureKey() {
return secureKey;
}
public void setSecureKey(String securityKey) {
this.secureKey = securityKey;
}
public String getMiddleCertPath() {
return middleCertPath;
}
public void setMiddleCertPath(String middleCertPath) {
this.middleCertPath = middleCertPath;
}
public boolean isIfValidateCNName() {
return ifValidateCNName;
}
public void setIfValidateCNName(boolean ifValidateCNName) {
this.ifValidateCNName = ifValidateCNName;
}
public boolean isIfValidateRemoteCert() {
return ifValidateRemoteCert;
}
public void setIfValidateRemoteCert(boolean ifValidateRemoteCert) {
this.ifValidateRemoteCert = ifValidateRemoteCert;
}
public String getSignMethod() {
return signMethod;
}
public void setSignMethod(String signMethod) {
this.signMethod = signMethod;
}
public String getQrcBackTransUrl() {
return qrcBackTransUrl;
}
public void setQrcBackTransUrl(String qrcBackTransUrl) {
this.qrcBackTransUrl = qrcBackTransUrl;
}
public String getQrcB2cIssBackTransUrl() {
return qrcB2cIssBackTransUrl;
}
public void setQrcB2cIssBackTransUrl(String qrcB2cIssBackTransUrl) {
this.qrcB2cIssBackTransUrl = qrcB2cIssBackTransUrl;
}
public String getQrcB2cMerBackTransUrl() {
return qrcB2cMerBackTransUrl;
}
public void setQrcB2cMerBackTransUrl(String qrcB2cMerBackTransUrl) {
this.qrcB2cMerBackTransUrl = qrcB2cMerBackTransUrl;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getFrontUrl() {
return frontUrl;
}
public void setFrontUrl(String frontUrl) {
this.frontUrl = frontUrl;
}
public String getBackUrl() {
return backUrl;
}
public void setBackUrl(String backUrl) {
this.backUrl = backUrl;
}
public String getRootCertPath() {
return rootCertPath;
}
public void setRootCertPath(String rootCertPath) {
this.rootCertPath = rootCertPath;
}
}
五、其他接口如果有操作權限,按照文檔填充代碼:
package com.bdt.etc.recharge;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Map.Entry;
import com.alibaba.fastjson.JSON;
import com.bdt.etc.recharge.sdk.SDKConstants;
import com.dev.util.secret.AesSecret;
public class UnionpayRequstPar
{
public static final String host;
//pc端host
public static final String host2;
//默認配置的是UTF-8
public static String encoding_UTF8 = "UTF-8";
public static String encoding_GBK = "GBK";
//全渠道固定值
public static String version = "5.0.0";
//回調host+"/rechargeCallBack"
public static final String backUrl;//受理方和髮卡方自選填寫的域[O]--後臺通知地址
//後臺服務對應的寫法參照 BackRcvResponse.java
//public static String backUrl = "http://110.249.159.218:9090/Unionpay_AppServer/BackResponse";//受理方和髮卡方自選填寫的域[O]--後臺通知地址
static{
InputStream in = UnionpayRequstPar. class .getResourceAsStream("/acp_sdk.properties");
Properties prop = new Properties();
try {
prop.load(in);
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
host = prop.getProperty("backUrl");
host2 = prop.getProperty("pcBackUrl");
backUrl = host;
}
// 商戶發送交易時間 格式:YYYYMMDDhhmmss
public static String getCurrentTime() {
return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
}
// AN8..40 商戶訂單號,不能含"-"或"_"
public static String getOrderId() {
return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
}
/**
* 組裝請求,返回報文字符串用於顯示
* @param data
* @return
*/
public static String genHtmlResult(Map<String, String> data){
TreeMap<String, String> tree = new TreeMap<String, String>();
Iterator<Entry<String, String>> it = data.entrySet().iterator();
while (it.hasNext()) {
Entry<String, String> en = it.next();
tree.put(en.getKey(), en.getValue());
}
it = tree.entrySet().iterator();
StringBuffer sf = new StringBuffer();
while (it.hasNext()) {
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();
}
/**
* 功能:解析全渠道商戶對賬文件中的ZM文件並以List<Map>方式返回
* 適用交易:對賬文件下載後對文件的查看
* @param filePath ZM文件全路徑
* @return 包含每一筆交易中 序列號 和 值 的map序列
*/
@SuppressWarnings("rawtypes")
public static List<Map> parseZMFile(String filePath){
int lengthArray[] = {3,11,11,6,10,19,12,4,2,21,2,32,2,6,10,13,13,4,15,2,2,6,2,4,32,1,21,15,1,15,32,13,13,8,32,13,13,12,2,1,131};
return parseFile(filePath,lengthArray);
}
/**
* 功能:解析全渠道商戶對賬文件中的ZME文件並以List<Map>方式返回
* 適用交易:對賬文件下載後對文件的查看
* @param filePath ZME文件全路徑
* @return 包含每一筆交易中 序列號 和 值 的map序列
*/
@SuppressWarnings("rawtypes")
public static List<Map> parseZMEFile(String filePath){
int lengthArray[] = {3,11,11,6,10,19,12,4,2,21,2,32,2,6,10,13,13,4,15,2,2,6,2,4,32,1,21,15,1,15,32,13,13,8,32,13,13,12,2,1,131};
return parseFile(filePath,lengthArray);
}
/**
* 功能:解析全渠道商戶 ZM,ZME對賬文件
* @param filePath
* @param lengthArray 參照《全渠道平臺接入接口規範 第3部分 文件接口》 全渠道商戶對賬文件 6.1 ZM文件和6.2 ZME 文件 格式的類型長度組成int型數組
* @return
*/
@SuppressWarnings("rawtypes")
private static List<Map> parseFile(String filePath,int lengthArray[]){
List<Map> ZmDataList = new ArrayList<Map>();
try {
String encoding="UTF-8";
File file=new File(filePath);
if(file.isFile() && file.exists()){ //判斷文件是否存在
InputStreamReader read = new InputStreamReader(
new FileInputStream(file),encoding);//考慮到編碼格式
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
while((lineTxt = bufferedReader.readLine()) != null){
//解析的結果MAP,key爲對賬文件列序號,value爲解析的值
Map<Integer,String> ZmDataMap = new LinkedHashMap<Integer,String>();
//左側遊標
int leftIndex = 0;
//右側遊標
int rightIndex = 0;
for(int i=0;i<lengthArray.length;i++){
rightIndex = leftIndex + lengthArray[i];
String filed = lineTxt.substring(leftIndex,rightIndex);
leftIndex = rightIndex+1;
ZmDataMap.put(i, filed);
}
ZmDataList.add(ZmDataMap);
}
read.close();
}else{
System.out.println("找不到指定的文件");
}
} catch (Exception e) {
System.out.println("讀取文件內容出錯");
e.printStackTrace();
}
/*
for(int i=0;i<ZmDataList.size();i++){
//System.out.println("行數: "+ (i+1));
Map<Integer,String> ZmDataMapTmp = ZmDataList.get(i);
for(Iterator<Integer> it = ZmDataMapTmp.keySet().iterator();it.hasNext();){
Integer key = it.next();
String value = ZmDataMapTmp.get(key);
System.out.println("序號:"+ key + " 值: '"+ value +"'");
}
}*/
return ZmDataList;
}
public static HashMap<String,String> getIosRechargeAskPara(String orderId,String txnAmt,String txnTime,HashMap<String,String> reqReserved)
{
HashMap<String,String>map=new HashMap<String,String>();
map.put("version", version); //版本號,全渠道默認值
map.put("encoding", encoding_UTF8);
map.put("signMethod", "01"); //簽名方法
map.put("txnType", "01"); //交易類型 ,01:消費
map.put("txnSubType", "01"); //交易子類型, 01:自助消費
map.put("bizType", "000201");
map.put("channelType", "08");
/***商戶接入參數***/
map.put("merId", "898130173991161"); //商戶號碼,請改成自己申請的正式商戶號或者open上註冊得來的777測試商戶號
map.put("accessType", "0");
map.put("orderId", orderId);
map.put("txnTime", txnTime);
map.put("accType", "01");
map.put("txnAmt", txnAmt);
map.put("currencyCode", "156");
map.put("reqReserved",AesSecret.encode(JSON.toJSONString(reqReserved)));
map.put("backUrl", backUrl);
return map;
}
public static HashMap<String,String> getRechargeAskPara(String orderId,String txnAmt,HashMap<String, String> reqReserved,String txnTime,String host)
{
HashMap<String,String>map=new HashMap<String,String>();
map.put("orderId",orderId);
map.put("txnAmt", txnAmt);
//map.put("cardNum",cardNum);
map.put("reqReserved",AesSecret.encode(JSON.toJSONString(reqReserved))); //請求方保留域,如需使用請啓用即可;透傳字段(可以實現商戶自定義參數的追蹤)本交易的後臺通知,對本交易的交易狀態查詢交易、對賬文件中均會原樣返回,商戶可以按需上傳,長度爲1-1024個字節。出現&={}[]符號時可能導致查詢接口應答報文解析失敗,建議儘量只傳字母數字並使用|分割,或者可以最外層做一次base64編碼(base64編碼之後出現的等號不會導致解析失敗可以不用管)。
/***銀聯全渠道系統,產品參數,除了encoding自行選擇外其他不需修改***/
map.put("version", version); //版本號,全渠道默認值
map.put("encoding", encoding_UTF8); //字符集編碼,可以使用UTF-8,GBK兩種方式
map.put("signMethod", "01"); //簽名方法
map.put("txnType", "01"); //交易類型 ,01:消費
map.put("txnSubType", "01"); //交易子類型, 01:自助消費
map.put("bizType", "000201"); //業務類型,B2C網關支付,手機wap支付
map.put("channelType", "08"); //渠道類型,這個字段區分B2C網關支付和手機wap支付;07:PC,平板 08:手機
/***商戶接入參數***/
map.put("merId", "898130173991161"); //商戶號碼,請改成自己申請的正式商戶號或者open上註冊得來的777測試商戶號
map.put("accessType", "0"); //接入類型,0:直連商戶
map.put("txnTime",txnTime); //訂單發送時間,取系統時間,格式爲YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效
map.put("currencyCode", "156"); //交易幣種(境內商戶一般是156 人民幣)
//交易金額,單位分,不要帶小數點
//前臺通知地址 (需設置爲外網能訪問 http https均可),支付成功後的頁面 點擊“返回商戶”按鈕的時候將異步通知報文post到該地址
//如果想要實現過幾秒中自動跳轉回商戶頁面權限,需聯繫銀聯業務申請開通自動返回商戶權限
//異步通知參數詳見open.unionpay.com幫助中心 下載 產品接口規範 網關支付產品接口規範 消費交易 商戶通知
map.put("frontUrl", host);
//後臺通知地址(需設置爲【外網】能訪問 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 在後臺通知處理程序驗證簽名之前需要編寫邏輯將這些字段去掉再驗籤,否則將會驗籤失敗
map.put("backUrl", backUrl);
// 訂單超時時間。
// 超過此時間後,除網銀交易外,其他交易銀聯繫統會拒絕受理,提示超時。 跳轉銀行網銀交易如果超時後交易成功,會自動退款,大約5個工作日金額返還到持卡人賬戶。
// 此時間建議取支付時的北京時間加15分鐘。
// 超過超時時間調查詢接口應答origRespCode不是A6或者00的就可以判斷爲失敗。
map.put("payTimeout", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date().getTime() + 15 * 60 * 1000));
return map;
}
public static HashMap<String,String> getPcRechargePara(String orderId,String txnAmt,HashMap<String,String> reqReserved,String txnTime,String host)
{
HashMap<String,String>map=new HashMap<String,String>();
map.put("orderId",orderId);
map.put("txnAmt", txnAmt);
//map.put("cardNum",cardNum);
map.put("reqReserved",AesSecret.encode(JSON.toJSONString(reqReserved))); //請求方保留域,如需使用請啓用即可;透傳字段(可以實現商戶自定義參數的追蹤)本交易的後臺通知,對本交易的交易狀態查詢交易、對賬文件中均會原樣返回,商戶可以按需上傳,長度爲1-1024個字節。出現&={}[]符號時可能導致查詢接口應答報文解析失敗,建議儘量只傳字母數字並使用|分割,或者可以最外層做一次base64編碼(base64編碼之後出現的等號不會導致解析失敗可以不用管)。
/***銀聯全渠道系統,產品參數,除了encoding自行選擇外其他不需修改***/
map.put("version", version); //版本號,全渠道默認值
map.put("encoding", encoding_UTF8); //字符集編碼,可以使用UTF-8,GBK兩種方式
map.put("signMethod", "01"); //簽名方法
map.put("txnType", "01"); //交易類型 ,01:消費
map.put("txnSubType", "01"); //交易子類型, 01:自助消費
map.put("bizType", "000201"); //業務類型,B2C網關支付,手機wap支付
map.put("channelType", "08"); //渠道類型,這個字段區分B2C網關支付和手機wap支付;07:PC,平板 08:手機
/***商戶接入參數***/
map.put("merId", "898130173991161"); //商戶號碼,請改成自己申請的正式商戶號或者open上註冊得來的777測試商戶號
map.put("accessType", "0"); //接入類型,0:直連商戶
map.put("txnTime",txnTime); //訂單發送時間,取系統時間,格式爲YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效
map.put("currencyCode", "156"); //交易幣種(境內商戶一般是156 人民幣)
//交易金額,單位分,不要帶小數點
//前臺通知地址 (需設置爲外網能訪問 http https均可),支付成功後的頁面 點擊“返回商戶”按鈕的時候將異步通知報文post到該地址
//如果想要實現過幾秒中自動跳轉回商戶頁面權限,需聯繫銀聯業務申請開通自動返回商戶權限
//異步通知參數詳見open.unionpay.com幫助中心 下載 產品接口規範 網關支付產品接口規範 消費交易 商戶通知
map.put("frontUrl", host);
//後臺通知地址(需設置爲【外網】能訪問 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 在後臺通知處理程序驗證簽名之前需要編寫邏輯將這些字段去掉再驗籤,否則將會驗籤失敗
map.put("backUrl", backUrl);
// 訂單超時時間。
// 超過此時間後,除網銀交易外,其他交易銀聯繫統會拒絕受理,提示超時。 跳轉銀行網銀交易如果超時後交易成功,會自動退款,大約5個工作日金額返還到持卡人賬戶。
// 此時間建議取支付時的北京時間加15分鐘。
// 超過超時時間調查詢接口應答origRespCode不是A6或者00的就可以判斷爲失敗。
map.put("payTimeout", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date().getTime() + 15 * 60 * 1000));
return map;
}
}