在商城小程序和前端上线用了一阵子之后,用户提出了体验提升的需求,如忘记密码、绑定用户、快捷注册等,作为业界最佳实践的短信验证码登录、重置密码和注册等功能开发也就提上日程了,本文就以重置密码为例,将验证码功能的设计与开发进行整理,供小伙伴们参考。
一、业务及技术实现概要设计
1、业务流程概要设计
场景一:验证码登录/注册
用户输入手机号,并请求验证码,平台产生随机6位验证码,调用腾讯云短信SDK给该手机号发送。
用户收到验证码后,在小程序端输入验证码发送给平台。
平台接收到手机号与验证码后,核验验证码是否有效(包括正确性和在有效期内),检查现有用户列表中的登录账号或者手机号码中是否包含该手机号码,如果有,则进行平台登录操作并返回,如没有找到对应的用户,进行新用户注册操作,新用户的登录账号和手机号码字段填入相同号码,并进行平台登录操作后返回。
场景二:密码重置
用户在登录界面中点击“忘记密码”后进入密码重置页,在这个页面中可以输入手机号,并点击“获取验证码”,平台收到请求后核验是否存在有该号码或相同账号名称的用户,没有找到则返回错误提示信息,找到用户后则产生随机6位验证码,调用腾讯云短信SDK给该手机号发送。
用户收到验证码后,在密码重置页输入验证码及重置密码和确认的重置密码,点击“重置”按钮后发送给平台,平台接收到所有信息后,首先核验验证码是否有效(包括正确性和在有效期内),然后核验是否存在有该号码或相同账号名称的用户,没有找到则返回错误提示信息,找到用户后则进行该用户密码的重置。
场景三:用户绑定
主要针对一些预分配用户或其他已有用户账号和密码,而用户使用了第三方认证的登录方式,如微信/微博/QQ等授权登录,然后将两个账号关联或合并的场景。
用户使用第三方授权登录后,在“我的”页面中可选择“绑定账号”操作,在绑定页面中输入手机号码,并点击“获取验证码”,平台收到请求后核验是否存在有该号码或相同账号名称的用户,没有找到则返回错误提示信息,找到用户后则产生随机6位验证码,调用腾讯云短信SDK给该手机号发送。
用户收到验证码后,在绑定页面中输入验证码,并点击“账号绑定”操作,平台接收到手机和验证码信息后,首先核验验证码是否有效(包括正确性和在有效期内),然后核验是否存在有该号码或相同账号名称的用户,没有找到则返回错误提示信息,找到用户后则将两个账号进行合并。
其他设计要求
前端验证码发送间隔控制:验证码发送后,需要防止用户马上进行二次发送,一般在“发送验证码”按钮上进行disable操作,并进行有效期倒计时,一般是2分钟或1分钟,即从120秒或60秒开始倒计时。
后端验证码有效期控制:后端接收到验证码发送请求后,先去检查是否超过有效期,如果没有超过则直接返回已发送成功,如果超过有效期才会调用腾讯云短信SDK再次发送验证码,有效期一般设置为5分钟。
2、技术实现概要设计
前端概要设计
小程序页面设计参照上述的场景进行开发即可,并无特别困难的地方,稍微需要注意的是实现“验证码发送”的倒计时控制。
后端概要设计
腾讯云SDK的基础接入和调用具体见之前的文章-《Step by Step之最简腾讯云短信实践》,就不再重新赘述。
不同的是验证码生成及生效时间的控制,采用Redis实现,即平台随机生成验证码,并调用腾讯云短信SDK发送成功后,在Redis中写入对应的Key和有效期,这样在核验验证码时,直接查询Redis是否存在对应的Key即可。
二、验证码重置密码实践
1、前端实践及相关代码
参考界面如下:
//手机号码校验
let reg = /^1[3|5|6|7|8|9]\d{9}$/;
if (!reg.test(this.data.mobile)) {
wx.showToast({
title: '手机号码输入错误',
icon: 'none'
})
return
}
// 验证码发送倒计时
// wxml
{{txtVerify}}
// js
data: {
txtVerify: '获取验证码',
verifyTimer: null,
verifyTimerValue: 60,
},
// 发送验证码成功后
var that = this;
if (!that.data.verifyTimer) {
that.data.verifyTimer = setInterval( function () {
if (that.data.verifyTimerValue == 0) {
clearInterval(that.data.verifyTimer)
that.data.verifyTimer = null
that.setData({
txtVerify: '获取验证码'
})
} else {
that.setData({
txtVerify: '请等候' + that.data.verifyTimerValue + '秒'
})
}
that.data.verifyTimerValue = that.data.verifyTimerValue - 1;
}, 1000)
}
// handleVerifyCode函数中初始校验
// check the status of timer
if (this.data.verifyTimer !== null) {
return
}
这里也可以把text组件换成Button组件,就可以使用button的disabled属性进行控制,就不需要在回调函数开头进行判断。
2、后端实践及相关代码
其他逻辑都很简单,把随机数及Redis部分代码贴出以供参考。
// 随机数相关
StringBuilder verifyCode = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 6; i++) {
verifyCode.append(random.nextInt(10));
}
// Redis相关
// 检查是否在有效期内发送过验证码
if (RedisUtil.hasKey(CONSTANTS_REDIS_VERIFY_PREFIX+mobileNumber)) {
return "验证码已发送,请稍后再重试";
}
// 发送验证码
MessageUtils.sendVerifyCode(mobileNumber, verifyCode.toString(), CONSTANTS_VERIFY_CODE_EXPIRE_TIME
// 在Redis中增加对应的键值
RedisUtil.set(CONSTANTS_REDIS_VERIFY_PREFIX+mobileNumber, verifyCode, CONSTANTS_VERIFY_CODE_EXPIRE_TIME);
本文暂时没有评论,来添加一个吧(●'◡'●)