sms.js 3.55 KB
/**
 * 短信controller
 * @author: leo <qi.li@yoho.cn>
 * @date: 2017/06/26
 */
'use strict';
const _ = require('lodash');
const moment = require('moment');
const EventEmitter = require('events');
const SmsModel = require('../models/sms');

const smsController = {

    /**
     * 发送短信前
     * @param req
     * @param res
     * @param next
     * @returns {*}
     */
    beforeSend(req, res, next) {
        const count = _.get(req.session, 'smsSend.count');
        const interval = _.get(req.session, 'smsSend.interval', 0);

        // 重发次数用完了, 冻结5min
        // 过了冻结期, count重设为5次
        // 没有用完, 判断是否请求太频繁
        const now = Date.now();
        const during = moment.duration(interval - now, 'ms').minutes();
        const msg = {
            code: 429,
            message: `请${during || 1}分钟后再试`
        };

        if (interval > now) {
            return res.json(msg);
        }

        // 重置可发送次数
        !count && _.set(req.session, 'smsSend.count', 5);

        next();
    },

    /**
     * 发送短信验证码
     * @param req
     * @param res
     * @returns {*|boolean}
     */
    sendCode(req, res) {
        const em = new EventEmitter();
        const area = (req.body.area || '86').trim();
        const mobile = (req.body.mobile || '').trim();
        const inValid = [area, mobile].some(v => v === '');

        em.on('resolve', () => {
            req.ctx(SmsModel).sendSMS(mobile, area, 1)
                .then(result => {
                    if (result.code === 200) {
                        _.set(req.session, 'smsSend.area', area);
                        _.set(req.session, 'smsSend.mobile', mobile);

                        // 剩余次数
                        --req.session.smsSend.count;

                        if (!req.session.smsSend.count) {
                            _.set(req.session, 'smsSend.interval', Date.now() + 5 * 60 * 1000);
                        } else {
                            _.set(req.session, 'smsSend.interval', Date.now() + 60 * 1000);
                        }

                        return res.json({
                            code: 200,
                            message: '验证码发送成功'
                        });
                    }

                    res.json({
                        code: 500,
                        message: '验证码发送失败'
                    });
                });
        });

        em.on('reject', error => {
            res.json(error);
        });


        if (!inValid) {
            em.emit('resolve');
            return;
        }

        em.emit('reject', {
            code: 400,
            message: '请填写手机号'
        });
    },

    /**
     * 验证码校验
     * @param req
     * @param res
     */
    checkCode(req, res, next) {
        const code = (req.body.code || '').trim();
        const area = _.get(req.session, 'smsSend.area', '');
        const mobile = _.get(req.session, 'smsSend.mobile', '');

        req.ctx(SmsModel).verifySMS(mobile, area, code, 1)
            .then(result => {
                if (result.code !== 200) {
                    res.json(result);
                    return;
                }

                if (result.data.is_pass !== 'Y') {
                    res.json({
                        code: 501,
                        message: '验证码与手机号不匹配'
                    });
                    return;
                }
                next();
            });
    }
};

module.exports = smsController;