您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關微信小程序 支付后臺java實現實例,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
微信小程序 支付后臺java實現實例
前言:
前些天使用 LeanCloud 云引擎寫了個小程序的支付相關 以前只做過 APP 支付 這次在小程序支付爬了兩天的坑 把代碼也分享出來
支付流程:
1.小程序前端獲取微信 openId 以及訂單號 傳給后臺
2,后臺根據 openId 和訂單號進行簽名 post 微信統一下單接口
3.后臺獲取微信返回的xml字符串 解析 二次簽名以后返回給前端
4.前端調起支付微信支付 API
先看支付函數:
//獲取支付信息 @EngineFunction("getPayInformation") public static Map<String, Object> getPayInformation( @EngineFunctionParam("orderId") String orderId ) throws AVException, UnsupportedEncodingException, DocumentException { Map<String, Object> reqMap = new TreeMap<String, Object>( new Comparator<String>() { public int compare(String obj1, String obj2) { // 升序排序 return obj1.compareTo(obj2); } }); if (AVUser.getCurrentUser() != null) { String authDataJson = JSONArray.toJSONString(AVUser.getCurrentUser().get("authData")); JSONObject jsonObject = JSON.parseObject(authDataJson); jsonObject.get("lc_weapp"); JSONObject j2 = JSON.parseObject(jsonObject.get("lc_weapp").toString()); String openId = (String) j2.get("openid"); AVQuery<Order> query = AVObject.getQuery(Order.class); Order order = query.get(orderId); reqMap.put("appid", System.getenv("appid")); reqMap.put("mch_id", System.getenv("mch_id")); reqMap.put("nonce_str", WXPayUtil.getNonce_str()); reqMap.put("body", new String(order.getDishesList().toString().getBytes("UTF-8"))); reqMap.put("openid", openId); reqMap.put("out_trade_no", order.getObjectId()); reqMap.put("total_fee", 1); //訂單總金額,單位為分 reqMap.put("spbill_create_ip", "192.168.0.1"); //用戶端ip reqMap.put("notify_url", System.getenv("notify_url")); //通知地址 reqMap.put("trade_type", System.getenv("trade_type")); //trade_type=JSAPI時(即公眾號支付),此參數必傳,此參數為微信用戶在商戶對應appid下的唯一標識 String reqStr = WXPayUtil.map2Xml(reqMap); String resultXml = HttpRequest.sendPost(reqStr); System.out.println("微信請求返回:" + resultXml); //解析微信返回串 如果狀態成功 則返回給前端 if (WXPayUtil.getReturnCode(resultXml) != null && WXPayUtil.getReturnCode(resultXml).equals("SUCCESS")) { //成功 Map<String, Object> resultMap = new TreeMap<>( new Comparator<String>() { public int compare(String obj1, String obj2) { // 升序排序 return obj1.compareTo(obj2); } }); resultMap.put("appId", System.getenv("appid")); resultMap.put("nonceStr", WXPayUtil.getNonceStr(resultXml));//解析隨機字符串 resultMap.put("package", "prepay_id=" + WXPayUtil.getPrepayId(resultXml)); resultMap.put("signType", "MD5"); resultMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));//時間戳 String paySign = WXPayUtil.getSign(resultMap); resultMap.put("paySign", paySign); return resultMap; } else { throw new AVException(999, "微信請求支付失敗"); } } else { throw new AVException(98, "當前未登錄用戶"); } }
其中appid和mch_id可以用系統常量
PS:這里注意一個坑
二次簽名的時候使用 appId nonceStr package signType timeStamp 這五個key生成簽名(這里無視微信官方文檔 以及注意 appId 的大小寫)
前端調起API支付時 按照官方文檔就可以
網絡請求類:
HttpRequest
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; public class HttpRequest { /** * 向指定URL發送GET方法的請求 * * @param url 發送請求的URL * @param param 請求參數,請求參數應該是 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("發送GET請求出現異常!" + e); e.printStackTrace(); } // 使用finally塊來關閉輸入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 發送POST方法的請求 * * @param url 發送請求的 URL * @param param 請求參數,請求參數應該是 name1=value1&name2=value2 的形式。 * @return 所代表遠程資源的響應結果 */ public static String sendPost(String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder"); // 打開和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)"); // conn.setRequestProperty("Pragma:", "no-cache"); // conn.setRequestProperty("Cache-Control", "no-cache"); // conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8"); // 發送POST請求必須設置如下兩行 conn.setDoOutput(true); conn.setDoInput(true); // 獲取URLConnection對象對應的輸出流 out = new PrintWriter(conn.getOutputStream()); // 發送請求參數 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("發送 POST 請求出現異常!" + e); e.printStackTrace(); } //使用finally塊來關閉輸出流、輸入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } }
XML解析工具類
WXPayUtil
import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.Random; public class WXPayUtil { //生成隨機字符串 public static String getNonce_str() { String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Random random = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 15; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } //map轉xml 加上簽名信息 public static String map2Xml(Map<String, Object> map) throws UnsupportedEncodingException { StringBuffer sb = new StringBuffer(); StringBuilder sb2 = new StringBuilder(); sb2.append("<xml>"); for (String key : map.keySet()) { sb.append(key); sb.append('='); sb.append(map.get(key)); sb.append('&'); // sb2是用來做請求的xml參數 sb2.append("<" + key + ">"); // sb2.append("<![CDATA[" + map.get(key) + "]]>"); sb2.append(map.get(key)); sb2.append("</" + key + ">"); } sb.append(System.getenv("signKey")); String sign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); sb2.append("<sign>"); sb2.append(sign); sb2.append("</sign>"); sb2.append("</xml>"); return sb2.toString(); } //解析微信返回return_code SUCCESS或FILE //根據微信返回resultXml再次生成簽名 public static String getSign(Map<String, Object> map) { StringBuffer sb = new StringBuffer(); for (String key : map.keySet()) { sb.append(key); sb.append('='); sb.append(map.get(key)); sb.append('&'); } sb.append(System.getenv("signKey")); System.out.println("第二次簽名內容:" + sb); System.out.println("第二次簽名SING:" + MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase()); return MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); } //解析微信返回return_code SUCCESS或FILE public static String getReturnCode(String resultXml) { String nonceStr; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = dbf.newDocumentBuilder(); InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes()); org.w3c.dom.Document doc = builder.parse(inputStream); // // 下面開始讀取 org.w3c.dom.Element root = doc.getDocumentElement(); // 獲取根元素 NodeList nl = root.getElementsByTagName("return_code"); org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.Node nd = el.getFirstChild(); nonceStr = nd.getNodeValue(); return nonceStr; } catch (Exception e) { e.printStackTrace(); return null; } } //解析微信返回return_msg public static String getReturn_msg(String resultXml) { String nonceStr; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = dbf.newDocumentBuilder(); InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes()); org.w3c.dom.Document doc = builder.parse(inputStream); // // 下面開始讀取 org.w3c.dom.Element root = doc.getDocumentElement(); // 獲取根元素 NodeList nl = root.getElementsByTagName("return_msg"); org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.Node nd = el.getFirstChild(); nonceStr = nd.getNodeValue(); return nonceStr; } catch (Exception e) { e.printStackTrace(); return null; } } //解析微信返回appid public static String getAppId(String resultXml) { String nonceStr; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = dbf.newDocumentBuilder(); InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes()); org.w3c.dom.Document doc = builder.parse(inputStream); // // 下面開始讀取 org.w3c.dom.Element root = doc.getDocumentElement(); // 獲取根元素 NodeList nl = root.getElementsByTagName("appid"); org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.Node nd = el.getFirstChild(); nonceStr = nd.getNodeValue(); return nonceStr; } catch (Exception e) { e.printStackTrace(); return null; } } //解析微信返回mch_id public static String getMchId(String resultXml) { String nonceStr; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = dbf.newDocumentBuilder(); InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes()); org.w3c.dom.Document doc = builder.parse(inputStream); // // 下面開始讀取 org.w3c.dom.Element root = doc.getDocumentElement(); // 獲取根元素 NodeList nl = root.getElementsByTagName("mch_id"); org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.Node nd = el.getFirstChild(); nonceStr = nd.getNodeValue(); return nonceStr; } catch (Exception e) { e.printStackTrace(); return null; } } //解析微信返回nonce_str public static String getNonceStr(String resultXml) { String nonceStr; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = dbf.newDocumentBuilder(); InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes()); org.w3c.dom.Document doc = builder.parse(inputStream); // // 下面開始讀取 org.w3c.dom.Element root = doc.getDocumentElement(); // 獲取根元素 NodeList nl = root.getElementsByTagName("nonce_str"); org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.Node nd = el.getFirstChild(); nonceStr = nd.getNodeValue(); return nonceStr; } catch (Exception e) { e.printStackTrace(); return null; } } //解析微信返回prepay_id public static String getPrepayId(String resultXml) { String nonceStr; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = dbf.newDocumentBuilder(); InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes()); org.w3c.dom.Document doc = builder.parse(inputStream); // // 下面開始讀取 org.w3c.dom.Element root = doc.getDocumentElement(); // 獲取根元素 NodeList nl = root.getElementsByTagName("prepay_id"); org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.Node nd = el.getFirstChild(); nonceStr = nd.getNodeValue(); return nonceStr; } catch (Exception e) { e.printStackTrace(); return null; } } }
關于“微信小程序 支付后臺java實現實例”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。