~wechat.js 2.9 KB
/**
 *
 * @author: jiangfeng<jeff.jiang@yoho.cn>
 * @date: 16/7/22
 */

'use strict';

const moment = require('moment');
const rq = require('request-promise');
const common = require('./common');
const sign = require('./sign');
const md5 = require('md5');
const _ = require('lodash');
const logger = global.yoho.logger;
const config = global.yoho.config;

const wechatUnifiedOrderUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';

const Wechat = {
    pay(user, order, info) {
        let expire = common.getPayExpireCouple(order.payExpire);

        info = JSON.parse(info.payParams || '{}');

        let unifiedOrder = {
            body: 'BLK订单号:' + order.orderCode,
            out_trade_no: order.orderCode,
            total_fee: parseInt(order.paymentAmount * 100, 10),
            time_start: moment(expire.start).format('YYYYMMDDHHmmss'),
            time_expire: moment(expire.end).format('YYYYMMDDHHmmss'),
            trade_type: 'NATIVE',
            product_id: order.orderCode,
            notify_url: config.pay.serviceNotify + 'payment/weixin_notify',
            appid: info.app_id,
            mch_id: info.partner_id,
            nonce_str: common.nonceStr()
        };

        let signStr = md5(sign.raw(unifiedOrder) + '&key=' + info.partner_key);

        unifiedOrder.sign = _.toUpper(signStr);

        return this.unifiedOrder(unifiedOrder).then(result => {
            if (result && result.xml) {
                let data = result.xml || {};

                if (data.return_code === 'SUCCESS' && Wechat.checkSign(data, info)) {
                    return {
                        code: 200,
                        data: {
                            href: data.code_url
                        }
                    };
                }
            }
            return {
                code: 400,
                message: '请稍后重试'
            };

        });
    },

    unifiedOrder(unifiedOrder) {
        let xml = common.toXml(unifiedOrder);

        return rq({
            method: 'POST',
            uri: wechatUnifiedOrderUrl,
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': Buffer.byteLength(xml)
            },
            body: xml,
            timeout: 1000
        }).then(result => {
            if (result) {
                return common.xml2Obj(result);
            } else {
                return {};
            }
        }).catch(err => {
            logger.error(`call wechat pay unifiedOrder fail. order=${JSON.stringify(unifiedOrder)}`, err);
            return {};
        });
    },

    notify(data, info) {  // eslint-disable-line

    },

    checkSign(data, info) {
        if (data && data.sign) {
            let signStr = data.sign || '';

            delete data.sign;
            return signStr === md5(sign.raw(data) + info.partner_key);
        }
        return false;
    }
};

module.exports = Wechat;