Authored by 郝肖肖

微信支付成功 数据处理

... ... @@ -9,10 +9,7 @@
const headerModel = require('../../../doraemon/models/simple-header');
const PayData = require('../models/pay');
const PayHelpers = require('../helpers/payment');
const paySign = require('../helpers/pay/sign');
const helpers = global.yoho.helpers;
const _ = require('lodash');
const md5 = require('md5');
const integerTest = /^\d+$/;
/**
... ... @@ -32,8 +29,6 @@ const online = (req, res, next) => {
PayData.getPayInfo(uid, orderCode).then(result => {
let order = result.order;
let promotion = order.promotion_formulas;
let coin = 0;
let amount = _.toNumber(order.payment_amount);
let header = headerModel.setSimpleHeaderData() || {};
... ... @@ -42,7 +37,7 @@ const online = (req, res, next) => {
return next();
}
result.order.payment_name = (result.order.payment_type === 1 ? '在线支付' : '货到付款');
result.order.payment_name = (parseInt(result.order.payment_type, 10) === 1 ? '在线支付' : '货到付款');
if (amount > 0) {
res.render('pay', Object.assign({
... ... @@ -53,21 +48,9 @@ const online = (req, res, next) => {
username: decodeURIComponent(req.user.name) || ''
}, result));
} else {
_.forEach(promotion, p => {
if (p.promotion === 'YOHO币') {
coin = parseInt(parseFloat(p.payment_amount.substring(2, p.payment_amount.length)) * 100, 10);
}
});
res.render('pay-success', {
content: {
amount: order.payment_amount,
orderNum: order.order_code,
coin: coin,
orderHref: helpers.urlFormat('/me/order/detail', {
orderCode: order.order_code
}),
walkHref: helpers.urlFormat('/')
}
simpleHeader: header,
order: order
});
}
... ... @@ -123,23 +106,16 @@ const weixinQr = (req, res, next) => {
return next();
}
PayData.orderDetail(uid, code).then(result => {
if (result && result.data) {
return result.data;
} else {
return {};
}
}).then(order => {
PayData.orderDetail(uid, code).then(d => {
d = d && d.data || {};
res.render('weixin-pay', {
module: 'shopping',
page: 'wxpay',
title: '微信扫码支付页面',
simpleHeader: header,
choosePayUrl: helpers.urlFormat('/shopping/pay', {
order_code: order.order_code
}),
choosePayUrl: `//www.yohobuy.com/shopping/pay?ordercode=${d.order_code}`,
qrcodeUrl: qrcodeUrl,
order: order
order: d
});
}).catch(next);
};
... ... @@ -155,32 +131,8 @@ const weixinPayState = (req, res) => {
});
}
PayData.orderDetail(uid, code).then(result => {
let data = {};
result = result && result.data || {};
if (result.is_cancel === 'Y') {
data = {
code: 401,
message: '订单已取消'
};
} else if (result.payment_status === 'Y') {
let payParams = {
orderCode: code,
totalFee: _.round(parseFloat(result.payment_amount), 2)
};
data = {
code: 200,
data: {
href: helpers.urlFormat('/shopping/pay/callback/wechat', Object.assign(payParams, {
sign: md5(paySign.raw(Object.assign({tradeStatus: 'Y'}, payParams)))
}))
}
};
}
return res.json(data);
PayHelpers.getWxSign(uid, code).then(d => {
return res.json(d);
}).catch(() => {
return res.json({});
});
... ... @@ -195,6 +147,7 @@ const callback = (req, res, next) => {
let type = req.params.type;
let payId = PayData.payments[type];
let query = req.query;
let header = headerModel.setSimpleHeaderData() || {};
if (!payId) {
return next();
... ... @@ -202,35 +155,14 @@ const callback = (req, res, next) => {
PayHelpers.afterPay(query, payId, req.user).then(result => {
if (result.code === 200 && result.data && result.data.order) {
let order = result.data.order;
let promotion = order.promotion_formulas;
let coin = 0;
_.forEach(promotion, p => {
if (p.promotion === 'YOHO币') {
coin = parseInt(parseFloat(p.promotion_amount.substring(2, p.promotion_amount.length)) * 100, 10);
}
});
res.render('pay-success', {
defaultHeader: false,
bcNavFocus: 3,
content: {
cost: order.payment_amount,
orderNum: order.order_code,
coin: coin,
orderHref: helpers.urlFormat('/me/order/detail', {
orderCode: order.order_code
}),
walkHref: helpers.urlFormat('/')
}
simpleHeader: header,
order: result.data.order
});
} else {
res.render('pay-fail', {
defaultHeader: false,
payName: result.payName,
bcNavFocus: 3
simpleHeader: header,
payName: result.payName
});
}
}).catch(next);
... ...
... ... @@ -42,8 +42,6 @@ const Wechat = {
unifiedOrder.sign = _.toUpper(signStr);
return this.unifiedOrder(unifiedOrder).then(result => {
console.log(result);
if (result && result.xml) {
let data = result.xml || {};
... ... @@ -77,7 +75,6 @@ const Wechat = {
body: xml,
timeout: 1000
}).then(result => {
console.log(result);
if (result) {
return common.xml2Obj(result);
} else {
... ...
... ... @@ -17,6 +17,8 @@ const co = Promise.coroutine;
const logger = global.yoho.logger;
const md5 = require('md5');
const paySign = require('./pay/sign');
const helpers = global.yoho.helpers;
const _ = require('lodash');
const Payment = {
pay(user, order, payType, protocol) {
... ... @@ -48,7 +50,7 @@ const Payment = {
return result;
}
let method = paymentPars[0] * 1;
let method = parseInt(paymentPars[0], 10);
if (method === PayData.payments.wechat) {
// 如果是微信支付,不需要调用获取支付方式详情接口
... ... @@ -145,7 +147,7 @@ const Payment = {
if (payResult && payResult.payResult === 200) {
if (payResult.orderCode) {
logger.info('pay back confirm');
yield PayData.sendPayConfirm(payResult.orderCode, payId, user.uid);
PayData.sendPayConfirm(payResult.orderCode, payId, user.uid);
}
payData = yield PayData.procOrderData(payResult, user.uid);
... ... @@ -184,6 +186,40 @@ const Payment = {
return payData;
})();
},
getWxSign(uid, code) {
return PayData.orderDetail(uid, code).then(result => {
let data = {};
result = (result.code === 200 ? result.data : {});
if (result.is_cancel === 'Y') {
return {
code: 401,
message: '订单已取消'
};
}
if (result.payment_status === 'Y') {
let payParams = {
orderCode: code,
tradeStatus: 'Y',
totalFee: _.round(parseFloat(result.payment_amount), 2)
};
data = {
code: 200,
data: {
href: helpers.urlFormat('/shopping/pay/callback/wechat', Object.assign(payParams, {
sign: md5(paySign.raw(payParams))
}))
}
};
}
return data;
});
}
};
... ...
... ... @@ -7,6 +7,7 @@
'use strict';
const api = global.yoho.API;
const serviceApi = global.yoho.ServiceAPI;
// 获取支付宝等平台支付方式列表
const getPayProvider = () => {
... ... @@ -100,6 +101,19 @@ const updateOrderPayment = (code, payment, uid) => {
});
};
/**
* [获取资源数据]
* @param {[type]} code [资源位code]
* @return {[type]} [{}]
*/
const getResourceData = (code) => {
return serviceApi.get('operations/api/v5/resource/get', {
content_code: code
}, {
cache: true
});
};
module.exports = {
getPayProvider,
getPaymentInfo,
... ... @@ -109,5 +123,6 @@ module.exports = {
sendPayConfirm,
sendMessage,
orderDetail,
updateOrderPayment
updateOrderPayment,
getResourceData
};
... ...
... ... @@ -12,7 +12,8 @@ const co = Promise.coroutine;
const payHelpersBank = require('./../helpers/bank');
const logger = global.yoho.logger;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const FRAUD_CONTENT_CODE = '78d0fb6c97d691863286edcb4d8abfa9';
const payments = {
alipay: 2,
wechat: 21,
... ... @@ -169,9 +170,7 @@ const getPaymentInfo = (id) => {
*/
const setOrderPayBank = (code, payment, bankCode) => {
return co(function *() {
let data = yield payApi.setOrderPayBank(code, payment, bankCode);
return data;
return yield payApi.setOrderPayBank(code, payment, bankCode);
})();
};
... ... @@ -183,9 +182,7 @@ const setOrderPayBank = (code, payment, bankCode) => {
*/
const updateOrderPayBank = (code, payment, bankCode) => {
return co(function *() {
let data = yield payApi.updateOrderPayBank(code, payment, bankCode);
return data;
return yield payApi.updateOrderPayBank(code, payment, bankCode);
})();
};
... ... @@ -214,48 +211,61 @@ const procOrderData = (payResult, uid) => {
let result = {code: 400, message: ''};
if (!orderCode) {
result.message = '未查到订单信息,订单状态更新失败!';
result.message = '订单不存在';
return result;
}
let orderInfo = yield orderDetail(uid, orderCode);
return Promise.all([orderDetail(uid, orderCode), payApi.getResourceData(FRAUD_CONTENT_CODE)]).then(procData => {
let orderInfo = procData[0].code === 200 && procData[0].data;
let fraudData = _.result(_.find(procData[1].data, {template_name: 'text'}), 'data') || {};
let resultOrder;
if (orderInfo && orderInfo.data) {
let order = orderInfo.data;
let amount = order.payment_amount;
if (!orderInfo) {
result.message = '订单不存在!';
return result;
}
if (order.is_cancel === 'Y') {
logger.warn('front pay success but order is cancel.', {payResult: payResult, order: order});
let amount = orderInfo.payment_amount;
payApi.sendMessage(order.mobile, 'error_sms', '支付成功,但订单已取消,订单号为' + orderCode);
if (orderInfo.is_cancel === 'Y') {
logger.warn('front pay success but order is cancel.', {payResult: payResult, order: orderInfo});
return {code: 417, message: '支付成功,但订单已取消,需联系客服!'};
}
if (order.payment_status === 'N') {
if (orderInfo.payment_status === 'N') {
logger.warn('front pay success but may be notify fail');
}
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});
logger.warn('front pay success but the amount is not same.', {payResult: payResult, order: orderInfo});
return {
code: 415,
message: '支付金额与订单金额不一致,订单状态更新失败!'
};
}
resultOrder = {
paymentTypes: (orderInfo.payment_type === 1 ? '在线支付' : '货到付款'),
multiPackage: orderInfo.is_multi_package === 'Y',
ordersUrl: helpers.urlFormat('/home/orders'),
vipUrl: helpers.urlFormat('/help/detail', {id: 9}),
returnGoodsUrl: helpers.urlFormat('/help/detail', {id: 49}),
yohoCoinUrl: helpers.urlFormat('/help/detail', {id: 105, contId: 233}),
detailUrl: helpers.urlFormat('/home/orders/detail', {
orderCode: orderInfo.order_code
}),
packageTitle: orderInfo.package_title || '商品需要品牌商调货',
fraudTip: fraudData.text || ''
};
return {
code: 200,
message: '支付成功,请等待发货',
data: {
order: order
order: Object.assign(orderInfo, resultOrder)
}
};
} else {
result.message = '未查到订单信息,订单状态更新失败!';
}
return result;
});
})();
};
... ...
{{> settle-header}}
<div class="pay-page pay-fail-page blk-page">
<div class="center-content">
{{> bc-nav}}
<div class="pay-fail-group">
<div class="pay-fail-bg"></div>
<p class="pay-fail-info big">抱歉!订单支付失败,请立即联系客服</p>
<p class="pay-fail-info small">I'm sorry! Order failed to pay, please contact customer service</p>
<p class="pay-fail-info small">感谢您选择{{payName}}支付方式,我们的客服随后会和您确认订单</p>
<p class="pay-fail-info medium">客服电话:<span class='blue'>400-889-9646</span></p>
<a href="/" class="go-to-home">
<span class="btn">返回BLK首页</span>
</a>
<div class="pay-notice-wechatqrcodereturn-page yoho-page clearfix">
<div class="wechatqrcodereturn">
<div class="pay-title">
<div class="step5"></div>
<ul>
<li><span>查看购物车</span></li>
<li><span>填写订单</span></li>
<li class="end"><span>付款,完成购买</span></li>
</ul>
</div>
<div class="pay-wechat-return">
<p class="payerror">
很抱歉,订单支付失败,请立即联系客服!
</p>
<p class="arrival-time">
客服电话:
<b class="tell-phone">
400-889-9646
</b>
</p>
</div>
<div class="cart-bigbtns">
<span class="btn-type">
<a href="/">返回首页</a>
</span>
</div>
<div class="we-alert">
<span class="we-font">感谢您选择 {{payName}} 的方式,我们的客服随后会和您确认订单。</span>
</div>
</div>
</div>
... ...
{{> settle-header}}
<div class="pay-page pay-success-page blk-page">
<div class="center-content">
{{> bc-nav}}
{{# content}}
<div class="order-info clearfix">
<div class="left">
<p class="success-tip">
恭喜您,购买完成!您已成功支付
{{#if cost}}
{{round cost 2}}
<div class="pay-notice-page yoho-page">
{{# order}}
<div class="order-wrap">
<h1><i class="pay-sure-icon"></i>恭喜您,购买完成!您已成功支付<span class="red">{{payment_amount}}</span>元!</h1>
{{#if coin}}
,有货币{{coin}}
{{/if}}
{{^}}
有货币{{coin}}
{{/if}}
</p>
<p class="order-num">订单编号:{{orderNum}}</p>
{{#if cost}}
<p class="payment-online">在线支付:¥{{round cost 2}}</p>
{{/if}}
{{#if coin}}
<p class="payment-coin">有货币支付:{{coin}}</p>
{{/if}}
</div>
<div class="btns right">
<a class="btn go-check-order" href="{{https orderHref}}">查看订单详情</a>
<a class="btn" href="{{https walkHref}}">继续逛逛</a>
</div>
</div>
<div class="order-info">
<ul>
<li><span class="l-b">订单号: {{order_code}}</span></li>
<li><span class="l-b">在线金额: {{payment_amount}}</span></li>
<li>
<span class="l-b back-yoho-coin">共返有货币:{{yoho_give_coin}}</span>
<a href="{{yohoCoinUrl}}" class="notice-link" target="_blank">有货币能做什么>></a>
</li>
<li>
<span class="l-b">获得VIP累计金额:{{payment_amount}}</span>
<a href="{{vipUrl}}" class="notice-link" target="_blank">查看VIP特权>></a>
</li>
<li class="opt-btns">
<a href="{{detailUrl}}">查看订单详情</a>
<a href="/">继续逛逛</a>
</li>
</ul>
</div>
</div>
<div class="tip-info">
<p class="title">温馨提示:</p>
<p>
1.当订单发货后,您可以登录<a class="blue" href="/me/order">订单中心</a>查询快递发货详情。
2.YOHO!BLK有货支持“开箱验货”和“15天退换货保障”收货后请当面验货,如果发现商品有任何问题请致电客服电话400-889-9646,
<a class="blue" href="/help?id=43">“退换货政策”</a>请点击查看。<em class="blue">3.尊敬的用户:近期为网络诈骗高发期,YOHO!BLK有货郑重声明,不会以任何形式索取客户的账户信息或引导转账,敬请提高警惕,谨防诈骗</em>
</p>
</div>
{{/ content}}
<div class="extra-wrap">
<h5>温馨提示:</h5>
{{#if multiPackage}}
<p>
1.{{packageTitle}}至有货仓库,预计3-5日内发货给您。<br>
2.当订单发货后,您可以登录<a href="{{ordersUrl}}" class="notice-link" target="_blank">订单中心</a>查询快递发货详情。<br>
3.YOHO!BUY有货支持 “开箱验货” 和 “15天退换货保障”,收货后请当面验货,如果发现商品有任何问题请致电客服电话400-889-9646,
<a href="{{returnGoodsUrl}}" class="notice-link" target="_blank">“退换货政策”</a> 请点击查看。<br>
4.VIP金额的累计,将在您订单签收15天后积累到您的账户,请您知悉。<br>
5.购买商品及参与促销活动赠送的有货币,将在您订单签收7天后积累到您的账户,您可以在个人中心-我的有货币中查看。<br>
{{#if fraudTip}}
<span class="red">6.{{{fraudTip}}}</span>
{{/if}}
</p>
{{^}}
<p>
1.当订单发货后,您可以登录<a href="{{ordersUrl}}" class="notice-link" target="_blank">订单中心</a>查询快递发货详情。<br>
2.YOHO!BUY有货支持 “开箱验货” 和 “15天退换货保障”,收货后请当面验货,如果发现商品有任何问题请致电客服电话400-889-9646,
<a href="{{returnGoodsUrl}}" class="notice-link" target="_blank">“退换货政策”</a> 请点击查看。<br>
3.VIP金额的累计,将在您订单签收15天后积累到您的账户,请您知悉。<br>
4.购买商品及参与促销活动赠送的有货币,将在您订单签收7天后积累到您的账户,您可以在个人中心-我的有货币中查看。<br>
{{#if fraudTip}}
<span class="red">5.{{{fraudTip}}}</span>
{{/if}}
</p>
{{/if}}
</div>
{{/order}}
</div>
... ...
@import "pay";
@import "wxpay";
@import "cashondelivery";
@import "wechatqrcodereturn";
@import "notice";
... ...
.pay-notice-page {
width: 990px;
margin: 0 auto;
padding: 30px 0;
font-size: 14px;
color: #444;
.red {
color: #ce0b24;
}
.order-wrap {
padding: 40px 50px;
background-color: #f5f5f5;
border: 1px solid #e0e0e0;
> h1 {
font-size: 28px;
line-height: 1;
.pay-sure-icon {
display: inline-block;
width: 32px;
height: 32px;
margin-right: 20px;
background: resolve('pay/pay-sure-icon.png');
vertical-align: text-bottom;
}
}
}
.order-info {
margin-top: 40px;
border-top: 1px solid #e0e0e0;
padding-top: 30px;
position: relative;
li {
padding-bottom: 18px;
.l-b {
display: inline-block;
width: 200px;
}
.back-yoho-coin:after {
content: '';
display: inline-block;
width: 14px;
height: 14px;
background: resolve('cart/yoho-coin.png');
margin-left: 6px;
vertical-align: bottom;
}
.notice-link {
color: #0883d1;
}
}
.opt-btns {
padding-top: 10px;
padding-bottom: 0;
> a {
width: 120px;
height: 32px;
line-height: 32px;
color: #fff;
background-color: #3a3a3a;
display: inline-block;
text-align: center;
margin-right: 54px;
}
}
&:after {
content: '';
width: 450px;
height: 170px;
background: resolve('pay/qr-img.png');
position: absolute;
top: 30px;
right: 0;
}
}
.extra-wrap {
padding: 30px 40px;
line-height: 2;
color: #bbb;
border: 1px solid #e0e0e0;
margin-top: 30px;
.notice-link {
color: #0883d1;
}
}
.best-for-you {
margin-top: 30px;
.top-title {
font-weight: 300;
border-bottom: 1px solid #e0e0e0;
span {
font-size: 18px;
display: inline-block;
padding: 0 4px;
height: 40px;
border-bottom: 3px solid #4a4a4a;
}
.change-btn {
float: right;
font-size: 16px;
line-height: 18px;
cursor: pointer;
display: none;
&:after {
content: '';
width: 13px;
height: 13px;
margin-left: 8px;
display: inline-block;
vertical-align: middle;
background: resolve('pay/change-icon.png');
}
}
}
.product-wrap {
margin-top: 30px;
overflow: hidden;
ul {
width: 3010px;
height: 307px;
overflow: hidden;
}
li {
width: 190px;
margin-right: 10px;
font-size: 12px;
font-weight: bold;
line-height: 1.5;
float: left;
text-align: center;
}
.thumb {
height: 256px;
}
.name {
padding: 0 10px;
margin-top: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
... ...
.wechatqrcodereturn {
width: 990px;
margin: 0 auto;
font-size: 12px;
font-family: Arial,helvetica,sans-serif;
.pay-title {
height: 65px;
overflow: hidden;
padding: 20px 0px 0px 0px;
margin: 0px auto;
border-bottom: 2px solid #000000;
ul {
width: 446px;
height: 12px;
float: right;
list-style: none;
padding: 0;
margin: 0;
background: resolve(pay/pay-list.png) no-repeat top right;
}
li {
width: 176px;
height: 12px;
text-align: center;
color: #999;
float: left;
span {
display: block;
height: 15px;
padding: 15px 0px 0px 0px;
line-height: 15px;
}
}
.end {
width: 93px;
height: 18px;
color: #000;
span {
text-align: right;
}
}
}
.step5 {
height: 33px;
width: 97px;
overflow: hidden;
background-image: resolve(pay/finsh.png);
float: left;
}
.pay-wechat-return {
overflow: hidden;
padding-top: 10px;
}
.payerror {
margin: 50px 0 0 300px;
font-size: 14px;
font-weight: bold;
color: #000;
padding-left: 25px;
line-height: 21px;
background: resolve(pay/pay-fail.png) no-repeat;
}
.arrival-time {
margin: 10px 0 0 325px;
color: #666;
}
.tell-phone {
color: #e8044f;
font-weight: bold;
font-size: 16px;
}
.cart-bigbtns {
span {
margin-right: 5px;
}
}
.btn-type {
display: inline-block;
height: 35px;
padding: 0 0 0 2px;
overflow: hidden;
font-size: 14px;
margin: 40px 0 0 320px;
a {
display: inline-block;
height: 35px;
line-height: 32px;
padding: 0 20px;
background: resolve(pay/btnby.png) no-repeat;
border: none;
overflow: visible;
cursor: pointer;
margin: 0;
color: #666;
}
}
.we-font {
margin: 20px 0 0 320px;
height: 36px;
line-height: 36px;
padding-left: 16px;
color: #999;
display: block;
background: resolve(pay/pay-plaint.png) no-repeat 1px;
}
}
... ...