uniCloud云开发
事先声明,本人没有恰uniCloud
的饭,但uniCloud
确实好用,阿里云给的免费额度也高。我已经多次使用uniCloud
零成本搭了好几个应用了。甚至后端用uniCloud
,前端用Flutter
的事儿我也干过。
云开发的好处已经不用多讲了吧?FAAS = Functions as a Service
有了云开发,我们开发者只需要专注于业务逻辑代码的编写,以上那些和业务无关的知识都不需要掌握了。原先开发一个产品的业务流程也发生了很大的变化
传统流程
基于云开发的流程
uniCloud
提供以下这些服务,但这些基础服务其实是由阿里云
和腾讯云
提供的,使用前你要选择用哪个服务商。
在这里直接推荐大家使用
uniCloud
时选择阿里云,因为腾讯真抠啊~那点免费额度还是算了吧,不过选腾讯云的唯一好处是腾讯系生态可以免鉴权
获取微信用户信息
获取openid
uni.login({ provider:"weixin", success:(res)=>{ uniCloud.callFunction({ name:"login", data:{ code:res.code } }) } })
通过小程序后台获取到的AppId
和AppSecret
,在云函数里调用微信服务端APIcode2session
const { code } = event; const res = await uniCloud.httpclient.request( "https://api.weixin.qq.com/sns/jscode2session?appid="+appId+"&secret="+appSecret+"&js_code="+code+"&grant_type=authorization_code", { dataType:"json" } ) const openid = res.data.openid;
这样我们就拿到了微信用户的openid
,已经可以用来建立识别用户,建立用户系统了。后续所有用户产品的数据,都会和这个openid
关联起来。
JWT实现用户凭证
在云开发里没有Session这回事,所以就不能使用Session那套机制来实现用户凭证
不过,有更先进的机制为我们所用。
- 服务端将用户的id或需要携带的信息加密成Token,加密使用的密钥仅在服务端保存。
- 通过登录接口返回给前端,前端自己缓存起来。
- 后续所有请求都携带这个
Token
作为参数,云函数里获取Token解密,并检查有效性
安装jsonwebtoken
依赖
npm install jsonwebtoken
使用jwt签名,我这里就是为了不直接暴露openid,密钥自己随便写一个字符串就行,这里图省事儿,直接用了小程序的appSecret
const jwt = require('jsonwebtoken'); //生成token //jwt.sign(携带数据,密钥,过期时间等选项); jwt.sign({openid:openid},appSecret,{expiresIn:60*60*24});
前端封装了网络请求的api,只要发现有缓存的token,后续请求都会自动携带。需要对用户进行校验的接口也通通会校验token的有效性,然后解密取出openid用于用户的数据操作。
jwt.verify(token,appSecret); //校验成功的话会解密出 {openid:openid}
获取昵称头像
小程序SDK也一直在迭代,今年很多小程序里的用户昵称都变成了微信用户
对不对,就是因为这个接口改掉了。
过去使用的getUserInfo
方法,改为使用getUserProfile
,我们就能获得微信用户的昵称头像等数据了。只是这个api每次都会有弹窗提示用户
uni.getUserProfile({ desc: '用于完善会员资料',//必填参数 success: (res) => { res.userInfo; } })
我个人的做法是先通过login换取openid。然后用户会看到自己没有昵称和头像,通过按钮提示用户同步微信用户信息。点击后调用getUserProfile获取信息显示并更新到用户数据库中。
//云函数取参 const { userInfo,token } = event; //获取数据库对象 const db = uniCloud.database(); //校验并解密token const payload = verifyToken(token); //更新数据库中指定openid的用户信息 const dbRes = await db.collection("users").where({ openid:payload.openid }).update({ nickName:userInfo.nickName, avatarUrl:userInfo.avatarUrl, gender:userInfo.gender, country:userInfo.country, province:userInfo.province, city:userInfo.city });
云数据库操作
有了上面基于
jsonwebtoken
的用户凭证后,接下来的业务基本就是对其他数据集合的CRUD了,创建书架,上传图书,获取书架列表,获取图书列表,删除书架,删除图书...
书房/书架数据库
const payload = event.token?verifyToken(event.token):null; const action = event.action; let dbRes; if(action=="create"){ //将书房的名字提交至内容安全审核 const res = await msgSecCheck(payload.openid,event.name); if(res.result.suggest!="pass"){ return {err:1,msg:"内容不安全"}; } //安全内容则写入数据库,建立书架数据 dbRes = await db.collection("bookshelfs").add({ owner:payload.openid, name:event.name, address:event.address, geopoint:new db.Geo.Point(event.longitude, event.latitude), totalbook:0 }) return dbRes; }
创建书房时,由于书房名称由用户自定义,并且其他用户可见。这就叫UGC的内容,必须通过内容安全审核
...
uniCloud里实现内容安全审查
const res = await uniCloud.httpclient.request("https://api.weixin.qq.com/wxa/msg_sec_check?access_token="+access_token,{ method:"POST", dataType:"json", headers:{ "Content-Type":"application/json" }, data:{ version:"2", openid:"内容产出者的openid", scene:2, content:"要审查的文本内容" } });
我们的书架需要在地图上显示,所以必须让用户选择并提交一个地理位置。而云数据库还可以非常方便的添加基于地理位置的索引,让我们可以通过地理位置相关的查询方法来罗列书架数据
new db.Geo.Point(经度, 纬度)