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

'use strict';

const payApi = require('./pay-api');
const Promise = require('bluebird');
const co = Promise.coroutine;
const payHelpersBank = require('./../helpers/bank');
const logger = global.yoho.logger;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const FRAUD_CONTENT_CODE = '78d0fb6c97d691863286edcb4d8abfa9';
const payments = {
    alipay: 2,
    wechat: 21,
    alibank: 12
};

/**
 * [更新订单支付方式]
 * @param  {[type]} code    [订单号]
 * @param  {[type]} payment [支付方式]
 * @param  {[type]} uid     [用户uid]
 * @return {[type]}         [{}]
 */
const updateOrderPayment = (code, payment, uid) => {
    return payApi.updateOrderPayment(code, payment, uid);
};

/**
 * [订单详情]
 * @param  {[type]} uid       [用户uid]
 * @param  {[type]} orderCode [订单号]
 * @return {[type]}           [{}]
 */
const orderDetail = (uid, orderCode)=>{
    return payApi.orderDetail(uid, orderCode);
};

/**
 * 获取在线支付方式
 * @returns {*|Promise.<TResult>}
 */
const getOnlinePayProvider = () => {
    return payApi.getPayProvider().then(result => {
        let payPattern = [], nav = [];

        if (!(result.code && result.code === 200)) {
            return payPattern;
        }

        // 处理支付宝等平台数据
        _.each(result.data, val => {
            // 去除icon为空的
            if (_.isEmpty(val.payIcon)) {
                return true;
            }

            nav.push({
                id: val.id,
                name: val.payName,
                value: val.id + '_platform',
                img: val.payIcon
            });
        });

        payPattern.push({
            name: '支付宝等平台',
            children: nav
        });

        // 处理使用银行卡数据
        nav = [];
        _.each(payHelpersBank.getList(), (val, key) => {
            nav.push({
                id: payments.alibank,
                name: val.name,
                value: payments.alibank + '_' + key,
                img: val.ico
            });
        });
        payPattern.push({
            name: '使用银行卡',
            children: nav
        });

        return payPattern;
    });
};

/**
 * 获取订单详情
 * @param uid
 * @param code
 */
const getOrderInfo = (uid, code) => {
    return orderDetail(uid, code).then(data => {
        return data && data.code === 200 && data.data || {};
    });
};

/**
 * 获取订单支付银行信息
 * @param id
 */
const getBankByOrder = (id) => {
    return payApi.getBankByOrder(id).then(data => {
        return data && data.code === 200 && data.data || {};
    });
};

/**
 * 获取支付页数据
 * @param uid
 * @param code
 */
const getPayInfo = (uid, code) => {
    return Promise.all([getOnlinePayProvider(), getOrderInfo(uid, code), getBankByOrder(code)])
        .then(payment => {
            let paymentId = parseInt(payment[2].payment || 0, 10);
            let findIndex;
            let payDefault;

            // 渲染选择的默认支付方式
            if (paymentId === payments.alibank && payment[0][1] && payment[2]) { // 银行支付
                findIndex = _.findIndex(payment[0][1].children, {value: payments.alibank + '_' + payment[2].bankCode});
                findIndex = findIndex > 0 ? findIndex : 0;
                payment[0][1].selected = true;
                payment[0][1].children[findIndex].selected = true;

                payDefault = payment[0][1].children[findIndex];
            } else if (payment[0] && payment[0][0]) { // 支付宝等平台
                findIndex = _.findIndex(payment[0][0].children, {id: paymentId});
                findIndex = findIndex > 0 ? findIndex : 0;
                payment[0][0].selected = true;
                payment[0][0].children[findIndex].selected = true;

                payDefault = payment[0][0].children[findIndex];
            }

            return {
                pay: payment[0],
                order: payment[1],
                payDefault: payDefault
            };
        });
};

/**
 * 获取支付方式的相关参数, (密钥等信息)
 * @param id
 */
const getPaymentInfo = (id) => {
    return co(function *() {
        let data = yield payApi.getPaymentInfo(id);

        return data && data.code === 200 && data.data || {};
    })();
};

/**
 * 设置订单支付银行
 * @param code
 * @param payment
 * @param bankCode
 */
const setOrderPayBank = (code, payment, bankCode) => {
    return co(function *() {
        return yield payApi.setOrderPayBank(code, payment, bankCode);
    })();
};

/**
 * 更新订单支付银行
 * @param code
 * @param payment
 * @param bankCode
 */
const updateOrderPayBank = (code, payment, bankCode) => {
    return co(function *() {
        return yield payApi.updateOrderPayBank(code, payment, bankCode);
    })();
};

/**
 * 支付确认
 * @param code
 * @param payment
 * @param uid
 */
const sendPayConfirm = (code, payment, uid) => {
    return co(function *() {
        let data = yield payApi.sendPayConfirm(code, payment, uid);

        return data;
    })();
};

/**
 * 支付成功,前端回调时,处理订单信息
 * @param payResult
 * @param uid
 */
const procOrderData = (payResult, uid) => {
    return co(function *() {
        let orderCode = payResult.orderCode;
        let result = {code: 400, message: ''};

        if (!orderCode) {
            result.message = '订单不存在';
            return result;
        }

        return Promise.all([orderDetail(uid, orderCode), payApi.getResourceData(FRAUD_CONTENT_CODE)]).then(procData => {
            let orderInfo = procData[0].code === 200 && procData[0].data;
            let fraudData = _.result(_.find(procData[1].data, {template_name: 'text'}), 'data') || {};
            let resultOrder;

            if (!orderInfo) {
                result.message = '订单不存在!';
                return result;
            }

            let amount = orderInfo.payment_amount;

            if (orderInfo.is_cancel === 'Y') {
                logger.warn('front pay success but order is cancel.', {payResult: payResult, order: orderInfo});
                return {code: 417, message: '支付成功,但订单已取消,需联系客服!'};
            }

            if (orderInfo.payment_status === 'N') {
                logger.warn('front pay success but may be notify fail');
            }

            if (_.round(parseFloat(amount), 2) !== _.round(parseFloat(payResult.totalFee), 2)) {
                logger.warn('front pay success but the amount is not same.', {payResult: payResult, order: orderInfo});
                return {
                    code: 415,
                    message: '支付金额与订单金额不一致,订单状态更新失败!'
                };
            }

            resultOrder = {
                paymentTypes: (orderInfo.payment_type === 1 ? '在线支付' : '货到付款'),
                multiPackage: orderInfo.is_multi_package === 'Y',
                ordersUrl: helpers.urlFormat('/home/orders'),
                vipUrl: helpers.urlFormat('/help/detail', {id: 9}),
                returnGoodsUrl: helpers.urlFormat('/help/detail', {id: 49}),
                yohoCoinUrl: helpers.urlFormat('/help/detail', {id: 105, contId: 233}),
                detailUrl: helpers.urlFormat('/home/orders/detail', {
                    orderCode: orderInfo.order_code
                }),
                packageTitle: orderInfo.package_title || '商品需要品牌商调货',
                fraudTip: fraudData.text || ''
            };
            return {
                code: 200,
                message: '支付成功,请等待发货',
                data: {
                    order: Object.assign(orderInfo, resultOrder)
                }
            };

        });
    })();
};

module.exports = {
    orderDetail,
    getPayInfo,
    getPaymentInfo,
    getBankByOrder,
    setOrderPayBank,
    updateOrderPayBank,
    sendPayConfirm,
    procOrderData,
    updateOrderPayment,
    payments
};