<?php if (!defined('DASHBOARD_ROOT')) { http_response_code(403); exit; } function verifyPayment(int $orderId, string $method, array $data): array { $order = Database::fetchOne( "SELECT id, order_ref, subtotal, status_code, payment_method FROM orders WHERE id = :id", [':id' => $orderId] ); if (!$order) return ['ok' => false, 'error' => 'Order not found']; if ((int)$order['status_code'] !== StatusCode::ORDER_PENDING) return ['ok' => false, 'error' => 'Order not pending']; $adminId = (int)($_SESSION['admin_id'] ?? 0); if ($method === 'crypto') { $txHash = trim($data['tx_hash'] ?? ''); if ($txHash === '') return ['ok' => false, 'error' => 'TX hash required']; Database::execute("UPDATE orders SET status_code = :sc, updated_at = NOW() WHERE id = :id", [':sc' => StatusCode::ORDER_PAID, ':id' => $orderId]); Events::record(Events::CAT_VERIFY, 'payment.crypto_verified', 'order', $orderId, ['tx_hash' => $txHash, 'admin_id' => $adminId]); return ['ok' => true]; } elseif ($method === 'card') { Database::execute("UPDATE orders SET status_code = :sc, updated_at = NOW() WHERE id = :id", [':sc' => StatusCode::ORDER_PAID, ':id' => $orderId]); Events::record(Events::CAT_VERIFY, 'payment.card_force_marked', 'order', $orderId, ['admin_id' => $adminId, 'forced' => true]); return ['ok' => true]; } return ['ok' => false, 'error' => 'Unknown method']; } function renderPaymentVerify(): string { $pending = Database::fetchAll( "SELECT id, order_ref, subtotal, payment_method, status_label, created_at          FROM orders WHERE status_code = :sc AND payment_method IN ('crypto','card')          ORDER BY created_at", [':sc' => StatusCode::ORDER_PENDING] ); $html = '<div class="payment-verify"><span class="section-label">Payment Verifications</span>'; foreach ($pending as $p) { $method = UI::e($p['payment_method']); $badge = $method === 'crypto' ? 'badge-info' : 'badge-default'; $html .= '<div class="verify-card" data-order-id="' . (int)$p['id'] . '">'; $html .= '<div class="verify-card-top">'; $html .= '<span class="verify-ref">#' . UI::e($p['order_ref']) . '</span>'; $html .= '<span class="verify-amount">$' . number_format((float)$p['subtotal'], 2) . '</span>'; $html .= '</div>'; $html .= '<div class="verify-card-bot">'; $html .= '<span class="badge ' . $badge . '">' . strtoupper($method) . '</span>'; $html .= '<span class="verify-date">' . UI::e($p['created_at']) . '</span>'; $html .= '</div>'; if ($p['payment_method'] === 'crypto') { $html .= '<div class="verify-action">'; $html .= '<input type="text" class="form-group input" id="tx-' . (int)$p['id'] . '" placeholder="Paste TX hash" style="width:100%;margin-bottom:6px">'; $html .= '<a class="btn btn-primary btn-sm" href="javascript:void(0)" data-action="verify-payment" data-id="' . (int)$p['id'] . '" data-method="crypto"><span>Verify</span></a>'; $html .= '</div>'; } else { $html .= '<a class="btn btn-warning btn-sm" href="javascript:void(0)" data-action="verify-payment" data-id="' . (int)$p['id'] . '" data-method="card"><span>Force Mark Paid</span></a>'; } $html .= '</div>'; } if (empty($pending)) $html .= '<div class="empty-state"><span>No pending payment verifications.</span></div>'; $html .= '</div>'; return $html; } 