diff --git a/api/pay.php b/api/pay.php index 14b340e..bdef0f8 100644 --- a/api/pay.php +++ b/api/pay.php @@ -258,7 +258,7 @@ function ensureWebTransactionsTable($db) { // ==================================================================== // 动作:create_order // ==================================================================== -function createOrder($token) { +function createOrder($token, $productId = 0) { $keys = loadPayKeys(); if (empty($keys['pid']) || empty($keys['private_key']) || empty($keys['public_key'])) { error('支付密钥未配置,请联系管理员', 500); @@ -298,10 +298,45 @@ function createOrder($token) { $cleanStmt->bindValue(':stale', $staleThreshold, SQLITE3_INTEGER); $cleanStmt->execute(); - // ===== 0.01 元测试档位(固定映射:0.01 元 → 1 债券) ===== - $money = PAY_TEST_MONEY; - $bonds = PAY_TEST_BONDS; - $name = PAY_TEST_NAME; + // ===== 获取商品信息 ===== + $money = PAY_TEST_MONEY; // 默认测试价格 + $bonds = PAY_TEST_BONDS; // 默认测试债券 + $name = PAY_TEST_NAME; // 默认测试名称 + + if ($productId > 0) { + // 从shop_configs表获取商品信息 + $stmt = $db->prepare("SELECT * FROM shop_configs WHERE id = :id AND is_active = 1"); + $stmt->bindValue(':id', $productId, SQLITE3_INTEGER); + $product = $stmt->execute()->fetchArray(SQLITE3_ASSOC); + + if ($product) { + // 检查库存 + if ($product['stock'] == 0) { + error('商品已售罄'); + } + + $money = number_format($product['price'], 2, '.', ''); + $name = $product['item_name']; + + // 解析债券范围 + $bondReward = $product['bond_reward']; + if (preg_match('/^(\d+)-(\d+)$/', $bondReward, $m)) { + // 随机范围内的债券数量 + $bondMin = intval($m[1]); + $bondMax = intval($m[2]); + $bonds = mt_rand($bondMin, $bondMax); + } else { + $bonds = intval($bondReward); + } + + // 更新库存(如果不是无限库存) + if ($product['stock'] > 0) { + $updateStmt = $db->prepare("UPDATE shop_configs SET stock = stock - 1 WHERE id = :id AND stock > 0"); + $updateStmt->bindValue(':id', $productId, SQLITE3_INTEGER); + $updateStmt->execute(); + } + } + } $outTradeNo = 'RE' . date('YmdHis') . sprintf('%04d', mt_rand(0, 9999)); @@ -869,6 +904,65 @@ function findRecentOrder($token) { success(['orders' => $rows, 'player' => $info['player']]); } +// ==================================================================== +// 动作:get_shop_products — 获取上架商品列表(前端充值页面使用) +// ==================================================================== +function getShopProducts() { + $db = getOrdersDB(); + + // 确保shop_configs表存在 + $db->exec("CREATE TABLE IF NOT EXISTS shop_configs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + item_name TEXT NOT NULL DEFAULT '', + stock INTEGER NOT NULL DEFAULT -1, + temporary_offer TEXT NOT NULL DEFAULT '', + offer_expire TEXT NOT NULL DEFAULT '', + price REAL NOT NULL DEFAULT 0, + bond_reward TEXT NOT NULL DEFAULT '1-1', + is_active INTEGER NOT NULL DEFAULT 1, + created_at INTEGER NOT NULL DEFAULT 0 + )"); + + // 查询上架商品(is_active=1) + $stmt = $db->query("SELECT * FROM shop_configs WHERE is_active = 1 ORDER BY id ASC"); + $products = []; + while ($row = $stmt->fetchArray(SQLITE3_ASSOC)) { + // 检查库存:stock=0(售罄)的商品不返回 + if ($row['stock'] == 0) { + continue; + } + + // 解析债券范围(支持 "1-10" 格式) + $bondReward = $row['bond_reward']; + if (preg_match('/^(\d+)-(\d+)$/', $bondReward, $m)) { + $bondMin = intval($m[1]); + $bondMax = intval($m[2]); + } else { + $bondMin = $bondMax = intval($bondReward); + } + + // 解析有效期 + $expireInfo = parseExpireDate($row['offer_expire']); + + $products[] = [ + 'id' => $row['id'], + 'item_name' => $row['item_name'], + 'stock' => $row['stock'], + 'temporary_offer' => $row['temporary_offer'], + 'offer_expire' => $row['offer_expire'], + 'expire_valid' => $expireInfo['valid'], + 'expire_display' => $expireInfo['display'], + 'price' => $row['price'], + 'bond_reward' => $bondReward, + 'bond_min' => $bondMin, + 'bond_max' => $bondMax, + 'is_active' => $row['is_active'] + ]; + } + + success(['products' => $products]); +} + // ==================================================================== // 入口分发 // ==================================================================== @@ -876,7 +970,7 @@ $action = getParam('action', ''); try { switch ($action) { case 'create_order': - createOrder(getParam('token')); + createOrder(getParam('token'), intval(getParam('product_id', 0))); break; case 'notify': handleNotify(); // 内部已 exit @@ -893,6 +987,9 @@ try { case 'find_recent_order': findRecentOrder(getParam('token')); break; + case 'get_shop_products': + getShopProducts(); + break; default: error('未知操作: ' . $action); } diff --git a/player.php b/player.php index fa49127..1b0ca2d 100644 --- a/player.php +++ b/player.php @@ -1054,31 +1054,26 @@ if ($currentVersion !== $BUILD_VERSION) { else if (page === 'recharge') renderRecharge(c); } - // ==================== 债券在线充值(测试:0.01元 → 1债券) ==================== + // ==================== 债券在线充值(动态加载商品) ==================== function renderRecharge(el) { + // 先显示加载状态 el.innerHTML = `

💳 债券在线充值

-

测试阶段:¥0.01 = 1 债券(仅支付宝)。支付成功后游戏内即时到账。

- -
-
- 测试充值档位 - 测试 -
-
-
¥0.01
支付金额
-
→ 1 债券
-
+

支付成功后游戏内即时到账。

+
+
加载商品中...
- - +
-

说明:点击后跳转至支付宝完成付款,浏览器会自动跳回本页并自动确认到账。若未自动到账,可点击下方按钮手动查询。

+

说明:点击后跳转至支付页面完成付款,浏览器会自动跳回本页并自动确认到账。若未自动到账,可点击下方按钮手动查询。

`; + // 加载商品列表 + loadShopProducts(); + // 处理支付回跳 ?paid=1 const paid = new URLSearchParams(location.search).get('paid'); const lastNo = localStorage.getItem('sdf1_last_recharge_no'); @@ -1102,7 +1097,7 @@ if ($currentVersion !== $BUILD_VERSION) { st.innerHTML = '✅ 此订单已支付完成,可以发起新订单。'; localStorage.removeItem('sdf1_last_recharge_no'); const btn = document.getElementById('rechargeBtn'); - btn.disabled = false; btn.textContent = '🅰️ 支付宝支付 ¥0.01'; btn.onclick = startRecharge; + btn.disabled = false; btn.textContent = '支付'; btn.onclick = startRecharge; } else { st.innerHTML = '检测到订单 ' + latest.out_trade_no + ',正在确认到账…'; pollRechargeOrder(false); @@ -1134,7 +1129,7 @@ if ($currentVersion !== $BUILD_VERSION) { localStorage.removeItem('sdf1_last_recharge_no'); st.innerHTML = '✅ 此订单已支付完成,可以发起新订单。'; btn.disabled = false; - btn.textContent = '🅰️ 支付宝支付 ¥0.01'; + btn.textContent = '支付'; btn.onclick = startRecharge; } else if (res.data.status === 'created') { // 检查订单是否已过期(5分钟) @@ -1145,7 +1140,7 @@ if ($currentVersion !== $BUILD_VERSION) { localStorage.removeItem('sdf1_last_recharge_no'); st.innerHTML = '订单已过期(超过5分钟),请重新下单。'; btn.disabled = false; - btn.textContent = '🅰️ 支付宝支付 ¥0.01'; + btn.textContent = '支付'; btn.onclick = startRecharge; } else { // 未支付:显示继续支付 @@ -1186,6 +1181,86 @@ if ($currentVersion !== $BUILD_VERSION) { } } + // 加载商店商品列表 + async function loadShopProducts() { + const container = document.getElementById('shopProductsContainer'); + try { + const res = await api('pay.php', {action: 'get_shop_products'}); + if (res.success && res.data && res.data.products) { + const products = res.data.products; + if (products.length === 0) { + container.innerHTML = '
暂无商品
'; + return; + } + + // 渲染商品列表 + let html = ''; + products.forEach((product, index) => { + const isSelected = index === 0; // 默认选中第一个 + const offerText = product.temporary_offer ? `
🎁 ${product.temporary_offer}${product.expire_display ? ' (有效期: ' + product.expire_display + ')' : ''}
` : ''; + const stockText = product.stock === -1 ? '无限库存' : (product.stock > 0 ? `库存: ${product.stock}` : '售罄'); + const stockColor = product.stock === -1 ? 'var(--green)' : (product.stock > 0 ? 'var(--dim)' : 'var(--red)'); + + html += ` +
+
+ ${product.item_name} + ${stockText} +
+
+
¥${product.price}
支付金额
+
→ ${product.bond_min === product.bond_max ? product.bond_min + ' 债券' : product.bond_min + '-' + product.bond_max + ' 债券'}
+
+ ${offerText} +
+ `; + }); + + container.innerHTML = html; + + // 选中第一个商品 + if (products.length > 0) { + selectShopProduct(document.querySelector('.shop-product-card')); + } + } else { + container.innerHTML = '
加载商品失败
'; + } + } catch (e) { + container.innerHTML = '
加载商品失败: ' + e.message + '
'; + } + } + + // 选择商品 + function selectShopProduct(el) { + // 取消所有选中 + document.querySelectorAll('.shop-product-card').forEach(card => { + card.style.borderColor = 'var(--border)'; + card.style.background = 'transparent'; + }); + + // 选中当前 + el.style.borderColor = 'var(--accent)'; + el.style.background = 'linear-gradient(135deg,rgba(63,185,80,0.08),rgba(88,166,255,0.06))'; + + // 更新支付按钮 + const btn = document.getElementById('rechargeBtn'); + const price = el.dataset.price; + const bondMin = el.dataset.bondMin; + const bondMax = el.dataset.bondMax; + const bondText = bondMin === bondMax ? bondMin + ' 债券' : bondMin + '-' + bondMax + ' 债券'; + btn.style.display = 'block'; + btn.textContent = `支付宝支付 ¥${price} → ${bondText}`; + btn.dataset.productId = el.dataset.productId; + + // 保存选中商品信息 + window.selectedShopProduct = { + id: el.dataset.productId, + price: price, + bondMin: bondMin, + bondMax: bondMax + }; + } + async function startRecharge() { const btn = document.getElementById('rechargeBtn'); const st = document.getElementById('rechargeStatus'); @@ -1194,16 +1269,18 @@ if ($currentVersion !== $BUILD_VERSION) { btn.textContent = '⏳ 正在创建订单…'; st.innerHTML = '正在请求支付订单…'; try { - const res = await api('pay.php', {action: 'create_order'}); + // 获取选中的商品ID + const productId = window.selectedShopProduct ? window.selectedShopProduct.id : 0; + const res = await api('pay.php', {action: 'create_order', product_id: productId}); if (!res.success) { st.innerHTML = '创建订单失败:' + (res.message || '未知错误') + ''; btn.disabled = false; - btn.textContent = '🅰️ 支付宝支付 ¥0.01'; + btn.textContent = '支付'; return; } const { pay_url, out_trade_no, reused } = res.data; localStorage.setItem('sdf1_last_recharge_no', out_trade_no); - st.innerHTML = '' + (reused ? '恢复支付链接' : '订单已创建') + ',正在跳转支付宝…(如未弹出,请允许浏览器打开新窗口)'; + st.innerHTML = '' + (reused ? '恢复支付链接' : '订单已创建') + ',正在跳转支付…(如未弹出,请允许浏览器打开新窗口)'; document.getElementById('rechargeQueryBtn').style.display = 'block'; const w = window.open(pay_url, '_blank'); if (!w) { @@ -1214,7 +1291,7 @@ if ($currentVersion !== $BUILD_VERSION) { } catch (e) { st.innerHTML = '请求异常:' + e.message + ''; btn.disabled = false; - btn.textContent = '🅰️ 支付宝支付 ¥0.01'; + btn.textContent = '支付'; } }