背景
商城項目客戶需要提現(xiàn)功能,之前沒有對接過,也遇到了一些小問題,防止以后出問題,這里做下簡單記錄。第一次寫可能不是特別好,希望大家能夠指出,一起進步。
準備
-
獲取微信商戶證書
獲取方式:微信商戶后臺-》賬戶中心-》API安全-》申請證書
-
微信證書轉16進制字符串存儲(感謝 CS*N-代碼風)
try {
FileInputStream file = new FileInputStream("E://xxx.p12");
String s1 = Hex.encodeHexString(StreamUtils.copyToByteArray(file));
System.out.println(s1);
} catch (Exception e) {
e.printStackTrace();
}
}
image.png
-
商戶APIkey
微信商戶后臺-》賬戶中心-》API安全-》API秘鑰(沒有的話生成一個)
使用條件
- 商戶號(或同主體其他非服務商商戶號)已入駐90日
- 截止今日回推30天,商戶號(或同主體其他非服務商商戶號)連續(xù)不間斷保持有交易
- 登錄微信支付商戶平臺-產(chǎn)品中心,開通企業(yè)付款。
(否則接口會返回沒有權限,而且需要注意的是,未達到條件的微信商戶,無法在產(chǎn)品中心看到該功能)
1.企業(yè)付款到零錢
- API調用類
/**
* 企業(yè)付款到零錢
* @param vo
* @param mchApiKey
* 必傳參數(shù)
* vo => mch_appid 申請商戶號的appid或商戶號綁定的appid 微信appid 小程序appid
* mchid 商戶號id
* partner_trade_no 商戶訂單號
* openid 用戶openid
* amount 金額 單位 分
* desc 備注
* @return
*/
public static Map<String,Object> cashTransfers(TransfresParamsVo vo, String mchApiKey){
Map<String,Object> returnMap = null; //返回結果
try {
//計算簽名
vo.setNonce_str(RandomUtil.randomString(32)); //隨機字符串
//實體類轉map 工具包 hutool
Map<String,Object> paramMap = BeanUtil.beanToMap(vo);
//獲取簽名
String sign = WechatSginUtils.getWechatPaySignStr(paramMap , mchApiKey);
vo.setSign(sign); //設置簽名
//對象轉xml ture:是否去掉默認報文頭 true去掉
String apiParamXml = XmlUtils.beanToXml(vo, TransfresParamsVo.class, true);
logger.info("transfresParams:{}", apiParamXml);
//提交請求
String reponseStr = HttpRequest.sendP12PostRequest(WECHAT_TRANSFRES_API, WECHAT_CRET_P12, apiParamXml, vo.getMchid());
//xml轉map
returnMap = XmlUtils.xml2map(reponseStr, false);
} catch (JAXBException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return returnMap;
}
- 參數(shù)實體類
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 微信提現(xiàn)到零錢參數(shù)
*/
@XmlRootElement(name = "xml") //實體轉xml時的根節(jié)點
public class TransfresParamsVo {
private String mch_appid; //申請商戶號的appid或商戶號綁定的appid 微信appid 小程序appid
private String mchid; //商戶號id
private String nonce_str; //隨機字符串
private String sign; //簽名
private String partner_trade_no; //商戶訂單號
private String openid; //用戶openid
private String check_name = "NO_CHECK"; //校驗用戶姓名選項 NO_CHECK 不校驗真實姓名 FORCE_CHECK:強校驗真實姓名
private int amount; //金額 單位 分
private String desc; //備注
@XmlElement(name="mch_appid")
public String getMch_appid() {
return mch_appid;
}
public void setMch_appid(String mch_appid) {
this.mch_appid = mch_appid;
}
@XmlElement(name="mchid")
public String getMchid() {
return mchid;
}
public void setMchid(String mchid) {
this.mchid = mchid;
}
@XmlElement(name="nonce_str")
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
@XmlElement(name="sign")
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
@XmlElement(name="partner_trade_no")
public String getPartner_trade_no() {
return partner_trade_no;
}
public void setPartner_trade_no(String partner_trade_no) {
this.partner_trade_no = partner_trade_no;
}
@XmlElement(name="openid")
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
@XmlElement(name="check_name")
public String getCheck_name() {
return check_name;
}
public void setCheck_name(String check_name) {
this.check_name = check_name;
}
@XmlElement(name="amount")
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@XmlElement(name="desc")
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
2.企業(yè)付款到銀行卡
接口: https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
是否需要證書:需要
按照常用慣例,得吐槽一下,微信文檔,真的有點折磨人,本來倆個小時搞定的事情,偏偏因為一個小問題多花了一個小時,微信文檔真不適合小白看。
與付款到零錢不同,付款到銀行卡需要提供 銀行卡號,收款方用戶名(廢話),且在微信傳參時 RSA加密,而這個RSA加密,需要調用 接口 獲取 微信方的RSA公鑰;然后按照下面的方式,對字符進行處理:
- 調用獲取RSA公鑰API獲取RSA公鑰,落地成本地文件,假設為public.pem
- 確定public.pem文件的存放路徑,同時修改代碼中文件的輸入路徑,加載RSA公鑰
- 用標準的RSA加密庫對敏感信息進行加密,選擇RSA_PKCS1_OAEP_PADDING填充模式
(eg:Java的填充方式要選 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING")- 得到進行rsa加密并轉base64之后的密文
- 將密文傳給微信側相應字段,如付款接口(enc_bank_no/enc_true_name)
(我星星特m的星星)
- 獲取微信RSA公鑰
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("mch_id","***");
map.put("nonce_str",RandomUtil.randomString(32));
map.put("sign_type","MD5");
String sign =WechatSginUtils.getWechatPaySignStr(map, "*****");
map.put("sign", sign);
Map<String, Object> map2 = map;
String apiParamXml = XmlUtils.map2XmlString(map2); //對象轉xml
//帶證書請求獲取RSA公鑰
String reponseStr = HttpRequest.sendP12PostRequest("https://fraud.mch.weixin.qq.com/risk/getpublickey", WECHAT_CRET_P12, apiParamXml, "1584991451");
System.out.println(reponseStr);
}
- 獲取到的RSA公鑰轉一下 PKCS#8 這里我用的網(wǎng)頁轉的:傳送門
- 轉換前:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQC9XrJWcWbj0LhDBzN4uwEOLA/UJKmCkkbvlVgN/qei3e/jVFpx
R6D3fzshnv5QNB4+BJ/rjRWbbxCJ0djzPxsLS1dJ+bDwagZWZ9hNXARTq4K0uxw6
Ol5jGD9Od6w5n5uxyaEk9/edvYwMhthIxC/uADRp2pNSutwyLX3bUJnHZwIDAQAB
AoGANN3S+7788my6hDvmarYKPWKfqKHzkLg1hX0z7/Q/6H/9EIHkHevZTD8AywoQ
BWQHbVjtLF1ewt3myBMFdiMP8UOx0WVErcyuVRh8AUcRZIEwz73jmLmpRd8fVAzy
8uoijKvExt/fdu9aIfVmV4nXvL5dDpsoL/mVRDgNCZ+9mMECQQDzWLnqty25mgEs
73rJ8mhehifwblg44uO+9xpmKZhG3NFZW+beG1iPZklBVlaQ6m53e77VbVotC+LF
efsaOtU7AkEAxzd3q0REhF/FaFcq9TV3Eu3C4B/aqARKgkpJKiaCC4tnAqny7Rvd
/anxLBf8DFPYjPMkPrNqXoDA8rAC9TwDxQJBAPF6mHOMdvl5E7WNp6GCxYMXScbT
GQTKUgoMl8vNdujK84vjIMRDCqyyaftGO/zuRdSXnZWZQCT3aH9iPoWW4EUCQB1r
NYLXK/8YXYCRDsjzQkhLUDHkwld5er9O1QsicKXfyjB8hGE7ckbZZ8IJMLFpWFtI
NJwFxrl57gRotacdW7kCP2r3MkJqtHdrjUbaCJJCnHmX9BhYcBhaYS2yGFW9uyNT
5TGOrrzjz+CXBNrif3JkDbDYv2z/cCgd7kqV1kPl/g==
-----END RSA PRIVATE KEY-----
- 轉換后
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1eslZxZuPQuEMH
M3i7AQ4sD9QkqYKSRu+VWA3+p6Ld7+NUWnFHoPd/OyGe/lA0Hj4En+uNFZtvEInR
2PM/GwtLV0n5sPBqBlZn2E1cBFOrgrS7HDo6XmMYP053rDmfm7HJoST39529jAyG
2EjEL+4ANGnak1K63DItfdtQmcdnAgMBAAECgYA03dL7vvzybLqEO+Zqtgo9Yp+o
ofOQuDWFfTPv9D/of/0QgeQd69lMPwDLChAFZAdtWO0sXV7C3ebIEwV2Iw/xQ7HR
ZUStzK5VGHwBRxFkgTDPveOYualF3x9UDPLy6iKMq8TG399271oh9WZXide8vl0O
mygv+ZVEOA0Jn72YwQJBAPNYueq3LbmaASzvesnyaF6GJ/BuWDji4773GmYpmEbc
0Vlb5t4bWI9mSUFWVpDqbnd7vtVtWi0L4sV5+xo61TsCQQDHN3erRESEX8VoVyr1
NXcS7cLgH9qoBEqCSkkqJoILi2cCqfLtG939qfEsF/wMU9iM8yQ+s2pegMDysAL1
PAPFAkEA8XqYc4x2+XkTtY2noYLFgxdJxtMZBMpSCgyXy8126Mrzi+MgxEMKrLJp
+0Y7/O5F1JedlZlAJPdof2I+hZbgRQJAHWs1gtcr/xhdgJEOyPNCSEtQMeTCV3l6
v07VCyJwpd/KMHyEYTtyRtlnwgkwsWlYW0g0nAXGuXnuBGi1px1buQI/avcyQmq0
d2uNRtoIkkKceZf0GFhwGFphLbIYVb27I1PlMY6uvOPP4JcE2uJ/cmQNsNi/bP9w
KB3uSpXWQ+X+
-----END PRIVATE KEY-----
-
獲取到pks8私鑰后你可以轉存文件xxx.pem,或者用靜態(tài)常量存儲調用,常量存儲需要去掉-----BEGIN PRIVATE KEY----- -----END PRIVATE KEY-----,只留下中間的字符
image.png API調用
/**
* 企業(yè)付款到銀行卡
* @param vo
* @param mchApiKey
* @return
*/
public static Map<String, Object> cashPayBank(CashPayBankVo vo, String mchApiKey){
Map<String, Object> returnMap = null; //返回結果
try {
//銀行卡用戶名稱 RSA加密
String enctrueName = WechatRsaUtils.encrypt(vo.getEnc_true_name().getBytes("UTF-8"), WechatRsaUtils.loadPublicKey(WECHAT_PUB_KEY));//rsa公鑰加密 用戶名稱
String encBankNo = WechatRsaUtils.encrypt(vo.getEnc_bank_no().getBytes("UTF-8"), WechatRsaUtils.loadPublicKey(WECHAT_PUB_KEY)); //rsa公鑰加密 用戶銀行卡
vo.setEnc_true_name(Base64.encode(enctrueName)); //用戶名稱 base64
vo.setEnc_bank_no(Base64.encode(encBankNo)); //用戶銀行卡 base64
vo.setNonce_str(RandomUtil.randomString(32)); //隨機字符串
//獲取簽名
vo.setSign(WechatSginUtils.getWechatPaySignStr(BeanUtil.beanToMap(vo), mchApiKey)); //簽名
//對象轉xml
String apiParamXml = XmlUtils.beanToXml(vo, CashPayBankVo.class, true); //對象轉xml
logger.info("cashPayBank:{}", apiParamXml);
//提交請求
String reponseStr = HttpRequest.sendP12PostRequest(WECHAT_PAYBANK_API, WECHAT_CRET_P12, apiParamXml, vo.getMch_id());
//xml轉map
returnMap = XmlUtils.xml2map(reponseStr, false);
} catch (Exception e) {
e.printStackTrace();
}
return returnMap;
}
- 參數(shù)實體類
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 企業(yè)付款到銀行卡 參數(shù)對象
*/
@XmlRootElement(name = "xml")
public class CashPayBankVo {
private String mch_id; //商戶號
private String partner_trade_no; //商戶企業(yè)付款單號
private String nonce_str; //隨機字符串
private String sign; //簽名
private String enc_bank_no; //收款方銀行卡號
private String enc_true_name; //收款方用戶名
private String bank_code; //收款方開戶行
private int amount; //付款金額 單位 分
private String desc; //付款說明
@XmlElement(name="sign")
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
@XmlElement(name="amount")
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@XmlElement(name="desc")
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@XmlElement(name="mch_id")
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
@XmlElement(name="partner_trade_no")
public String getPartner_trade_no() {
return partner_trade_no;
}
public void setPartner_trade_no(String partner_trade_no) {
this.partner_trade_no = partner_trade_no;
}
@XmlElement(name="nonce_str")
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
@XmlElement(name="enc_bank_no")
public String getEnc_bank_no() {
return enc_bank_no;
}
public void setEnc_bank_no(String enc_bank_no) {
this.enc_bank_no = enc_bank_no;
}
@XmlElement(name="enc_true_name")
public String getEnc_true_name() {
return enc_true_name;
}
public void setEnc_true_name(String enc_true_name) {
this.enc_true_name = enc_true_name;
}
@XmlElement(name="bank_code")
public String getBank_code() {
return bank_code;
}
public void setBank_code(String bank_code) {
this.bank_code = bank_code;
}
}
3.工具類
工具包:Hutool
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.9</version>
</dependency>
- xml工具類
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.*;
/**
* xml工具類
*/
public class XmlUtils {
/**
* 實體轉xml
* @param obj
* @param load
* @param is_fragment 是否去掉默認報文頭
* @return
* @throws JAXBException
*/
public static String beanToXml(Object obj, Class<?> load, boolean is_fragment) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(load);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, is_fragment);
StringWriter writer = new StringWriter();
marshaller.marshal(obj,writer);
return writer.toString();
}
/**
* xml字符轉對象
* @param xmlStr
* @param load
* @return
* @throws JAXBException
*/
public static Object xmlToBean(String xmlStr, Class<?> load) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(load);
// 進行將Xml轉成對象的核心接口
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader sr = new StringReader(xmlStr);
return unmarshaller.unmarshal(sr);
}
/**
* map 轉xml
* @param map
* @return
*/
public static String map2XmlString(Map<String, Object> map) {
String xmlResult = "";
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
for (String key : map.keySet()) {
String value = "<![CDATA[" + map.get(key) + "]]>";
sb.append("<" + key + ">" + value + "</" + key + ">");
}
sb.append("</xml>");
xmlResult = sb.toString();
return xmlResult;
}
/**
* xml轉map 不帶屬性
* @param xmlStr
* @param needRootKey 是否需要在返回的map里加根節(jié)點鍵
* @return
*/
public static Map xml2map(String xmlStr, boolean needRootKey) {
Map<String, Object> map = null;
try {
Document doc = DocumentHelper.parseText(xmlStr);
Element root = doc.getRootElement();
map = (Map<String, Object>) xml2map(root);
if(root.elements().size()==0 && root.attributes().size()==0){
return map;
}
if(needRootKey){
//在返回的map里加根節(jié)點鍵(如果需要)
Map<String, Object> rootMap = new HashMap<String, Object>();
rootMap.put(root.getName(), map);
return rootMap;
}
} catch (DocumentException e) {
e.printStackTrace();
}
return map;
}
/**
* xml轉map 不帶屬性
* @param e
* @return
*/
private static Map xml2map(Element e) {
Map map = new LinkedHashMap();
List list = e.elements();
if (list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
Element iter = (Element) list.get(i);
List mapList = new ArrayList();
if (iter.elements().size() > 0) {
Map m = xml2map(iter);
if (map.get(iter.getName()) != null) {
Object obj = map.get(iter.getName());
if (!(obj instanceof List)) {
mapList = new ArrayList();
mapList.add(obj);
mapList.add(m);
}
if (obj instanceof List) {
mapList = (List) obj;
mapList.add(m);
}
map.put(iter.getName(), mapList);
} else
map.put(iter.getName(), m);
} else {
if (map.get(iter.getName()) != null) {
Object obj = map.get(iter.getName());
if (!(obj instanceof List)) {
mapList = new ArrayList();
mapList.add(obj);
mapList.add(iter.getText());
}
if (obj instanceof List) {
mapList = (List) obj;
mapList.add(iter.getText());
}
map.put(iter.getName(), mapList);
} else
map.put(iter.getName(), iter.getText());
}
}
} else
map.put(e.getName(), e.getText());
return map;
}
}
- 微信簽名工具類
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.jeespring.common.security.MD5Tools;
import com.jeespring.common.weike.wechat.config.WechatApiContext;
import com.jeespring.common.weike.wechat.vo.pay.WechatSignVo;
import java.util.*;
public class WechatSginUtils {
/**
* 獲取微信支付簽名
* @param paramMap
* @param mchApiKey
* @return
* @throws Exception
*/
public static String getWechatPaySignStr(Map<String,Object> paramMap ,String mchApiKey) throws Exception{
StringBuffer sbuff = new StringBuffer();
//字典排序
List<String> paramsList = new ArrayList<>(paramMap.keySet());
Collections.sort(paramsList);
for (int i = 0; i < paramsList.size(); i++){
String key = paramsList.get(i);
Object val = paramMap.get(key);
if (val != null){
sbuff.append(key);
sbuff.append("=");
sbuff.append(val);
sbuff.append("&");
}
}
//拼接商戶APIkey
sbuff.append("key=".concat(mchApiKey));
//簽名MD5轉大寫加密
String sign = MD5Tools.MD5(sbuff.toString()).toUpperCase();
return sign;
}
/**
* 預支付返回簽名
* @param vo
* @param mchApiKey
* @throws Exception
*/
public static void getWechatReturnSgin(WechatSignVo vo , String mchApiKey) throws Exception{
StringBuffer sbuff = new StringBuffer();
//隨機字符串
vo.setNonceStr(RandomUtil.randomString(32));
//字典排序
Map<String,Object> paramMap = BeanUtil.beanToMap(vo);
List<String> paramsList = new ArrayList<>(paramMap.keySet());
Collections.sort(paramsList);
for (int i = 0; i < paramsList.size(); i++){
String key = paramsList.get(i);
Object val = paramMap.get(key);
if (val != null){
if ((WechatApiContext.WECHAT_PAY_SGIN_PACKAGE_SGINSTR.concat("Str")).equals(key)){
key = WechatApiContext.WECHAT_PAY_SGIN_PACKAGE_SGINSTR;
}
sbuff.append(key);
sbuff.append("=");
sbuff.append(val);
sbuff.append("&");
}
}
//拼接商戶APIkey
sbuff.append("key=".concat(mchApiKey));
//簽名MD5轉大寫加密
String sign = MD5Tools.MD5(sbuff.toString()).toUpperCase();
vo.setPaySign(sign);
}
}
- RSA工具類
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import static com.jeespring.common.utils.Encodes.decodeBase64;
public class WechatRsaUtils {
private static String RSA = "RSA";
private static final int KEYLENGTH = 2048;
private static final int RESERVESIZE = 11;
/**
* 指定填充模式
*/
private static final String CIPHERALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
/**
* 用公鑰加密 <br>
* 每次加密的字節(jié)數(shù),不能超過密鑰的長度值減去11
*
* @param plainBytes 需加密數(shù)據(jù)的byte數(shù)據(jù)
* @param publicKey 公鑰
* @return 加密后的byte型數(shù)據(jù)
*/
public static String encrypt(byte[] plainBytes, PublicKey publicKey) throws Exception {
int keyByteSize = KEYLENGTH / 8;
int encryptBlockSize = keyByteSize - RESERVESIZE;
int nBlock = plainBytes.length / encryptBlockSize;
if ((plainBytes.length % encryptBlockSize) != 0) {
nBlock += 1;
}
ByteArrayOutputStream outbuf = null;
try {
Cipher cipher = Cipher.getInstance(CIPHERALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {
int inputLen = plainBytes.length - offset;
if (inputLen > encryptBlockSize) {
inputLen = encryptBlockSize;
}
byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
outbuf.write(encryptedBlock);
}
outbuf.flush();
byte[] encryptedData = outbuf.toByteArray();
return Base64.encodeBase64String(encryptedData);
} catch (Exception e) {
throw new Exception("ENCRYPT ERROR:", e);
} finally {
try {
if (outbuf != null) {
outbuf.close();
}
} catch (Exception e) {
throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
}
}
}
/**
* 從字符串中加載公鑰
*
* @param publicKeyStr 公鑰數(shù)據(jù)字符串
* @throws Exception 加載公鑰時產(chǎn)生的異常
*/
public static PublicKey loadPublicKey(String publicKeyStr){
PublicKey publicKey = null;
try {
byte[] buffer = decodeBase64(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
publicKey = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
return publicKey;
}
}
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
public class HttpRequest {
/**
* 向指定URL發(fā)送GET方法的請求
*
* @param url
* 發(fā)送請求的URL
* @param param
* 請求參數(shù),請求參數(shù)應該是 name1=value1&name2=value2 的形式。
* @return URL 所代表遠程資源的響應結果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打開和URL之間的連接
URLConnection connection = realUrl.openConnection();
// 設置通用的請求屬性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立實際的連接
connection.connect();
// 獲取所有響應頭字段
//Map<String, List<String>> map = connection.getHeaderFields();
// 遍歷所有的響應頭字段
//for (String key : map.keySet()) {
// System.out.println(key + "--->" + map.get(key));
//}
// 定義 BufferedReader輸入流來讀取URL的響應
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("發(fā)送GET請求出現(xiàn)異常!" + e.toString());
result="Down";
//e.printStackTrace();
}
// 使用finally塊來關閉輸入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 發(fā)送POST方法的請求
*
* @param url
* 發(fā)送請求的 URL
* @param param
* 請求參數(shù),請求參數(shù)應該是 name1=value1&name2=value2 的形式。
* @return 所代表遠程資源的響應結果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設置通用的請求屬性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 發(fā)送POST請求必須設置如下兩行
conn.setDoOutput(true);
conn.setDoInput(true);
// 獲取URLConnection對象對應的輸出流
out = new PrintWriter(conn.getOutputStream());
// 發(fā)送請求參數(shù)
out.print(param);
// flush輸出流的緩沖
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("發(fā)送 POST 請求出現(xiàn)異常!"+e.toString());
//e.printStackTrace();
}
//使用finally塊來關閉輸出流、輸入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
public static String sendP12PostRequest(String url, String cretCode, String param, String cretkey){
CloseableHttpClient client = null;
HttpPost httpPost = null;
try {
//解析證書
byte[] bytes = Hex.decodeHex(cretCode.toCharArray()); //解密出16進制原證書文件內容為字節(jié)數(shù)組
ByteArrayInputStream input = new ByteArrayInputStream(bytes); //讀取字節(jié)數(shù)組
KeyStore clientTrustKeyStore = KeyStore.getInstance("PKCS12"); //獲取PKCS12秘鑰庫實例
clientTrustKeyStore.load(input, cretkey.toCharArray()); //秘鑰解析
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientTrustKeyStore, cretkey.toCharArray());
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(kmf.getKeyManagers(), tm, new java.security.SecureRandom());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
client = HttpClients.custom().setSSLSocketFactory(sslsf).build();
httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(param, "utf-8"));
CloseableHttpResponse response = client.execute(httpPost);
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() == 200) {
return EntityUtils.toString(entity, "utf-8");
}
} catch (DecoderException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
public static String getParameterMapString(HttpServletRequest request){
if(request.getQueryString()!=null){
if(request.getQueryString().length()>0){
return request.getQueryString();
}
}
Map map = request.getParameterMap();
java.util.Enumeration enumx = request.getParameterNames();
String result="";
while(enumx.hasMoreElements()){
String paramName=(String)enumx.nextElement();
String[] values=request.getParameterValues(paramName);
for(int i=0;i<values.length;i++){
result+=paramName+"="+values[i]+"&";
}
}
return result;
}
private static class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}