小程序接口服务迁移
接口服务迁移重写
前情提要:腾讯云开发预备收费和个人小程序的迁移。
经过一小段时间的拖延,最后还是完成了小程序接口服务从腾讯云函数迁移至 restful api 服务。使用了 nestjs + mongoose。数据库一样使用了 mongodb,和之间几乎一样的 api 让迁移阻碍少了很多。
这里也不再说一些项目技术选用什么的,主要还是讲一下一些比较值得说的在迁移中遇到的问题。
数据库迁移
腾讯云开发数据库导出 json 的话,_id 会被默认为 string 类型。而如果在 mongoose 中未在 schema 中指定 _id 为 string 类型的话,会出现 cast id ... 问题
。因为 mongoose 会默认 _id 类型为 ObjectId。也就是说,可能出现两种不同类型的 _id,这会在数据 update 或者 remove 时出现异常。
我的处理方式是给每一个集合的 _id 手动设置为 string 类型。那在 create 的时候就会是 string 类型的 _id。
// schema
@Schema()
// ... 省略
@Prop()
_id: string;
// service
await this.UserModel.create({
_id: new mongoose.Types.ObjectId(),
...others
})
用户信息绑定
原本用户信息表仅仅保存了用户的 openId。因为云开发具有天然的鉴权机制,所以在用户无感知的情况下就可以拿到用户在该小程序中的唯一 id,也就是 openId。而新的接口服务,不再依赖于云开发的鉴权机制,统一使用邮箱 + 密码的方式注册登录。这就有一个用户数据迁移,openId 绑定邮箱的问题了。
当一个用户刚使用新的接口服务,会被提示”未登录”,如果需要继续使用,就必须进行注册。
注意下面省略了邮箱收取验证码并进行校验等安全流程,只描述主要流程。
注册
因为要关联用户的 openId 到用户新建的邮箱,而服务端是不明确用户的 openId 指的是谁,所以需要在一段时间内从原本的云开发服务中拿到用户的 openId。云开发获取的 openId 是能信任的。
- 如果该 openId 查询到的用户信息已有邮箱和密码,返回用户已绑定并注册账户。
- 如果该 openId 查询到的用户信息中邮箱和密码为空,则走注册流程,将用户填写的密码和邮箱写入到用户表中。
登录
用户直接使用邮箱和密码登录。但登录还要处理 openId 问题。
如果用户已经注册过了,即使用了不同的手机进行小程序登录,也应该保持注册邮箱的那个 openId 。这可能会和注册冲突,因为注册时也用到了openId。所以目前是判断如果登录用户的 openId 和云开发返回的 openId 不一致,提示目前不支持换设备登录。这个限制会在一段时间后移除。
最终的目的是持有邮箱和密码就可以在任何设备进行登录,目前的做法是为了方便用户正确的迁移账户数据。
服务部署
在最后一刻我才回想起来,小程序接口服务需要 https 不说,还需要该服务器在国内备案,我买的轻量应用服务器在新加坡😠。搜索无果后,没办法,找了一个勉强能使用的方法:使用云函数中转请求。
云函数大概的长这样:
return new Promise((resolve, reject) => {
request({
url,
headers,
method: method || 'get',
body: data,
json: true
}, (error, response, body) => {
if (!error) {
try {
resolve({
statusCode: response.statusCode,
data: body
})
} catch (e) {
reject()
}
}
})
})
使用云函数的缺点就是还不能完全摆脱云开发,每月还得付费。计划等用户数据迁移完成后,买个国内的服务器然后备案。还是不走捷径了。💔。