HTTP + 加密 + 認證 + 完整性保護 = HTTPS,小程序考慮到信息安全的問題,選用了更爲穩定安全的https 來進行信息傳遞。php
HTTPS協議的主要做用能夠分爲兩種:一種是創建一個信息安全通道,來保證數據傳輸的安全;另外一種就是確認網站的真實性。html
這就致使了許多好用的http API沒法在小程序中被調用。前端
可是也有解決方案。java
中繼訪問有兩種方式,一種須要本身擁有一個雲服務和域名。sql
域名完成備案以後下載證書json
https指引教程以下------> 小程序
再講域名解析到你的雲服務器的IP。微信小程序
這樣子你的域名就是https的了,小程序能夠訪問你的服務器了,如今就開始在雲服務上實現訪問http API 服務api
實際上只須要面向小程序和API Server 作一個雙面響應便可。安全
實現這種功能,顯而易見,在服務器上部署一個Web項目是最簡單的實現方式:
咱們以訪問豆瓣圖書API 爲例:https://api.douban.com/v2/book/isbn/
豆瓣API雖然是https的,可是來自小程序的訪問是被禁止的。下面代碼一樣適用於http 鏈接
Java代碼:
這個是通用代碼,不管是訪問什麼API
package DataService; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.sql.ResultSet; import com.google.gson.Gson; /* * Author:陳浩東 * QQ:1025584691 */ public class DouBanBook { //豆瓣接口實現 public static String doPost(String url, String params, Integer connTimeout, Integer readTimeout, String contentType) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打開和URL之間的鏈接,根據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("Content-Type", contentType == null? "application/json" : contentType); // 發送POST請求必須設置以下兩行 conn.setDoOutput(true); conn.setDoInput(true); // 設置請求超時時間和讀取超時時間 conn.setConnectTimeout(connTimeout == null ? 180 : connTimeout); conn.setReadTimeout(readTimeout == null ? 180 : readTimeout); // 獲取URLConnection對象對應的輸出流,設置utf-8編碼 out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8")); // 發送請求參數 out.print(params); // flush輸出流的緩衝 out.flush(); // 定義BufferedReader輸入流來讀取URL的響應,設置utf-8編碼 in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); String line; while ((line = in.readLine()) != null) result += line; } catch (Exception e) { e.printStackTrace(); result = null; } //使用finally塊來關閉輸出流、輸入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } }
根據訪問不一樣的API,只須要修改Servlet的寫法就能夠:
Servlet:
package Servlet; import java.io.IOException; import java.io.Writer; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson; import DataService.DouBanBook; /** * Servlet implementation class doubanbook */ @WebServlet("/doubanbook") public class doubanbook extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "GET,POST"); String isbn = request.getParameter("isbn")==null?"no":request.getParameter("isbn"); String sshpwd = request.getParameter("ssh_secret")==null?"no":request.getParameter("ssh_secret"); System.out.println(sshpwd); System.out.println(isbn); Map<String, Object> result = new HashMap<String, Object>(); String json = new Gson().toJson(result); Writer out = response.getWriter(); out.write(DouBanBook.doPost("https://api.douban.com/v2/book/isbn/"+isbn, null, null, null, null)); out.flush(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
一樣,你也能夠用Python,php等語言來實現中繼訪問這個功能。
對於我的開發者來講,尤爲是學生來講,又是是沒有條件購買長時間的雲服務器的,這個時候咱們若是是開發小程序的話,能夠用他們提供的空間。
使用微信小程序的雲開發能力,Node.js 函數,用js 實現服務端的響應,訪問非https API。
參照寫法一(不建議,處理的返回數據必須爲JSON才能夠):
雲函數調用方式訪問API
const cloud = require('wx-server-sdk') cloud.init() // 雲函數入口函數 exports.main = async (event, context) => { console.log(event) console.log(context) return new Promise((resolve, reject) => { var url = event.url;//前端小程序傳的data var https = require('https'); https.get(url, function (res) { var size = 0; var chunks = []; res.on('data', function (chunk) { size += chunk.length; chunks.push(chunk); }); res.on('end', function () { var data = Buffer.concat(chunks, size).toString(); console.log(data) resolve(JSON.parse(data)) }); }).on('error', (e) => { console.log(`url:${url} error: ${e.message}`); }); }) }
參考寫法二,須要導入http包,返回的數據在小程序端須要用JSON.parse(res.result) 轉爲JSON數據
這個api是根據isbn碼訪問並得到圖書信息的接口
// 雲函數入口文件 const cloud = require('wx-server-sdk') var request = require('request') cloud.init() // 雲函數入口函數 exports.main = async(event, context) => { var isbn = event.isbn return new Promise((resolve, reject) => { request.get('http://isbn.szmesoft.com/ISBN/Query?ISBN=' + isbn, (error, response, body) => { if (error) { reject() } else { try { resolve(body) } catch (e) { reject() } } }) }) }
參照寫法三:要在雲函數開始調用的部分添加參數,且只適合POST方式,把參數所有用&鏈接到URL上
// 雲函數入口文件 const cloud = require('wx-server-sdk') var request = require('request') cloud.init() // 雲函數入口函數 exports.main = async (event, context) => { //qz return new Promise((resolve, reject) => { request({ url: event.URL, method: "POST", json: true, headers: { "content-type": "application/json", "token":event.token }, }, function (error, response, body) { if (!error && response.statusCode == 200) { try { resolve(body) } catch (e) { reject() } } }) }) }
不知道什麼緣由,雲函數我感受並非很穩定,建議有條件的仍是用本身的服務器來實現吧。