payment.js 5.33 KB
/**
 * 各种支付的入口
 * TAR NOTE: 本项目中仅支持支付宝支付,微信支付,其他支付方式需调试
 * @author: jiangfeng<jeff.jiang@yoho.cn>
 * @date: 16/7/22
 */

'use strict';
const PayModel = require('../models/pay');
const Alipay = require('./pay/alipay');
const Wechat = require('./pay/wechat');
const Promise = require('bluebird');
const co = Promise.coroutine;
const logger = global.yoho.logger;
const common = require('./pay/common');
const utils = '../../../utils';
const payProcess = require(`${utils}/pay-process`);

class Payment extends global.yoho.BaseModel {
    constructor(ctx) {
        super(ctx);
    }

    /**
     * 统一支付入口
     * reqParams: 需要从 controller 传递的参数,支付宝需要 req.protocol,微信需要 openId、ip
     */
    pay(user, order, payType, reqParams) {
        let self = this;

        return co(function* () {
            let result = {
                code: 400,
                message: '获取支付方式信息失败'
            };
            let payInfo;
            let bankCode = '';

            if (!order.order_code) {
                result.message = '没有找到该订单';
                return result;
            }

            if (order.is_cancel && order.is_cancel === 'Y') {
                result.message = '该订单已经取消';
                return result;
            }

            let method = common.getPaymentCode(payType);

            if (!method) {
                logger.info('payCenter: payment no method params');
                return result;
            }

            if (method === payProcess.PAYMENTS.WECHAT) {
                result = yield Wechat.pay(self.ctx, order, {
                    openId: reqParams.openId,
                    ip: reqParams.ip,
                    paymentCode: method
                });
            } else {
                payInfo = yield self.ctx.req.ctx(PayModel).getPaymentInfo(method);

                if (!payInfo.payParams) {
                    return result;
                }

                switch (payInfo.id) {
                    case payProcess.PAYMENTS.ALIPAY:
                        payInfo.paymentCode = method;
                        result = yield Alipay.pay(self.ctx, order, payInfo, reqParams.protocol);
                        break;
                    default:
                        break;
                }
            }

            logger.info(`pay to url, params = ${JSON.stringify(result)}`);

            if (result.code === 200) {
                let updateInfo = yield self.beforePay(user, order, method, bankCode);

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

            return result;
        })();
    }

    beforePay(user, order, method, bankCode) {
        return Promise.all([
            this.ctx.req.ctx(PayModel).updateOrderPayment(order.order_code, method, user.uid),
            this.ctx.req.ctx(PayModel).getBankByOrder(order.order_code)
        ]).then(result => {
            let paymentRecord = result[0];
            let bankRecord = result[1];

            if (!paymentRecord || paymentRecord.code !== 200) {
                let message = paymentRecord && paymentRecord.message ? paymentRecord.message : '系统繁忙,请稍后再试';

                return { code: 400, message: message };
            }

            if (bankRecord && bankRecord.bankCode) {
                return this.ctx.req.ctx(PayModel).updateOrderPayBank(order.order_code, method, bankCode);
            } else {
                return this.ctx.req.ctx(PayModel).setOrderPayBank(order.order_code, method, bankCode);
            }

        }).catch(e => {
            logger.error('update order pay info error.', e);

            return Promise.resolve({
                code: 400,
                message: '更新订单支付信息失败'
            });
        });
    }

    afterPay(query, payId, user, sessionKey) {
        let self = this;

        return co(function*() {
            let payInfo = yield self.ctx.req.ctx(PayModel).getPaymentInfo(payId);
            let payResult = {};
            let payData = {};
            let payName = '';

            if (payId === payProcess.PAYMENTS.ALIPAY) {
                payResult = Alipay.notify(query, payInfo);
            }

            payResult.bankName = payName = payResult.bankName || payInfo.payName || '';
            payResult.bankCode = payResult.bankCode || payInfo.pay_code || '';

            // 记录日志
            logger.info(`\r\n\r\n pay back confirmreq = ${JSON.stringify({
                query: query,
                payId: payId,
                user: user,
                payResult: payResult
            })}`);

            if (payResult && payResult.payResult === 200) {
                if (payResult.orderCode) {
                    logger.info('pay back confirm');
                    yield self.ctx.req.ctx(PayModel).sendPayConfirm(payResult.orderCode, payId, user.uid);
                }

                payData = yield self.ctx.req.ctx(PayModel).procOrderData(payResult, user.uid, sessionKey);
            } else {
                payData = {
                    code: 500,
                    message: '支付失败'
                };
            }

            payData.payName = payName;

            return payData;
        })();
    }
}

module.exports = Payment;