20261008
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 余额记录改为读取订单付款单(jjx-order-pay-list)。
|
||||
* 只允许查询当前登录用户作为卖家的付款单,避免客户端伪造 uid 查询其他用户数据。
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* @url client/userBalanceLog/kh/getList 前端调用的url参数地址
|
||||
* @param {Object} data
|
||||
* @param {String} data.queryDate 查询日期,格式 yyyyMMdd
|
||||
*/
|
||||
main: async (event) => {
|
||||
const {data = {}, userInfo = {}, util} = event;
|
||||
const {vk, _} = util;
|
||||
const sellerUid = userInfo._id || userInfo.uid;
|
||||
const pageIndex = Math.max(parseInt(data.pageIndex, 10) || 1, 1);
|
||||
const pageSize = Math.min(Math.max(parseInt(data.pageSize, 10) || 10, 1), 1000);
|
||||
|
||||
if (!sellerUid) {
|
||||
return {code: 0, msg: '', rows: [], total: 0, pageIndex, pageSize};
|
||||
}
|
||||
|
||||
const requestedDate = String(data.queryDate || '').trim();
|
||||
let dateText = /^\d{8}$/.test(requestedDate) ? requestedDate : formatDate(new Date());
|
||||
let dateRange = getDateRange(dateText);
|
||||
if (!dateRange) {
|
||||
dateText = formatDate(new Date());
|
||||
dateRange = getDateRange(dateText);
|
||||
}
|
||||
const whereJsonArr = [{sellerUid}];
|
||||
|
||||
// _add_time 是付款单的创建时间,按所选日期过滤;保留 _add_time_str 兼容历史字符串数据。
|
||||
if (dateRange) {
|
||||
whereJsonArr.push(_.or([
|
||||
_.and([
|
||||
{_add_time: _.gte(dateRange.start)},
|
||||
{_add_time: _.lt(dateRange.end)}
|
||||
]),
|
||||
_.and([
|
||||
{_add_time: _.gte(dateRange.start.getTime())},
|
||||
{_add_time: _.lt(dateRange.end.getTime())}
|
||||
]),
|
||||
_.and([
|
||||
{_add_time_str: _.gte(dateRange.startText)},
|
||||
{_add_time_str: _.lt(dateRange.endText)}
|
||||
])
|
||||
]));
|
||||
}
|
||||
|
||||
const result = await vk.baseDao.select({
|
||||
dbName: 'jjx-order-pay-list',
|
||||
getCount: true,
|
||||
whereJson: _.and(whereJsonArr),
|
||||
sortArr: [{name: '_add_time', type: 'desc'}],
|
||||
pageIndex,
|
||||
pageSize
|
||||
});
|
||||
|
||||
const rows = Array.isArray(result.rows) ? result.rows : [];
|
||||
let merNo = String(userInfo.merNo || '').trim();
|
||||
if (!merNo) {
|
||||
const currentUser = await vk.baseDao.findById({dbName: 'uni-id-users', id: sellerUid});
|
||||
merNo = String((currentUser && currentUser.merNo) || '').trim();
|
||||
}
|
||||
|
||||
// 银联交易明细查询(202007)按 seqId 查询。单条查询失败不影响其他记录返回。
|
||||
await Promise.all(rows.map(async (row) => {
|
||||
const notifyData = parseObject(row.payNotifyData);
|
||||
const seqId = notifyData && notifyData.seqId;
|
||||
if (seqId && merNo) {
|
||||
try {
|
||||
row.flowData = await vk.request({
|
||||
url: 'http://jjx-union-pay.gxwebsoft.com/api/union-pay-jjx/getFlow',
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
header: {'content-type': 'application/json; charset=utf-8'},
|
||||
data: {
|
||||
accNo: merNo,
|
||||
transDate: dateText,
|
||||
// 202007 查询项约定:A-请求流水号(seqId)。
|
||||
queryItem: 'A',
|
||||
queryValue: String(seqId)
|
||||
},
|
||||
timeout: 60000
|
||||
});
|
||||
row.flowStatus = pickFlowValue(row.flowData, ['orderStatus', 'transStatus', 'status', 'respCode']);
|
||||
row.flowErrMsg = pickFlowValue(row.flowData, ['errMsg', 'respMsg', 'msg', 'message']);
|
||||
} catch (error) {
|
||||
row.flowError = error && error.message ? error.message : '流水状态查询失败';
|
||||
}
|
||||
}
|
||||
|
||||
// 给原余额记录表保留一组兼容字段,同时返回付款单原始字段供页面使用。
|
||||
row.reqJournalNo = row.reqJournalNo || row.orderNo || row.orderId || row._id;
|
||||
const amountYuan = row.amount !== undefined && row.amount !== null
|
||||
? Number(row.amount)
|
||||
: Number(row.payAmount || 0) / 100;
|
||||
row.orderAmt = (Number.isFinite(amountYuan) ? amountYuan : 0) * 100;
|
||||
row.orderStatus = normalizeOrderStatus(row.flowStatus, row.hasPaid, row.status);
|
||||
row.errMsg = row.errMsg || row.flowErrMsg || row.refuseReason || '';
|
||||
row.tradeTime = row.paidAt || row._add_time_str || row._add_time || '';
|
||||
row.payerName = row.payerName || row.buyerName || '';
|
||||
row.payerAcctNo = row.payerAcctNo || '';
|
||||
}));
|
||||
|
||||
return {
|
||||
...result,
|
||||
rows,
|
||||
pageIndex,
|
||||
pageSize
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function parseObject(value) {
|
||||
if (!value) return null;
|
||||
if (typeof value === 'object') return value;
|
||||
if (typeof value !== 'string') return null;
|
||||
try {
|
||||
const parsed = JSON.parse(value);
|
||||
return parsed && typeof parsed === 'object' ? parsed : null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function pickFlowValue(value, keys) {
|
||||
const objects = [value, value && value.data, value && value.info, value && value.content]
|
||||
.filter(item => item && typeof item === 'object' && !Array.isArray(item));
|
||||
for (const object of objects) {
|
||||
for (const key of keys) {
|
||||
if (object[key] !== undefined && object[key] !== null && object[key] !== '') return object[key];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function normalizeOrderStatus(flowStatus, hasPaid, localStatus) {
|
||||
if (flowStatus !== undefined && flowStatus !== null && flowStatus !== '') {
|
||||
const status = String(flowStatus);
|
||||
if (/^[0-4]$/.test(status)) return Number(status);
|
||||
if (['SUCCESS', 'TRADE_SUCCESS', 'PAID', '00'].includes(status.toUpperCase())) return 1;
|
||||
if (['FAIL', 'FAILED', 'TRADE_FAIL', 'CLOSED'].includes(status.toUpperCase())) return 2;
|
||||
}
|
||||
// 付款单 status 0~4 表示支付流程阶段,并非银联失败码;只要已进入已支付流程即展示成功。
|
||||
if (hasPaid === true || Number(localStatus) > 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function formatDate(date) {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}${month}${day}`;
|
||||
}
|
||||
|
||||
function getDateRange(dateText) {
|
||||
const year = Number(dateText.slice(0, 4));
|
||||
const month = Number(dateText.slice(4, 6));
|
||||
const day = Number(dateText.slice(6, 8));
|
||||
const start = new Date(year, month - 1, day);
|
||||
if (Number.isNaN(start.getTime()) || start.getFullYear() !== year || start.getMonth() !== month - 1 || start.getDate() !== day) {
|
||||
return null;
|
||||
}
|
||||
const end = new Date(start.getTime());
|
||||
end.setDate(end.getDate() + 1);
|
||||
const startText = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')} 00:00:00`;
|
||||
const endText = `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, '0')}-${String(end.getDate()).padStart(2, '0')} 00:00:00`;
|
||||
return {start, end, startText, endText};
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const balanceUtil = require('../../../admin/finance/balance/sys/util.js');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* 查询当前用户商户的实时余额。
|
||||
* @url client/userBalanceLog/kh/getMerchantBalance 前端调用的url参数地址
|
||||
* @param {String} accNo 企业用户号/商户号
|
||||
*/
|
||||
main: async (event) => {
|
||||
const { data = {}, userInfo = {}, util } = event;
|
||||
const { vk } = util;
|
||||
const requestedAccNo = String(data.accNo || '').trim();
|
||||
const userAccNo = String(userInfo.merNo || '').trim();
|
||||
|
||||
// 商户号来自当前登录用户,避免通过客户端参数查询其他企业的余额。
|
||||
if (requestedAccNo && userAccNo && requestedAccNo !== userAccNo) {
|
||||
return {
|
||||
code: 403,
|
||||
msg: '无权查询该商户余额'
|
||||
};
|
||||
}
|
||||
const accNo = userAccNo || requestedAccNo;
|
||||
|
||||
if (!accNo) {
|
||||
return {
|
||||
code: -1,
|
||||
msg: 'accNo不能为空'
|
||||
};
|
||||
}
|
||||
|
||||
const remoteResponse = await balanceUtil.requestMerchantBalance({
|
||||
vk,
|
||||
accNo
|
||||
});
|
||||
const merchantBalance = balanceUtil.getRemoteMerchantBalance(remoteResponse);
|
||||
|
||||
if (merchantBalance === null) {
|
||||
return {
|
||||
code: -1,
|
||||
msg: (remoteResponse && (remoteResponse.msg || remoteResponse.message)) || '未获取到余额'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
code: 0,
|
||||
msg: '',
|
||||
data: {
|
||||
accNo,
|
||||
balance: merchantBalance
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user