1. 程式人生 > >微信小程式http連線訪問解決方案

微信小程式http連線訪問解決方案

HTTP + 加密 + 認證 + 完整性保護 = HTTPS,小程式考慮到資訊保安的問題,選用了更為穩定安全的https 來進行資訊傳遞。

HTTPS協議的主要作用可以分為兩種:一種是建立一個資訊保安通道,來保證資料傳輸的安全;另一種就是確認網站的真實性。

這就導致了許多好用的http  API無法在小程式中被呼叫。

但是也有解決方案。

1.中繼訪問

中繼訪問有兩種方式,一種需要自己擁有一個雲服務和域名。

擁有域名和雲伺服器

域名完成備案之後下載證書

https指引教程如下------> 

再講域名解析到你的雲伺服器的IP。

這樣子你的域名就是https的了,小程式可以訪問你的伺服器了,現在就開始在雲服務上實現訪問http 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。

參照寫法一:

雲函式呼叫方式訪問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}`);
    });
  })
}

不知道什麼原因,雲函式我感覺並不是很穩定,建議有條件的還是用自己的伺服器來實現吧。