Authored by 郭成尧

pay-ctx

... ... @@ -6,479 +6,430 @@
'use strict';
const api = global.yoho.API;
const serviceAPI = global.yoho.ServiceAPI;
const utils = '../../../utils';
const productProcess = require(`${utils}/product-process`);
const ApipayConfig = global.yoho.config.alipayConfig;
const md5 = require('yoho-md5');
const payApi = require('./pay-api');
const helpers = global.yoho.helpers;
const payApiModel = require('./pay-api');
const _ = require('lodash');
const co = require('bluebird').coroutine;
const logger = global.yoho.logger;
const stringProcess = require(`${global.utils}/string-process`);
// 支付方式
const payments = {
alipay: 18,
wechat: 22
};
// 资源位
const _getBanner = (param) => {
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: param.contentCode,
platform: 'iphone'
}, { code: 200 }).then((result) => {
result = result.data;
return result;
});
};
// 购买此商品的用户也购买了
const _getOthersBuy2 = (param) => {
return api.get('', {
method: 'app.recommend.purchased',
productSkn: param.skn,
udid: param.uid,
rec_pos: '100005',
limit: 2,
client_id: param.client_id
}, { code: 200 }).then((result) => {
if (result && result.data && result.data.product_list) {
return productProcess.processProductList(result.data.product_list);
}
});
};
// 订单信息
const _getOtherDetail = (param) => {
if (!param.uid || !param.orderCode || !stringProcess.isNumeric(param.orderCode)) {
return Promise.resolve({});
class payModel extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
this.ctx = _.get(ctx, 'req.ctx');
}
return api.get('', {
method: 'app.SpaceOrders.detail',
uid: param.uid,
order_code: param.orderCode,
session_key: param.sessionKey
}, { code: 200 }).then(result => {
return result;
});
};
// 购买此商品的用户也购买了,要先从订单详情获取商品skn
const _getOthersBuy = (param) => {
return api.all([
_getOtherDetail(param)
]).then((result) => {
let goodSkn = '';
if (result && result[0] && result[0].data && result[0].data.order_goods) {
goodSkn = result[0].data.order_goods[0].product_skn;
}
return _getOthersBuy2(Object.assign(param, { skn: goodSkn }));
// 资源位
_getBanner(param) {
return this.get({
api: serviceAPI,
url: 'operations/api/v5/resource/get',
data: {
content_code: param.contentCode,
platform: 'iphone'
},
param: { code: 200 }
}).then((result) => {
result = result.data;
}).then((result) => {
return result;
});
}
return result;
});
};
// 购买此商品的用户也购买了
_getOthersBuy2(param) {
return this.get({data: {
method: 'app.recommend.purchased',
productSkn: param.skn,
udid: param.uid,
rec_pos: '100005',
limit: 2,
client_id: param.client_id
}, param: { code: 200 }}).then((result) => {
if (result && result.data && result.data.product_list) {
return productProcess.processProductList(result.data.product_list);
}
/**
* 获取订单支付银行信息
* @param id
*/
const getBankByOrder = (id) => {
return co(function* () {
let result = yield payApi.getBankByOrder(id);
});
}
if (result && result.code === 200 && result.data) {
return result.data;
// 订单信息
getOtherDetail(param) {
if (!param.uid || !param.orderCode || !stringProcess.isNumeric(param.orderCode)) {
return Promise.resolve({});
}
return {};
})();
};
/**
* 设置订单支付银行
* @param code
* @param payment
* @param bankCode
*/
const setOrderPayBank = (code, payment, bankCode) => {
return co(function* () {
let data = yield payApi.setOrderPayBank(code, payment, bankCode);
return data;
})();
};
/**
* 获取支付方式的相关参数, (密钥等信息)
* @param id
*/
const getPaymentInfo = (id) => {
return co(function* () {
let result = yield payApi.getPaymentInfo(id);
return this.get({data: {
method: 'app.SpaceOrders.detail',
uid: param.uid,
order_code: param.orderCode,
session_key: param.sessionKey
}, param: { code: 200 }}).then(result => {
return result;
});
}
if (result && result.code === 200 && result.data) {
return result.data;
}
return {};
})();
};
// 购买此商品的用户也购买了,要先从订单详情获取商品skn
_getOthersBuy(param) {
return Promise.all([
this.getOtherDetail(param)
]).then((result) => {
/**
* 支付确认
* @param code
* @param payment
* @param uid
*/
const sendPayConfirm = (code, payment, uid) => {
return co(function* () {
let data = yield payApi.sendPayConfirm(code, payment, uid);
let goodSkn = '';
return data;
})();
};
if (result && result[0] && result[0].data && result[0].data.order_goods) {
goodSkn = result[0].data.order_goods[0].product_skn;
}
/**
* 更新订单支付方式
* @param code
* @param payment
* @param uid
* @returns {*}
*/
const updateOrderPayment = (code, payment, uid) => {
return api.get('', {
method: 'app.SpaceOrders.updateOrdersPaymentByCode',
order_code: code,
payment: payment,
uid: uid
});
};
return this._getOthersBuy2(Object.assign(param, { skn: goodSkn }));
/**
* 更新订单支付银行
* @param code
* @param payment
* @param bankCode
*/
const updateOrderPayBank = (code, payment, bankCode) => {
return co(function* () {
let data = yield payApi.updateOrderPayBank(code, payment, bankCode);
}).then((result) => {
return data;
})();
};
return result;
});
}
/**
* 支付成功,前端回调时,处理订单信息
* @param payResult
* @param uid
* @param sessionKey
*/
const procOrderData = (payResult, uid, sessionKey) => {
return co(function* () {
let orderCode = payResult.orderCode;
let result = { code: 400, message: '' };
/**
* 获取订单支付银行信息
* @param id
*/
getBankByOrder(id) {
let self = this;
if (!orderCode) {
result.message = '未查到订单信息,订单状态更新失败!';
return result;
} else {
let orderInfo = yield _getOtherDetail({
uid: uid,
orderCode: orderCode,
sessionKey: sessionKey
});
return co(function* () {
let result = yield self.ctx(payApiModel).getBankByOrder(id);
if (orderInfo && orderInfo.data) {
let order = orderInfo.data;
let amount = order.payment_amount;
if (result && result.code === 200 && result.data) {
return result.data;
}
return {};
})();
}
if (order.is_cancel === 'Y') {
logger.warn('front pay success but order is cancel.', { payResult: payResult, order: order });
/**
* 设置订单支付银行
* @param code
* @param payment
* @param bankCode
*/
setOrderPayBank(code, payment, bankCode) {
let self = this;
payApi.sendMessage(order.mobile, 'error_sms', '支付成功,但订单已取消,订单号为' + orderCode);
return { code: 417, message: '支付成功,但订单已取消,需联系客服!' };
}
return co(function* () {
let data = yield self.ctx(payApiModel).setOrderPayBank(code, payment, bankCode);
if (order.payment_status === 'N') {
logger.warn('front pay success but may be notify fail');
}
return data;
})();
}
if (_.round(parseFloat(amount), 2) !== _.round(parseFloat(payResult.totalFee), 2)) {
logger.warn('front pay success but the amount is not same.', {
payResult: payResult, order: order
});
return {
code: 415,
message: '支付金额与订单金额不一致,订单状态更新失败!'
};
}
/**
* 获取支付方式的相关参数, (密钥等信息)
* @param id
*/
getPaymentInfo(id) {
let self = this;
return {
code: 200,
message: '支付成功,请等待发货',
data: {
order: order
}
};
return co(function* () {
let result = yield self.ctx(payApiModel).getPaymentInfo(id);
} else {
result.message = '未查到订单信息,订单状态更新失败!';
if (result && result.code === 200 && result.data) {
return result.data;
}
}
return {};
})();
}
return result;
})();
};
/**
* 支付确认
* @param code
* @param payment
* @param uid
*/
sendPayConfirm(code, payment, uid) {
let self = this;
/**
* 支付相关的数据处理函数
*/
const payTool = {
return co(function* () {
let data = yield self.ctx(payApiModel).sendPayConfirm(code, payment, uid);
return data;
})();
}
/**
* 支持的支付方式列表
* @returns {[*,*]}
* 更新订单支付方式
* @param code
* @param payment
* @param uid
* @returns {*}
*/
payAppInfo(orderCode) {
return [{
appIcon: '',
payLink: helpers.urlFormat('/cart/index/new/pay', {
payment: payments.alipay + '_platform',
order_code: orderCode
}),
appId: 'alipay',
app: '支付宝支付',
hint: '支付宝钱包支付',
subHint: '推荐支付宝用户使用'
}, {
appIcon: '',
payLink: '',
appId: 'weixin',
app: '微信支付',
hint: '推荐使用',
subHint: ''
}];
},
updateOrderPayment(code, payment, uid) {
return this.get({data: {
method: 'app.SpaceOrders.updateOrdersPaymentByCode',
order_code: code,
payment: payment,
uid: uid
}});
}
/**
* 计算购买商品总数量
* @param goodsArray
* @returns {number}
* @private
* 更新订单支付银行
* @param code
* @param payment
* @param bankCode
*/
calBuyNumCount(goodsArray) {
let buyNumCount = 0;
updateOrderPayBank(code, payment, bankCode) {
let self = this;
if (_.isArray(goodsArray)) {
_.forEach(goodsArray, value => {
buyNumCount = value.buy_number ? parseInt(value.buy_number, 10) : 0;
});
}
return co(function* () {
let data = yield self.ctx(payApiModel).updateOrderPayBank(code, payment, bankCode);
return buyNumCount;
return data;
})();
}
};
/**
* 支付中心
* @param params
*/
const payCenter = (params) => {
return _getOtherDetail({
uid: params.uid,
orderCode: params.orderCode,
sessionKey: params.sessionKey
}).then(result => {
return _.get(result, 'data', {});
});
};
// 货到付款
const getPayCod = (param) => {
return api.all([
_getBanner(param),
_getOthersBuy(param),
_getOtherDetail(param)
]).then((result) => {
let resu = {
match: true,
banner: [],
othersBuy: []
};
if (result && result[0]) {
_.forEach(result[0], function(val) {
if (val.template_name === 'single_image') {
resu.banner = val;
} else if (val.template_name === 'text') {
resu.prompt = val.data;
}
});
}
/**
* 支付成功,前端回调时,处理订单信息
* @param payResult
* @param uid
* @param sessionKey
*/
procOrderData(payResult, uid, sessionKey) {
let self = this;
if (result && result[1]) {
resu.othersBuy = result[1];
}
return co(function* () {
let orderCode = payResult.orderCode;
let result = { code: 400, message: '' };
if (result && result[2] && result[2].data && result[2].data.payment_amount) {
resu.payment = result[2].data.payment_amount;
if (!orderCode) {
result.message = '未查到订单信息,订单状态更新失败!';
return result;
} else {
let orderInfo = yield self._getOtherDetail({
uid: uid,
orderCode: orderCode,
sessionKey: sessionKey
});
} else {
resu.match = false;
}
if (orderInfo && orderInfo.data) {
let order = orderInfo.data;
let amount = order.payment_amount;
resu.orderCode = param.orderCode;
if (order.is_cancel === 'Y') {
logger.warn('front pay success but order is cancel.', { payResult: payResult, order: order });
resu.orderUrl = '/home/orders/detail?order_code=' + param.orderCode;
self.ctx(payApiModel).sendMessage(order.mobile, 'error_sms', '支付成功,但订单已取消,订单号为' + orderCode);
return { code: 417, message: '支付成功,但订单已取消,需联系客服!' };
}
return resu;
});
};
if (order.payment_status === 'N') {
logger.warn('front pay success but may be notify fail');
}
const _raw = (args) => {
let keys = Object.keys(args);
if (_.round(parseFloat(amount), 2) !== _.round(parseFloat(payResult.totalFee), 2)) {
logger.warn('front pay success but the amount is not same.', {
payResult: payResult, order: order
});
return {
code: 415,
message: '支付金额与订单金额不一致,订单状态更新失败!'
};
}
keys = keys.filter(k => {
let keyValueCheck =
k === 'sign' ||
k === 'sign_type' ||
k === 'code' ||
args[k] === '' ||
args[k] === 'undefined';
return {
code: 200,
message: '支付成功,请等待发货',
data: {
order: order
}
};
return !keyValueCheck;
}).sort();
} else {
result.message = '未查到订单信息,订单状态更新失败!';
}
}
return keys.map(k => {
return k + '=' + decodeURI(args[k]);
}).join('&');
};
return result;
})();
}
/**
* 验证返回结果的正确性
*/
const _checkResponse = (params) => {
if (!params.sign) {
return false;
/**
* 支付中心
* @param params
*/
payCenter(params) {
return this.getOtherDetail({
uid: params.uid,
orderCode: params.orderCode,
sessionKey: params.sessionKey
}).then(result => {
return _.get(result, 'data', {});
});
}
let rawResult = _raw(params);
let sign = rawResult + ApipayConfig.alipayKey;
let md5Result = md5(sign);
return md5Result === params.sign;
};
// 货到付款
getPayCod(param) {
return Promise.all([
this._getBanner(param),
this._getOthersBuy(param),
this.getOtherDetail(param)
]).then((result) => {
let resu = {
match: true,
banner: [],
othersBuy: []
};
if (result && result[0]) {
_.forEach(result[0], function(val) {
if (val.template_name === 'single_image') {
resu.banner = val;
} else if (val.template_name === 'text') {
resu.prompt = val.data;
}
});
}
if (result && result[1]) {
resu.othersBuy = result[1];
}
/**
* 支付宝支付结果校验
*/
const alipayResultVerify = (params) => {
let checkResult = {};
if (result && result[2] && result[2].data && result[2].data.payment_amount) {
resu.payment = result[2].data.payment_amount;
if (params.q) {
delete params.q;
}
} else {
resu.match = false;
}
resu.orderCode = param.orderCode;
if (!_checkResponse(params)) {
checkResult.payResult = false;
} else {
_.assign(checkResult, {
bankName: '',
orderCode: params.out_trade_no,
payResult: params.trade_status === 'TRADE_SUCCESS',
payTime: params.gmt_payment || '',
totalFee: params.total_fee,
resultMsg: params.notify_type,
payOrderCode: params.out_trade_no,
tradeNo: params.trade_no,
bankBillNo: ''
resu.orderUrl = '/home/orders/detail?order_code=' + param.orderCode;
return resu;
});
}
return checkResult;
};
// 支付宝支付
const getPayAli = (param) => {
return api.all([
_getBanner(param),
_getOthersBuy(param),
_getOtherDetail(param)
]).then((result) => {
let resu = {
match: true,
banner: [],
othersBuy: []
};
if (result && result[0]) {
_.forEach(result[0], function(val) {
if (val.template_name === 'single_image') {
resu.banner = val;
} else if (val.template_name === 'text') {
resu.prompt = val.data;
}
});
_raw(args) {
let keys = Object.keys(args);
keys = keys.filter(k => {
let keyValueCheck =
k === 'sign' ||
k === 'sign_type' ||
k === 'code' ||
args[k] === '' ||
args[k] === 'undefined';
return !keyValueCheck;
}).sort();
return keys.map(k => {
return k + '=' + decodeURI(args[k]);
}).join('&');
}
/**
* 验证返回结果的正确性
*/
_checkResponse(params) {
if (!params.sign) {
return false;
}
let rawResult = this._raw(params);
let sign = rawResult + ApipayConfig.alipayKey;
let md5Result = md5(sign);
return md5Result === params.sign;
}
/**
* 支付宝支付结果校验
*/
alipayResultVerify(params) {
let checkResult = {};
if (params.q) {
delete params.q;
}
if (result && result[1]) {
resu.othersBuy = result[1];
if (!this._checkResponse(params)) {
checkResult.payResult = false;
} else {
_.assign(checkResult, {
bankName: '',
orderCode: params.out_trade_no,
payResult: params.trade_status === 'TRADE_SUCCESS',
payTime: params.gmt_payment || '',
totalFee: params.total_fee,
resultMsg: params.notify_type,
payOrderCode: params.out_trade_no,
tradeNo: params.trade_no,
bankBillNo: ''
});
}
if (result && result[2] && result[2].data && result[2].data.payment_amount) {
resu.packageTitle = _.get(result[2], 'data.package_title', '');
return checkResult;
}
// 支付宝支付
getPayAli(param) {
return Promise.all([
this._getBanner(param),
this._getOthersBuy(param),
this.getOtherDetail(param)
]).then((result) => {
let resu = {
match: true,
banner: [],
othersBuy: []
};
if (result && result[0]) {
_.forEach(result[0], function(val) {
if (val.template_name === 'single_image') {
resu.banner = val;
} else if (val.template_name === 'text') {
resu.prompt = val.data;
}
});
}
if (result && result[1]) {
resu.othersBuy = result[1];
}
if (result && result[2] && result[2].data && result[2].data.payment_amount) {
resu.packageTitle = _.get(result[2], 'data.package_title', '');
resu.payment = result[2].data.payment_amount;
resu.payment = result[2].data.payment_amount;
if (param.isPay && param.isPay === true) {
if (result[2].data.payment_status && result[2].data.payment_status === 'Y') {
resu.payWay = false;
if (param.isPay && param.isPay === true) {
if (result[2].data.payment_status && result[2].data.payment_status === 'Y') {
resu.payWay = false;
} else {
resu.isCancel = true;
}
} else {
resu.isCancel = true;
resu.payWay = true;
}
} else {
resu.payWay = true;
resu.match = false;
}
} else {
resu.match = false;
}
resu.orderCode = param.orderCode;
resu.orderUrl = '/home/orders/detail?order_code=' + param.orderCode;
return resu;
});
}
}
resu.orderCode = param.orderCode;
resu.orderUrl = '/home/orders/detail?order_code=' + param.orderCode;
return resu;
});
};
module.exports = {
payments,
getOtherDetail: _getOtherDetail,
updateOrderPayment,
updateOrderPayBank,
getBankByOrder,
getPaymentInfo,
setOrderPayBank,
sendPayConfirm,
procOrderData,
payCenter,
payTool,
getPayCod,
getPayAli,
alipayResultVerify
};
module.exports = payModel;
... ...