【nodejs】网易云信短信接入&融云IM-token获取

网易云信短信接口签名生成方法

短信接入文档

1.配置

在网易云信管理中心->应用管理->自己的应用里查看appkey和appsecret

Paste_Image.png
'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/forgeh2non/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为验证码
Paste_Image.png

融云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
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,312评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,578评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,337评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,134评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,161评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,303评论 1 280
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,761评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,421评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,609评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,450评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,504评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,194评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,760评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,836评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,066评论 1 257
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,612评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,178评论 2 341

推荐阅读更多精彩内容

  • 一、背景介绍 作为一名Android开发,从最初的跌跌撞撞到现在小有所悟,这其中经历过的辛酸苦辣也是一种痛并快乐着...
    freecats08阅读 4,811评论 7 54
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,315评论 25 707
  • 窗外风大得狠,窗子一直丝丝作响,也许我是被它叫醒的,又或许是心里被压着需要醒来。脑子里还想着人间四月天里的故事情节...
    下雨了收衣服阅读 206评论 3 1
  • 有个家长跟我分享了这样一个故事:有一天他的孩子坚持看电视而不写作业,他很生气。但他一直压抑着自己的情绪,心里默念着...
    拂景阅读 1,069评论 0 2