- 云开发新能力,支持 HTTP 调用 API
今天来上班打开电脑,总感觉微信开发文档哪里有点不太一样,研究了半天原来是云开发又多了神级功能——HTTP API! HTTP API是什么?简单来说就是通过云开发HTTP API,可以不需要通过微信小程序或云开发控制台,就能够管理云开发能力。 技能一 花式触发云函数 在此之前,云函数只能通过微信小程序、定时触发器或其他云函数触发。借助HTTP API,可以在微信小程序环境外随时触发云函数啦! 但是,需要注意的是:HTTP API 途径触发云函数不包含用户信息。 请求地址 [代码]POST https://api.weixin.qq.com/tcb/invokecloudfunction?access_token=ACCESS_TOKEN&env=ENV&name=FUNCTION_NAME [代码] 请求参数 [图片] Tips 1.使用本API触发云函数,在云函数中无法获取OpenID等用户相关信息,无法使用涉及用户登录态的其他API。 2.注意 POST BODY 部分会传递给云函数作为输入参数。 3.由 HTTP API 触发的云函数可以使用云调用。 4.由 HTTP API 触发云函数的超时时间为5s,请注意云函数的执行时间不能过长。 技能二 数据库导入导出 近期有很多小伙伴问我们,为什么数据只能通过云开发控制台手动导出?太麻烦啦!这不,在开发哥哥的不懈努力下,支持通过API导入导出数据啦! 数据库导入 请求地址 [代码]POST https://api.weixin.qq.com/tcb/databasemigrateimport?access_token=ACCESS_TOKEN [代码] 请求参数 [图片] 数据库导出 请求地址 POST https : //api.weixin.qq.com/tcb/databasemigrateexport?access_token=ACCESS_TOKEN 请求参数 [图片] 技能三 管理云存储文件 现在可以便捷地在小程序前端快速实现文件上传/下载及管理功能,同时也可以在开发者工具「云开发」控制台内进行管理。 获取文件上传链接 请求地址 [代码]POST https://api.weixin.qq.com/tcb/uploadfile?access_token=ACCESS_TOKEN [代码] 请求参数 [图片] 获取文件下载链接 请求地址 [代码]POST https://api.weixin.qq.com/tcb/batchdownloadfile?access_token=ACCESS_TOKEN [代码] 请求参数 [图片] 删除文件 请求地址 [代码]POST https://api.weixin.qq.com/tcb/batchdeletefile?access_token=ACCESS_TOKEN [代码] 如要详细了解,点击"https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/"查阅《小程序·云开发文档》 [图片] 如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心!
2019-07-24 - 小程序·云开发的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”**undefined在网上查了下,有很多遇到这个问题的。但如何解决说的大都不明不白,或者未解决,或者解决了帖子未更新。 本人遇到该问题时,先是在官方社区搜索了相关提问,发现官方回复,在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相关的技术故事/技术实战经验,请扫码关注【腾讯云云开发】公众号 ~ [图片]
2019-09-19