api接口编写
后端在编写好一些api接口之后会需要对接口进行测试,这时候就需要用到微信小程序来发送一些http请求了,由于需要测试的按钮非常多,而关键在于测试api而不是样式,所以引入小程序组件库来创建这些接口,里面已经实现好了很多不同的按钮或者菜单等基本组件的样式,直接调用就好了。
npm init
,再在小程序设置中打开使用npm模块
,加载lin-ui(此次要使用的组件库)npm i lin-ui
,导入好包之后点击微信开发者工具中的 工具-构建npm,这时会出现miniprogram_npm文件夹,里面有lin-ui中编译好的所有组件;一般来说wx.request()里有如下参数
在HTTP中,基本认证(Basic access authentication)是一种用来允许网页浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。
这一个典型的HTTP客户端和HTTP服务器的对话,服务器安装在同一台计算机上(localhost),包含以下步骤:
Authorization: Basic base64encode(username+":"+password)
注意: 客户端有可能不需要用户交互,在第一次请求中就发送认证消息头。
1、postman:
2、小程序发送请求时直接携带token令牌(账号密码也一样):
Authorization: Basic base64encode(username+":"+password)
wx.request({
url: ‘http://localhost:3000/v1/classic/latest‘,
method: "GET",
header: {
Authorization: this._encode()
},
success: (res) => {
console.log(res.data)
}
})
_encode() {
const token = wx.getStorageSync(‘token‘)
return ‘Basic ‘ + Base64.encode(token + ‘:‘)
}
这部分其实就是登录部分,也就是要记录或合适登录用户的信息,所以创建的数据表是User表
数据:type(登录方式)、nickname(用户昵称)、email、password、openid()
在models下创建user.js文件专门来控制user表的数据
用switch...case语句通过当前type(登录方式)的不同来选择不同的处理函数,成功的话最后都要返回给用户token值:
若是Email登录,则肯定输入了账号和密码,调用emailLogin函数(这个函数还是在登录api文件里,但为了代码简洁性 写个函数放在外面处理);
若是小程序登录,这样用户不需要输入密码,因为不需要校验了 肯定是合法的,调用WXManager中的codeToToken方法(在services/wx.js中),为什么要专门写个类来操作呢,我觉得应该是这部分涉及到了微信的官方获取openid的操作,而且还有用户的信息等?
这种情况下通过微信官方的方式获取用户的openid(具体可见微信文档,其实就是通过axios发送个请求到一个特定的网址 同时在路径里携带好官方凭证);
获取到openid后,去user表里查询看该openid是否有相应的数据条目,没有就创建一条;
最后用用户的id和scope来生成token返回回去。
onGetToken () {
// 通过微信官方提供的登录能力方便地获取微信提供的用户身份标识
wx.login({
// 调用login函数 在这里面去请求token什么的
success: (res) => {
if (res.code) {
wx.request({
url: ‘http://localhost:3000/v1/token‘,
method: ‘POST‘, // 默认是GET 注意这里是POST
data: {
account: res.code,
type: 100
},
success: (res) => {
const status = res.statusCode.toString()
if (status.startsWith(‘2‘)) {
wx.setStorageSync(‘token‘, res.data)
}
}
})
}
}
})
},
onVerifyToken () {
wx.request({
url: ‘http://localhost:3000/v1/token/verify‘,
method: ‘POST‘,
data: {
// 检验缓存里的token是否合法
token: wx.getStorageSync(‘token‘)
},
success: (res) => {
console.log(res.data)
}
})
}
这个大家都一样,就不说了
like/cacel和like思路几乎一模一样,这里就不重复赘述。
onLike () {
wx.request({
url: ‘http://localhost:3000/v1/like‘,
method: ‘POST‘,
header: {
Authorization: this._encode()
},
data: {
art_id: 1,
type: 100
},
success: res => {
console.log(res.data)
}
})
},
参数校验需要校验type和id, 这里直接用LikeValidator
调用flow里写好的getFavor函数
把当前uid和type id一起传进去, uid通过ctx.auth.uid得到, 这就是在token校验的时候把uid和scope放到ctx上下文中的好处, 可以随时在中间件中拿到
这里的数据又是在一张表里查不完的数据, 需要返回fav_nums id like_status三个数据, 其中flow表中只有id这一个数据, 另外fav_nums要去具体type对应的表中找, 而like_status要去favor中看有没有这一期刊对应的信息, 所以涉及到了三张表
大概思想就是按照上面这样去查找
// artInfoList是从favor表里查询出来的所有数据的数组
static async getList (artInfoList) {
const arts = {
100: [],
200: [],
300: []
}
for (let artInfo of artInfoList) {
// 将不同type的id放到相应arts对象下的数组里
arts[artInfo.type].push(artInfo.art_id)
}
let res = []
for (let key in arts) {
if (key.length === 0) {
continue
}
// 遍历三种type, 分别调用下面这个函数
res.push(await this._getListType(arts[key], parseInt(key)))
}
// 最后返回的是个一维数组, 打瘪一下
res = flatten(res)
return res
}
static async _getListType (ids, key) {
// 在type是key的表里进行查找, 如100就在movie里查找
let res
const finder = {
// 这里利用了sequelize库查找里的[Op.in]方法, 只要id在ids数组里有就放入结果里返回
where: {
id: ids
}
}
// 根据key不同查找出这些id对应的结果
switch (key) {
case 100:
res = await Movie.findAll(finder)
break
case 200:
res = await Music.findAll(finder)
break;
case 300:
res = await Sentence.findAll(finder)
break
default:
break
}
return res
}
const favors = await Favor.findAll({
where: {
art_id: {
[Op.in]: ids
},
type: 400
},
group: [‘art_id‘],
attributes: [‘art_id‘, [Sequelize.fn(‘COUNT‘, ‘*‘), ‘count‘]]
})
static async getAll () {
// 获取HotBook数据表中所有图书
const books = await HotBook.findAll()
const ids = []
// 将图书id放到一个数组里,方便后续查找
books.forEach(item => {
ids.push(item.id)
})
const favors = await Favor.findAll({
where: {
art_id: {
[Op.in]: ids
},
type: 400
},
// 根据art_id分好组
group: [‘art_id‘],
// 计算每个不同的art_id组里有多少条记录,并且用一个count属性存下来
attributes: [‘art_id‘, [Sequelize.fn(‘COUNT‘, ‘*‘), ‘count‘]]
})
books.forEach(book => {
// 遍历books里每本书,在刚刚的favors里查找有没有对应一样id的书,有的话就把count拿过来赋值
book.setDataValue(‘count‘, HotBook._getBookStatus(book, favors))
})
return books
}
static _getBookStatus (book, favors) {
const fs = favors.filter(favor => book.id === favor.art_id)
if (fs.length === 0) {
return 0
}
return parseInt(fs[0].get(‘count‘))
}
原文:https://www.cnblogs.com/TRY0929/p/13910424.html