| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- 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
- }
|