reg.js 8.03 KB
const _ = require('lodash');
const url = require('url');
const helpers = global.yoho.helpers;
const RegServiceModel = require('../models/reg-service');
const utils = require(global.utils);
const sign = global.yoho.sign;
const co = require('bluebird').coroutine;
const cookie = global.yoho.cookie;
const AuthHelperModel = require('../models/auth-helper');
const config = global.yoho.config;

class Reg {
    /**
     * 注册页面
     */
    regPage(req, res, next) {
        if (req.user.uid) {
            return res.redirect(req.get('refer') || '/');
        }

        // 判断是否 来自 个人中心
        if (!_.get(req.session, 'phoneReg.isFromMy')) {
            let referer = req.get('Referer') || '';
            let urlObj = url.parse(referer, true, true);

            referer = _.get(urlObj, 'query.refer', '');

            urlObj = url.parse(referer, true, true);
            urlObj.path === '/home' && _.set(req.session, 'phoneReg.isFromMy', '1');
        }

        // 设置注册有效时间30分钟, 防机器刷
        // req.session.REG_EXPIRE = Date.now() + 1800000;
        let refer = req.query.refer;

        refer = utils.refererLimit(refer);

        refer && res.cookie('refer', encodeURI(refer), {
            domain: 'yohobuy.com'
        });

        // session init
        _.set(req.session, 'phoneReg.step', 1);

        if (req.session.captchaValidCount == null) { // eslint-disable-line
            req.session.captchaValidCount = 5;
        }

        if (req.session.phoneReg.count == null) { // eslint-disable-line
            req.session.phoneReg.count = 5;
        }

        co(function* () {
            let inviteValue = '';
            let inviteCode = req.query.inviteCode;

            if (inviteCode) {
                let inviteUserInfo = yield req.ctx(RegServiceModel).inviteUserInfo(inviteCode);

                inviteValue = _.get(inviteUserInfo, 'data.trendWord', inviteCode);
            }

            res.render('reg/reg-new', {
                module: 'passport',
                page: 'reg-new',
                localCss: true,
                width750: true,
                inviteValue: inviteValue,
                countrys: req.ctx(RegServiceModel).getAreaData(), // 地区信息列表
                captchaShow: req.yoho.captchaShow
            });
        })().catch(next);
    }

    /**
     * 注册请求处理
     */
    register(req, res, next) {
        let postResult = {
            code: 400
        };

        let mobile = +req.body.phoneNum;
        let area = +(req.body.areaCode || 86);
        let password = req.body.password;
        let smsCode = +req.body.smsCode;
        let inviteCode = req.body.inviteCode || '';
        let isFromMy = _.get(req.session, 'phoneReg.isFromMy', '0');
        let token = req.body.token;
        let clientIp = req.yoho.clientIp || '';
        let from = req.cookies.from || 'yohobuy';

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

        // 判断参数是否合法
        if (!smsCode || !_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) {
            postResult.message = '请求参数不合法';
            return res.json(postResult);
        }

        // 判断是否允许访问
        if (!sign.verifyToken(mobile, token)) {
            postResult.message = '非法 token';
            return res.json(postResult);
        }

        // 判断密码是否符合规则
        if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/.test(password)) {
            postResult.message = '密码格式不正确';
            return res.json(postResult);
        }

        co(function* () {
            let validMobileCodeResult = yield req.ctx(RegServiceModel).validMobileCode(area, mobile, smsCode);

            if (!validMobileCodeResult.code) {
                return res.json(validMobileCodeResult);
            }

            let resultCode = _.get(validMobileCodeResult, 'code');

            if (resultCode !== 200) {
                return res.json(validMobileCodeResult);
            }

            let regMobileAesResult = yield req.ctx(RegServiceModel).regMobileAes(area, mobile, password,
                shoppingKey, smsCode, inviteCode, isFromMy, clientIp, from);

            if (regMobileAesResult.code !== 200 || !regMobileAesResult.data ||
                !regMobileAesResult.data.uid) {
                return res.json(regMobileAesResult);
            }

            let authData = yield req.ctx(AuthHelperModel).syncUserSession(regMobileAesResult.data.uid,
                req, res, regMobileAesResult.data.session_key);

            // 返回跳转到来源页面
            let refer = req.cookies.refer;

            if (regMobileAesResult.data.newUserPage) {
                refer = regMobileAesResult.data.msgDelivery; // 来自个人中心,跳新人会场
            } else {
                if (refer) {
                    refer = decodeURI(req.cookies.refer);
                } else {
                    refer = '/home';
                }

                if (/sign|login/.test(refer)) {
                    refer = '/home';
                }

                refer = utils.refererLimit(refer);
            }

            delete req.session.phoneNum;

            return res.json({
                code: 200,
                message: '注册成功',
                data: {
                    session: refer,
                    href: _.get(authData, 'refer') || '//m.yohobuy.com/activity/invite-reg',
                    msgDelivery: _.get(regMobileAesResult, 'data.msgDelivery', '')
                }
            });
        })().catch(next);
    }

    verifyMobile(req, res, next) {
        let data = {
            code: 400,
            message: '手机号已存在',
            data: ''
        };

        let mobile = +req.body.phoneNum;
        let area = +(req.body.areaCode || 86);
        let inviteCode = req.body.inviteCode || '';
        let udid = req.sessionID;
        let captcha = req.body.captcha;
        let superCapture = '';

        // 判断参数是否合法
        if (!_.isNumber(mobile) || !_.isNumber(area)) {
            data.message = '手机号错误';
            return res.json(data);
        }

        if (req.body.geetest_challenge) {
            captcha = '';
            superCapture = config.superCapture;
        }

        // 向手机发送注册验证码
        req.ctx(RegServiceModel).sendCodeToMobile({
            area, mobile, udid, captcha, superCapture
        }).then((result) => {
            if (result.code !== 200) {
                data.message = result.message;
                return res.json(data);
            }

            // 返回跳转到验证页面的链接
            if (result.code === 200) {
                let token = sign.makeToken(mobile);

                _.set(req.session, 'phoneReg.step', 2); // go step 2
                --req.session.phoneReg.count;

                // count is 0, will freeze;
                if (!req.session.phoneReg.count) {
                    _.set(req.session, 'phoneReg.expire', Date.now() + 5 * 60 * 1000);
                }

                result.data = {
                    href: helpers.urlFormat('/passport/reg/code', {
                        token: token,
                        phoneNum: mobile,
                        areaCode: area,
                        inviteCode: inviteCode
                    }),
                    token: token
                };
            }
            return res.json(result);
        }).catch(next);
    }

    sendCodeBusyBoy(req, res, next) {
        let count = _.get(req.session, 'phoneReg.count');
        let expire = _.get(req.session, 'phoneReg.expire');

        if (count) {
            return next();
        } else {
            let now = Date.now();

            if (now > expire) {
                _.set(req.session, 'phoneReg.count', 5);
                return next();

            } else {
                return res.json({
                    code: 400,
                    message: '发送次数太多, 5分钟稍后再试'
                });
            }

        }
    }
}

module.exports = new Reg();