|
|
/**
|
|
|
*
|
|
|
* @author: jiangfeng<jeff.jiang@yoho.cn>
|
|
|
* @date: 16/9/8
|
|
|
/*
|
|
|
* @Author: Targaryen
|
|
|
* @Date: 2017-01-03 17:42:41
|
|
|
* @Last Modified by: Targaryen
|
|
|
* @Last Modified time: 2017-01-09 17:53:16
|
|
|
*/
|
|
|
|
|
|
'use strict';
|
|
|
const config = global.yoho.config;
|
|
|
const WxPayConfig = config.WxPayConfig;
|
|
|
const _ = require('lodash');
|
|
|
const logger = global.yoho.logger;
|
|
|
const rp = require('request-promise');
|
|
|
const Promise = require('bluebird');
|
|
|
const co = Promise.coroutine;
|
|
|
const sign = require('./sign');
|
|
|
const md5 = require('md5');
|
|
|
const common = require('./common');
|
|
|
|
|
|
/**
|
|
|
* 微信支付相关工具类
|
|
|
*/
|
|
|
const tools = {
|
|
|
|
|
|
/**
|
|
|
* 拼接签名字符串
|
|
|
*/
|
|
|
toUrlParams(urlObj) {
|
|
|
let buff = '';
|
|
|
|
|
|
_.forEach(urlObj, (value, key) => {
|
|
|
if (key !== 'sign') {
|
|
|
buff += key + '=' + value + '&';
|
|
|
}
|
|
|
});
|
|
|
|
|
|
buff = _.trimEnd(buff, '&');
|
|
|
|
|
|
const ServiceAPI = global.yoho.ServiceAPI;
|
|
|
const helpers = global.yoho.helpers;
|
|
|
return buff;
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 构造获取code的url连接
|
|
|
*/
|
|
|
createOauthUrlForCode(redirectUrl) {
|
|
|
let urlObj = {
|
|
|
appid: WxPayConfig.appId,
|
|
|
redirect_uri: redirectUrl,
|
|
|
response_type: 'code',
|
|
|
scope: 'snsapi_base',
|
|
|
state: 'STATE#wechat_redirect',
|
|
|
};
|
|
|
|
|
|
let bizString = tools.toUrlParams(urlObj);
|
|
|
|
|
|
return 'https://open.weixin.qq.com/connect/oauth2/authorize?' + bizString;
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 构造获取open和access_toke的url地址
|
|
|
*/
|
|
|
createOauthUrlForOpenid(code) {
|
|
|
let urlObj = {
|
|
|
appid: WxPayConfig.appId,
|
|
|
secret: WxPayConfig.appSecret,
|
|
|
code: code,
|
|
|
grant_type: 'authorization_code'
|
|
|
};
|
|
|
|
|
|
let bizString = tools.toUrlParams(urlObj);
|
|
|
|
|
|
return 'https://api.weixin.qq.com/sns/oauth2/access_token?' + bizString;
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 通过code从工作平台获取openid机器access_token
|
|
|
*/
|
|
|
getOpenidFromMp(code) {
|
|
|
let uri = tools.createOauthUrlForOpenid(code);
|
|
|
|
|
|
let rpOption = {
|
|
|
method: 'POST',
|
|
|
uri: uri,
|
|
|
body: {
|
|
|
some: 'payload'
|
|
|
},
|
|
|
json: true
|
|
|
};
|
|
|
|
|
|
return rp(rpOption).then(resultFromWx => {
|
|
|
return resultFromWx && resultFromWx.openid;
|
|
|
}).catch(err => {
|
|
|
logger.error(err);
|
|
|
});
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 微信统一下单接口
|
|
|
*/
|
|
|
unifiedOrder(params) {
|
|
|
let unifiedParams = {
|
|
|
appid: WxPayConfig.appId,
|
|
|
mch_id: WxPayConfig.mchId,
|
|
|
notify_url: WxPayConfig.notifyUrl,
|
|
|
device_info: 'WEB',
|
|
|
nonce_str: common.nonceStr(),
|
|
|
body: '有货订单号:' + params.orderCode,
|
|
|
out_trade_no: 'YOHOBuy_' + params.orderCode,
|
|
|
total_fee: params.totalFee * 100,
|
|
|
trade_type: 'JSAPI',
|
|
|
openid: params.openId,
|
|
|
sign_type: 'MD5'
|
|
|
};
|
|
|
let signStr = md5(sign.raw(unifiedParams) + '&key=' + WxPayConfig.key).toUpperCase();
|
|
|
|
|
|
_.assign(unifiedParams, { sign: signStr });
|
|
|
|
|
|
let xml = common.toXml(unifiedParams);
|
|
|
|
|
|
let xmlParams = {
|
|
|
method: 'POST',
|
|
|
uri: 'https://api.mch.weixin.qq.com/pay/unifiedorder',
|
|
|
headers: {
|
|
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
|
},
|
|
|
body: xml,
|
|
|
timeout: 1000
|
|
|
};
|
|
|
|
|
|
return co(function* () {
|
|
|
let xmlResult = yield rp(xmlParams);
|
|
|
let jsonResult = yield common.xml2Obj(xmlResult);
|
|
|
|
|
|
return jsonResult && jsonResult.xml;
|
|
|
})();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// TODO 微信支付
|
|
|
const Wechat = {
|
|
|
pay(user, order, info) {
|
|
|
return ServiceAPI.get('payment/weixin_data', {
|
|
|
order_code: order.order_code,
|
|
|
payment_code: info.id,
|
|
|
app_key: 'blkpc'
|
|
|
}).then(result => {
|
|
|
if (result && result.code === 200 && result.data) {
|
|
|
let url = `/shopping/pay/online/weixin?url=${result.data.codeUrl}&code=${order.order_code}`;
|
|
|
/**
|
|
|
* 支付中心微信支付相关处理
|
|
|
*/
|
|
|
getOpenid(code, originalUrl) {
|
|
|
if (!code) {
|
|
|
let baseUrl = 'http://m.yohobuy.com' + originalUrl;
|
|
|
let redirectUrl = tools.createOauthUrlForCode(baseUrl);
|
|
|
|
|
|
return Promise.resolve({ redirectUrl: redirectUrl });
|
|
|
} else {
|
|
|
return tools.getOpenidFromMp(code).then(openid => {
|
|
|
return { openid: openid };
|
|
|
});
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 异步拉起微信支付相关处理
|
|
|
*/
|
|
|
pay(user, order, openId) {
|
|
|
|
|
|
return co(function* () {
|
|
|
let unifiedOrderResult = yield tools.unifiedOrder({
|
|
|
orderCode: order.order_code,
|
|
|
totalFee: parseFloat(order.payment_amount),
|
|
|
openId: openId
|
|
|
});
|
|
|
|
|
|
if (unifiedOrderResult) {
|
|
|
let nonceStr = common.nonceStr();
|
|
|
|
|
|
let resParams = {
|
|
|
appId: unifiedOrderResult.appid,
|
|
|
timeStamp: parseInt(Date.parse(new Date()) / 1000, 10),
|
|
|
nonceStr: nonceStr,
|
|
|
package: 'prepay_id=' + unifiedOrderResult.prepay_id,
|
|
|
signType: 'MD5',
|
|
|
};
|
|
|
|
|
|
let paySign = md5(sign.raw(resParams) + '&key=' + WxPayConfig.key).toUpperCase();
|
|
|
|
|
|
_.assign(resParams, { paySign: paySign });
|
|
|
return {
|
|
|
code: 200,
|
|
|
data: {
|
|
|
href: helpers.urlFormat(url)
|
|
|
jsApiParameters: resParams
|
|
|
}
|
|
|
};
|
|
|
} else {
|
|
|
return {
|
|
|
code: 400,
|
|
|
message: result.message
|
|
|
};
|
|
|
return {};
|
|
|
}
|
|
|
});
|
|
|
|
|
|
})();
|
|
|
}
|
|
|
};
|
|
|
|
...
|
...
|
|