const db = require('../plugin/DataBase/db') const Redis = require('../plugin/DataBase/Redis') const { releaseUsageForOrder } = require('./CouponService') const { insertLedgerRecord } = require('./Lepao/CountLedger') const ORDER_STATE_PENDING = 0 const ORDER_STATE_PROCESSING = 1 const ORDER_STATE_COMPLETED = 2 const ORDER_STATE_CLOSED = 3 const ORDER_STATE_ERROR = 4 function normalizeResult(result) { return Array.isArray(result) ? result[0] : result } async function closePendingOrder({ orderId, operatorUuid = null, payId = null, logger } = {}) { if (!orderId) return { closed: false, reason: 'missing_order_id' } const conn = await db.connect() try { await conn.beginTransaction() const [orderRows] = await conn.execute( 'SELECT orderId, state, goods_id, create_user FROM orders WHERE orderId = ? FOR UPDATE', [orderId] ) const order = orderRows?.[0] if (!order) { await conn.rollback() return { closed: false, reason: 'not_found' } } if (Number(order.state) !== ORDER_STATE_PENDING) { await conn.rollback() return { closed: false, reason: 'state_changed', state: Number(order.state) } } const params = payId ? [ORDER_STATE_CLOSED, payId, orderId, ORDER_STATE_PENDING] : [ORDER_STATE_CLOSED, orderId, ORDER_STATE_PENDING] const sql = payId ? 'UPDATE orders SET state = ?, pay_id = ? WHERE orderId = ? AND state = ?' : 'UPDATE orders SET state = ? WHERE orderId = ? AND state = ?' const [closeRes] = await conn.execute(sql, params) if (!closeRes || closeRes.affectedRows !== 1) { await conn.rollback() return { closed: false, reason: 'update_failed' } } if (order.goods_id != null) { await conn.execute('UPDATE goods SET num = num + 1 WHERE id = ?', [order.goods_id]) } await conn.commit() } catch (error) { try { await conn.rollback() } catch (_) { } logger?.error?.(`关闭订单失败 ${orderId}: ${error.stack || error}`) throw error } try { await releaseUsageForOrder(orderId) await Redis.del(`payData:${orderId}`) } catch (cleanupError) { logger?.warn?.(`关闭订单后清理资源失败 ${orderId}: ${cleanupError.stack || cleanupError}`) } logger?.info?.(`订单已关闭并返还库存,订单号:${orderId}${operatorUuid ? `,操作人:${operatorUuid}` : ''}`) return { closed: true } } async function completePaidOrder({ orderId, payType, payId, payTime = Date.now(), paidAmount = null, logger } = {}) { if (!orderId) return { completed: false, reason: 'missing_order_id' } const conn = await db.connect() try { await conn.beginTransaction() const [lockRows] = await conn.execute( 'SELECT orderId, state, price FROM orders WHERE orderId = ? FOR UPDATE', [orderId] ) const locked = lockRows?.[0] if (!locked || Number(locked.state) !== ORDER_STATE_PENDING) { await conn.rollback() return { completed: false, reason: locked ? 'state_changed' : 'not_found', state: locked ? Number(locked.state) : null } } if (paidAmount !== null && Math.abs(Number(locked.price) - Number(paidAmount)) > 0.001) { await conn.rollback() logger?.error?.(`订单支付金额不匹配,订单号:${orderId},应付:${locked.price},实付:${paidAmount}`) return { completed: false, reason: 'amount_mismatch' } } const [markRows] = await conn.execute( 'UPDATE orders SET state = ?, pay_type = ?, pay_id = ?, pay_time = ? WHERE orderId = ? AND state = ?', [ORDER_STATE_PROCESSING, payType, payId, payTime, orderId, ORDER_STATE_PENDING] ) if (!markRows || markRows.affectedRows !== 1) { await conn.rollback() return { completed: false, reason: 'state_changed' } } const [orderRows] = await conn.execute( `SELECT o.create_user, g.lepao_count, g.ic_count, g.vip FROM orders o LEFT JOIN goods g ON o.goods_id = g.id WHERE o.orderId = ? LIMIT 1`, [orderId] ) const order = orderRows?.[0] if (!order || !order.create_user) { await conn.execute('UPDATE orders SET state = ? WHERE orderId = ?', [ORDER_STATE_ERROR, orderId]) await conn.commit() return { completed: false, reason: 'bad_order_data' } } const addLepao = Number(order.lepao_count || 0) const addIc = Number(order.ic_count || 0) const [userRows] = await conn.execute( 'SELECT lepao_count FROM users WHERE uuid = ? FOR UPDATE', [order.create_user] ) if (!userRows || userRows.length !== 1) { await conn.execute('UPDATE orders SET state = ? WHERE orderId = ?', [ORDER_STATE_ERROR, orderId]) await conn.commit() return { completed: false, reason: 'user_not_found' } } const beforeLepao = Number(userRows[0].lepao_count || 0) const afterLepao = beforeLepao + addLepao const [updateUserRes] = await conn.execute( 'UPDATE users SET lepao_count = lepao_count + ?, ic_count = ic_count + ?, vip = ? WHERE uuid = ?', [addLepao, addIc, order.vip, order.create_user] ) if (!updateUserRes || updateUserRes.affectedRows !== 1) { await conn.execute('UPDATE orders SET state = ? WHERE orderId = ?', [ORDER_STATE_ERROR, orderId]) await conn.commit() return { completed: false, reason: 'update_user_failed' } } const [finishRes] = await conn.execute( 'UPDATE orders SET state = ? WHERE orderId = ? AND state = ?', [ORDER_STATE_COMPLETED, orderId, ORDER_STATE_PROCESSING] ) if (!finishRes || finishRes.affectedRows !== 1) { await conn.rollback() return { completed: false, reason: 'finish_failed' } } if (addLepao !== 0) { await insertLedgerRecord({ executor: conn, userUuid: order.create_user, delta: addLepao, balanceBefore: beforeLepao, balanceAfter: afterLepao, bizType: 'purchase', bizId: orderId, remark: `订单号:${orderId}` }) } await conn.commit() try { await Redis.del(`payData:${orderId}`) } catch (_) { } logger?.info?.(`订单支付处理完成,订单号:${orderId}`) return { completed: true, userUuid: order.create_user, addLepao } } catch (error) { try { await conn.rollback() } catch (_) { } logger?.error?.(`完成订单失败 ${orderId}: ${error.stack || error}`) throw error } } module.exports = { ORDER_STATE_PENDING, ORDER_STATE_PROCESSING, ORDER_STATE_COMPLETED, ORDER_STATE_CLOSED, ORDER_STATE_ERROR, closePendingOrder, completePaidOrder, normalizeResult }