This commit is contained in:
2025-09-15 17:27:13 +08:00
parent d50290e8fe
commit 14a3c39f9d
27 changed files with 3571 additions and 31198 deletions

View File

@@ -10,7 +10,7 @@ class AlipayService {
this.alipayPublicKey = null;
this.alipaySdk = null;
this.isInitialized = false;
this.initializeAlipay();
}
@@ -25,26 +25,10 @@ class AlipayService {
console.log('支付宝私钥路径:', privateKeyPath);
console.log('支付宝公钥路径:', publicKeyPath);
// 验证文件有效性
if (!this.isValidFile(privateKeyPath)) {
throw new Error(`支付宝私钥文件无效或不存在: ${privateKeyPath}`);
}
if (!this.isValidFile(publicKeyPath)) {
throw new Error(`支付宝公钥文件无效或不存在: ${publicKeyPath}`);
}
console.log('尝试加载支付宝私钥文件:', privateKeyPath);
this.privateKey = fs.readFileSync(privateKeyPath, 'utf8');
console.log('支付宝私钥加载成功');
console.log('尝试加载支付宝公钥文件:', publicKeyPath);
this.alipayPublicKey = fs.readFileSync(publicKeyPath, 'utf8');
console.log('支付宝公钥加载成功');
this.initializeSDK();
} catch (error) {
console.error('支付宝服务初始化失败:', error.message);
console.error('支付宝功能将不可用');
@@ -60,7 +44,7 @@ class AlipayService {
console.warn('支付宝密钥未加载跳过SDK初始化');
return;
}
// 支付宝配置
this.config = {
appId: process.env.ALIPAY_APP_ID || '2021001161683774', // 替换为实际的应用ID
@@ -82,7 +66,7 @@ class AlipayService {
signType: this.config.signType,
timeout: this.config.timeout
});
this.isInitialized = true;
console.log('支付宝SDK初始化成功');
}
@@ -132,16 +116,16 @@ class AlipayService {
if (!this.isServiceAvailable()) {
throw new Error('支付宝服务未初始化或不可用');
}
try {
const db = getDB();
// 生成订单号
const outTradeNo = this.generateOrderNo();
const totalFee = 39900; // 399元单位
const subject = '用户注册激活费用';
const body = `用户${username}(${phone})注册激活费用`;
// 业务参数
const bizContent = {
out_trade_no: outTradeNo,
@@ -149,16 +133,16 @@ class AlipayService {
subject: subject,
body: body,
product_code: 'QUICK_WAP_WAY',
quit_url: process.env.ALIPAY_QUIT_URL || 'https://your-domain.com/payment/cancel'
quit_url: process.env.ALIPAY_QUIT_URL
};
// 使用新版SDK的pageExecute方法生成支付URL
const payUrl = this.alipaySdk.pageExecute('alipay.trade.wap.pay', 'GET', {
bizContent: bizContent,
notifyUrl: process.env.ALIPAY_NOTIFY_URL || 'https://your-domain.com/api/payment/alipay/notify',
returnUrl: process.env.ALIPAY_RETURN_URL || 'https://your-domain.com/payment/success'
notifyUrl: process.env.ALIPAY_NOTIFY_URL,
returnUrl: process.env.ALIPAY_RETURN_URL
});
// 保存订单到数据库
await db.execute(
`INSERT INTO payment_orders
@@ -166,14 +150,14 @@ class AlipayService {
VALUES (?, ?, ?, ?, ?, ?, NOW())`,
[userId, outTradeNo, totalFee, body, 'ALIPAY_WAP', 'pending']
);
console.log('支付宝支付订单创建成功:', {
userId,
outTradeNo,
totalFee,
payUrl
});
return {
success: true,
data: {
@@ -202,18 +186,18 @@ class AlipayService {
if (!this.isServiceAvailable()) {
throw new Error('支付宝服务未初始化或不可用');
}
try {
const result = await this.alipaySdk.exec('alipay.trade.query', {
bizContent: {
out_trade_no: outTradeNo
}
});
if (result.code === '10000') {
// 查询成功
const tradeStatus = result.tradeStatus;
// 如果支付成功,更新数据库
if (tradeStatus === 'TRADE_SUCCESS') {
await this.updatePaymentStatus(outTradeNo, {
@@ -222,7 +206,7 @@ class AlipayService {
paidAt: new Date()
});
}
return {
success: true,
data: {
@@ -256,7 +240,7 @@ class AlipayService {
async updatePaymentStatus(outTradeNo, updateData) {
try {
const db = getDB();
// 更新订单状态
await db.execute(
`UPDATE payment_orders
@@ -264,21 +248,21 @@ class AlipayService {
WHERE out_trade_no = ?`,
[updateData.status, updateData.transactionId, updateData.paidAt, outTradeNo]
);
// 如果支付成功,更新用户支付状态
if (updateData.status === 'paid') {
const [orders] = await db.execute(
'SELECT user_id FROM payment_orders WHERE out_trade_no = ?',
[outTradeNo]
);
if (orders.length > 0) {
const userId = orders[0].user_id;
await db.execute(
'UPDATE users SET payment_status = ? WHERE id = ?',
['paid', userId]
);
console.log('用户支付状态更新成功:', { userId, outTradeNo });
}
}
@@ -299,7 +283,7 @@ class AlipayService {
console.error('支付宝服务未初始化,无法验证签名');
return false;
}
try {
return this.alipaySdk.checkNotifySign(params);
} catch (error) {

View File

@@ -724,6 +724,7 @@ class MatchingService {
AND u.audit_status = 'approved'
AND u.user_type != 'directly_operated'
AND u.payment_status = 'paid'
AND u.province = ?
ORDER BY
CASE
WHEN u.city = ? AND u.district_id = ? THEN 1 -- 相同城市且相同区县排第一
@@ -732,7 +733,7 @@ class MatchingService {
ELSE 4 -- 其他省份排第四
END,
u.balance ASC`,
[excludeUserId, currentUserCity, currentUserDistrictId, currentUserCity, currentUserProvince]
[excludeUserId,currentUserProvince, currentUserCity, currentUserDistrictId, currentUserCity, currentUserProvince]
);
// 处理查询到的负余额用户
@@ -795,7 +796,23 @@ class MatchingService {
// 所有查询到的用户都是负余额用户,直接添加到可用列表
}
userBalanceResult = userBalanceResult.filter(user => user.has_active_allocations < -100);
userBalanceResult = userBalanceResult.sort((a, b) => a.has_active_allocations - b.has_active_allocations);
userBalanceResult = userBalanceResult.sort((a, b) => {
const getPriority = (user) => {
if (user.district_id === currentUserDistrictId) return 1; // 同区县
if (user.city === currentUserCity) return 2; // 同城市
return 3; // 其他
};
const priorityA = getPriority(a);
const priorityB = getPriority(b);
if (priorityA !== priorityB) {
return priorityA - priorityB; // 优先级小的排前
}
// 同优先级里越接近0数值越大排前 -> 使用降序
return b.has_active_allocations - a.has_active_allocations;
});
for (const user of userBalanceResult) {
if (maxTransfers > availableUsers.length + 1) {
if (minTransfers === 3 && availableUsers.length < 3) {

View File

@@ -163,17 +163,18 @@ class TransferService {
if (transfer.matching_order_id) {
// 查询该匹配订单下所有transfers的状态
const [allTransfers] = await connection.execute(
`SELECT status FROM transfers
`SELECT status
FROM transfers
WHERE matching_order_id = ?`,
[transfer.matching_order_id]
);
let matchingOrderStatus;
// 根据所有相关transfers的状态来决定matching_order的状态
const transferStatuses = allTransfers.map(t => t.status);
console.log(transferStatuses,'transferStatuses');
console.log(transferStatuses, 'transferStatuses');
if (transferStatuses.every(status => status === 'cancelled' || status === 'rejected' || status === 'not_received')) {
// 如果所有transfers都被取消/拒绝/未收到,匹配订单标记为已完成
matchingOrderStatus = 'completed';
@@ -187,15 +188,15 @@ class TransferService {
// 其他情况为待处理状态
matchingOrderStatus = 'matching';
}
await connection.execute(
`UPDATE matching_orders
SET status = ?,
`UPDATE matching_orders
SET status = ?,
updated_at = NOW()
WHERE id = ?`,
[matchingOrderStatus, transfer.matching_order_id]
);
logger.info('Matching order status updated after transfer confirmation', {
matchingOrderId: transfer.matching_order_id,
transferId: transferId,
@@ -238,16 +239,16 @@ class TransferService {
}
// 获取转账列表
async getTransfers(filters = {}, pagination = {},user_type = 'user_to_user') {
async getTransfers(filters = {}, pagination = {}, user_type = 'user_to_user') {
const db = getDB();
const {page = 1, limit = 10, sort = 'created_at', order = 'desc'} = pagination;
const pageNum = parseInt(page, 10) || 1;
const limitNum = parseInt(limit, 10) || 10;
const offset = (pageNum - 1) * limitNum;
let whereClause = 'WHERE 1=1 ';
let whereClause = 'WHERE ';
const params = [];
whereClause += `AND transfer_type='${user_type}'`;
whereClause += `transfer_type='${user_type}'`;
// 构建查询条件
if (filters.user_id) {
whereClause += ' AND (from_user_id = ? OR to_user_id = ?)';
@@ -298,20 +299,52 @@ class TransferService {
params
);
const total = countResult[0].total;
console.log(`SELECT t.*,
fu.username as from_username,
fu.real_name as from_real_name,
tu.username as to_username,
tu.real_name as to_real_name,
f_p.name as from_province,
f_c.name as from_city,
f_d.name as from_district,
t_p.name as to_province,
t_c.name as to_city,
t_d.name as to_district
FROM transfers t
LEFT JOIN users fu ON t.from_user_id = fu.id
LEFT JOIN users tu ON t.to_user_id = tu.id
LEFT JOIN china_regions f_p on f_p.code = fu.province
LEFT JOIN china_regions f_c on f_c.code = fu.city
LEFT JOIN china_regions f_d on f_d.code = fu.district_id
LEFT JOIN china_regions t_p on t_p.code = tu.province
LEFT JOIN china_regions t_c on t_c.code = tu.city
LEFT JOIN china_regions t_d on t_d.code = tu.district_id
${whereClause} ${orderClause}
LIMIT ${limitNum} OFFSET ${offset}`)
// 获取数据
const [transfers] = await db.execute(
`SELECT t.*,
fu.username as from_username,
fu.real_name as from_real_name,
tu.username as to_username,
tu.real_name as to_real_name
tu.real_name as to_real_name,
f_p.name as from_province,
f_c.name as from_city,
f_d.name as from_district,
t_p.name as to_province,
t_c.name as to_city,
t_d.name as to_district
FROM transfers t
LEFT JOIN users fu ON t.from_user_id = fu.id
LEFT JOIN users tu ON t.to_user_id = tu.id
LEFT JOIN china_regions f_p ON f_p.code = fu.province
LEFT JOIN china_regions f_c ON f_c.code = fu.city
LEFT JOIN china_regions f_d ON f_d.code = fu.district_id
LEFT JOIN china_regions t_p ON t_p.code = tu.province
LEFT JOIN china_regions t_c ON t_c.code = tu.city
LEFT JOIN china_regions t_d ON t_d.code = tu.district_id
${whereClause} ${orderClause}
LIMIT ${limitNum}
OFFSET ${offset}`,
LIMIT ${limitNum}`,
params
);
@@ -329,7 +362,8 @@ class TransferService {
throw error;
}
}
async getTransfersHistory(filters = {}, pagination = {},user_type = 'user_to_user') {
async getTransfersHistory(filters = {}, pagination = {}, user_type = 'user_to_user') {
const db = getDB();
const {page = 1, limit = 10, sort = 'created_at', order = 'desc'} = pagination;
const pageNum = parseInt(page, 10) || 1;
@@ -401,13 +435,29 @@ class TransferService {
LEFT JOIN users fu ON t.from_user_id = fu.id
LEFT JOIN users tu ON t.to_user_id = tu.id
${whereClause} ${orderClause}
LIMIT ${limitNum}
OFFSET ${offset}`,
LIMIT ${limitNum} OFFSET ${offset}`,
params
);
//获取总数
const stats = {};
//获取系统转给融豆的总数
let [total_to_admin] = await db.execute(`SELECT SUM(t.amount) as total FROM transfers t WHERE t.source_type = 'system'`)
stats.total_to_admin = total_to_admin[0].total || 0
//转给代理的融豆总数
let [total_to_agent] = await db.execute(`SELECT SUM(t.amount) as total FROM transfers t WHERE t.source_type = 'agent'`)
stats.total_to_agent = total_to_agent[0].total || 0
//转给直营代理的融豆数量
let [total_to_agent_directly] = await db.execute(`SELECT SUM(t.amount) as total FROM transfers t WHERE t.source_type = 'operated_agent'`)
stats.total_to_agent_directly = total_to_agent_directly[0].total || 0
//转给直营的融豆总数
let [total_to_directly_operated] = await db.execute(`SELECT SUM(t.amount) as total FROM transfers t WHERE t.source_type = 'directly_operated'`)
stats.total_to_directly_operated = total_to_directly_operated[0].total || 0
//提现总数
let [total_get] = await db.execute(`SELECT SUM(t.amount) as total FROM transfers t WHERE t.source_type = 'withdraw'`)
stats.total_get = total_get[0].total || 0
return {
transfers,
stats,
pagination: {
page: pageNum,
limit: limitNum,
@@ -722,7 +772,7 @@ class TransferService {
// 更新转账状态
await connection.execute(
'UPDATE transfers SET status = ? WHERE id = ?',
[TRANSFER_STATUS.REJECTED, transferId]
[TRANSFER_STATUS.REJECTED, transferId]
);
// 注意在新逻辑下CONFIRMED状态时发送方余额还没有被扣除所以无需回滚
@@ -735,11 +785,13 @@ class TransferService {
});
// 如果是分配类型的转账需要更新对应的matching_order状态
if ( transfer.matching_order_id) {
if (transfer.matching_order_id) {
// 查询该matching_order下所有source_type为allocation的transfers状态
const [allTransfers] = await connection.execute(
`SELECT status FROM transfers
WHERE matching_order_id = ? AND source_type = 'allocation'`,
`SELECT status
FROM transfers
WHERE matching_order_id = ?
AND source_type = 'allocation'`,
[transfer.matching_order_id]
);
@@ -781,8 +833,9 @@ class TransferService {
// 更新matching_order状态
await connection.execute(
`UPDATE matching_orders
SET status = ?, updated_at = NOW()
`UPDATE matching_orders
SET status = ?,
updated_at = NOW()
WHERE id = ?`,
[matchingOrderStatus, transfer.matching_order_id]
);
@@ -897,40 +950,41 @@ class TransferService {
if (transfer.matching_order_id) {
// 查询该匹配订单下所有transfers的状态
const [allTransfers] = await connection.execute(
`SELECT status FROM transfers
`SELECT status
FROM transfers
WHERE matching_order_id = ?`,
[transfer.matching_order_id]
);
let matchingOrderStatus;
// 根据所有相关transfers的状态来决定matching_order的状态
const transferStatuses = allTransfers.map(t => t.status);
console.log(transferStatuses,'transferStatuses');
console.log(transferStatuses, 'transferStatuses');
if (transferStatuses.every(status => status === 'cancelled' || status === 'rejected' || status === 'not_received' || status === 'confirmed' || status === 'received')) {
// 如果所有transfers都被取消/拒绝/未收到,匹配订单标记为已完成
matchingOrderStatus = 'completed';
} else if (transferStatuses.every(status => status === 'received')) {
// 如果所有transfers都已收到匹配订单完成
matchingOrderStatus = 'completed';
} else if (transferStatuses.includes('cancelled') || transferStatuses.includes('rejected') || transferStatuses.includes('not_received') ) {
// 如果有任何一个transfer被取消/拒绝/未收到或者有transfers已确认或已收到匹配订单为进行中状态
matchingOrderStatus = 'matching';
} else {
// 其他情况为待处理状态
matchingOrderStatus = 'pending';
}
// 如果所有transfers都被取消/拒绝/未收到,匹配订单标记为已完成
matchingOrderStatus = 'completed';
} else if (transferStatuses.every(status => status === 'received')) {
// 如果所有transfers都已收到匹配订单完成
matchingOrderStatus = 'completed';
} else if (transferStatuses.includes('cancelled') || transferStatuses.includes('rejected') || transferStatuses.includes('not_received')) {
// 如果有任何一个transfer被取消/拒绝/未收到或者有transfers已确认或已收到匹配订单为进行中状态
matchingOrderStatus = 'matching';
} else {
// 其他情况为待处理状态
matchingOrderStatus = 'pending';
}
console.log('matchingOrderStatus', matchingOrderStatus);
await connection.execute(
`UPDATE matching_orders
SET status = ?,
`UPDATE matching_orders
SET status = ?,
updated_at = NOW()
WHERE id = ?`,
[matchingOrderStatus, transfer.matching_order_id]
);
logger.info('Matching order status updated based on all transfers', {
matchingOrderId: transfer.matching_order_id,
transferId: transferId,
@@ -998,9 +1052,9 @@ class TransferService {
if (transfer.to_user_id) {
await connection.execute(
'UPDATE users SET balance = balance - ? WHERE id = ?',
[transfer.amount, transfer.to_user_id]
[transfer.amount, transfer.to_user_id]
);
logger.info('Receiver balance and points deducted due to status change', {
transferId,
userId: transfer.to_user_id,
@@ -1009,7 +1063,7 @@ class TransferService {
newStatus
});
}
await connection.execute(
'UPDATE users SET balance = balance + ?, points = points - ? WHERE id = ?',
[transfer.amount, transfer.amount, transfer.from_user_id]
@@ -1043,7 +1097,7 @@ class TransferService {
'UPDATE users SET balance = balance - ? WHERE id = ?',
[transfer.amount, transfer.to_user_id]
);
logger.info('Receiver balance and points deducted due to status change from received to confirmed', {
transferId,
userId: transfer.to_user_id,
@@ -1058,7 +1112,7 @@ class TransferService {
'UPDATE users SET balance = balance - ?, points = points + ? WHERE id = ?',
[transfer.amount, transfer.amount, transfer.from_user_id]
);
logger.info('Status change from confirmed to received - sender balance and points deducted', {
transferId,
userId: transfer.from_user_id,
@@ -1074,7 +1128,7 @@ class TransferService {
if (adjust_balance && newStatus === TRANSFER_STATUS.RECEIVED && oldStatus !== TRANSFER_STATUS.RECEIVED && transfer.to_user_id) {
await connection.execute(
'UPDATE users SET balance = balance + ? WHERE id = ?',
[transfer.amount, transfer.to_user_id]
[transfer.amount, transfer.to_user_id]
);
logger.info('Receiver balance and points increased due to status change', {