在小程序后端中轉獲取接口數據,繞過前端調用限制


我們知道,很多時候為了方便,直接在小程序前端直接調用第三方提供商的接口獲取數據,然后顯示在小程序上,這種方式也是我們常規的使用接口方式,不過這種方式有個弊端,就是一旦第三方對小程序禁止,那么就無法再獲取數據了,類似於豆瓣的電影數據接口,在前幾個月還是可以正常訪問的,后來不知基於什么原因,就禁止了小程序端的接口調用了,為了解決這個問題,我們可以使用接口中轉的代理方式,通過調用自身的API接口獲取數據,自身的API對第三方接口進行封裝即可。本篇隨筆以豆瓣接口為例,實現接口的中轉處理,從而確保小程序前端數據獲取的正常。

1、小程序豆瓣接口調用異常

我在較早期的隨筆中《微信小程序豆瓣電影項目的改造過程經驗分享》介紹一個利用豆瓣接口獲取其電影資料的小程序,小程序的界面如下所示。

不過由於小程序被豆瓣端進行調用接口,那么再運行小程序就有接口錯誤了,如下所示。

而我們一般都已經在小程序的設置上添加了豆瓣的域名了

不過由於豆瓣官方對小程序端的限制,那么我們就無法進行正常的接口數據獲取了。

 

2、豆瓣電影數據接口

 我們可以從豆瓣的接口文檔中了解到,豆瓣提供了不少電影相關的數據接口,這個是我們用來練手或者加工小程序的很好數據來源,它的接口如下所示。

豆瓣電影接口的API地址如下所示:https://developers.douban.com/wiki/?title=movie_v2

 

3、前端接口的修改

 既然小程序段無法再通過接口方式獲取電影數據,但測試電腦端是沒問題的,那么我們可以利用自己的API接口對豆瓣接口進行封裝,從而實現接口數據的代理接口處理,為了方便,我們還是盡可能把代理接口弄得通用一些,以便其他接口也可以通過中轉方式獲取,提高中轉接口的通用性。

我們先來看看小程序端的JS端對接口的調用代碼,如下是獲取電影數據的其中一個接口,如下所示。

    
    //通用的熱映、待映的獲取方式
    fetchFilms: function(page, url, city, start, count) {
      return new Promise((resolve, reject) => {
        var that = page;
        var json = {city: city, start: start, count: count };
        var type = "json";//特殊設置,默認是application/json
        if (that.data.hasMore) {
          app.utils.get(url, json, type).then(res => {
              if(res.subjects.length === 0){
                that.setData({
                  hasMore: false,
                })
              }else{
                that.setData({
                  films: that.data.films.concat(res.subjects),
                  start: that.data.start + res.subjects.length,
                  showLoading: false
                })
              }
              wx.stopPullDownRefresh();

              resolve(res);            
          })
        }
      })
    },

這里面核心是通過調用 app.utils.get(url, json, type) 的方式來處理對API的GET方式調用,我們再來看看這個Get方式的調用

//發布的接口
module.exports = {
  Promise,makeArray,getUserInfo,
  get:requestGet,post:requestPost,request,decodeHtml,
  setStorage,getStorage,getLocation,getCityName,

  getDate,getTime,formatTime,getDateDiff,getWeek,get2,post2
}

這個 util.js 里面公布的get接口就是 requestGet函數,我們用了別名的方式,它的詳細代碼如下所示

function requestGet(url,data,type){
  return request(url,'GET',data,type)
}

function requestPost(url,data,type){
  return request(url,'POST',data,type)
}

//封裝Request請求方法
function request(url, method, data = {}, type='application/json'){
  wx.showNavigationBarLoading();
  
  return new Promise((resove,reject) => {
    wx.request({
      url: url,
      data: data,
      header: {'Content-Type': type},
      method: method.toUpperCase(), // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
      success: function(res){
        wx.hideNavigationBarLoading()
        resove(res.data)
      },
      fail: function(msg) {
        console.log('reqest error',msg)
        wx.hideNavigationBarLoading()
        reject('fail')
      }
    })
  })
}

通過以上的分析,如果我們需要避免修改太多地方,那么我們把 app.utils.get(url, json, type) 里面的 get 修改為 get2 的方式就好了,其他參數變化等中轉信息,封裝在 get2 函數內部就好,這樣我們只需修改一個函數名稱就是了。

中轉接口后,處理的方式有所不同,我們需要把整個帶有參數的地址作為一個完整的URL傳遞給服務器接口(需要URL編碼,否則無法獲得參數),而且由於通用接口無法返回JSON格式,我們還需要返回的字符串內容進行JSON格式的轉換。

//使用內部接口進行中轉
var wrapper_get_url = 'http://localhost:27206/api/third/httpwrapper/httpget';
function get2(url, data = {}, type='application/json') {
    var newdata = {};
    var newUrl = wrapper_get_url + "?url=" + encodeURIComponent(url + "?" + json2Form(data));
    console.log(newUrl);

    return new Promise((resolve, reject) => {
        wx.request({
          url: newUrl,
          data: newdata,
          headers: {'Content-Type': type},
          success: function(res) {
            //將中轉接口返回的字符串轉換為JSON對象
            var res = convertJson(res.data);
            resolve(res)
          },
          fail: function(res) {
             //將中轉接口返回的字符串轉換為JSON對象
             var res = convertJson(res.data);
              reject(res)
          }
        })
    })
}

上面的代碼我們使用自己的本地接口進行測試,其中需要提交的URL是我們服務器的URL,原先的URL+數據組合為一個新的參數傳遞給服務器使用。

另外,由於返回的中轉接口數據為字符串信息,非JSON格式,那么還需要將中轉接口返回的字符串轉換為JSON對象。

//轉義字符串為JSON對象
function convertJson(res) {
  //將中轉獲取到的字符串轉換為JSON對象
  var jsonStr = JSON.stringify(res);
  var jsonStrSym = jsonStr.replace('/', '\\');
  var jsondata = JSON.parse(JSON.parse(jsonStr));
  console.log(jsondata);
  return jsondata;
};

以上就是完整的前端代碼了,通過上面的處理,我們可以正常的獲得接口的數據,並可以正常的展示了,正式發布的時候,我們修改用上自己的服務器域名地址即可發布使用了。

 

4、后端的代理接口代碼封裝

前面介紹了小程序的前端代碼修改,只需要引入一個新的函數就可以實現數據的中轉獲取了,后端我們自然配合這個接口實現數據的獲取即可。

我們在后端增加一個控制器,增加對應的接口定義,如下代碼所示。

namespace WebAPI.Areas.Third.Controllers
{
    /// <summary>
    /// 對第三方的Http接口數據進行包裝,獲取數據,避免小程序並禁止獲取數據的問題
    /// </summary>
    public class HttpWrapperController : BaseApiController
    {
        /// <summary>
        /// get方式獲取數據
        /// </summary>
        /// <param name="url">接口URL</param>
        /// <returns></returns>
        [HttpGet]
        public string HttpGet(string url)
        {
            HttpHelper helper = new HttpHelper();
            var html = helper.GetHtml(url, "", false);
            return html;
        }

是不是比較簡單,這樣就可以實現通用的接口數據中轉了。

最后測試得到的正常數據展示界面,如下所示。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM