1、微信支付之Native支付
關於如何開通微信支付大家可以直接去【微信支付】官網查閱。這裏我們直接進入正題。
1.1 Native支付場景(以電商網站爲例)
1.2 支付場景示例圖
1.3 核心代碼
1.3.1 統一下單封裝後的方法
public static WeixinPayResult createNative(String callbackUrl, String app_id, String mch_id, String api_key, String out_trade_no, Integer total_fee, String body) {
//1.參數封裝
Map param = new HashMap();
param.put("appid", app_id);//公衆賬號ID
param.put("mch_id", mch_id);//商戶
param.put("nonce_str", WXPayUtil.generateNonceStr());//隨機字符串
param.put("body", body);
param.put("out_trade_no", out_trade_no);//交易訂單號(是由系統內部來生成)
param.put("total_fee", total_fee.toString());//金額(分)
param.put("spbill_create_ip", "127.0.0.1");//支付客戶端的IP地址(這裏沒做記錄)
param.put("notify_url", callbackUrl);
param.put("trade_type", "NATIVE");//交易類型
try {
//根據appkey來生成簽名,並同時將參數進行轉換爲xml格式
String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
//2.發送請求(按照官方接口要求,將數據以post請求方式發送)
HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
httpClient.setHttps(true);//以https的協議發送請求
httpClient.setXmlParam(xmlParam);//設置post請求的參數列表
httpClient.post();
//3.獲取結果
String xmlResult = httpClient.getContent();
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
//將返回的結果轉換爲對象
WeixinPayResult weixinPayResult = new WeixinPayResult();
//防止進行bean複製時,日期爲null時報錯
ConvertUtils.register(new DateConverter(null), Date.class);
BeanUtils.copyProperties(weixinPayResult, mapResult);
//注意:付款訂單編號是後臺動態生成,必須要手動添加到返回結果中 勿忘,切記!!!
weixinPayResult.setOut_trade_no(out_trade_no);
return weixinPayResult;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
- 封裝統一下單涉及到的工具類
WXPayUtil.java
代碼需要導入微信支付開發的pom座標
<!-- 微信支付所需的依賴包-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
1.3.2 根據訂單號查詢訂單狀態
public static WeixinPayResult queryPayStatus(String app_id, String mch_id, String api_key, String out_trade_no) {
Map resultMap = new HashMap();
//1.封裝參數
Map param = new HashMap();
param.put("appid", app_id);//appid
param.put("mch_id", mch_id);//商戶ID
param.put("out_trade_no", out_trade_no);//要查詢的訂單號(自己系統所生成訂單號)
param.put("nonce_str", WXPayUtil.generateNonceStr());
try {
String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
//2.發送請求
HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
httpClient.setHttps(true);
httpClient.setXmlParam(xmlParam);
httpClient.post();
//3.獲取結果
String xmlResult = httpClient.getContent();
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
//封裝結果數據
WeixinPayResult weixinPayResult = new WeixinPayResult();
//防止進行bean複製時,日期爲null時報錯
ConvertUtils.register(new DateConverter(null), Date.class);
BeanUtils.copyProperties(weixinPayResult, mapResult);
return weixinPayResult;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
1.3.3 關於生成付款碼時的回調方法應用(重點!重點!重點!)
相信很多新手在使用【微信支付】接口時,都會選擇在前端設置定時器來間隔查詢,如果查詢到訂單狀態爲【支付成功】再走生成訂單的流程。如這種方法的操作是非常錯誤的,而且還有非常多的安全隱患。
- 正確處理查看支付成功並處理後續業務的流程如下:
你沒看錯,流程圖也沒畫錯。其實正確的付款支付接口時,生成的付款碼和查詢訂單支付狀態是兩個完全獨立的操作。
- 前端在調用[統一下單]接口並生成【付款碼】後,這步操作就結束
- 當用戶掃碼後,無論付款成功還是失敗,只要完成這個掃碼操作,就會調用【統一下單】接口中所配置的callback回調url。
- 這種實現方式優點:
- 支持離線支付(複製付款碼後,可以關閉當前付款頁面,只要掃碼成功支付,購買成功業務都會執行)
- 支持代付(用戶可以把付款碼截圖發給其他人代付)
- 安全性高
1.3.4 附加回調的方法
防止有些朋友不知道回調方法怎麼寫,這裏也貼出回調方法的實現
- 如果你在調用【統一下單】封裝方法,傳入的callback參數值爲
callbackUrl: http://你服務器的回調方法根路徑/callbackpay
那麼就應該在你當前工程的方法中,添加一個回調方法的實現
/**
* 微信支付成功後的回調函數
*/
@RequestMapping("/callbackpay")
public Result callbackPay(HttpServletRequest request) {
StringBuffer sb = new StringBuffer();
try {
List<String> readLines = IOUtils.readLines(request.getInputStream(), "utf-8");
for (String readLine : readLines) {
sb.append(readLine);
}
Map<String, String> mapResult = WXPayUtil.xmlToMap(sb.toString());
//防止進行bean複製時,日期爲null時報錯
ConvertUtils.register(new DateConverter(null), Date.class);
WeixinPayResult weixinPayResult = new WeixinPayResult();
BeanUtils.copyProperties(weixinPayResult, mapResult);
return weixinPayService.callbackPay(weixinPayResult);//這行代碼是調用業務層的付款成功後的處理邏輯
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "服務器異常");
}
}
注意:最後提醒一下,上面這個回調方法的url,一定要記得在你的權限框架中放行。
下一章會介紹【微信支付----- 微信紅包和企業付款到微信用戶零錢】