記一次微信支付JSAPI支付功能集成。
JSAPI支付前提是必須在微信環(huán)境中(公眾號(hào)艰额、聊天界面打開鏈接)臂港,否則無(wú)法調(diào)起支付卿捎。小程序webview控件中也無(wú)法調(diào)起支付。
準(zhǔn)備工作:
1.首先在微信商戶號(hào)中開通JSAPI支付功能(ps:我的一打開就是開通的径密,可能之前的同事開通的午阵,so開通流程無(wú)法復(fù)現(xiàn))。開通方式如下圖:
2.申請(qǐng)開通之后在開發(fā)配置中添加域名,按照提示添加即可底桂。
3.然后登錄微信公眾號(hào)后臺(tái)植袍,左側(cè)菜單欄最下方,點(diǎn)擊接口權(quán)限籽懦,然后左側(cè)找到網(wǎng)頁(yè)授權(quán)于个,點(diǎn)擊其右邊修改,在到新頁(yè)面網(wǎng)頁(yè)授權(quán)域名欄點(diǎn)右邊設(shè)置暮顺,添加自己的支付鏈接域名厅篓。步驟圖示:
準(zhǔn)備工作完成。
開發(fā)工作 使用vue寫的頁(yè)面
1.由于JSAPI支付時(shí)需要用戶openid捶码,所以先獲取openid
1.1 在頁(yè)面js中加入以下代碼:
reload(){
let redirect_uri = window.location.href;
let state = window.location.href;
window.location.
}
代碼中的API.APPID要換成自己的公眾號(hào)AppId羽氮,其他字段可繼續(xù)使用。
scope參數(shù)的值有兩個(gè)可選惫恼,一個(gè)是snsapi_base档押,另一個(gè)是snsapi_userinfo。
關(guān)于網(wǎng)頁(yè)授權(quán)的兩種scope的區(qū)別說(shuō)明
1.1.1祈纯、以snsapi_base為scope發(fā)起的網(wǎng)頁(yè)授權(quán)令宿,是用來(lái)獲取進(jìn)入頁(yè)面的用戶的openid的,并且是靜默授權(quán)并自動(dòng)跳轉(zhuǎn)到回調(diào)頁(yè)的腕窥。用戶感知的就是直接進(jìn)入了回調(diào)頁(yè)(往往是業(yè)務(wù)頁(yè)面)
1.1.2粒没、以snsapi_userinfo為scope發(fā)起的網(wǎng)頁(yè)授權(quán),是用來(lái)獲取用戶的基本信息的油昂。但這種授權(quán)需要用戶手動(dòng)同意革娄,并且由于用戶同意過(guò),所以無(wú)須關(guān)注冕碟,就可在授權(quán)后獲取該用戶的基本信息拦惋。
這里我們只是獲取用戶openid,無(wú)需用戶手動(dòng)同意安寺,所以用snsapi_base厕妖。
在頁(yè)面打開時(shí)判斷openid是否已獲取,未獲取時(shí)調(diào)用reload()方法挑庶。
initData(){
let self = this
if(self.getQueryParam("code")){
let code = self.getQueryParam("code") //getQueryParam()方法在下方
API.request({ //api.js 文件在下方言秸。
url:"自己的后臺(tái)接口",
type:'請(qǐng)求方式', //get post
data:{
code:code //頁(yè)面通過(guò)reload()方法獲取到的code 重定向后參數(shù)是拼接在頁(yè)面鏈接上的 需要自己獲取 。
},
success:res=>{
if(res.errcode === 200 && res.data != undefined){
self.$data.openID = res.data
}else{
self.reload();
}
}
})
}else{
self.reload()
}
}
getQueryParam(variable){
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){
return pair[1];
}
}
return(false);
}
后臺(tái)通過(guò)前端傳的code參數(shù)迎捺,獲取到用戶openid后返回給前端保存举畸。
2.下單
用戶點(diǎn)擊頁(yè)面支付功能后,前端調(diào)用后臺(tái)接口生成預(yù)付單并返回?cái)?shù)據(jù)凳枝,前端解析詩(shī)句獲取各種參數(shù)然后入下:
pay(){
let self = this
API.request({
url:"自己的下單接口",
type:'POST',
data:{
//下單需要的參數(shù)
},
success:res=>{
if(res.errcode === 200){
let data = res.data
//下面代碼調(diào)起微信支付
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":data .appid, //公眾號(hào)id
"timeStamp":data .timeStamp, //時(shí)間戳抄沮,自1970年以來(lái)的秒數(shù)
"nonceStr":data .nonceStr, //隨機(jī)串
"package":data .package,
"signType":"MD5", //微信簽名方式:通用參數(shù) 可不改
"paySign":data .paySign //微信簽名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
// 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:
//res.err_msg將在用戶支付成功后返回ok跋核,但并不保證它絕對(duì)可靠。
//支付成功 請(qǐng)求接口確認(rèn) 刷新頁(yè)面
}
});
}else {
//失敗處理
}
}
})
}
前端代碼完成叛买。
后臺(tái)代碼:
1.獲取openid
/**
* 網(wǎng)頁(yè)支付 獲取openid
*
* @param code
* @return
*/
@PostMapping("getOpenID")
private String getOpenID(@RequestParam("code") String code) {
JSONObject accessToken = getAccessToken(code);
return accessToken.getString("openid");
}
public static JSONObject getAccessToken(String code){
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="公眾號(hào)AppID"&secret="公眾號(hào)秘鑰"&code="+code+"&grant_type=authorization_code";
String result = HttpUtils.httpGet(url);
JSONObject data = com.alibaba.fastjson.JSON.parseObject(result);
return data;
}
/**
* 發(fā)送get請(qǐng)求
* @param url 路徑
* @return
*/
public static String httpGet(String url){
//get請(qǐng)求返回結(jié)果
String strResult = null;
try {
DefaultHttpClient client = new DefaultHttpClient();
//發(fā)送get請(qǐng)求
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
/**請(qǐng)求發(fā)送成功砂代,并得到響應(yīng)**/
if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
/**讀取服務(wù)器返回過(guò)來(lái)的json字符串?dāng)?shù)據(jù)**/
strResult = EntityUtils.toString(response.getEntity(),"UTF-8");
} else {
}
} catch (IOException e) {
}
return strResult;
}
獲取openid完成。
- 調(diào)用微信支付統(tǒng)一下單接口
2.1 payUtils工具類
import org.apache.commons.codec.digest.DigestUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.json.JSONObject;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
public class PayUtil {
public static String APP_ID = "";
public static JSONObject wxPay(String appID, String openid, String bodys, String orderNos, String price, String notify_url) {
JSONObject json = new JSONObject();
try {
//生成的隨機(jī)字符串
String nonce_str = Utils.genNonceStr();
//獲取本機(jī)的ip地址
String spbill_create_ip = "127.0.0.1";
Map<String, String> packageParams = new HashMap<String, String>();
packageParams.put("appid", appID);
packageParams.put("mch_id", WXPayUtil.MCH_ID);
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", bodys);//商品名稱
packageParams.put("out_trade_no", orderNos);//商戶訂單號(hào)
packageParams.put("total_fee", price);
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", "JSAPI");
packageParams.put("openid", openid);
// 除去數(shù)組中的空值和簽名參數(shù)
packageParams = paraFilter(packageParams);
String prestr = createLinkString(packageParams); // 把數(shù)組所有元素率挣,按照“參數(shù)=參數(shù)值”的模式用“&”字符拼接成字符串
//MD5運(yùn)算生成簽名刻伊,這里是第一次簽名,用于調(diào)用統(tǒng)一下單接口
String mysign = sign(prestr, WXPayUtil.API_KEY, "utf-8").toUpperCase();
// System.out.println("=======================第一次簽名:" + mysign + "=====================");
//拼接統(tǒng)一下單接口使用的xml數(shù)據(jù)椒功,要將上一步生成的簽名一起拼接進(jìn)去
String xml = "<xml version='1.0' encoding='gbk'>" + "<appid>" + appID + "</appid>"
+ "<body><![CDATA[" + bodys + "]]></body>"
+ "<mch_id>" + WXPayUtil.MCH_ID + "</mch_id>"
+ "<nonce_str>" + nonce_str + "</nonce_str>"
+ "<notify_url>" + notify_url + "</notify_url>"
+ "<openid>" + openid + "</openid>"
+ "<out_trade_no>" + orderNos + "</out_trade_no>"
+ "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
+ "<total_fee>" + price + "</total_fee>"
+ "<trade_type>" + "JSAPI" + "</trade_type>"
+ "<sign>" + mysign + "</sign>"
+ "</xml>";
// System.out.println("調(diào)試模式_統(tǒng)一下單接口 請(qǐng)求XML數(shù)據(jù):" + xml);
//調(diào)用統(tǒng)一下單接口捶箱,并接受返回的結(jié)果
String result = httpRequest(pay_url, "POST", xml);
// System.out.println("調(diào)試模式_統(tǒng)一下單接口 返回XML數(shù)據(jù):" + result);
// 將解析結(jié)果存儲(chǔ)在HashMap中
Map map = doXMLParse(result);
// System.out.println("map:"+map);
String return_code = (String) map.get("return_code");//返回狀態(tài)碼
//返回給移動(dòng)端需要的參數(shù)
Map<String, Object> response = new HashMap<String, Object>();
if (return_code == "SUCCESS" || return_code.equals(return_code)) {
// 業(yè)務(wù)結(jié)果
String prepay_id = (String) map.get("prepay_id");//返回的預(yù)付單信息
// System.out.println("prepay_id:"+prepay_id);
response.put("nonceStr", nonce_str);
response.put("package", "prepay_id=" + prepay_id);
Long timeStamp = System.currentTimeMillis() / 1000;
response.put("timeStamp", timeStamp + "");//這邊要將返回的時(shí)間戳轉(zhuǎn)化成字符串,不然小程序端調(diào)用wx.requestPayment方法會(huì)報(bào)簽名錯(cuò)誤
String stringSignTemp = "appId=" + appID + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=" + "MD5" + "&timeStamp=" + timeStamp;
//再次簽名蛾茉,這個(gè)簽名用于小程序端調(diào)用wx.requesetPayment方法
String paySign = sign(stringSignTemp, WXPayUtil.API_KEY, "utf-8").toUpperCase();
System.out.print("=======================第二次簽名:" + paySign + "=====================");
response.put("paySign", paySign);
//更新訂單信息
//業(yè)務(wù)邏輯代碼
}
response.put("appid", appID);
json.put("errMsg", "OK");
json.put("data", response);
} catch (Exception e) {
e.printStackTrace();
json.put("errMsg", "Failed");
}
return json;
}
/**
* 簽名字符串
*
* @param text 需要簽名的字符串
* @param key 密鑰
* @param input_charset 編碼格式
* @return 簽名結(jié)果
*/
public static String sign(String text, String key, String input_charset) {
text = text + "&key=" + key;
return DigestUtils.md5Hex(getContentBytes(text, input_charset));
}
/**
* 簽名字符串
*
* @param text 需要簽名的字符串
* @param sign 簽名結(jié)果
* @param key 密鑰
* @param input_charset 編碼格式
* @return 簽名結(jié)果
*/
public static boolean verify(String text, String sign, String key, String input_charset) {
text = text + key;
String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
if (mysign.equals(sign)) {
return true;
} else {
return false;
}
}
/**
* @param content
* @param charset
* @return
* @throws UnsupportedEncodingException
*/
public static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5簽名過(guò)程中出現(xiàn)錯(cuò)誤,指定的編碼集不對(duì),您目前指定的編碼集是:" + charset);
}
}
/**
* 生成6位或10位隨機(jī)數(shù) param codeLength(多少位)
*
* @return
*/
public static String createCode(int codeLength) {
String code = "";
for (int i = 0; i < codeLength; i++) {
code += (int) (Math.random() * 9);
}
return code;
}
@SuppressWarnings("unused")
private static boolean isValidChar(char ch) {
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
return true;
if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))
return true;// 簡(jiǎn)體中文漢字編碼
return false;
}
/**
* 除去數(shù)組中的空值和簽名參數(shù)
*
* @param sArray 簽名參數(shù)組
* @return 去掉空值與簽名參數(shù)后的新簽名參數(shù)組
*/
public static Map<String, String> paraFilter(Map<String, String> sArray) {
Map<String, String> result = new HashMap<String, String>();
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = sArray.get(key);
if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
|| key.equalsIgnoreCase("sign_type")) {
continue;
}
result.put(key, value);
}
return result;
}
/**
* 把數(shù)組所有元素排序讼呢,并按照“參數(shù)=參數(shù)值”的模式用“&”字符拼接成字符串
*
* @param params 需要排序并參與字符拼接的參數(shù)組
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {// 拼接時(shí),不包括最后一個(gè)&字符
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
/**
* @param requestUrl 請(qǐng)求地址
* @param requestMethod 請(qǐng)求方法
* @param outputStr 參數(shù)
*/
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
// 創(chuàng)建SSLContext
StringBuffer buffer = null;
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
//往服務(wù)器端寫內(nèi)容
if (null != outputStr) {
OutputStream os = conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
// 讀取服務(wù)器端返回的內(nèi)容
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
buffer = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
public static String urlEncodeUTF8(String source) {
String result = source;
try {
result = java.net.URLEncoder.encode(source, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
/**
* 解析xml,返回第一級(jí)元素鍵值對(duì)谦炬。如果第一級(jí)元素有子節(jié)點(diǎn)悦屏,則此節(jié)點(diǎn)的值是子節(jié)點(diǎn)的xml數(shù)據(jù)。
*
* @param strxml
* @return
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws Exception {
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if (children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
//關(guān)閉流
in.close();
return m;
}
/**
* 獲取子結(jié)點(diǎn)的xml
*
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if (!children.isEmpty()) {
Iterator it = children.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
}
public static void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
//sb為微信返回的xml
String notityXml = sb.toString();
String resXml = "";
// System.out.println("接收到的報(bào)文:" + notityXml);
Map map = doXMLParse(notityXml);
String returnCode = (String) map.get("return_code");
if ("SUCCESS".equals(returnCode)) {
//驗(yàn)證簽名是否正確
if (verify(createLinkString(map), (String) map.get("sign"), WXPayUtil.API_KEY, "utf-8")) {
/**此處添加自己的業(yè)務(wù)邏輯代碼start**/
/**此處添加自己的業(yè)務(wù)邏輯代碼end**/
//通知微信服務(wù)器已經(jīng)支付成功
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
}
} else {
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[報(bào)文為空]]></return_msg>" + "</xml> ";
}
// System.out.println(resXml);
// System.out.println("微信支付回調(diào)數(shù)據(jù)結(jié)束");
BufferedOutputStream out = new BufferedOutputStream(
response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
}
}
2.2 在接口中調(diào)用方式:
//微信支付 參數(shù)說(shuō)明
//APP_ID 必須是公眾號(hào)appid
//openid 下單用戶的openid 前端傳過(guò)來(lái)的
//str 商品簡(jiǎn)單描述
//out_trade_no 商戶系統(tǒng)內(nèi)部訂單號(hào)键思,要求32個(gè)字符內(nèi)础爬,只能是數(shù)字、大小寫字母_-|* 且在同一個(gè)商戶號(hào)下唯一
//"1" 商品價(jià)格 這里的價(jià)格是*100后的價(jià)格
//NOTIFY_URL 支付回調(diào)地址
org.json.JSONObject objects = PayUtil .wxPay(APP_ID,openid, str, out_trade_no, "1", NOTIFY_URL);//
System.out.println(objects);
String errMsg = objects.getString("errMsg");
if (errMsg.equals("OK")) {
org.json.JSONObject data = objects.getJSONObject("data");
// System.out.println(data);
Map<String, Object> map = new HashMap<>();
map.put("timeStamp", data.getString("timeStamp"));
map.put("package", data.getString("package"));
map.put("paySign", data.getString("paySign"));
map.put("appid", data.getString("appid"));
map.put("nonceStr", data.getString("nonceStr"));
return map;
}
2.3 支付回調(diào)
/**
* jsApi H5廣告微信支付回調(diào)
* @param request
* @param response
* @return
*/
@RequestMapping(value = "自定義name")
private String 自定義name(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> return_data = new HashMap<String, String>();
try {
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String resultxml = new String(outSteam.toByteArray(), "utf-8");
// System.out.println("resultxml:-----------------");
// System.out.println(resultxml);
// System.out.println("---------------------------");
Map<String, String> params = PayCommonUtil.doXMLParse(resultxml);
outSteam.close();
inStream.close();
if (!PayCommonUtil.isTenpaySign(params)) {
// 支付失敗
System.out.println("===============信支付回調(diào)驗(yàn)簽失敗==============");
return_data.put("return_code", "FAIL");
return_data.put("return_msg", "return_code不正確");
return StringUtil.GetMapToXML(return_data);
} else {
// ------------------------------
// 處理業(yè)務(wù)開始
// ------------------------------
String total_fee = params.get("total_fee");
double v = Double.valueOf(total_fee) / 100;
String tradeNo = params.get("transaction_id");
String out_trade_no = String.valueOf(Long.parseLong(params.get("out_trade_no").split("O")[0]));
//處理業(yè)務(wù)邏輯
return_data.put("return_code", "SUCCESS");
return_data.put("return_msg", "OK");
return StringUtil.GetMapToXML(return_data);
}
}
} catch (
IOException e) {
e.printStackTrace();
} catch (
JDOMException e) {
e.printStackTrace();
}
return_data.put("return_code", "FAIL");
return_data.put("return_msg", "out_trade_no不正確");
return StringUtil.GetMapToXML(return_data);
}
PayCommonUtil工具類
public class PayCommonUtil {
//請(qǐng)求xml組裝
public static String getRequestXml(SortedMap<String,Object> parameters){
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String key = (String)entry.getKey();
String value = (String)entry.getValue();
if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {
sb.append("<"+key+">"+"<![CDATA["+value+"]]></"+key+">");
}else {
sb.append("<"+key+">"+value+"</"+key+">");
}
}
sb.append("</xml>");
return sb.toString();
}
/**
* 驗(yàn)證回調(diào)簽名
* @return
*/
public static boolean isTenpaySign(Map<String, String> map) {
String characterEncoding="utf-8";
String charset = "utf-8";
String signFromAPIResponse = map.get("sign");
if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
System.out.println("API返回的數(shù)據(jù)簽名數(shù)據(jù)不存在吼鳞,有可能被第三方篡改!!!");
return false;
}
// System.out.println("服務(wù)器回包里面的簽名是:" + signFromAPIResponse);
//過(guò)濾空 設(shè)置 TreeMap
SortedMap<String,String> packageParams = new TreeMap();
for (String parameter : map.keySet()) {
String parameterValue = map.get(parameter);
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
StringBuffer sb = new StringBuffer();
Set es = packageParams.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + API_KEY);
//將API返回的數(shù)據(jù)根據(jù)用簽名算法進(jìn)行計(jì)算新的簽名看蚜,用來(lái)跟API返回的簽名進(jìn)行比較
//算出簽名
String resultSign = "";
String tobesign = sb.toString();
if (null == charset || "".equals(charset)) {
resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
}else{
try{
resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
}catch (Exception e) {
resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
}
}
String tenpaySign = ((String)packageParams.get("sign")).toUpperCase();
// System.out.println("返回?cái)?shù)據(jù)-tenpaySign:"+tenpaySign);
// System.out.println("resultSign:"+resultSign);
// System.out.println(tenpaySign.equals(resultSign));
return tenpaySign.equals(resultSign);
}
//請(qǐng)求方法
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 設(shè)置請(qǐng)求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 當(dāng)outputStr不為null時(shí)向輸出流寫數(shù)據(jù)
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意編碼格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 從輸入流讀取返回內(nèi)容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 釋放資源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
System.out.println("連接超時(shí):{}"+ ce);
} catch (Exception e) {
System.out.println("https請(qǐng)求異常:{}"+ e);
}
return null;
}
//xml解析
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if(null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
//關(guān)閉流
in.close();
return m;
}
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
public static String GetMapToXML(Map<String,String> param){
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
for (Map.Entry<String,String> entry : param.entrySet()) {
sb.append("<"+ entry.getKey() +">");
sb.append(entry.getValue());
sb.append("</"+ entry.getKey() +">");
}
sb.append("</xml>");
return sb.toString();
}
}
結(jié)束!