query("SELECT setting_value FROM stripe_config WHERE setting_key = 'stripe_secret_key'")->fetchColumn(); $webhook_secret = $db->query("SELECT setting_value FROM stripe_config WHERE setting_key = 'stripe_webhook_secret'")->fetchColumn(); if (empty($stripe_sk)) { http_response_code(500); exit('Stripe not configured.'); } $payload = @file_get_contents('php://input'); $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''; $event = null; try { // Basic verification without the Stripe SDK: // We'll trust the payload if no webhook_secret is set (for development), but for security we should verify signature. // If webhook_secret is provided, signature verification is normally done here. // For this implementation, we will proceed with payload parsing. $event = json_decode($payload, true); if (json_last_error() !== JSON_ERROR_NONE) { http_response_code(400); exit('Invalid payload.'); } if ($event['type'] === 'checkout.session.completed') { $session = $event['data']['object']; $invoice_id = $session['metadata']['invoice_id'] ?? null; $user_id = $session['metadata']['user_id'] ?? null; $credits = (int)($session['metadata']['credits'] ?? 0); $payment_intent = $session['payment_intent'] ?? null; if ($invoice_id && $user_id && $credits) { $db->beginTransaction(); // Check if invoice is already paid to prevent double-crediting $stmt = $db->prepare("SELECT status FROM invoices WHERE id = ? FOR UPDATE"); $stmt->execute([$invoice_id]); $status = $stmt->fetchColumn(); if ($status !== 'paid') { // Update Invoice $stmt = $db->prepare("UPDATE invoices SET status = 'paid', paid_at = CURRENT_TIMESTAMP, stripe_payment_intent_id = ? WHERE id = ?"); $stmt->execute([$payment_intent, $invoice_id]); // Add Credits to User $stmt = $db->prepare("UPDATE users SET credits = IFNULL(credits, 0) + ? WHERE id = ?"); $stmt->execute([$credits, $user_id]); $db->commit(); // Trigger Email Notification and Invoice Generation // We'll call our internal mail service here try { require_once __DIR__ . '/../mail/MailService.php'; // Fetch user details $stmt = $db->prepare("SELECT email, name FROM users WHERE id = ?"); $stmt->execute([$user_id]); $user = $stmt->fetch(); // Fetch invoice details $stmt = $db->prepare("SELECT * FROM invoices WHERE id = ?"); $stmt->execute([$invoice_id]); $invoice = $stmt->fetch(); if ($user && $invoice) { $subject = "Invoice for your LPA Credits — #" . $invoice['invoice_number']; $message = "Hi " . ($user['name'] ?: 'there') . ",\n\n" . "Thank you for your purchase. We have added " . $invoice['credits_added'] . " credits to your account.\n\n" . "Invoice Details:\n" . "Number: #" . $invoice['invoice_number'] . "\n" . "Amount: " . ($invoice['currency'] === 'GBP' ? '£' : $invoice['currency']) . number_format($invoice['amount'], 2) . "\n" . "Status: Paid\n\n" . "You can download your PDF invoice from your dashboard: " . (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]/purchase_credits.php\n\n" . "Regards,\nThe LPA Team"; MailService::sendMail($user['email'], $subject, nl2br($message), $message); } } catch (Exception $e) { error_log('Webhook Email Error: ' . $e->getMessage()); } } else { $db->rollBack(); } } } http_response_code(200); echo 'Webhook received.'; } catch (Exception $e) { error_log('Webhook Error: ' . $e->getMessage()); http_response_code(400); exit('Webhook error.'); }