seckill.js 6.04 KB
/**
 *  秒杀结算
 */
'use strict';
const _ = require('lodash');
const crypto = global.yoho.crypto;
const co = require('bluebird').coroutine;
const seckillModel = require('../models/seckill');
const headerModel = require('../../../doraemon/models/header'); // 头部model

const BAD_REQUEST = '非法请求';
const SLAT = 'yohobuyseckill98';

exports.ensure = (req, res, next) => {
    const sku = Number.parseInt(req.query.sku, 10);
    const skn = Number.parseInt(req.query.skn, 10);
    const uid = req.user.uid;
    let activityId;

    let orderInfo = req.cookies['order-info'];

    try {
        orderInfo = JSON.parse(req.cookies['order-info']);
    } catch (e) {
        orderInfo = {};
    }

    // require skn, sku;
    if (!(sku && skn)) {
        return next();
    }

    co(function*() {
        let paymentOption = {
            buy_number: 1,
            yoho_coin_mode: 0, // 默认不使用有货币
            product_sku: sku,
            sku_type: 'S',
            uid
        };
        let skillData = yield seckillModel.skillData(skn); // 根据skn查活动信息
        let view = {
            orderEnsure: false,
            message: ''
        };

        skillData = skillData.data;

        // 不在秒杀中
        if (skillData && (skillData.status !== 2)) {
            return res.redirect('/product/seckill');
        }

        if (!(
                skillData &&
                skillData.secKillSku.some(obj => obj.productSku === sku)  // skn has sku;
            )) {
            view.message = '挤爆啦,系统繁忙';
            return res.render('order-ensure', Object.assign({
                module: 'cart',
                page: 'seckill',
                pageHeader: headerModel.setNav({
                    navTitle: '确认订单',
                    backUrl: '/product/show_' + skn + '.html'
                }),
            }, view));
        }

        paymentOption.activity_id = activityId = skillData.activityId;

        let orderComputerData;

        if (orderInfo) {
            orderComputerData = yield seckillModel.compute(_.assign(paymentOption, {
                delivery_way: orderInfo.deliveryId || 1,
                payment_type: orderInfo.paymentType || 1,
                use_yoho_coin: orderInfo.yohoCoin || 0
            }));
        }

        // 获取结算 数据
        let paymentInfo = yield seckillModel.payment(paymentOption, orderInfo, orderComputerData.data);

        if (paymentInfo.code !== 200) {
            view = {
                orderEnsure: false,
                message: paymentInfo.message
            };

            // hotfix: nginx 接口限流, code:9999991时没message 信息
            if (!view.message) {
                view.message = '挤爆啦,系统繁忙';
            }
        } else {
            // 渲染
            view = Object.assign({
                seckill: skillData,
                orderEnsure: true,
                sku,
            }, paymentInfo.data);
        }

        res.locals.title = '确认订单';
        res.render('order-ensure', Object.assign({
            module: 'cart',
            page: 'seckill',
            pageHeader: headerModel.setNav({
                navTitle: '确认订单',
                backUrl: '/product/show_' + skn + '.html'
            }),
            cartToken: crypto.encryption(SLAT, [sku, activityId].join(''))
        }, view));
    })().catch(next);
};

exports.compute = (req, res, next) => {
    const uid = req.user.uid,
        sku = req.body.sku,
        paymentType = Number.parseInt(req.body.paymentType || 1, 10),
        activityId = req.body.activityId;

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

    // 必填字段
    if ([uid, sku, activityId, paymentType].some(field => !field)) {
        return res.status(400).json({
            code: 400,
            msg: BAD_REQUEST
        });
    }

    const options = {
        sku_type: 'S', // 秒杀
        buy_number: 1,
        yoho_coin_mode: 1,
        payment_type: paymentType,
        uid: req.user.uid,
        product_sku: sku,
        delivery_way: req.body.deliveryId || 1,
        use_yoho_coin: req.body.yohoCoin || 0,
        activity_id: activityId
    };

    return seckillModel.compute(options)
        .then(result => {
            res.json(result.data);
        })
        .catch(next);
};


exports.submit = (req, res, next) => {
    const uid = req.user.uid,
        sku = req.body.sku,
        activityId = req.body.activityId,
        deliveryTime = Number.parseInt(req.body.deliveryTime, 10),
        deliveryWay = Number.parseInt(req.body.deliveryWay, 10),
        paymentId = Number.parseInt(req.body.paymentId, 10),
        paymentType = Number.parseInt(req.body.paymentType, 10),
        token = req.body.cartToken;

    let addressId = req.body.addressId || '';

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

    let compareToken = crypto.encryption(SLAT, [sku, activityId].join(''));

    if (token !== compareToken) {
        return next();
    }

    if (!addressId) {
        return res.json({code: 400, message: '请选择地址'});
    } else {
        addressId = Number.parseInt(crypto.decrypt(null, req.body.addressId), 10);
    }

    if ([uid, sku, activityId, addressId, deliveryTime,
        deliveryWay, paymentId, paymentType
    ].some(field => !field)) {
        return res.status(400).json({
            code: 400,
            message: BAD_REQUEST
        });
    }

    const options = {
        sku_type: 'S',
        buy_number: 1,
        invoices_title: req.body.invoicesTitle || '',
        invoices_type_id: req.body.invoicesTypeId || '',
        use_yoho_coin: Number.parseFloat(req.body.useYohoCoin) || 0,
        remark: req.body.remark || '',

        address_id: addressId,
        delivery_time: deliveryTime,
        delivery_way: deliveryWay,
        payment_id: paymentId,
        payment_type: paymentType,
        product_sku: sku,
        activity_id: activityId,
        uid
    };

    return seckillModel.submit(options)
        .then(result => {
            res.clearCookie('order-info');
            res.json(result);
        })
        .catch(next);
};