3party-bind.js 8.29 KB
/**
 * Created by yoho on 2016/11/23.
 */

'use strict';

const _ = require('lodash');

const passport = require('passport');
const uuid = require('uuid');
const log = global.yoho.logger;
const userModel = require('../models/user-service');
const config = global.yoho.config;
const authcode = require(`${global.utils}/authcode`);
const AUTH_TIME = 2592000000;

const updateSessionKey = (res, sessionKey) => {
    if (sessionKey) {
        res.cookie('_SESSION_KEY', authcode(sessionKey, '_SESSION_KEY', AUTH_TIME, 'encode'), {
            domain: config.cookieDomain,
            httpOnly: true
        });
    }
};

function bindSuccess(res, type) {
    return res.render('home/user/bind-result', {
        module: 'home',
        page: 'bind-result',
        layout: false,
        type: type,
        bindResult: 'success',
        message: '绑定成功!'
    });
}

function bindFail(res, message, type) {
    return res.render('home/user/bind-result', {
        module: 'home',
        page: 'bind-result',
        layout: false,
        type: type,
        bindResult: 'fail',
        bindResultMessage: message || '绑定失败,请稍后再试!'
    });
}

const bind3party = (req, res, user) => {
    req.ctx(userModel).bind3partyAccount(req.user.uid, user)
        .then(ret => {

            if (ret && ret.code === 200) {
                updateSessionKey(res, _.get(ret, 'data.session_key', ''));
                return bindSuccess(res, user.sourceType);
            }
            return bindFail(res, ret && ret.message, user.sourceType);
        })
        .catch(err => {
            return bindFail(res, err, user.sourceType);
        });
};

const wechat = {
    login: (req, res, next) => {
        req.session.authState = uuid.v4();
        return passport.authenticate('home-wechat', {
            state: req.session.authState
        })(req, res, next);
    },
    callback: (req, res, next) => {
        if (req.session && req.session.authState && req.session.authState === req.query.state) {
            passport.authenticate('home-wechat', (err, user) => {
                if (err) {
                    log.error(`wechat authenticate error : ${JSON.stringify(err)}`);
                    return bindFail(res, '微信登录失败,请稍后再试!', 'wechat');
                } else {
                    bind3party(req, res, {
                        openId: user._json.unionid, // user._json.openid,
                        unionId: user._json.unionid || user.id,
                        nickname: user._json.nickname || user.displayName,
                        sourceType: 'wechat',
                        rawUser: user
                    });
                }
            })(req, res, next);
        } else {
            // return next(new Error('Wechat Auth State Mismatch'));
            return bindFail(res, '微信登录失败,请稍后再试!', 'wechat');
        }
    }
};

const sina = {
    login: (req, res, next) => {
        req.session.authState = uuid.v4();
        return passport.authenticate('home-sina', {
            state: req.session.authState
        })(req, res, next);
    },
    callback: (req, res, next) => {
        if (req.session && req.session.authState && req.session.authState === req.query.state) {
            passport.authenticate('home-sina', (err, user) => {
                if (err) {
                    log.error(`sina authenticate error : ${JSON.stringify(err)}`);
                    return bindFail(res, '新浪微博登录失败,请稍后再试!', 'sina');
                }
                let nickname = _.trim(user.screen_name);
                let openId = user.id;

                bind3party(req, res, {
                    openId: openId,
                    nickname: nickname,
                    sourceType: 'sina'
                });
            })(req, res, next);
        } else {
            // return next(new Error('Sina Auth State Mismatch'));
            return bindFail(res, '微信登录失败,请稍后再试!', 'sina');
        }
    }
};

const qq = {
    login: (req, res, next) => {
        let type = req.query.type || 'yohobuy';
        let authState = req.session.authState = (req.query.state || uuid.v4()) + '::' + type;

        return passport.authenticate('home-qq', {
            state: authState
        })(req, res, next);
    },
    callback: (req, res, next) => {

        if (req.session && req.session.authState && req.session.authState === req.query.state) {
            passport.authenticate('home-qq', (err, user) => {
                if (err) {
                    log.error(`qq authenticate error : ${JSON.stringify(err)}`);
                    return bindFail(res, 'QQ登录失败,请稍后再试!', 'qq');
                }
                let nickname = _.trim(user.nickname);
                let openId = user.id;

                bind3party(req, res, {
                    openId: openId,
                    nickname: nickname,
                    sourceType: 'qq'
                });
            })(req, res, next);
        } else {
            return bindFail(res, '微信登录失败,请稍后再试!', 'qq');
        }
    }
};

const alipay = {
    login: (req, res, next) => {
        return passport.authenticate('home-alipay')(req, res, next);
    },
    callback: (req, res, next) => {
        passport.authenticate('home-alipay', (err, user) => {
            if (err) {
                log.error(`alipay authenticate error : ${JSON.stringify(err)}`);
                return bindFail(res, '支付宝登录失败,请稍后再试!', 'alipay');
            }
            let nickname = _.trim(user.realName);
            let openId = user.userId;

            bind3party(req, res, {
                openId: openId,
                nickname: nickname,
                sourceType: 'alipay'
            });
        })(req, res, next);
    }
};

const douban = {
    login: (req, res, next) => {
        req.session.authState = uuid.v4() + '::bind';
        return passport.authenticate('douban', {
            state: req.session.authState
        })(req, res, next);
    },
    callback: (req, res, next) => {
        passport.authenticate('douban', (err, user) => {
            if (err) {
                log.error(`douban authenticate error : ${JSON.stringify(err)}`);
                return bindFail(res, '豆瓣登录失败,请稍后再试!', 'douban');
            }

            let nickname = _.trim(user.displayName);
            let openId = user.id;

            bind3party(req, res, {
                openId: openId,
                nickname: nickname,
                sourceType: 'douban'
            });
        })(req, res, next);
    }
};

const renren = {
    login: (req, res, next) => {
        req.session.authState = uuid.v4();
        return passport.authenticate('home-renren', {
            state: req.session.authState
        })(req, res, next);
    },
    callback: (req, res, next) => {
        passport.authenticate('home-renren', (err, user) => {
            if (err) {
                log.error(`renren authenticate error : ${JSON.stringify(err)}`);
                return bindFail(res, '人人网登录失败,请稍后再试!', 'renren');
            }

            let nickname = _.trim(user.displayName);
            let openId = user.id;

            bind3party(req, res, {
                openId: openId,
                nickname: nickname,
                sourceType: 'renren'
            });
        })(req, res, next);
    }
};

const cancelBind = (req, res) => {
    let type = req.params.type;


    if (!(req.get('Referer') || '').match(/yohobuy.com/)) {
        return res.send({
            code: 501,
            message: '非法请求'
        });
    }

    if (!type) {
        res.status(400).json({
            code: 400,
            message: '解绑类型不正确!'
        });
    }

    req.ctx(userModel).cancelBind3partyAccount(req.user.uid, type)
        .then(ret => {
            if (ret && ret.code === 200) {
                return res.send(ret);
            }
            return res.send({
                code: 401
            });
        })
        .catch(err => {
            res.send({
                code: 401,
                message: err
            });
        });
};

module.exports = {
    wechat: wechat,
    sina: sina,
    qq: qq,
    alipay: alipay,
    douban: douban,
    renren: renren,
    cancelBind,
    bindFail,
    bind3party
};