verifyWebhookSignature($payload, $sigHeader, STRIPE_WEBHOOK_SECRET); $event = json_decode($payload, true); } catch (Exception $e) { error_log('Stripe webhook signature verification failed: ' . $e->getMessage()); http_response_code(400); exit(); } } else { $event = json_decode($payload, true); if (!$event) { http_response_code(400); exit(); } } $eventType = $event['type'] ?? ''; $data = $event['data']['object'] ?? []; switch ($eventType) { case 'checkout.session.completed': // Stripe Checkout (hosted page) — metadata is on the session $orderId = $data['metadata']['order_id'] ?? ''; $paymentIntentId = $data['payment_intent'] ?? ''; if ($orderId && ($data['payment_status'] ?? '') === 'paid') { db()->update('orders', [ 'payment_status' => 'paid', 'order_status' => 'confirmed', 'stripe_payment_intent' => $paymentIntentId, ], 'order_id = :id', ['id' => $orderId] ); $order = db()->fetch("SELECT * FROM orders WHERE order_id = :id", ['id' => $orderId]); if ($order) { emailService()->sendOrderConfirmation($order); } } break; case 'payment_intent.succeeded': // Payment Intent flow (embedded/direct) - skip if already confirmed by checkout.session.completed $paymentIntentId = $data['id'] ?? ''; $orderId = $data['metadata']['order_id'] ?? ''; if ($orderId) { $order = db()->fetch("SELECT * FROM orders WHERE order_id = :id", ['id' => $orderId]); if ($order && $order['order_status'] !== 'confirmed') { db()->update('orders', [ 'payment_status' => 'paid', 'order_status' => 'confirmed', 'stripe_payment_intent' => $paymentIntentId, ], 'order_id = :id', ['id' => $orderId] ); $order = db()->fetch("SELECT * FROM orders WHERE order_id = :id", ['id' => $orderId]); if ($order) { emailService()->sendOrderConfirmation($order); } } } break; case 'payment_intent.payment_failed': $orderId = $data['metadata']['order_id'] ?? ''; if ($orderId) { db()->update('orders', ['payment_status' => 'failed'], 'order_id = :id', ['id' => $orderId] ); } break; case 'charge.refunded': $paymentIntentId = $data['payment_intent'] ?? ''; if ($paymentIntentId) { db()->update('orders', [ 'payment_status' => 'refunded', 'order_status' => 'refunded', ], 'stripe_payment_intent = :pi', ['pi' => $paymentIntentId] ); } break; } http_response_code(200); echo json_encode(['received' => true]);