pay.js 6.56 KB
/**
 * 订单支付
 * @author: jiangfeng<jeff.jiang@yoho.cn>
 * @date: 2016/07/18
 */

'use strict';

const PayData = require('../models/pay');
const OrderData = require('../models/order');
const PayHelpers = require('../helpers/payment');
const paySign = require('../helpers/pay/sign');
const cleanHtml = require(`${global.utils}/cleanHtml`);
const camelCase = global.yoho.camelCase;
const helpers = global.yoho.helpers;
const _ = require('lodash');
const md5 = require('md5');
const integerTest = /^[0-9]*$/;

/**
 * 支付页
 * @param req
 * @param res
 * @param next
 */
const online = (req, res, next) => {
    let orderCode = req.query.code;
    let uid = req.user.uid;

    if (!integerTest.test(orderCode)) {
        // 不合法订单号
        return next();
    }

    PayData.getPayInfo(uid, orderCode).then(result => {
        let order = result.order;
        let promotion = order.promotionFormulas;
        let coin = 0;
        let amount = _.toNumber(order.paymentAmount);

        if (!order.orderCode) {
            // 不合法订单号
            return next();
        }

        _.forEach(promotion, p => {
            if (p.promotion === 'YOHO币') {
                coin = parseInt(parseFloat(p.promotionAmount.substring(2, p.promotionAmount.length)) * 100, 10);
            }
        });

        if (order.address) {
            order.address = cleanHtml.htmlDecode(order.address);
        }

        if (amount > 0) {
            res.display('pay', Object.assign({
                defaultHeader: false,
                module: 'shopping',
                page: 'pay',
                title: '支付页面',
                bcNavFocus: 3,
                username: req.user.username
            }, result));
        } else {
            res.display('pay-success', {
                defaultHeader: false,
                module: 'shopping',
                page: 'pay-over',
                bcNavFocus: 3,
                content: {
                    cost: order.paymentAmount,
                    orderNum: order.orderCode,
                    coin: coin,
                    orderHref: helpers.urlFormat('/me/order/detail', {
                        orderCode: order.orderCode
                    }),
                    walkHref: helpers.urlFormat('/')
                }
            });
        }

    }).catch(next);

};

/**
 * 获取第三方支付跳转url
 * @param req
 * @param res
 * @param next
 */
const toPay = (req, res, next) => {
    let orderCode = req.body.code;
    let payType = req.body.payType;
    let uid = req.user.uid;
    let user = req.user;

    if (!integerTest.test(orderCode)) {
        // 不合法订单号
        return next();
    }

    OrderData.orderDetail(uid, orderCode).then(result => {
        if (result && result.data) {
            return PayHelpers.pay(user, result.data, payType, req.protocol);
        } else {
            return {
                code: 400,
                message: '获取订单失败'
            };
        }
    }).then(result => {
        res.json(result);
    }).catch(next);
};

/**
 * 微信扫码支付页面
 * @param req
 * @param res
 * @param next
 */
const weixinQr = (req, res, next) => {
    let code = req.query.code;
    let url = req.query.url;
    let uid = req.user.uid;

    if (!integerTest.test(code)) {
        // 不合法订单号
        return next();
    }

    OrderData.orderDetail(uid, code).then(result => {
        if (result && result.data) {
            return camelCase(result.data);
        } else {
            return {};
        }
    }).then(order => {
        res.display('weixin-pay', {
            defaultHeader: false,
            bcNavFocus: 3,
            module: 'shopping',
            page: 'wxpay',
            title: '微信扫码支付页面',
            code: code,
            url: url,
            order: order
        });
    }).catch(next);
};

const weixinPayState = (req, res) => {
    let code = req.query.code;
    let uid = req.user.uid;

    OrderData.orderDetail(uid, code).then(result => {
        if (result && result.data && result.data.payment_status === 'Y') {
            let payParams = {
                orderCode: code,
                totalFee: _.round(parseFloat(result.data.payment_amount), 2)
            };

            // payment_status: 'Y' <=> tradeStatus: 'Y'
            res.json({
                code: 200,
                data: {
                    href: helpers.urlFormat('/shopping/pay/callback/wechat', Object.assign(payParams, {
                        sign: md5(paySign.raw(Object.assign({tradeStatus: 'Y'}, payParams)))
                    }))
                }
            });
        } else {
            return res.json({});
        }
    }).catch(() => {
        return res.json({});
    });
};

/**
 * 支付成功回调
 * @param req
 * @param res
 */
const callback = (req, res, next) => {
    let type = req.params.type;
    let payId = PayData.payments[type];
    let query = req.query;

    if (!payId) {
        return next();
    }

    PayHelpers.afterPay(query, payId, req.user).then(result => {
        if (result.code === 200 && result.data && result.data.order) {
            let order = result.data.order;
            let promotion = order.promotion_formulas;
            let coin = 0;


            _.forEach(promotion, p => {
                if (p.promotion === 'YOHO币') {
                    coin = parseInt(parseFloat(p.promotion_amount.substring(2, p.promotion_amount.length)) * 100, 10);
                }
            });

            res.display('pay-success', {
                defaultHeader: false,
                module: 'shopping',
                page: 'pay-over',
                bcNavFocus: 3,
                content: {
                    cost: order.payment_amount,
                    orderNum: order.order_code,
                    coin: coin,
                    orderHref: helpers.urlFormat('/me/order/detail', {
                        orderCode: order.order_code
                    }),
                    walkHref: helpers.urlFormat('/')
                }
            });
        } else {
            res.display('pay-fail', {
                defaultHeader: false,
                payName: result.payName,
                bcNavFocus: 3
            });
        }
    }).catch(next);
};

// 支付确认
const sendPayConfirm = (req, res, next) => {
    let code = req.body.code;
    let payment = req.body.payment;
    let uid = req.user.uid;

    PayData.sendPayConfirm(code, payment, uid).then(result => {
        res.json(result);
    }).catch(next);
};


module.exports = {
    online,
    callback,
    toPay,
    weixinQr,
    weixinPayState,
    sendPayConfirm
};