小程序·雲開發的HTTP API調用丨實戰

小程序雲開發之httpApi調用。

小程序雲開發之httpApi調用(返回“47001處理”)

技術棧

採用 nodejs + express 搭建web服務器,採用 axios 請求第三方 httpApi

nodejs
express
axios

項目結構

通過應用生成器工具 express-generator 可以快速創建一個應用的骨架。

主要的核心文件 routes/base.js(api設置),util/rq.js(axios封裝),views/base.pug(接口文檔)

  
|---bin (框架生成,服務啓動命令文件夾)
|---public (框架生成,靜態資源存儲)
|-------images
|-------javascripts
|-------stylesheets
|---routes (框架生成,路由配置/api)
|-------base.js // base相關接口及文檔說明頁
|---util (自行添加文件夾,放置公用js)
|-------result.js // 最終返回結果包裝js
|-------rq.js // axios封裝
|---views (框架生成,頁面存放)
|-------error.pug
|-------base.pug (自行添加pug模板頁面,用於base接口說明)
|-------index.pug
|-------layout.pug
|---app.js (框架生成,項目核心)
  • axios封裝(util/rq.js)

// 模塊引用
let axios = require("axios")
let qs = require("qs")

// 變量聲明
const CONFKEY = "dev"
const BASECONF = {
    "dev":{
        baseUrl:'https://api.weixin.qq.com/',
    },
    "prod":{
        baseUrl:'https://api.weixin.qq.com/'
    }
}[CONFKEY]

// 創建rq請求並設置基礎信息
const rq = axios.create({
    baseURL: BASECONF.baseUrl,
    timeout: 10000,
    headers: { // 請求頭設置,(微信雲開發數據APi採用application/json格式入參,否則導致47001錯誤)
        "Content-Type":"application/json; charset=utf-8"
    }
})

// axios 請求頭攔截器
rq.interceptors.request.use(req => {
    // 有需要的,在此處攔截請求入參進行處理
    return req
},error => {
    return Promise.reject(error)
})

// axios 返回信息攔截器
rq.interceptors.response.use(res => {
    return res.data
},error => {
    return Promise.reject(error)
})

const $rq = { // 封裝get,post請求

    get(url,params) { // axios.get(url,config)
        return rq.get(url,{
            params: params
        })
    },
    post(url,params={}) {
        return rq({ // axios(config)
            url: url,
            method: 'post',
            data:params
        })
    }
}

module.exports = {
    $rq
}
  • api設置 (routes/base.js)

var express = require('express');
var router = express.Router();
var { $rq } = require("../util/rq")
let result = require("../util/result.js")

/* GET base page. */
router.get('/', function(req, res, next) { // base pugApi說明文檔
    res.render('base', { title: 'baseApi', 
        apiList:[
            {
                url:"base/getAccessToken(請求第三方Api,獲取access_token)",
                method:"GET",
                params:{
                    key:"grant_type",
                    appid:"小程序appid",
                    secret: "小程序密鑰"
                },
                result:{
                    "success": true,
                    "data":`{
                        "access_token":"23_w0OtD1X72LIQo4dwctVsp99kjtIRRk9Gw5bx7UOglotfL7k9LqB1gKbZw86CNht6cnCv9oKBcFEcPg5u4seXN0hJMSEocsbun2dQxCTyZarP06YcToVbdP-MOLc7o7EhMSzqR4URT__BdZc-NMLbAIARQP",
                        "expires_in":7200
                    }`
                }
            },
            {
                url:"base/getdatabase(獲取指定雲環境集合信息)",
                method:"post",
                params:{
                    env:"雲開發數據庫環境id",
                    limit:"獲取數量限制,默認10",
                    offset:"偏移量,默認0"
                },
                result:{
                    "success": true,
                    "data":`{
                        {
                        "errcode": 0,
                        "errmsg": "ok",
                        "collections": [
                            {
                                "name": "geo",
                                "count": 13,
                                "size": 2469,
                                "index_count": 1,
                                "index_size": 36864
                            },
                            {
                                "name": "test_collection",
                                "count": 1,
                                "size": 67,
                                "index_count": 1,
                                "index_size": 16384
                            }
                        ],
                        "pager": {
                            "Offset": 0,
                            "Limit": 10,
                            "Total": 2
                        }
                      }
                    }`
                }
            }
        ]
    });
});

