修复数据库分离: pay_orders→orders.db + web_transactions→web.db,双库不再混用
This commit is contained in:
+20
-17
@@ -270,7 +270,7 @@ function createOrder($token) {
|
||||
}
|
||||
$player = $info['player'];
|
||||
|
||||
$db = getDB();
|
||||
$db = getOrdersDB();
|
||||
ensurePayOrdersTable($db);
|
||||
|
||||
// ★ 防重复支付:检查玩家是否有未支付的已有订单(仅5分钟内有效)
|
||||
@@ -391,9 +391,10 @@ function handleNotify() {
|
||||
exit;
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$db = getOrdersDB(); // orders.db — pay_orders
|
||||
ensurePayOrdersTable($db);
|
||||
ensureWebTransactionsTable($db);
|
||||
$webDb = getDB(); // web.db — web_transactions
|
||||
ensureWebTransactionsTable($webDb);
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM pay_orders WHERE out_trade_no = :no");
|
||||
$stmt->bindValue(':no', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -416,8 +417,8 @@ function handleNotify() {
|
||||
$ins->bindValue(':t', $now, SQLITE3_INTEGER);
|
||||
$ins->execute();
|
||||
|
||||
// 写 web_transactions
|
||||
$txIns = $db->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(callback同步)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
// 写 web_transactions → web.db
|
||||
$txIns = $webDb->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(callback同步)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$txIns->bindValue(':p', $platformPlayer, SQLITE3_TEXT);
|
||||
$txIns->bindValue(':a', $bonds, SQLITE3_INTEGER);
|
||||
$txIns->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -451,15 +452,15 @@ function handleNotify() {
|
||||
exit;
|
||||
}
|
||||
|
||||
// 5) 标记订单已支付
|
||||
// 5) 标记订单已支付(orders.db)
|
||||
$stmt = $db->prepare("UPDATE pay_orders SET status='paid', trade_no=:tn, paid_at=:t WHERE out_trade_no=:no");
|
||||
$stmt->bindValue(':tn', $params['trade_no'] ?? '', SQLITE3_TEXT);
|
||||
$stmt->bindValue(':t', time(), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':no', $outTradeNo, SQLITE3_TEXT);
|
||||
$stmt->execute();
|
||||
|
||||
// 6) 写 web_transactions(recharge) 供 Java 高频定时器拉取 → addBonds 到账
|
||||
$stmt = $db->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
// 6) 写 web_transactions(recharge) 供 Java 高频定时器拉取 → addBonds 到账 → web.db
|
||||
$stmt = $webDb->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$stmt->bindValue(':p', $row['player_name'], SQLITE3_TEXT);
|
||||
$stmt->bindValue(':a', (int)$row['bond_amount'], SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -483,7 +484,7 @@ function handlePayRedirect() {
|
||||
echo '缺少订单号';
|
||||
exit;
|
||||
}
|
||||
$db = getDB();
|
||||
$db = getOrdersDB();
|
||||
ensurePayOrdersTable($db);
|
||||
$stmt = $db->prepare("SELECT submit_params, status, player_name FROM pay_orders WHERE out_trade_no = :no");
|
||||
$stmt->bindValue(':no', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -555,7 +556,7 @@ function queryOrder($token) {
|
||||
if (!$outTradeNo) {
|
||||
error('缺少订单号');
|
||||
}
|
||||
$db = getDB();
|
||||
$db = getOrdersDB();
|
||||
ensurePayOrdersTable($db);
|
||||
$stmt = $db->prepare("SELECT * FROM pay_orders WHERE out_trade_no=:no AND player_name=:p");
|
||||
$stmt->bindValue(':no', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -607,12 +608,13 @@ function queryOrder($token) {
|
||||
$ins->bindValue(':t', $now, SQLITE3_INTEGER);
|
||||
$ins->execute();
|
||||
|
||||
// 写 web_transactions
|
||||
$txCheck = $db->prepare("SELECT id FROM web_transactions WHERE detail = :d AND type = 'recharge' LIMIT 1");
|
||||
// 写 web_transactions → web.db
|
||||
$webDb = getDB();
|
||||
$txCheck = $webDb->prepare("SELECT id FROM web_transactions WHERE detail = :d AND type = 'recharge' LIMIT 1");
|
||||
$txCheck->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
$txRow = $txCheck->execute()->fetchArray(SQLITE3_ASSOC);
|
||||
if (!$txRow) {
|
||||
$txIns = $db->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(查询同步)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$txIns = $webDb->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(查询同步)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$txIns->bindValue(':p', $platformPlayer, SQLITE3_TEXT);
|
||||
$txIns->bindValue(':a', $bonds, SQLITE3_INTEGER);
|
||||
$txIns->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -662,12 +664,13 @@ function queryOrder($token) {
|
||||
$upd->bindValue(':no', $outTradeNo, SQLITE3_TEXT);
|
||||
$upd->execute();
|
||||
|
||||
// 写 web_transactions(幂等)
|
||||
$txCheck = $db->prepare("SELECT id FROM web_transactions WHERE detail = :d AND type = 'recharge' LIMIT 1");
|
||||
// 写 web_transactions(幂等)→ web.db
|
||||
$webDb = getDB();
|
||||
$txCheck = $webDb->prepare("SELECT id FROM web_transactions WHERE detail = :d AND type = 'recharge' LIMIT 1");
|
||||
$txCheck->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
$txRow = $txCheck->execute()->fetchArray(SQLITE3_ASSOC);
|
||||
if (!$txRow) {
|
||||
$txIns = $db->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(直查)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$txIns = $webDb->prepare("INSERT INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(直查)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$txIns->bindValue(':p', $info['player'], SQLITE3_TEXT);
|
||||
$txIns->bindValue(':a', (int)$row['bond_amount'], SQLITE3_INTEGER);
|
||||
$txIns->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -839,7 +842,7 @@ function findRecentOrder($token) {
|
||||
if (!$info || empty($info['player'])) {
|
||||
error('登录状态无效', 401);
|
||||
}
|
||||
$db = getDB();
|
||||
$db = getOrdersDB();
|
||||
ensurePayOrdersTable($db);
|
||||
// 查最近5分钟内的订单(优先created,再paid)
|
||||
$fiveMinAgo = time() - 300;
|
||||
|
||||
+35
-20
@@ -32,8 +32,9 @@ $PLATFORM_DB_USER = defined('PAY_MYSQL_USER') ? PAY_MYSQL_USER : 'kH3C3LLinNwYdT
|
||||
$PLATFORM_DB_PASS = defined('PAY_MYSQL_PASS') ? PAY_MYSQL_PASS : 'sRhsdxrpHBhmSsp8';
|
||||
$GLOBALS['PLATFORM_DB_PREFIX'] = 'pay_'; $PLATFORM_DB_PREFIX = 'pay_';
|
||||
|
||||
// SQLite 数据库路径(与 core.php 一致:/caoyuan.ypshidifu.cn/plugin/db/web.db)
|
||||
$SQLITE_DB_PATH = __DIR__ . '/../db/web.db';
|
||||
// SQLite 数据库路径
|
||||
$GLOBALS['SQLITE_DB_PATH'] = __DIR__ . '/../db/web.db'; // web_transactions (Java读写)
|
||||
$GLOBALS['ORDERS_DB_PATH'] = __DIR__ . '/../db/orders.db'; // pay_orders (PHP读写)
|
||||
|
||||
if (!function_exists('debugLog')) {
|
||||
function debugLog($msg, $ctx = []) {
|
||||
@@ -47,13 +48,39 @@ function debugLog($msg, $ctx = []) {
|
||||
} // end if (!function_exists('debugLog'))
|
||||
|
||||
function getSQLite() {
|
||||
// web.db — Java 高频读写(web_transactions 表)
|
||||
static $db = null;
|
||||
if ($db === null) {
|
||||
$db = new SQLite3($GLOBALS['SQLITE_DB_PATH']);
|
||||
$db->enableExceptions(true);
|
||||
$db->exec('PRAGMA journal_mode=WAL');
|
||||
$db->exec('PRAGMA busy_timeout=5000');
|
||||
// 确保表存在(幂等兜底)
|
||||
// web_transactions 表(Java 读取补单)
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS web_transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
player_name TEXT,
|
||||
type TEXT,
|
||||
amount INTEGER,
|
||||
operator TEXT,
|
||||
reason TEXT,
|
||||
detail TEXT,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at INTEGER
|
||||
)");
|
||||
@$db->exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_web_tx_detail_type ON web_transactions(detail, type)");
|
||||
}
|
||||
return $db;
|
||||
}
|
||||
|
||||
function getOrdersSQLite() {
|
||||
// orders.db — PHP 订单库(pay_orders 表),独立于 Java 的 web.db
|
||||
static $db = null;
|
||||
if ($db === null) {
|
||||
$db = new SQLite3($GLOBALS['ORDERS_DB_PATH']);
|
||||
$db->enableExceptions(true);
|
||||
$db->exec('PRAGMA journal_mode=WAL');
|
||||
$db->exec('PRAGMA busy_timeout=5000');
|
||||
// pay_orders 表
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS pay_orders (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
out_trade_no TEXT UNIQUE,
|
||||
@@ -69,19 +96,6 @@ function getSQLite() {
|
||||
created_at INTEGER,
|
||||
paid_at INTEGER
|
||||
)");
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS web_transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
player_name TEXT,
|
||||
type TEXT,
|
||||
amount INTEGER,
|
||||
operator TEXT,
|
||||
reason TEXT,
|
||||
detail TEXT,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at INTEGER
|
||||
)");
|
||||
// 唯一约束:同 detail+type 不允许重复(防 race condition/重复补单)
|
||||
@$db->exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_web_tx_detail_type ON web_transactions(detail, type)");
|
||||
}
|
||||
return $db;
|
||||
}
|
||||
@@ -160,7 +174,8 @@ function pollPaidOrders() {
|
||||
return;
|
||||
}
|
||||
|
||||
$sqlite = getSQLite();
|
||||
$sqlite = getOrdersSQLite(); // orders.db(pay_orders)
|
||||
$webSqlite = getSQLite(); // web.db(web_transactions)
|
||||
|
||||
try {
|
||||
$pdo = getPlatformDB();
|
||||
@@ -267,8 +282,8 @@ function pollPaidOrders() {
|
||||
$upd->execute();
|
||||
}
|
||||
|
||||
// 写 web_transactions(幂等:INSERT OR IGNORE 防止竞态条件重复插入)
|
||||
$txIns = $sqlite->prepare("INSERT OR IGNORE INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(补单)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
// 写 web_transactions(幂等:INSERT OR IGNORE 防止竞态条件重复插入)→ web.db
|
||||
$txIns = $webSqlite->prepare("INSERT OR IGNORE INTO web_transactions (player_name, type, amount, operator, reason, detail, status, created_at) VALUES (:p, 'recharge', :a, '支付平台(补单)', '在线充值(支付宝)', :d, 'pending', :t)");
|
||||
$txIns->bindValue(':p', $playerName, SQLITE3_TEXT);
|
||||
$txIns->bindValue(':a', $bonds, SQLITE3_INTEGER);
|
||||
$txIns->bindValue(':d', $outTradeNo, SQLITE3_TEXT);
|
||||
@@ -276,7 +291,7 @@ function pollPaidOrders() {
|
||||
$txIns->execute();
|
||||
|
||||
// 检查是否是新插入的(affected_rows > 0 表示新插入,=0 表示已存在被忽略)
|
||||
if ($sqlite->changes() > 0) {
|
||||
if ($webSqlite->changes() > 0) {
|
||||
debugLog('[poller_online] 充值交易已写入 web_transactions', [
|
||||
'player' => $playerName, 'bonds' => $bonds,
|
||||
'out_trade_no' => $outTradeNo, 'money' => $money,
|
||||
|
||||
+25
-29
@@ -66,36 +66,32 @@ function handleOrderList() {
|
||||
$db = getOrdersDB();
|
||||
ensurePayOrdersTable($db);
|
||||
|
||||
// ★ 自动迁移:如果 orders.db 为空但 web.db 有 pay_orders 数据,从 web.db 迁移过来
|
||||
// ★ 增量迁移:从 web.db 同步缺失的 pay_orders 到 orders.db(处理历史数据)
|
||||
try {
|
||||
$countStmt = $db->query("SELECT COUNT(*) as cnt FROM pay_orders");
|
||||
$cnt = $countStmt->fetchArray(SQLITE3_ASSOC)['cnt'] ?? 0;
|
||||
if ($cnt == 0) {
|
||||
$webDb = getDB();
|
||||
// 检查 web.db 是否有 pay_orders 表
|
||||
$tableCheck = $webDb->query("SELECT name FROM sqlite_master WHERE type='table' AND name='pay_orders'");
|
||||
if ($tableCheck->fetchArray()) {
|
||||
// 迁移数据
|
||||
$migrateData = $webDb->query("SELECT * FROM pay_orders");
|
||||
$ins = $db->prepare("INSERT OR IGNORE INTO pay_orders (out_trade_no, trade_no, player_name, tier_id, money, bond_amount, status, name, platform_sign, submit_params, created_at, paid_at) VALUES (:no, :tn, :p, :ti, :m, :b, :s, :n, :ps, :sp, :ca, :pa)");
|
||||
$migrated = 0;
|
||||
while ($row = $migrateData->fetchArray(SQLITE3_ASSOC)) {
|
||||
$ins->bindValue(':no', $row['out_trade_no'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':tn', $row['trade_no'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':p', $row['player_name'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':ti', $row['tier_id'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->bindValue(':m', $row['money'] ?? '0', SQLITE3_TEXT);
|
||||
$ins->bindValue(':b', $row['bond_amount'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->bindValue(':s', $row['status'] ?? 'created', SQLITE3_TEXT);
|
||||
$ins->bindValue(':n', $row['name'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':ps', $row['platform_sign'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':sp', $row['submit_params'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':ca', $row['created_at'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->bindValue(':pa', $row['paid_at'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->execute();
|
||||
$migrated++;
|
||||
}
|
||||
debugLog('[handleOrderList] 自动迁移web.db→orders.db', ['migrated' => $migrated]);
|
||||
$webDb = getDB();
|
||||
$tableCheck = $webDb->query("SELECT name FROM sqlite_master WHERE type='table' AND name='pay_orders'");
|
||||
if ($tableCheck->fetchArray()) {
|
||||
$migrateData = $webDb->query("SELECT * FROM pay_orders");
|
||||
$ins = $db->prepare("INSERT OR IGNORE INTO pay_orders (out_trade_no, trade_no, player_name, tier_id, money, bond_amount, status, name, platform_sign, submit_params, created_at, paid_at) VALUES (:no, :tn, :p, :ti, :m, :b, :s, :n, :ps, :sp, :ca, :pa)");
|
||||
$migrated = 0;
|
||||
while ($row = $migrateData->fetchArray(SQLITE3_ASSOC)) {
|
||||
$ins->bindValue(':no', $row['out_trade_no'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':tn', $row['trade_no'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':p', $row['player_name'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':ti', $row['tier_id'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->bindValue(':m', $row['money'] ?? '0', SQLITE3_TEXT);
|
||||
$ins->bindValue(':b', $row['bond_amount'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->bindValue(':s', $row['status'] ?? 'created', SQLITE3_TEXT);
|
||||
$ins->bindValue(':n', $row['name'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':ps', $row['platform_sign'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':sp', $row['submit_params'] ?? '', SQLITE3_TEXT);
|
||||
$ins->bindValue(':ca', $row['created_at'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->bindValue(':pa', $row['paid_at'] ?? 0, SQLITE3_INTEGER);
|
||||
$ins->execute();
|
||||
if ($db->changes() > 0) $migrated++;
|
||||
}
|
||||
if ($migrated > 0) {
|
||||
debugLog('[handleOrderList] 增量迁移web.db→orders.db', ['migrated' => $migrated]);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
||||
Reference in New Issue
Block a user