Authored by 郝肖肖

银联支付

... ... @@ -158,6 +158,11 @@ const callback = (req, res, next) => {
return next();
}
// 银联支付是post返回的
if (type === 'unionpay') {
query = req.body;
}
PayHelpers.afterPay(query, payId, req.user).then(result => {
if (result.code === 200 && result.data && result.data.order) {
res.render('pay-success', {
... ...
... ... @@ -14,7 +14,7 @@ const payHelpersBank = require('../bank');
const md5 = require('md5');
const logger = global.yoho.logger;
const ALIPAY_URL = 'https://mapi.alipay.com/gateway.do';
const PAY_URL = 'https://mapi.alipay.com/gateway.do';
const Alibank = {
... ... @@ -49,7 +49,7 @@ const Alibank = {
return {
code: 200,
data: {
href: ALIPAY_URL + '?' + body
href: PAY_URL + '?' + body
}
};
},
... ... @@ -64,19 +64,18 @@ const Alibank = {
if (!this.checkNotify(data, payParams)) {
return {payResult: -1, bankName: bankName};
} else {
}
return {
bankName: bankName,
orderCode: orderCode,
payResult: data.trade_status === 'TRADE_SUCCESS' ? 200 : 400,
payTime: data.gmt_payment || '',
totalFee: data.total_fee,
resultMsg: data.notify_type,
payOrderCode: orderCode,
tradeNo: data.trade_no,
bankBillNo: data.bank_seq_no || ''
};
}
},
checkNotify(data, payParams) {
... ...
... ... @@ -13,7 +13,7 @@ const sign = require('./sign');
const md5 = require('md5');
const logger = global.yoho.logger;
const ALIPAY_URL = 'https://mapi.alipay.com/gateway.do';
const PAY_URL = 'https://mapi.alipay.com/gateway.do';
const Alipay = {
... ... @@ -46,32 +46,30 @@ const Alipay = {
return {
code: 200,
data: {
href: ALIPAY_URL + '?' + body
href: PAY_URL + '?' + body
}
};
},
notify(data, param) {
let payParams = JSON.parse(param.payParams);
let orderCode = parseInt(data.out_trade_no, 10);
logger.info(`Alipay notify, params = ${JSON.stringify(data)}`);
if (!this.checkNotify(data, payParams)) {
return {payResult: -1};
} else {
let orderCode = parseInt(data.out_trade_no, 10);
}
return {
bankName: '',
orderCode: orderCode,
payResult: data.trade_status === 'TRADE_SUCCESS' ? 200 : 400,
payTime: data.gmt_payment || '',
totalFee: data.total_fee,
resultMsg: data.notify_type,
payOrderCode: orderCode,
tradeNo: data.trade_no,
bankBillNo: ''
};
}
},
checkNotify(data, payParams) {
... ...
... ... @@ -6,8 +6,6 @@
'use strict';
const moment = require('moment');
// const xml2js = require('xml2js');
const common = {
getPayExpireMin(expire) {
let defaultValue = 120;
... ... @@ -45,29 +43,6 @@ const common = {
str += chars[parseInt(Math.random() * length, 10)];
}
return str;
},
toXml(obj, root) {
// let xmlBuilder = new xml2js.Builder({
// rootName: root || 'xml'
// });
// return xmlBuilder.buildObject(obj);
},
xml2Obj(xml) {
// let xmlParser = new xml2js.Parser({
// trim: true,
// explicitArray: false
// });
// return new Promise((resolve, reject) => {
// xmlParser.parseString(xml, (err, result) => {
// if (err) {
// reject(err);
// } else {
// resolve(result);
// }
// });
// });
}
};
... ...
... ... @@ -26,7 +26,7 @@ const Sign = {
}).sort();
return keys.map(k => {
return k.toLowerCase() + '=' + encodeURI(args[k]);
return k + '=' + encodeURI(args[k]);
}).join('&');
}
};
... ...
/**
* @author: xiaoxiao.hao<xiaoxiao.hao@yoho.cn>
* @date: 2017/3/23
*/
'use strict';
const ServiceAPI = global.yoho.ServiceAPI;
const helpers = global.yoho.helpers;
const sign = require('./sign');
const PAY_URL = 'https://gateway.95516.com/gateway/api/frontTransReq.do';
const unionpay = {
pay(user, order, info) {
return ServiceAPI.get('payment/unionpay_data', {
order_code: order.order_code,
payment_code: info.id,
uid: user.uid,
front_url: info.protocol + ':' + helpers.urlFormat('/shopping/pay/callback/unionpay')
}).then(result => {
if (result && result.code === 200 && result.data) {
return {
code: 200,
data: {
href: `${PAY_URL}?${sign.raw(result.data)}`
}
};
}
return {
code: 400,
message: result.message
};
});
},
notify(data, param) {
let payParams = JSON.parse(param.payParams);
let orderCode = parseInt(data.orderId, 10);
// https://open.unionpay.com/ajweb/help/faq/list?id=234&level=0&from=0
if (!data.respCode || (data.respCode.indexOf('00') < 0 && data.respCode.indexOf('A6') < 0)) {
return {payResult: -1};
}
return {
bankName: '',
orderCode: orderCode,
payResult: 200,
totalFee: data.txnAmt * 0.01,
resultMsg: data.notify_type,
payOrderCode: orderCode,
tradeNo: data.queryId,
bankBillNo: ''
};
}
};
module.exports = unionpay;
... ...
/**
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/9/8
* @author: xiaoxiao.hao<xiaoxiao.hao@yoho.cn>
* @date: 2017/3/23
*/
'use strict';
... ...
/**
*
* @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;
... ... @@ -11,6 +11,7 @@ const PayData = require('../models/pay');
const Alipay = require('./pay/alipay');
const Alibank = require('./pay/alibank');
const Wechat = require('./pay/wechat');
const Unionpay = require('./pay/unionpay');
const Promise = require('bluebird');
const common = require('./pay/common');
const co = Promise.coroutine;
... ... @@ -54,7 +55,10 @@ const Payment = {
if (method === PayData.payments.wechat) {
// 如果是微信支付,不需要调用获取支付方式详情接口
result = yield Wechat.pay(user, order, {id: PayData.payments.wechat});
result = yield Wechat.pay(user, order, {id: method});
} else if (method === PayData.payments.unionpay) {
// 不需要调用获取支付方式详情接口
result = yield Unionpay.pay(user, order, {id: method, protocol: protocol});
} else {
payInfo = yield PayData.getPaymentInfo(method);
... ... @@ -131,6 +135,8 @@ const Payment = {
payResult = Alipay.notify(query, payInfo);
} else if (payId === PayData.payments.alibank) {
payResult = Alibank.notify(query, payInfo);
} else if (payId === PayData.payments.unionpay) {
payResult = Unionpay.notify(query, payInfo);
}
payResult.bankName = payName = (payResult.bankName || payInfo.payName || '');
... ...
... ... @@ -18,7 +18,7 @@ const payments = {
alipay: 2, // 支付宝
wechat: 21, // 微信支付
alibank: 12, // 支付宝支联
unionpayweb: 25, // 银联支付
unionpay: 25, // 银联支付
chinabank: 4, // 网银在线
tenpay: 1, // 财付通
delivery: 3 // 货到付款和0元订单
... ... @@ -250,10 +250,10 @@ const sendPayConfirm = (code, payment, uid) => {
* [埋点数据公共处理]
* @param {[type]} orderInfo [订单详情]
* @param {[type]} payId [支付方式id]
* @param {[type]} payResult [支付成功状态]
* @param {[type]} payResultStatus [支付成功状态]
* @return {[type]} [{}]
*/
const _point = (orderInfo, payId, payResult) => {
const _point = (orderInfo, payId, payResultStatus) => {
let sknArr = [];
let skuArr = [];
... ... @@ -264,7 +264,7 @@ const _point = (orderInfo, payId, payResult) => {
return {
order_code: orderInfo.order_code,
payResult: payResult, // 1支付成功,2支付失败
payResult: payResultStatus, // 1支付成功,2支付失败
amount: orderInfo.payment_amount,
payStyle: payId, // 支付方式id
proSkn: sknArr.join(','),
... ...
... ... @@ -67,6 +67,9 @@
</div>
</div>
{{!--银联支付跳转地址--}}
<form action="" method="post" class='form-go hide' target="_blank"></form>
{{!--下面是统计,不确定有没有作用--}}
{{# order}}
<!-- Google Code for &#19979;&#21333;&#25104;&#21151; Conversion Page -->
... ...
... ... @@ -22,10 +22,10 @@ module.exports = {
// service: 'http://service-test3.yohops.com:9999/',
// prod
singleApi: 'http://single.yoho.cn/',
api: 'http://api.yoho.cn/',
service: 'http://service.yoho.cn/',
serviceNotify: 'http://service.yoho.cn/',
// singleApi: 'http://single.yoho.cn/',
// api: 'http://api.yoho.cn/',
// service: 'http://service.yoho.cn/',
// serviceNotify: 'http://service.yoho.cn/',
// gray
... ... @@ -34,8 +34,10 @@ module.exports = {
// service: 'http://service.gray.yohops.com/',
// dev
// api: 'http://dev-api.yohops.com:9999/',
// service: 'http://dev-service.yohops.com:9999/',
api: 'http://dev-api.yohops.com:9999/',
service: 'http://dev-service.yohops.com:9999/',
serviceNotify: 'http://dev-service.yohops.com:9999/',
singleApi: 'http://dev-api.yohops.com:9999/',
imSocket: 'ws://socket.yohobuy.com:10240',
imCs: 'http://im.yohobuy.com/api',
... ...
... ... @@ -9,6 +9,7 @@ var $btnby = $('input.btnby'),
$lightBox = $('.light-box'),
orderCode = $btnby.data('order'),
amount = $btnby.data('amount'),
$formGo = $('.form-go'),
C_ID;
require('../common');
... ... @@ -96,9 +97,23 @@ payPage = {
return new Alert(d.message).show();
}
if (!d.data.href) {
return new Alert('订单信息获取失败!').show();
}
$lightBox.show();
if (payType === '25_platform') {
$formGo.attr('action', d.data.href);
$formGo.submit();
setTimeout(function() {
$formGo.attr('action', '');
}, 10);
return true;
}
$open = window.open();
$open.location = d.data.href;
$lightBox.show();
},
error: function() {
$this.data('use', false);
... ...