參考:
騰訊雲短信文檔
國內短信快速入門
qcloudsms Node.js SDK
文檔中心>短信>錯誤碼node
const QcloudSms = require('qcloudsms_js');
const cfg = {
appid: 1400123123, // SDK AppID 以1400開頭
appkey: '...', // 短信應用 SDK AppKey
templateId: 402790, // 短信模板 ID,須要在短信控制檯中申請
smsSign: '個人過去公衆號', // NOTE: 簽名參數使用的是`簽名內容`,而不是`簽名ID`。這裏的簽名"騰訊雲"只是示例,真實的簽名須要在短信控制檯申請
}
// 簡單封裝一下, 向指定手機下發驗證碼
// sendCode('18212341234', 1234) // 發送短信
function sendCode (phone, code, time = 10) {
phone = typeof(phone) === 'object' ? phone : [phone]
const qcloudsms = QcloudSms(cfg.appid, cfg.appkey) // 實例化 QcloudSms
const msender = qcloudsms.SmsMultiSender()
msender.sendWithParam(86,
phone, // 一個數組
cfg.templateId, // 模版 id
[code, time], // 正文中的參數值
cfg.smsSign, // 簽名 未提供或者爲空時,會使用默認簽名發送短信
'', '',
(err, res, resData) => { // 回調函數
err && console.log('err: ', err)
console.log('request data: ', res.req)
console.log('response data: ', resData)
})
}
這裏的請求及回調與 sdk 中的是同樣的。git
參考:
文檔中心>短信>API 文檔>短信API>指定模板羣發短信github
URL 示例
POST https://yun.tim.qq.com/v5/tlssmssvr/sendmultisms2?sdkappid=xxxxx&random=xxxx數據庫
{
"ext": "",
"extend": "",
"params": [
"驗證碼",
"1234",
"4"
],
"sig": "...",
"sign": "騰訊雲",
"tel": [
{
"mobile": "13788888888",
"nationcode": "86"
},
{
"mobile": "13788888889",
"nationcode": "86"
}
],
"time": 1457336869,
"tpl_id": 19
}
{
"result": 0,
"errmsg": "OK",
"ext": "",
"detail": [
{
"errmsg": "OK",
"fee": 1,
"mobile": "13788888888",
"nationcode": "86",
"result": 0,
"sid": "xxxxxxx"
},
{
"errmsg": "OK",
"fee": 1,
"mobile": "13788888889",
"nationcode": "86",
"result": 0,
"sid": "xxxxxxx"
}
]
}
返回驗證碼及有效時間的加密爲字符串.json
query: {phone} response: {token}
phoneCode({
body: {},
query: {
phone: '18212341234',
}
})
async function phoneCode (ctx) {
let {phone} = ctx.query
let code = '1234' // 生成驗證碼用於測試
if(process.env.PRO_ENV === 'pro') { // 若是是正式環境, 修改驗證碼爲隨機
code = String(Math.random()).slice(-4)
sms.sendCode(phone, code) // 發送驗證碼
}
let token = jwt.sign(
{ // 加密的 json 信息
phone,
code,
iat: Date.now() + 1000 * 60 * 10, // 過時時間設置爲 10 分鐘後
},
config.jwt.secret, // secret 爲密匙
)
ctx.body = {token: token} // 返回加密後的內容
}
解密加密字符串, 判斷是否與用戶填寫的對應.api
body: { token, phone, code, } response: {...}
phoneChange({
body: {
token: '...',
phone: '18212341234',
code: '1111',
},
query: {},
})
async function phoneChange(ctx) {
const userModel = models.user // 數據庫中的 user 表
const { token, phone, code } = ctx.body
let decoded = jwt.decode(token, config.secret) // 使用 secret 密匙解密 token
let { creator_id } = ctx.state || {}
if(!creator_id) {return console.log('非法請求')}
const apiUser = await userModel.findOne({ where: { id: creator_id }}) // 查詢當前發起請求的用戶
if (apiUser && decoded) {
if(decoded.iat < Date.now()) {return console.log('驗證碼已過時')}
if(decoded.phone !== phone) {return console.log('接收驗證碼的手機號與要修改的手機號不匹配')}
if(decoded.code !== code) {return console.log('驗證碼錯誤')}
const bindUser = await userModel.findOne({where: {bind_phone: phone}, raw: true}) // 查詢是否存在已綁定
if(bindUser) {return console.log('該手機號已有綁定用戶')}
apiUser.bind_phone = phone // 修改成新手機並保存
return ctx.body = await apiUser.save({ new: true })
} else {
return console.log('該用戶不存在')
}
}