网易云信短信接口签名生成方法
短信接入文档
1.配置
在网易云信管理中心->应用管理->自己的应用里查看appkey和appsecret
'sms':{
appSecret:"xxxxxxxxxxxxx",
appKey:"xxxxxxxxxxxxxx"
}
2.生成签名
需要三样东西来生成签名
- 密钥 appSecret
- 随机字符串 nonce
- 时间戳 CurTime
//生成随机字符串 借用微信的
const createNonceStr = function () {
return Math.random().toString(36).substr(2, 15);
};
// 生成时间戳 秒值 借用微信的
const createTimestamp = function () {
return parseInt(new Date().getTime() / 1000) + "";
};
//进行SHA1哈希计算,转化成16进制字符 这里用的库为jshashes
const generateSHA1SignatureByHex = (appSecret, nonce, timestamp) => {
const sha1Str = appSecret + nonce + timestamp;
const SHA1 = new Hashes.SHA1().hex(sha1Str)
return SHA1;
}
可以不局限于这些生成方法 只要是满足位数条件都可以 比如生成随机字符串 可以用chance库也很不错,SHA1也有不少库digitalbazaar/forge、h2non/jshashes
3.拼请求参数
//可以写个业务方法包裹一下 或者直接在拼装header的方法散写也可以
const generateSignatureForCode = () => {
const appSecret = Config.sms.appSecret;
const Nonce = createNonceStr();
const CurTime = createTimestamp();
const SHA1 = Util.generateSHA1SignatureByHex(appSecret,Nonce,CurTime)
return {
Nonce:Nonce,
CurTime:CurTime,
SHA1:SHA1
};
}
// 拼装请求头
const getRequestSmsHeaders = function () {
const appkey = Config.sms.appKey;
const SHA1 = Util.generateSignatureForCode({
appsecret: Config.sms.appSecret,
})
return {
'Content-Type': "application/x-www-form-urlencoded;charset=utf-8",
'AppKey': appKey, //开发者平台分配的appkey 别写错了
'Nonce': Nonce,
'CurTime': CurTime,
'CheckSum': SHA1
}
}
4.发送请求
// 这里使用的request库 当然其他的随意
const requestService = function (options) {
return new Promise(function (resolve, reject) {
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
resolve(info)
} else {
reject(error);
}
});
})
}
//返回值
出错情况最多的:
{ code: 414, msg: 'checksum' }
文档里解释这是签名参数出错 但不是签名算法的问题 检查一下appKey appSecret的属性拼写
成功:
{ code: 200, msg: '1410', obj: '2846' }
obj为验证码
融云IM-TOKEN方法
如法炮制,把请求头改成符合他条件的就好
文档 融云文档真是比网易的强太多
const getRequestHeaders = function () {
const appkey = Config.im.appKey;
const appSecret = Config.im.appSecret;
const Nonce = Util.createNonceStr();
const Timestamp = Util.createTimestamp();
const SHA1HEX = Util.generateSHA1SignatureByHex(appSecret, Nonce, Timestamp);
return {
'Content-Type': "application/x-www-form-urlencoded;charset=utf-8",
'App-Key': appkey, //开发者平台分配的appkey
'Nonce': Nonce,
'Timestamp': Timestamp,
'Signature': SHA1HEX
}
}
const request = require('request')
const Hashes = require('jshashes')
const SmsCode = require("../util/codes")
const Config = require("../config/")
const Util = require("../util/")
const CommonModel = require("../model/common")
const generateSignatureForCode = () => {
const appSecret = Config.sms.appSecret;
const Nonce = Util.createNonceStr();
const CurTime = Util.createTimestamp();
const SHA1 = Util.generateSHA1SignatureByHex(appSecret, Nonce, CurTime)
return {
Nonce: Nonce,
CurTime: CurTime,
SHA1: SHA1
};
}
const getRequestSmsHeaders = function () {
const appKey = Config.sms.appKey;
const SignatureInfo = generateSignatureForCode()
return {
'Content-Type': "application/x-www-form-urlencoded;charset=utf-8",
'AppKey': appKey, //开发者平台分配的appkey
'Nonce': SignatureInfo.Nonce,
'CurTime': SignatureInfo.CurTime,
'CheckSum': SignatureInfo.SHA1
}
}
const sendcode = async function (query) {
let mobile = query.mobile;
if ("register" == query.type||"bind"==query.type) {
let _result = await CommonModel.findOne("auth", {
where: {
indentity_type: "1", //密码注册
indentifier: mobile
}
});
let _checkMobileResult = await CommonModel.findOne("user", {
where: {
mobile: mobile
}
});
if (!!_result || !!_checkMobileResult) {
return {
status: false,
code: -1,
msg: "手机号已经被绑定或注册~"
};
}
}
let _resBody = {};
let _reqUrl = "https://api.netease.im/sms/sendcode.action";
let _reqHeaders = getRequestSmsHeaders();
let options = {
url: _reqUrl,
method: "POST",
headers: _reqHeaders,
form: {
templateid: 3041014,
mobile: mobile
}
};
let _res = await Util.requestService(options);
switch (_res.code) {
case 200:
_resBody = {
status: true,
code: 0,
msg: "发送成功",
data: {
code: _res.obj,
}
}
break;
case 404:
_resBody = {
status: false,
code: 100400,
msg: "验证码过期"
}
break;
case 414:
_resBody = {
status: false,
code: 100414,
msg: "缺少参数"
}
break;
case 416:
_resBody = {
status: false,
code: 100416,
msg: "您发的太快啦"
}
break;
case 500:
_resBody = {
status: false,
code: 100500,
msg: "短信收发服务故障"
}
break;
case 413:
_resBody = {
status: false,
code: 100413,
msg: "短信验证失败"
}
break;
default:
_resBody = {
status: false,
code: -1,
msg: SmsCode[_res.code] || "未知错误"
}
break;
}
return _resBody;
}
const verifycode = async function (query) {
let mobile = query.mobile;
let code = query.code;
let _resBody = {};
let _reqUrl = "https://api.netease.im/sms/verifycode.action";
let _reqHeaders = getRequestSmsHeaders();
let options = {
url: _reqUrl,
method: "POST",
headers: _reqHeaders,
form: {
mobile: mobile,
code: code
}
};
let _res = await Util.requestService(options);
switch (_res.code) {
case 200:
_resBody = {
status: true,
code: 0,
msg: "校验成功"
}
break;
case 404:
_resBody = {
status: false,
code: 100400,
msg: "验证码过期"
}
break;
case 414:
_resBody = {
status: false,
code: 100414,
msg: "缺少参数"
}
break;
case 416:
_resBody = {
status: false,
code: 100416,
msg: "您发的太快啦"
}
break;
case 500:
_resBody = {
status: false,
code: 100500,
msg: "短信收发服务故障"
}
break;
case 413:
_resBody = {
status: false,
code: 100413,
msg: "短信验证失败"
}
break;
default:
_resBody = {
status: false,
code: -1,
msg: SmsCode[_res.code] || "未知错误"
}
break;
}
return _resBody;
}
const actionMap = {
sendcode: sendcode,
verifycode: verifycode
}
const handleAction = async(ctx, next) => {
let req = ctx.request.fields || ctx.request.query;
let action = req.action;
let _resBody = await actionMap[action].call(ctx, req);
ctx.body = _resBody;
return next()
}
module.exports = {
handleAction,
sendcode,
verifycode
}