微信公眾號支付——預支付訂單
1.需要一個可以登陸微信商戶平臺的賬號,此賬號是服務號並開通了微信支付,商戶在申請開通時,客服會發送郵件到你的郵箱,
上圖中有幾個重要資訊:商戶號和appid,務必記住商戶號和appid。其中登陸賬號和密碼用於登陸微信支付首頁點選開啟連結
2.點選上圖中的下載api證書,設定api密碼。這個證書主要在微信支付api中需要證書的地方使用中的退款等功能提示需要證書。
注:什麼時候載入使用該證書?當要實現微信退款時,發起退款請求前,需要先載入安全證書
package com.jy.common.pay.weixinpay;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
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.conn.ssl.SSLContexts;
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;
/*
* 載入安全證書、退款等需要證書的請求使用此類中的方法
* */
public class ClientCustomSSL {
public static String doRefund(String url, String data) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
URL luj = Thread.currentThread().getContextClassLoader().getResource("apiclient_cert.p12");//src目錄下的證書檔案
FileInputStream is = new FileInputStream(new File(luj.toURI()));
try {
keyStore.load(is, "這個是你設定的安全證書的密碼".toCharArray());// 這裡寫密碼..預設是你的mchid,也就是前面傳送給你的
郵件中的商戶號
} finally {
is.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "商戶號".toCharArray())// 這裡也是寫密碼的
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpPost httpost = new HttpPost(url); // 設定響應頭資訊
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httpost);
try {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(),
"UTF-8");
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
上面返回的jsonStr則是:你發起退款時返回的一些json資訊,這裡一般將其轉為map方便使用。
其中上面呼叫的方法需要2個引數:url,data
url:微信支付提供的退款介面https://api.mch.weixin.qq.com/secapi/pay/refund
data:這個引數微信支付官方推薦使用xml格式,所以一般都是用String字串構造一個xml,這個xml和官方文件一樣
<xml>
<appid>wx2421b1c4370ec43b</appid>
<mch_id>10000100</mch_id>
<nonce_str>6cefdb308e1e2e8aabd48cf79e546a02</nonce_str>
<out_refund_no>1415701182</out_refund_no>
<out_trade_no>1415757673</out_trade_no>
<refund_fee>1</refund_fee>
<total_fee>1</total_fee>
<transaction_id></transaction_id>
<sign>FE56DD4AA85C0EECA82C35595A69E153</sign>
</xml>
data就是上面這個xml的字串,一般先將退款介面需要的引數放入到map中,在將map轉為xml字串。
3.在實現預支付訂單前應先獲取到開發需要的一些引數:如openid、隨機字串、簽名、
1.openid獲取:
String url="https://api.weixin.qq.com/sns/oauth2/access_token?"
+ "appid="+你的appid
+ "&secret="+你的secret
+ "&code="+code
+ "&grant_type=authorization_code";
JSONObject jsonObject=HttpGet.getRes(url);
String usersWeixinId=jsonObject.getString("openid");
secret是公眾號的appsecret,這個在微信支付平臺中的開發者中心可以找到
code是應用授權作用域,官方提供兩個,任選一個:snsapi_base(不彈出授權視窗,只獲取openid),snsapi_userinfo(彈出授權視窗.....)
2.隨機字串獲取:這個引數一般是32位以內的大寫字母和0-9數字的隨機組合,不能超出32位
獲取簽名步驟:
根據上圖中的引數生成字串
stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
再接著串聯:
stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key為商戶平臺設定的金鑰key
sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5簽名方式
sign=hash_hmac("sha256",stringSignTemp,key) //注:HMAC-SHA256簽名方式
兩種簽名方式任選,sign這就是我們需要的簽名
4.簡單地說:實現微信支付中的各種功能只需要3個大步驟:1.微信公眾號支付的各個介面。2.生成發起訂單等功能的XML字串。3.傳送http請求,輸出返回的結果
1.預支付訂單介面:https://api.mch.weixin.qq.com/pay/unifiedorder
預支付訂單的通知地址:http://www.weixin.qq.com/wxpay/pay.php(即發起訂單後的回撥介面),此介面不能攜帶引數
2.查詢預支付訂單的介面:https://api.mch.weixin.qq.com/pay/orderquery
查詢預支付訂單時需要一個引數:微信訂單號或者商戶訂單號任選一個,一般優先微信訂單號,商戶訂單號的詳細演算法地址:
3.關閉訂單介面:https://api.mch.weixin.qq.com/pay/closeorder
4.申請退款介面:https://api.mch.weixin.qq.com/secapi/pay/refund 此功能需要安全證書,自己去開發者中心下載
退款介面中需要的商戶訂單號與商戶退款訂單號是一致的,主要實現:
public
static
String
getRandomStringByLength(
int
length)
{
String
base =
"0123456789"
;
Random
random =
new
Random();
StringBuffer
sb =
new
StringBuffer();
for
(
int
i
=
0
;
i < length; i++) {
int
number
= random.nextInt(base.length());
sb.append(base.charAt(number));
}
return
sb.toString();
}
/**
*
@function 生成商戶訂單號/退款單號
*
@date 2015-12-17
*
@return String
*/
public
static
String
getOrderNo(){
SimpleDateFormat
sdf =
new
SimpleDateFormat(
"yyyyMMddHHmmssSSS"
);
Date
date =
new
Date();
return
sdf.format(date)
+ getRandomStringByLength(
4
);
}
5.查詢退款介面:https://api.mch.weixin.qq.com/pay/refundquery
6.下載對賬單:https://api.mch.weixin.qq.com/pay/downloadbill
7.支付結果通知:https://pay.weixin.qq.com/wxpay/pay.action或者http://www.weixin.qq.com/wxpay/pay.php
8.獲取openid介面:https://api.weixin.qq.com/sns/oauth2/access_token需要部分引數,上面有例子