java实现微信支付之扫码支付
本文直接從代碼調(diào)用微信掃碼支付講起。賬號配置,參數(shù)生成等請參考官方文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1
微信掃碼支付。簡單來說,就是你把微信支付需要的信息,生成到二維碼圖片中。通過微信掃一掃,發(fā)起支付。我們需要做的就是二件事:
一是:按照微信掃碼支付規(guī)則生成二維碼信息.
二是:微信沒有提供生成二維碼圖片的接口。需要我們自己把二維碼信息生成到二維碼圖片中。
1.模式選擇:
微信掃碼支付,有兩種模式,文檔中有介紹。第二種模式,微信接口會返回二維碼信息給我們。而第一種模式則需要我們自己去生成二維碼信息。會有些麻煩。尤其 是參數(shù)大小寫,還有簽名的問題,容易出錯。總的來說第二種模式比第一種模式簡單。所有我采用的是第二種模式,比較通用。京東與攜程亦用的是第二種模式。
2.調(diào)用統(tǒng)一下單接口獲取帶有二維碼信息的url:(模式二)
模式二的微信掃碼支付,需要先調(diào)用微信的統(tǒng)一下單接口,生成預(yù)交易單。(參數(shù)傳遞與接收都是XML 數(shù)據(jù)格式。)
正確調(diào)用后,會返回含有交易標(biāo)示ID,和二維碼鏈接的URL。
?
3.實現(xiàn)掃碼支付(模式二)
?
private static String APPID = "";private static String MCHID= ""; private static String KEY= ""; private static String APPSECRET= ""; private static String body= ""; private static String notify_url= ""; //回調(diào)地址。測試回調(diào)必須保證外網(wǎng)能訪問到此地址
/*** 統(tǒng)一下單接口* 微信二維碼支付* @param params* @return*/public String weixin_pay(String out_trade_no,String product_id) {JSONObject retJson = new JSONObject();try {String currTime = PayCommonUtil.getCurrTime();String strTime = currTime.substring(8, currTime.length());String strRandom = PayCommonUtil.buildRandom(4) + "";String nonce_str = strTime + strRandom; //生成隨機字符串 JSONObject requestObj = JSONObject.fromObject(params);// 正式上線的時候價格根據(jù)訂單id查詢String order_price = "1"; // 價格 注意:價格的單位是分 SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();packageParams.put("appid", APPID);packageParams.put("mch_id", MCHID);packageParams.put("nonce_str", nonce_str);packageParams.put("body", body);packageParams.put("out_trade_no", out_trade_no);packageParams.put("total_fee", order_price);packageParams.put("spbill_create_ip", "用戶端ip");packageParams.put("notify_url", notify_url);packageParams.put("trade_type", "NATIVE");packageParams.put("product_id", product_id);Calendar nowTime = Calendar.getInstance();packageParams.put("time_start", DateFormatUtil.formatDate(nowTime.getTime(), "yyyyMMddHHmmss"));nowTime.add(Calendar.MINUTE, requestObj.getInt("expire_time"));packageParams.put("time_expire", DateFormatUtil.formatDate(nowTime.getTime(), "yyyyMMddHHmmss"));String sign = PayCommonUtil.createSign("UTF-8", packageParams,KEY);packageParams.put("sign", sign); //加密 String requestXML = PayCommonUtil.getRequestXml(packageParams);logger.info("支付請求:" + requestXML);long startTime=System.currentTimeMillis();String resXml = HttpRequest.postData("https://api.mch.weixin.qq.com/pay/unifiedorder",requestXML);long endTime=System.currentTimeMillis();Integer execute_time = (int) ((endTime-startTime)/1000);logger.info("支付結(jié)果:" + resXml);Map map = XMLUtil.doXMLParse(resXml);JSONObject reportParams = new JSONObject();reportParams.put("url", "https://api.mch.weixin.qq.com/pay/unifiedorder");reportParams.put("execute_time", execute_time);reportParams.put("return_code", map.get("return_code").toString());reportParams.put("return_msg", map.get("return_msg").toString());reportParams.put("result_code", map.get("result_code").toString());if (map.get("err_code") != null) {reportParams.put("err_code", map.get("err_code").toString());reportParams.put("err_code_des", map.get("err_code_des").toString());}reportParams.put("out_trade_no", out_trade_no);//交易保障 report(reportParams.toString());if (map.get("return_code").toString().equals("SUCCESS") && map.get("result_code").toString().equals("SUCCESS")) {String urlCode = (String) map.get("code_url"); //微信二維碼短鏈接retJson.put("code", 0);retJson.put("message", "下單成功.");retJson.put("data", urlCode);} else {retJson.put("code", 1);retJson.put("message", map.get("err_code_des").toString());retJson.put("data", "");}return retJson.toString();} catch (Exception e) {// TODO: handle exception e.printStackTrace();}}
?
?
4.支付工具類
public class PayCommonUtil {public static Logger log = LoggerFactory.getLogger(PayCommonUtil.class);/*** 是否簽名正確,規(guī)則是:按參數(shù)名稱a-z排序,遇到空值的參數(shù)不參加簽名。* @return boolean*/ public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { 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); //算出摘要 String mysign = MD5.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign = ((String)packageParams.get("sign")).toLowerCase(); //System.out.println(tenpaySign + " " + mysign); return tenpaySign.equals(mysign); } /*** @author* @date 2016-4-22* @Description:sign簽名* @param characterEncoding* 編碼格式* @param parameters* 請求參數(shù)* @return*/ public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { 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 = "";try {v = (String) entry.getValue();} catch (Exception e) {// TODO: handle exceptionv = entry.getValue() + "";}if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); String sign = MD5.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } /*** @author* @date 2016-4-22* @Description:將請求參數(shù)轉(zhuǎn)換為xml格式的string* @param parameters* 請求參數(shù)* @return*/ public static String getRequestXml(SortedMap<Object, 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 k = (String) entry.getKey();String v = "";try {v = (String) entry.getValue();} catch (Exception e) {// TODO: handle exceptionv = entry.getValue() + "";}if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) { sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">"); } else { sb.append("<" + k + ">" + v + "</" + k + ">"); } } sb.append("</xml>"); return sb.toString(); } /*** 取出一個指定長度大小的隨機正整數(shù).* * @param length* int 設(shè)定所取出隨機數(shù)的長度。length小于11* @return int 返回生成的隨機數(shù)。*/ public static int buildRandom(int length) { int num = 1; double random = Math.random(); if (random < 0.1) { random = random + 0.1; } for (int i = 0; i < length; i++) { num = num * 10; } return (int) ((random * num)); } /*** 獲取當(dāng)前時間 yyyyMMddHHmmss* * @return String*/ public static String getCurrTime() { Date now = new Date(); SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String s = outFormat.format(now); return s; } public static JSONObject httpsRequestToJsonObject(String requestUrl,String requestMethod, String outputStr) {JSONObject jsonObject = null;try {StringBuffer buffer = httpsRequest(requestUrl, requestMethod,outputStr);jsonObject = JSONObject.fromObject(buffer.toString());} catch (ConnectException ce) {log.error("連接超時:" + ce.getMessage());} catch (Exception e) {log.error("https請求異常:" + e.getMessage());}return jsonObject;}private static StringBuffer httpsRequest(String requestUrl,String requestMethod, String output)throws NoSuchAlgorithmException, NoSuchProviderException,KeyManagementException, MalformedURLException, IOException,ProtocolException, UnsupportedEncodingException {URL url = new URL(requestUrl);HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();connection.setDoOutput(true);connection.setDoInput(true);connection.setUseCaches(false);connection.setRequestMethod(requestMethod);if (null != output) {OutputStream outputStream = connection.getOutputStream();outputStream.write(output.getBytes("UTF-8"));outputStream.close();}// 從輸入流讀取返回內(nèi)容InputStream inputStream = connection.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;connection.disconnect();return buffer;} }?
轉(zhuǎn)載于:https://www.cnblogs.com/fanyu666/p/5868536.html
總結(jié)
以上是生活随笔為你收集整理的java实现微信支付之扫码支付的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神通数据库知识点整理
- 下一篇: JSON 的几种简单格式和转换