reg.js 12.2 KB
const request = require('request-promise');
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 BaiduSDK {
    /*
     * @ description: 广告主回传转化数据接口, 上报百度
     * @ author: huzhiming
     * @ date: 2019-11-19 17:21:29
     * @ version: v1.0.0
     * 详情见文档:[http://ocpc.baidu.com/developer/d/guide/?iurl=api%2Fapi-doc%2Fapi-interface%2F]
    */
    static reportOcpcApi({
        token = '7GULUkX90QLZU6cHO9OEqUsRKttGNqpN@O62eFfb91OUVhmkakV1bQHIxF8xURBvP',
        conversionTypes = [{ logidUrl: '', newType: null }]
    }) {
        request({
            method: 'POST',
            uri: 'http://ocpc.baidu.com/ocpcapi/api/uploadConvertData',
            body: {
                token,
                conversionTypes
            },
            json: true
        }).then((result) => {
            console.log(`[账号注册成功后上报 百度ocpc返回信息:${JSON.stringify(result)}`);
        }).catch((error) => {
            console.log(`[账号注册成功后上报 百度ocpc失败 错误信息:${error}`);
        });
    }
}

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);
    }

    /**
     * 首次注册成功领券页面
     * @param req
     * @param res
     * @param next
     */
    regSuccessPage(req, res, next) {
        let {activityId = 5475, templateId = 6047} = req.query;

        if ((!global.isProduction) && (!req.query.activityId || !req.query.templateId)) {
            activityId = 528;
            templateId = 4166;
        }

        if (!req.user.uid) {
            res.redirect('//m.yohobuy.com');
            return;
        }

        let user_info = {
            uid: req.query.uid || req.session.LOGIN_UID_ || req.user.uid.toString() || 0,
            session_key: req.query.session_key || req.session.SESSION_KEY || req.user.uid.sessionKey || '',
            app_version: req.query.app_version || config.appVersion,
            app_client_type: req.query.app_client_type || config.app
        };

        let userInfoParams = '?uid=' + user_info.uid + '&session_key=' + user_info.session_key +
            '&app_version=' + user_info.app_version + '&app_client_type=' + user_info.app_client_type;

        if (!user_info.uid || !user_info.session_key) {
            userInfoParams = '?1=1';
        }

        req.ctx(RegServiceModel).regSuccessPrize(activityId, templateId).then(result => {
            let regSuccessCouponInfo = {
                activityId: activityId,
                templateId: templateId,
                totalPrice: 0,
                normalCoupon: [],
                shareCoupon: [],
                boughtCoupon: [],
                userInfo: userInfoParams
            };

            _.each(result.data, (couponData) => {
                _.each(couponData.coupons, (coupon) => {
                    if (couponData.name === 'NEW_USER_REGISTER') {
                        regSuccessCouponInfo.totalPrice += parseInt(coupon.amount, 10) || 0;
                        regSuccessCouponInfo.normalCoupon.push(coupon);
                    } else if (couponData.name === 'NEW_USER_SHARE') {
                        regSuccessCouponInfo.shareCoupon.push(coupon);
                    } else if (couponData.name === 'ORDER_BUY') {
                        regSuccessCouponInfo.boughtCoupon.push(coupon);
                    }

                });
            });

            res.render('reg/reg-success-prize', {
                module: 'passport',
                page: 'reg-success-prize',
                localCss: true,
                width750: true,
                regSuccessCouponInfo: regSuccessCouponInfo
            });
        }).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;

            /*
             * @ description: feat(oCPC搜索推广): 推广链接转化数据发送给百度服务器,埋点:OCPC推广链接打开并完成注册进行数据上报
             * @ author: huzhiming
             * @ date: 2019-11-19 19:09:39
             * @ version: v1.0.0
             * bd_vid_path存值见:public/js/common.js 文件
            */
            const logidUrl = req.cookies.bd_vid_path;

            if (logidUrl) {
                BaiduSDK.reportOcpcApi({
                    conversionTypes: {
                        logidUrl,
                        newType: 3
                    }
                });
            }

            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.cookies.udid;
        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') || 0;

        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();