router.get('/getAccessToken', function(req, res, next) { // 請求第三方Api,獲取access_token
    let urlParam = { // appID,secret信息最好是不暴露在外故在此處直接寫死即可
        grant_type:"client_credential",
        appid: "appid",
        secret: "secret"
    };
    $rq.get("cgi-bin/token",urlParam).then(response=>{
        global.TOKEN_INFO = response // global nodejs 全局對象,佔用內存
        let r =  result.createResult(true, response); // 返回結果包裝成固定格式
        res.json(r);
    }).catch(err=>{
        let r =  result.createResult(false, err);
        res.json(r);
        console.log(err)
    })
});

router.get('/getdatabase', function(req, res, next) { // 獲取指定雲環境集合信息
    let urlParam = { // 獲取access_token之後才能調用其他接口,其他接口的入參就無需傳入access_token因爲皆須要拼接在接口後
        // access_token: req.query.access_token?req.query.access_token:"",
        env: req.query.env?req.query.env:"test-3b6a08",
        limit: req.query.limit?req.query.limit:10,
        offset: req.query.offset?req.query.offset:0
    };
    $rq.post("tcb/databasecollectionget?access_token="+global.TOKEN_INFO.access_token,urlParam).then(response=>{
        let r =  result.createResult(true, response);
        res.json(r);
    }).catch(err=>{
        let r =  result.createResult(false, err);
        res.json(r);
        // console.log(err)
    })
});

module.exports = router;
  • 配置app.js 使路由及接口生效(僅)

var createError = require('http-errors'); // 處理錯誤
var express = require('express');
var path = require('path'); // 路徑
var cookieParser = require('cookie-parser'); // cookie
var logger = require('morgan'); // 日誌
var sassMiddleware = require('node-sass-middleware'); // sass 中間件

var indexRouter = require('./routes/index'); // index 路由
var baseRouter = require('./routes/base') // base 路由

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views')); // 設置視圖根目錄
app.set('view engine', 'pug'); // 使用 pug 模板

// 聲明使用中間件
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(sassMiddleware({
  src: path.join(__dirname, 'public'),
  dest: path.join(__dirname, 'public'),
  indentedSyntax: true, // true = .sass and false = .scss
  sourceMap: true
}));
app.use(express.static(path.join(__dirname, 'public')));

app.all('/*',function (req, res, next) { // 解決跨越問題
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With');
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
  if (req.method == 'OPTIONS') {
    res.sendStatus(200);
  }
  else {
    next();
  }
});

// 聲明路由
app.use('/', indexRouter);
app.use('/base', baseRouter);

// catch 404 and forward to error handler 自定義404中間件
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler 自定義錯誤拋出中間件
app.use(function(err, req, res, next) { 
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

至此,小程序雲開發----httpApi調用已完成。

簡單的利用vue+elementui做個雲開發小程序後臺管理頁面調用下上面的接口

我們看下效果如下:

雲開發小程序後臺管理環境調整:

後臺管理環境調整

本地啓動上面的接口服務及調用結果:

本地啓動接口服務

本地啓動接口服務

本地接口調用結果

本地接口調用結果

接口上傳至服務器調用結果:

接口上傳至服務器調用結果

---

至此小程序雲開發----httpApi調用完工。

過程中遇到的問題

  • 在post獲取數據庫集合信息時,第三方返回錯誤碼“47001”

在網上查了下,有很多遇到這個問題的。但如何解決說的大都不明不白,或者未解決,或者解決了帖子未更新。

  • 本人遇到該問題時,先是在官方社區搜索了相關提問,發現官方回覆,在postman上嘗試調用如果無恙請檢查自身代碼。
  • 依言自行在postMan上自行查驗一波,發現我不論如何變更入參格式依然是“47001”的報錯。此時我的入參如下:

    
         {
             access_token:"獲取到的access_token",
             env: "雲開發環境Id",
             limit: 10,
             offset: 0
         }
    
  • 多次查看對應httpApi文檔,不斷思索問題出在哪裏。自身代碼也沒啥毛病啊,這是爲啥呢?會不會是入參的問題呢?access_token已經在請求url上拼過一次是不是入參的時候就不需要了呢?入參的格式是什麼呢?post默認的“application/x-www-form-urlencoded”,還是“application/json;”然後再一篇博客中看到,微信提供的接口入參格式爲“application/json”。
  • 鎖定了入參格式,但是再postMan上我是把所有的入參格式試了一遍的呀,那再試試入參裏面去掉access_token呢?
  • ok,大功告成。終於見到了正常的返回數據。
  • 總結兩點:

1,入參格式採用“application/json; charset=utf-8”;

2,需要拼接access_token的接口入參請幹掉access_token如上文中的代碼


如果你想要了解更多關於雲開發CloudBase相關的技術故事/技術實戰經驗,請掃碼關注【騰訊云云開發】公衆號~!
圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章