sms.js 8.1 KB
/* eslint no-unused-vars: ["error", { "args": "none" }] */
'use strict';
const helpers = global.yoho.helpers;
const cookie = global.yoho.cookie;
const RegService = require('../models/reg-service');
const PhoneService = require('../models/phone-service');
const AuthHelper = require('../models/auth-helper');

// constrant
const CODE_REQUIRED = '请输入校验码';
const PASSWORD_REQUIRED = '请输入密码';
const PASSWORD_LENGTH_ERROR = '密码6-20位,请重新输入';
const BAD_PASSWORD = '密码格式不正确';
const TOO_MANY = '请求太频繁';
const LOGIN_SUCCSS = '登录成功';
const VERIFY_ERROR = '校验失败';

exports.beforeIn = (req, res, next) => {
    res.set({
        'Cache-Control': 'no-cache, no-store, must-revalidate',
        Pragma: 'no-cache',
        Expires: 0
    });

    if (!req.xhr && req.user.uid) {
        return res.redirect(req.cookies.refer);
    }

    next();
};

// 短信登录 第一步: 展现页面
const _step1 = (req, res, next) => {
    let template = 'sms/login';
    let viewData = {
        module: 'passport',
        page: 'sms-login',
        title: '手机短信登录',
        isPassportPage: true,
        headerText: '手机号码快捷登录',
        areaCode: '+86', // 默认的区号
        countrys: RegService.getAreaData() // 地区信息列表
    };

    res.render(template, viewData);
};

// 短信登录 第二步: 输入 校验码
const _step2 = (req, res, next) => {
    const mobile = req.session.smsLogin.mobile;
    const area = req.session.smsLogin.area;
    const interval = req.session.smsLogin.interval;

    const template = 'sms/check';
    const viewData = {
        module: 'passport',
        page: 'sms-check',
        title: '手机短信登录',
        isPassportPage: true,
        headerText: '手机号码快捷登录',
        canResend: interval < Date.now(),
        mobile,
        area
    };

    res.render(template, viewData);
};

// 短信登录 第三步: 设置密码 (针对 改手机未注册用户)
const _step3 = (req, res, next) => {
    const template = 'sms/password';
    const viewData = {
        module: 'passport',
        page: 'sms-password',
        title: '设置密码',
        isPassportPage: true,
        headerText: '设置密码'
    };

    res.render(template, viewData);
};

// 短信 登录
exports.loginPage = (req, res, next) => {
    let step = Number(req.query.step) || 1;
    let smsLoginStep = req.session.smsLoginStep || 1;

    if (step === 2 && smsLoginStep !== 2) {
        return res.redirect(req.path);
    }

    if (step === 3 && smsLoginStep !== 3) {
        return res.redirect(req.path);
    }

    switch (step) {
        case 2:
            _step2(req, res, next);
            break;
        case 3:
            _step3(req, res, next);
            break;
        case 1:
        default:
            _step1(req, res, next);
    }
};

exports.tokenBefore = (req, res, next) => {
    let area = req.query.area = (req.query.area || '').trim();
    let mobile = req.query.mobile = (req.query.mobile || '').trim();

    if (!req.xhr) {
        return next(404);
    }

    if (req.session.smsLogin && req.session.smsLogin.interval > Date.now()) {
        return res.json({
            code: 429,
            message: TOO_MANY
        });
    }


    if ([area, mobile].some(val => val === '')) {
        return res.json({
            code: 401,
            message: '请求参数,无法处理'
        });
    }

    next();
};

// AJAX 获取验证码
exports.token = (req, res, next) => {
    let area = req.query.area;
    let mobile = req.query.mobile;

    PhoneService.sendSMS(mobile, area, 1).then(result => {
        if (result.code === 200) {
            req.session.smsLogin = {
                interval: Date.now() + 60 * 1000, // 重发验证码 间隔: 60s
                area,
                mobile
            };
            req.session.smsLoginStep = 2; // 进入短信登录 step2

            result.redirect = '/passport/sms_login?step=2';
            res.json(result);
            return;
        }

        res.json(result);
    });
};

exports.checkBefore = (req, res, next) => {
    let code = req.query.code = (req.query.code || '').trim();

    if (!req.xhr && req.session.smsLoginStep !== 2) {
        return next(404);
    }

    if (!code) {
        return res.json({
            code: 404,
            message: CODE_REQUIRED
        });
    }

    next();
};

// AJAX 校验验证码 in step2
exports.check = (req, res, next) => {
    const code = req.query.code;
    const mobile = req.session.smsLogin.mobile;
    const area = req.session.smsLogin.area;
    const shopping_key = cookie.getShoppingKey(req); // eslint-disable-line


    Promise.all([
        PhoneService.checkUserPhoneExist(mobile, area),
        PhoneService.verifySMS(mobile, area, code, 1)
    ])
        .then(result => {
            let r1 = result[0] || {};
            let r2 = result[1] || {};
            let redirect;

            // 验证码 校验异常
            if (r2.code !== 200) {
                res.json(r2);
                return;
            }

            // 检测 手机号 是否注册 异常
            if (r1.code !== 200) {
                res.json(r1);
                return;
            }

            // 校验失败
            if (r2.data.is_pass !== 'Y') {
                res.json({
                    code: 401,
                    message: VERIFY_ERROR
                });

                return;
            }

            // 手机号码 没注册
            if (r1.data.is_register !== 'Y') {
                redirect = '/passport/sms_login?step=3';
                req.session.smsLoginStep = 3;

                res.json({
                    code: 200,
                    redirect,
                    newer: true,
                });

                return;
            }

            // 手机号码已注册 --> 直接登录
            PhoneService.autoSignin({
                profile: mobile,
                code: r2.data.code,
                area,
                shopping_key
            })
                .then(info => {
                    if (info.code !== 200) {
                        return Promise.reject(info);
                    }

                    return AuthHelper.syncUserSession(info.data.uid, req, res);
                })
                .then(() => {
                    res.json({
                        code: 200,
                        message: LOGIN_SUCCSS,
                        redirect: req.cookies.refer
                    });

                    delete req.session.smsLogin;
                    delete req.session.smsLoginStep;
                })
                .catch(error => {
                    res.json(error);
                });

        })
        .catch(next);
};

// AJAX 短信登录 设置密码 in step3
exports.password = (req, res, next) => {
    if (req.session.smsLoginStep !== 3) {
        return next();
    }


    let data = {
        code: '400',
        message: BAD_PASSWORD
    };

    let smsLogin = req.session.smsLogin || {};
    let mobile = smsLogin.mobile;
    let area = smsLogin.area;
    let password = (req.body.password || '').trim();
    let smsCode = +req.body.smsCode || 0;

    if (!password) {
        data.message = PASSWORD_REQUIRED;
        return res.json(data);
    }

    if (password.length < 6 || password.length > 20) {
        data.message = PASSWORD_LENGTH_ERROR;
        return res.json(data);
    }

    if (!helpers.verifyPassword(password)) {
        return res.json(data);
    }

    // 购物车key
    let shoppingKey = cookie.getShoppingKey(req);


    RegService.regMobileAes(area, mobile, password, shoppingKey, smsCode).then(result => {
        if (!result.code || result.code !== 200) {
            return Promise.reject(result);
        }
        if (!result.data || !result.data.uid) {
            return Promise.reject(result);
        }

        return AuthHelper.syncUserSession(result.data.uid, req, res);
    }).then(() => {
        res.json({
            code: 200,
            message: LOGIN_SUCCSS,
            redirect: req.cookies.refer
        });
        delete req.session.smsLogin;
        delete req.session.smsLoginStep;
    }).catch(next);


};