1.阿里云短信准备
参考阿里云短信
2.安装@alicloud/pop-core
npm install @alicloud/pop-core
3.util/SmseCode.ts
根据openAPI的代码来修改
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Core = require('@alicloud/pop-core');
let transporter;
export default {
// 创建发送短信对象
createTransporterInstance(ctx) {
if (transporter) {
return transporter;
}
transporter = new Core({
accessKeyId: ctx.app.config.sms.accessKeyId,
accessKeySecret: ctx.app.config.sms.secretAccessKey,
endpoint: 'https://dysmsapi.aliyuncs.com',
apiVersion: '2017-05-25',
});
return transporter;
},
// 创建需要发送的内容
createSmsInfo(ctx, receiver:string) {
// 1.生成验证码
const code = Math.random().toString(16).slice(2, 6)
.toUpperCase();
const jsonCode = { code };
// 2.生成发送内容
const info = {
SignName: '小灰灰',
TemplateCode: 'SMS_247900215',
PhoneNumbers: receiver,
TemplateParam: JSON.stringify(jsonCode),
};
// 3.保存验证码
ctx.session.sms = {
code,
expire: Date.now() + 60 * 1000, // 验证码1分钟之后过期
};
return info;
},
// 发送短信
async sendSmsCode(ctx, receiver:string) {
const transporter = this.createTransporterInstance(ctx);
const info = this.createSmsInfo(ctx, receiver);
const requestOption = {
method: 'POST',
};
return new Promise((resolve, reject) => {
transporter.request('SendSms', info, requestOption).then(result => {
resolve(result);
}, ex => {
reject(ex);
});
});
},
verifySmsCode(ctx, clientCode) {
// 1.取出服务端中保存的验证码和过期时间
const serverCaptcha = ctx.session.sms;
let serverCode;
let serverExpire;
try {
serverCode = serverCaptcha.code;
serverExpire = serverCaptcha.expire;
} catch (e) {
throw new Error('请重新获取验证码');
}
if (Date.now() > serverExpire) {
throw new Error('验证码已经过期');
} else if (serverCode !== clientCode) {
throw new Error('验证码不正确');
}
// 注意点: 验证码无论验证成功还是失败, 都只能使用一次
ctx.session.email = null;
},
};
4.extend/helper.ts
// 异步发送短信
async sendSmsCode(receiver:string) {
return await SmseCode.sendSmsCode(this.ctx, receiver);
},
// 验证手机验证码
verifySmsCode(clientCode) {
SmseCode.verifySmsCode(this.ctx, clientCode);
},
5.controller/util.ts
public async smsCode() {
const { ctx } = this;
try {
const { phone } = ctx.query;
const data = await ctx.helper.sendSmsCode(phone);
ctx.success(data);
} catch (e:any) {
ctx.error(400, e.message);
}
}
6.controller/user.ts
case RegisterTypeEnum.Phone:
// 校验手机数据的格式是否正确
ctx.validate(PhoneUserRule, data);
// 校验手机验证码是否正确
ctx.helper.verifySmsCode(data.captcha);
break;
7.app/router.ts
router.get('/smscode', controller.util.smsCode);