pay.js 10.8 KB
/*
 * 支付
 * @Author: Targaryen
 * @Date: 2017-01-04 15:17:51
 * @Last Modified by: Targaryen
 */

'use strict';

const _ = require('lodash');
const mRoot = '../models';
const payModel = require(`${mRoot}/pay`);
const utils = '../../../utils';
const payProcess = require(`${utils}/pay-process`);
const payTool = payProcess.payTool;
const headerModel = require('../../../doraemon/models/header'); // 头部model
const aboutModel = require('../../../doraemon/models/about');
const co = require('bluebird').coroutine;
const helpers = global.yoho.helpers;
const Payment = require('../helpers/payment');
const WxPay = require('../helpers/pay/wechat');
const common = require('../helpers/pay/common');
const logger = global.yoho.logger;

/**
 * 支付中心
 * @param req
 * @param res
 * @param next
 */
const payCenter = (req, res, next) => {
    let orderCode = req.query.order_code;
    let uid = req.user.uid;
    let sessionKey = req.session.TOKEN;
    let userAgent = req.get('User-Agent') || '';
    let hasWxShare = Boolean(userAgent.match(/MicroMessenger/i) && userAgent.match(/MicroMessenger/i).length > 0);

    if (!orderCode || !uid) {
        logger.info(`payCenter:no orderCode or uid:orderCode ${orderCode}, uid ${uid}`);
        return res.redirect('/');
    }

    if (sessionKey) {
        sessionKey = sessionKey.substr(0, sessionKey.length - 8);
    } else {
        logger.info(`payCenter: orderCode-${orderCode} no sessionKey`);
    }

    co(function* () {
        let orderDetail = yield req.ctx(payModel).payCenter({
            orderCode: orderCode,
            uid: uid,
            sessionKey: sessionKey
        });

        let attribute = _.parseInt(_.get(orderDetail, 'attribute'));
        let paymentType = _.parseInt(_.get(orderDetail, 'payment_type')); // 支付类型,2 为货到付款

        if (attribute === 9 || attribute === 11 || paymentType === 2) {
            return res.redirect('/home/orders');
        }

        /* 判断订单是否已付款, 已付款跳到订单详情页 */
        if (orderDetail.payment_status === 'Y') {
            logger.info(`payCenter: orderCode-${orderCode} already paied`);
            return res.redirect(helpers.urlFormat('/cart/shopping/pay/payZero', {order_code: orderCode}));
        }

        if (hasWxShare) {
            let openId = req.cookies['weixinOpenId' + orderCode];

            if (!openId) {
                let getOpenidResult = yield WxPay.getOpenid(req.query.code, req.originalUrl);

                if (getOpenidResult.openid) {
                    openId = getOpenidResult.openid;
                }

                if (getOpenidResult.redirectUrl) {
                    return res.redirect(getOpenidResult.redirectUrl);
                }

                if (openId) {
                    res.cookie('weixinOpenId' + orderCode, openId, {
                        domain: 'yohobuy.com',
                        expires: new Date(Date.now() + 24 * 60 * 60 * 1000)
                    });
                }
            }
        }

        let responseData = {
            pageHeader: headerModel.setNav({
                navTitle: '支付中心',
                backUrl: 'javascript:void(0);' // eslint-disable-line
            }),
            module: 'cart',
            page: 'pay',
            title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停',
            payAppInfo: payTool.payAppInfo(orderCode),
            orderCode: orderCode,
            hasWxShare: hasWxShare,
            orderTotal: orderDetail.payment_amount || 0,
            orderTotalFormat: parseInt(orderDetail.payment_amount, 10),
            orderCount: payTool.calBuyNumCount(orderDetail.order_goods),
            uid: uid,
            isOldUser: Boolean(req.cookies._isOldUser && req.cookies._isOldUser === '4')
        };

        if (_.get(req, 'app.locals.wap.pay.alipayclose', false)) {
            _.set(responseData.payAppInfo, '[0]', {
                appIcon: '',
                appId: 'alipay',
                app: '支付宝支付',
                hint: '支付宝服务暂不可用',
                subHint: '推荐使用有货APP支付',
                disable: true
            });
        }

        res.render('pay/pay-center', responseData);
    })().catch(next);
};

/**
 * 统一支付入口
 * @param req
 * @param res
 */
