微信小程序http鏈接訪問解決方案

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

HTTPS協議的主要做用能夠分爲兩種:一種是創建一個信息安全通道,來保證數據傳輸的安全;另外一種就是確認網站的真實性。html

這就致使了許多好用的http  API沒法在小程序中被調用。前端

可是也有解決方案。java

1.中繼訪問

 

中繼訪問有兩種方式,一種須要本身擁有一個雲服務和域名。sql

擁有域名和雲服務器

域名完成備案以後下載證書json

https指引教程以下------> 小程序

騰訊雲上免費部署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()
        }
      }
    })
  })
}

 

 

不知道什麼緣由,雲函數我感受並非很穩定,建議有條件的仍是用本身的服務器來實現吧。

相關文章
相關標籤/搜索