HTTP + 加密 + 认证 + 完整性保护 = HTTPS, 小程序考虑到信息安全的问题, 选用了更为稳定安全的 https 来进行信息传递.
HTTPS 协议的主要作用可以分为两种: 一种是建立一个信息安全通道, 来保证数据传输的安全; 另一种就是确认网站的真实性.
这就导致了许多好用的 http API 无法在小程序中被调用.
但是也有解决方案.
1. 中继访问
中继访问有两种方式, 一种需要自己拥有一个云服务和域名.
拥有域名和云服务器
域名完成备案之后下载证书
https 指引教程如下 ------>
腾讯云上免费部署 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}`);
- });
- })
- }
不知道什么原因, 云函数我感觉并不是很稳定, 建议有条件的还是用自己的服务器来实现吧.
来源: https://www.cnblogs.com/masterchd/p/9895636.html