const pay = (req, res, next) => {
    let orderCode = req.query.order_code;
    let user = req.user;
    let uid = req.user.uid;
    let sessionKey = req.session.TOKEN;
    let payment = req.query.payment;
    let paymentCode = common.getPaymentCode(payment);
    let openId = req.cookies['weixinOpenId' + orderCode];
    let ip = req.ip;

    if (ip.substr(0, 7) === '::ffff:') {
        ip = ip.substr(7);
    }

    if (!orderCode || !uid) {
        return res.json({
            code: 400,
            message: '订单或用户信息不存在!',
            url: '/'
        });
    }

    co(function* () {
        let orderDetail = yield req.ctx(payModel).getOtherDetail({
            uid: uid,
            orderCode: orderCode,
            sessionKey: sessionKey
        });

        if (!orderDetail || !orderDetail.data) {
            return res.json({
                code: 400,
                message: '没有找到该订单!'
            });
        }

        let attribute = _.parseInt(_.get(orderDetail, 'data.attribute'));

        if (attribute === 9 || attribute === 11) {
            return res.json({
                code: 400,
                message: '此订单只能通过 APP 支付'
            });
        }

        if (orderDetail.data.is_cancel === 'Y') {
            let url = helpers.urlFormat('/home/orders/detail', { order_code: orderCode });

            return res.json({
                code: 400,
                message: '订单已经取消',
                url: url
            });
        }

        req.ctx(Payment).pay(user, orderDetail.data, payment, {
            protocol: req.protocol,
            openId: openId,
            ip: ip
        }).then(result => {
            if (result && paymentCode === payProcess.PAYMENTS.WECHAT) {
                if (result.code !== 200) {
                    res.clearCookie('weixinOpenId' + orderCode);
                }
                return res.json(result);
            }
            if (result && result.data && result.data.href && paymentCode === payProcess.PAYMENTS.ALIPAY) {
                return res.json({
                    code: 200,
                    message: '校验成功',
                    url: result.data.href
                });
            } else {
                return res.json({
                    code: 400,
                    message: '系统错误!',
                    url: '/'
                });
            }
        });
    })().catch(next);
};

// 货到付款
const payCod = (req, res, next) => {
    let headerData = headerModel.setNav({
        navTitle: '支付完成'
    });

    let responseData = {
        pageHeader: headerData,
        module: 'cart',
        page: 'pay',
        title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
    };

    let sessionKey = req.session.TOKEN;


    let param = {
        uid: req.user.uid,
        udid: req.cookies.udid || require('yoho-md5')(req.ip) || 'yoho',
        orderCode: req.query.order_code,
        contentCode: '78d0fb6c97d691863286edcb4d8abfa9',
        client_id: req.cookies._yasvd || '',
        sessionKey: sessionKey && sessionKey.substr(0, sessionKey.length - 8) || ''
    };

    // 如果没有uid,跳转到首页
    if (!param.uid) {
        res.redirect('/');
        return;
    }

    req.ctx(payModel).getPayCod(param).then(result => {
        if (result.match === true) {
            req.ctx(aboutModel).about(req.yoho.isApp).then(resu => {
                res.render('pay/pay-cod', Object.assign(responseData, result, {wxFooter: resu}));
            });
        } else {
            res.redirect('/');
        }

    }).catch(next);
};

// 支付宝支付结果页
const payAli = (req, res, next) => {
    let headerData = headerModel.setNav({
        navTitle: '支付完成'
    });

    let responseData = {
        pageHeader: headerData,
        module: 'cart',
        page: 'pay',
        title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
    };

    let responseFailure = {
        pageHeader: headerModel.setNav({
            navTitle: '支付中心',
            navBtn: false
        }),
        title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
    };

    let param = {
        uid: req.user.uid,
        udid: req.cookies.udid || require('yoho-md5')(req.ip) || 'yoho',
        orderCode: req.query.out_trade_no,
        contentCode: '78d0fb6c97d691863286edcb4d8abfa9',
        client_id: req.cookies._yasvd || ''
    };

    // 如果没有uid,跳转到首页
    if (!param.uid) {
        res.redirect('/');
        return;
    }

    let verifyResult = req.ctx(payModel).alipayResultVerify(req.query);

    // 支付宝支付校验
    if (!verifyResult.payResult) {
        return res.render('pay/pay-failure', _.assign(responseData, responseFailure));
    }

    req.ctx(payModel).getPayAli(param).then(result => {
        if (result.match === true) {
            // 支付成功,发送支付确认接口
            req.ctx(payModel).sendPayConfirm(param.orderCode, payProcess.PAYMENTS.ALIPAY, param.uid);

            req.ctx(aboutModel).about(req.yoho.isApp).then(resu => {
                res.render('pay/pay-ali', Object.assign(responseData, result, {wxFooter: resu}));
            });
        } else {
            res.redirect('/');
        }

    }).catch(next);
};

// 零元支付
const payZero = (req, res, next) => {
    let headerData = headerModel.setNav({
        navTitle: '支付完成'
    });

    let responseData = {
        pageHeader: headerData,
        module: 'cart',
        page: 'pay',
        title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
    };

    let responseFailure = {
        pageHeader: headerModel.setNav({
            navTitle: '支付中心',
            navBtn: false
        }),
        title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
    };

    let param = {
        uid: req.user.uid,
        udid: req.cookies.udid || require('yoho-md5')(req.ip) || 'yoho',
        orderCode: req.query.order_code,
        contentCode: '78d0fb6c97d691863286edcb4d8abfa9',
        isPay: true
    };

    // 如果没有uid,跳转到首页
    if (!param.uid) {
        res.redirect('/');
        return;
    }

    req.ctx(payModel).getPayAli(param).then(result => {

        if (result.match === true) {
            if (result.isCancel && result.isCancel === true) {
                return res.render('pay/pay-failure', responseFailure);
            } else {
                res.render('pay/pay-ali', Object.assign(responseData, result));
            }
        } else {
            res.redirect('/');
        }

    }).catch(next);
};

module.exports = {
    payCenter,
    pay,
    payCod,
    payAli,
    payZero
};