微信:微信掃碼支付、呼叫統一下單介面、網站支付 + springmvc
阿新 • • 發佈:2019-01-11
- 準備:根據統一下單介面API我先定義了三個物件:UnifiedOrderRequest(統一下單請求引數(必填))、UnifiedOrderRequestExt(統一下單請求引數(非必填))、UnifiedOrderRespose(統一下單返回引數);具體如下程式碼,get、set方法可自行生產,太佔篇幅。
UnifiedOrderRequest.class [javascript] view plain copy print?- /**
- * 統一下單請求引數(必填)
- * @author Y
- *
- */
- publicclass UnifiedOrderRequest {
- private
- private String mch_id; //商戶號
- private String nonce_str; //隨機字串
- private String sign; //簽名
- private String body; //商品描述
- private String out_trade_no; <span style="white-space:pre"> </span>
- private String total_fee; //總金額
- private String spbill_create_ip; <span style="white-space:pre"> </span>//終端IP
- private String notify_url; //通知地址
- private String trade_type; //交易型別
- }
UnifiedOrderRequestExt.class [javascript] view plain copy print?/** * 統一下單請求引數(必填) * @author Y * */ public class UnifiedOrderRequest { private String appid; //公眾賬號ID private String mch_id; //商戶號 private String nonce_str; //隨機字串 private String sign; //簽名 private String body; //商品描述 private String out_trade_no; <span style="white-space:pre"> </span>//商戶訂單號 private String total_fee; //總金額 private String spbill_create_ip; <span style="white-space:pre"> </span>//終端IP private String notify_url; //通知地址 private String trade_type; //交易型別 }
- /**
- * 統一下單請求引數(非必填)
- * @author Y
- *
- */
- publicclass UnifiedOrderRequestExt extends UnifiedOrderRequest{
- private String device_info; //裝置號
- private String detail; //商品詳情
- private String attach; //附加資料
- private String fee_type; //貨幣型別
- private String time_start; //交易起始時間
- private String time_expire; //交易結束時間
- private String goods_tag; //商品標記
- private String product_id; //商品ID
- private String limit_pay; //指定支付方式
- private String openid; //使用者標識
- }
UnifiedOrderRespose.class [javascript] view plain copy print?/** * 統一下單請求引數(非必填) * @author Y * */ public class UnifiedOrderRequestExt extends UnifiedOrderRequest{ private String device_info; //裝置號 private String detail; //商品詳情 private String attach; //附加資料 private String fee_type; //貨幣型別 private String time_start; //交易起始時間 private String time_expire; //交易結束時間 private String goods_tag; //商品標記 private String product_id; //商品ID private String limit_pay; //指定支付方式 private String openid; //使用者標識 }
- /**
- * 統一下單返回引數
- * @author Y
- *
- */
- publicclass UnifiedOrderRespose {
- private String return_code; //返回狀態碼
- private String return_msg; //返回資訊
- private String appid; //公眾賬號ID
- private String mch_id; //商戶號
- private String device_info; //裝置號
- private String nonce_str; //隨機字串
- private String sign; //簽名
- private String result_code; //業務結果
- private String err_code; //錯誤程式碼
- private String err_code_des; <span style="white-space:pre"> </span>//錯誤程式碼描述
- private String trade_type; //交易型別
- private String prepay_id; //預支付交易會話標識
- private String code_url; //二維碼連結
- }
/** * 統一下單返回引數 * @author Y * */ public class UnifiedOrderRespose { private String return_code; //返回狀態碼 private String return_msg; //返回資訊 private String appid; //公眾賬號ID private String mch_id; //商戶號 private String device_info; //裝置號 private String nonce_str; //隨機字串 private String sign; //簽名 private String result_code; //業務結果 private String err_code; //錯誤程式碼 private String err_code_des; <span style="white-space:pre"> </span>//錯誤程式碼描述 private String trade_type; //交易型別 private String prepay_id; //預支付交易會話標識 private String code_url; //二維碼連結 }
- Controller主入口:
[javascript]
view plain
copy
print?
- /**
- * 建立二維碼
- */
- @RequestMapping("createQRCode")
- publicvoid createQRCode(String orderId, HttpServletResponse response) {
- //生成訂單
- String orderInfo = createOrderInfo(orderId);
- //調統一下單API
- String code_url = httpOrder(orderInfo);
- //將返回預支付交易連結(code_url)生成二維碼圖片
- //這裡使用的是zxing <span style="color:#ff0000;"><strong>說明1(見文末)</strong></span>
- try {
- int width = 200;
- int height = 200;
- String format = "png";
- Hashtable hints = new Hashtable();
- hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
- BitMatrix bitMatrix = new MultiFormatWriter().encode(code_url, BarcodeFormat.QR_CODE, width, height, hints);
- OutputStream out = null;
- out = response.getOutputStream();
- MatrixToImageWriter.writeToStream(bitMatrix, format, out);
- out.flush();
- out.close();
- } catch (Exception e) {
- }
- }
/** * 建立二維碼 */ @RequestMapping("createQRCode") public void createQRCode(String orderId, HttpServletResponse response) { //生成訂單 String orderInfo = createOrderInfo(orderId); //調統一下單API String code_url = httpOrder(orderInfo); //將返回預支付交易連結(code_url)生成二維碼圖片 //這裡使用的是zxing <span style="color:#ff0000;"><strong>說明1(見文末)</strong></span> try { int width = 200; int height = 200; String format = "png"; Hashtable hints = new Hashtable(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); BitMatrix bitMatrix = new MultiFormatWriter().encode(code_url, BarcodeFormat.QR_CODE, width, height, hints); OutputStream out = null; out = response.getOutputStream(); MatrixToImageWriter.writeToStream(bitMatrix, format, out); out.flush(); out.close(); } catch (Exception e) { } }
- 生成訂單:分兩部分:一部分是業務需求的訂單資訊,就是發起支付前的訂單資訊,業務系統自行建立儲存;另一部分是滿足統一下單API要求的訂單資訊(也是我們這裡要講的)。“xxxxxx”:是你需要自己填寫的對應資訊:
[javascript]
view plain
copy
print?
- /**
- * 生成訂單
- * @param orderId
- * @return
- */
- private String createOrderInfo(String orderId) {
- //生成訂單物件
- UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();
- unifiedOrderRequest.setAppid("xxxxxxxxxxxxx");//公眾賬號ID
- unifiedOrderRequest.setMch_id("xxxxxxxxx");//商戶號
- unifiedOrderRequest.setNonce_str(StringUtil.makeUUID());//隨機字串 <span style="color:#ff0000;"><strong>說明2(見文末)</strong></span>
- unifiedOrderRequest.setBody("xxxxxx");//商品描述
- unifiedOrderRequest.setOut_trade_no(orderId);//商戶訂單號
- unifiedOrderRequest.setTotal_fee("x"); //金額需要擴大100倍:1代表支付時是0.01
- unifiedOrderRequest.setSpbill_create_ip("xxxxxxxxxxxxx");//終端IP
- unifiedOrderRequest.setNotify_url("xxxxxxxxxxxxxx");//通知地址
- unifiedOrderRequest.setTrade_type("NATIVE");//JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付
- unifiedOrderRequest.setSign(createSign(unifiedOrderRequest));//簽名<span style="color:#ff0000;"><strong>說明5(見文末,簽名方法一併給出)</strong></span>
- //將訂單物件轉為xml格式
- XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_"))); //<span style="color:#ff0000;"><strong>說明3(見文末)</strong></span>
- xStream.alias("xml", UnifiedOrderRequest.class);//根元素名需要是xml
- return xStream.toXML(unifiedOrderRequest);
- }
/** * 生成訂單 * @param orderId * @return */ private String createOrderInfo(String orderId) { //生成訂單物件 UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest(); unifiedOrderRequest.setAppid("xxxxxxxxxxxxx");//公眾賬號ID unifiedOrderRequest.setMch_id("xxxxxxxxx");//商戶號 unifiedOrderRequest.setNonce_str(StringUtil.makeUUID());//隨機字串 <span style="color:#ff0000;"><strong>說明2(見文末)</strong></span> unifiedOrderRequest.setBody("xxxxxx");//商品描述 unifiedOrderRequest.setOut_trade_no(orderId);//商戶訂單號 unifiedOrderRequest.setTotal_fee("x"); //金額需要擴大100倍:1代表支付時是0.01 unifiedOrderRequest.setSpbill_create_ip("xxxxxxxxxxxxx");//終端IP unifiedOrderRequest.setNotify_url("xxxxxxxxxxxxxx");//通知地址 unifiedOrderRequest.setTrade_type("NATIVE");//JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付 unifiedOrderRequest.setSign(createSign(unifiedOrderRequest));//簽名<span style="color:#ff0000;"><strong>說明5(見文末,簽名方法一併給出)</strong></span> //將訂單物件轉為xml格式 XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_"))); //<span style="color:#ff0000;"><strong>說明3(見文末)</strong></span> xStream.alias("xml", UnifiedOrderRequest.class);//根元素名需要是xml return xStream.toXML(unifiedOrderRequest); }
- 調統一下單API:根據要求將生成訂單中返回的xml向微信給定的統一下單URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder,傳送請求,成功並獲得二維碼。
[javascript]
view plain
copy
print?
- /**
- * 調統一下單API
- * @param orderInfo
- * @return
- */
- private String httpOrder(String orderInfo) {
- String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
- try {
- HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
- //加入資料
- conn.setRequestMethod("POST");
- conn.setDoOutput(true);
- BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream());
- buffOutStr.write(orderInfo.getBytes());
- buffOutStr.flush();
- buffOutStr.close();
- //獲取輸入流
- BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
- String line = null;
- StringBuffer sb = new StringBuffer();
- while((line = reader.readLine())!= null){
- sb.append(line);
- }
- XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));//說明3(見文末)
- //將請求返回的內容通過xStream轉換為UnifiedOrderRespose物件
- xStream.alias("xml", UnifiedOrderRespose.class);
- UnifiedOrderRespose unifiedOrderRespose = (UnifiedOrderRespose) xStream.fromXML(sb.toString());
- //根據微信文件return_code 和result_code都為SUCCESS的時候才會返回code_url
- //<span style="color:#ff0000;"><strong>說明4(見文末)</strong></span>
- if(null!=unifiedOrderRespose
- && "SUCCESS".equals(unifiedOrderRespose.getReturn_code())
- && "SUCCESS".equals(unifiedOrderRespose.getResult_code())){
- return unifiedOrderRespose.getCode_url();
- }else{
- returnnull;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- returnnull;
- }
/** * 調統一下單API * @param orderInfo * @return */ private String httpOrder(String orderInfo) { String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; try { HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); //加入資料 conn.setRequestMethod("POST"); conn.setDoOutput(true); BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream()); buffOutStr.write(orderInfo.getBytes()); buffOutStr.flush(); buffOutStr.close(); //獲取輸入流 BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null; StringBuffer sb = new StringBuffer(); while((line = reader.readLine())!= null){ sb.append(line); } XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));//說明3(見文末) //將請求返回的內容通過xStream轉換為UnifiedOrderRespose物件 xStream.alias("xml", UnifiedOrderRespose.class); UnifiedOrderRespose unifiedOrderRespose = (UnifiedOrderRespose) xStream.fromXML(sb.toString()); //根據微信文件return_code 和result_code都為SUCCESS的時候才會返回code_url //<span style="color:#ff0000;"><strong>說明4(見文末)</strong></span> if(null!=unifiedOrderRespose && "SUCCESS".equals(unifiedOrderRespose.getReturn_code()) && "SUCCESS".equals(unifiedOrderRespose.getResult_code())){ return unifiedOrderRespose.getCode_url(); }else{ return null; } } catch (Exception e) { e.printStackTrace(); } return null; }
- 將返回的支付交易連結生成二維碼展示:沒有異常的情況下,在頁面中使用<img>標籤接收就行。實際使用時,結合前端和業務的需求放置二維碼。可以在掃碼支付/案例及規範中找到部分素材和介面規範來設計微信風格的支付頁面。
[javascript]
view plain
copy
print?
- <img src="${ctx}/wxPay/createQRCode?orderId=1111" width="174px">
<img src="${ctx}/wxPay/createQRCode?orderId=1111" width="174px">
- 使用者可以通過維繫客戶端進行掃碼支付。支付完成後回撥我們notify_url設定的url,通過成功的回撥來更改業務系統中的訂單狀態或者一些業務需求。這裡回撥沒有寫出可以參考支付寶:web頁面掃碼支付、網站支付、支付寶即時到賬 + springmvc中的回撥。