feat: 补齐客户端/管理端服务模块与数据库 schema,完善登录短信、法大大签署及公共函数

This commit is contained in:
2026-10-14 21:55:08 +08:00
parent 3481fda7a0
commit 55bcf96889
545 changed files with 28151 additions and 415 deletions
@@ -0,0 +1,231 @@
'use strict';
const AUTO_TRANSFER_DAYS_DICT_ID = '238cef266a67e89a006025974a41dbd7';
const DEFAULT_AUTO_TRANSFER_DAYS = 3;
function nowText(vk) {
return vk.pubfn.timeFormat(new Date(), "yyyy-MM-dd hh:mm:ss");
}
async function getAutoTransferDays(vk) {
try {
const config = await vk.baseDao.findById({
dbName: 'jjx-dict',
id: AUTO_TRANSFER_DAYS_DICT_ID
});
const days = parseInt(config && config.content, 10);
if (Number.isFinite(days) && days > 0) return days;
} catch (err) {
console.error('getAutoTransferDays error:', err);
}
return DEFAULT_AUTO_TRANSFER_DAYS;
}
async function buildPayApplyFields(vk) {
const applyTimestamp = Date.now();
const autoTransferDays = await getAutoTransferDays(vk);
const autoTransferTimestamp = applyTimestamp + autoTransferDays * 24 * 60 * 60 * 1000;
return {
transferStatus: 0,
applyAt: nowText(vk),
applyTimestamp,
autoTransferDays,
autoTransferAt: vk.pubfn.timeFormat(new Date(autoTransferTimestamp), "yyyy-MM-dd hh:mm:ss"),
autoTransferTimestamp
};
}
async function findFullPayRecord(vk, orderId) {
const res = await vk.baseDao.select({
dbName: 'jjx-order-pay-list',
whereJson: {
orderId,
isNotaryFullPay: true,
buyerRefuse: false
},
sortArr: [{name: '_add_time', type: 'desc'}],
pageIndex: 1,
pageSize: 1
});
return res && res.rows && res.rows[0] ? res.rows[0] : null;
}
async function resolveTransferSourcePayRecord(vk, payRecord) {
if (!payRecord) return null;
if (payRecord.isNotaryFullPay) return payRecord;
if (payRecord.fullPayListId) {
const fullPayRecord = await vk.baseDao.findById({
dbName: 'jjx-order-pay-list',
id: payRecord.fullPayListId
});
if (fullPayRecord) return fullPayRecord;
}
if (payRecord.sourcePayListId) {
const fullPayRecord = await vk.baseDao.findById({
dbName: 'jjx-order-pay-list',
id: payRecord.sourcePayListId
});
if (fullPayRecord) return fullPayRecord;
}
if (payRecord.orderId) {
return await findFullPayRecord(vk, payRecord.orderId);
}
return null;
}
/**
* 获取卖家用于银联划付的企业用户号。
* 企业用户号属于卖家用户资料,不能使用客户端传入值或固定商户号。
*/
async function resolveSellerMerNo(vk, payRecord) {
const sellerUid = payRecord && payRecord.sellerUid;
if (!sellerUid) return '';
try {
const seller = await vk.baseDao.findById({
dbName: 'uni-id-users',
id: sellerUid
});
return String((seller && seller.merNo) || '').trim();
} catch (err) {
console.error('resolveSellerMerNo error:', err);
return '';
}
}
async function addMessage(vk, dataJson) {
if (!dataJson || !dataJson.uid) return;
await vk.baseDao.add({
dbName: 'jjx-message',
dataJson: {
...dataJson,
hasRead: false
}
});
}
async function notifyPaySuccess({ vk, payRecord, order }) {
await addMessage(vk, {
uid: payRecord.sellerUid,
title: '买家已完成公证支付',
content: `订单${order && order.orderNo ? order.orderNo : payRecord.orderId}买家已支付货款到金久信公证平台,请按约定发起付款单申请划付。`,
type: 'order-pay',
pk: payRecord.orderId
});
}
async function notifyPayApply({ vk, payRecord, order }) {
await addMessage(vk, {
uid: payRecord.buyerUid,
title: '卖家已发起付款单',
content: `订单${order && order.orderNo ? order.orderNo : payRecord.orderId}卖家已发起${payRecord.type || ''}付款单,金额${payRecord.amount}元,请及时通过申请或驳回。`,
type: 'order-pay',
pk: payRecord.orderId
});
}
async function executeTransfer({ vk, payRecord, operator = 'buyer' }) {
if (!payRecord) return { code: -1, msg: '支付单不存在' };
if (!payRecord.isNotaryApply) return { code: -1, msg: '当前支付单不是公证划付申请单' };
if (payRecord.buyerRefuse) return { code: -1, msg: '支付单已被买家驳回' };
if (!payRecord.hasPaid) return { code: -1, msg: '公证托管资金尚未支付' };
if (payRecord.sellerConfirm) return { code: 0, msg: '已划付', data: payRecord.transferResult || null };
const fullPayRecord = await resolveTransferSourcePayRecord(vk, payRecord);
const sourcePayOrderNo = fullPayRecord && fullPayRecord.orderNo ? fullPayRecord.orderNo : (payRecord.fullPayOrderNo || payRecord.sourcePayOrderNo || '');
const sourcePayListId = fullPayRecord && fullPayRecord._id ? fullPayRecord._id : (payRecord.fullPayListId || payRecord.sourcePayListId || '');
const sourcePayAmount = fullPayRecord && Number(fullPayRecord.amount || 0) > 0 ? Number(fullPayRecord.amount) : Number(payRecord.fullPayAmount || 0);
if (!sourcePayOrderNo) return { code: -1, msg: '未找到全额支付单单号,无法划付' };
if (fullPayRecord && !fullPayRecord.hasPaid) return { code: -1, msg: '全额支付单尚未支付,无法划付' };
// const buyer = await vk.baseDao.findById({
// dbName: 'uni-id-users',
// id: payRecord.buyerUid,
// });
// if (!buyer || !buyer.mid) {
// return { code: -1, msg: '买家商户号不存在' };
// }
const payAmt = Number(payRecord.amount || payRecord.price || 0);
if (!Number.isFinite(payAmt) || payAmt <= 0) {
return { code: -1, msg: '付款单金额不正确' };
}
const accNo = await resolveSellerMerNo(vk, payRecord);
if (!accNo) {
return { code: -1, msg: '卖家未配置企业用户号,无法划付' };
}
const transferResult = await vk.request({
url: 'http://jjx-union-pay.gxwebsoft.com/api/union-pay-jjx/transByOrder',
method: 'POST',
dataType: 'json',
header: {
'content-type': 'application/json; charset=utf-8'
},
data: {
accNo,
merOrderNo: sourcePayOrderNo,
payAmt,
amount: payAmt,
},
timeout: 60000
});
const transferAt = nowText(vk);
await vk.baseDao.updateById({
dbName: 'jjx-order-pay-list',
id: payRecord._id,
dataJson: {
sellerConfirm: true,
confirmAt: transferAt,
transferStatus: 1,
transferAt,
transferOperator: operator,
transferResult,
transferSourcePayListId: sourcePayListId,
transferSourceOrderNo: sourcePayOrderNo,
transferSourceAmount: sourcePayAmount
}
});
if (['尾款', '货到付款', '全款'].includes(payRecord.type)) {
await vk.baseDao.updateById({
dbName: 'jjx-order',
id: payRecord.orderId,
dataJson: {
orderStatus: 4,
}
});
}
await addMessage(vk, {
uid: payRecord.sellerUid,
title: '付款单已划付',
content: `付款单${payRecord.type || ''}已${operator === 'auto' ? '自动' : '由买家确认'}划付,金额${payRecord.amount}元,来源单号:${sourcePayOrderNo}。`,
type: 'order-pay-transfer',
pk: payRecord.orderId
});
return {
code: 0,
msg: '划付成功',
data: {
transferResult,
sourcePayOrderNo,
sourcePayListId,
sourcePayAmount
}
};
}
module.exports = {
AUTO_TRANSFER_DAYS_DICT_ID,
DEFAULT_AUTO_TRANSFER_DAYS,
getAutoTransferDays,
buildPayApplyFields,
findFullPayRecord,
resolveTransferSourcePayRecord,
addMessage,
notifyPaySuccess,
notifyPayApply,
resolveSellerMerNo,
executeTransfer
};