Files
portfoli-ulleres/checkout/stripe-webhook.php
T

133 lines
4.8 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/common.php';
$config = kapvoe_load_config();
$payload = file_get_contents('php://input') ?: '';
$sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';
$secret = (string)($config['stripe_webhook_secret'] ?? '');
if (!kapvoe_verify_stripe_signature($payload, $sigHeader, $secret)) {
http_response_code(400);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'ok' => false,
'error' => 'Signatura Stripe invàlida'
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
$event = json_decode($payload, true);
if (!is_array($event)) {
http_response_code(400);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'ok' => false,
'error' => 'Payload JSON invàlid'
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
$type = (string)($event['type'] ?? '');
$object = $event['data']['object'] ?? null;
error_log('[KAPVOE WEBHOOK] event_type=' . $type);
if (!is_array($object)) {
http_response_code(400);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'ok' => false,
'error' => 'Event sense objecte de dades'
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
try {
switch ($type) {
case 'checkout.session.completed':
$sessionId = (string)($object['id'] ?? '');
$paymentIntentId = (string)($object['payment_intent'] ?? '');
$paymentStatus = (string)($object['payment_status'] ?? '');
error_log('[KAPVOE WEBHOOK] checkout.session.completed session_id=' . $sessionId . ' payment_status=' . $paymentStatus);
if ($sessionId === '') {
throw new RuntimeException('Falta session id');
}
kapvoe_update_order_status(
$config,
$sessionId,
$paymentStatus === 'paid' ? 'paid' : 'pending',
$paymentIntentId
);
$order = kapvoe_get_order_by_session_id($config, $sessionId);
if (!$order) {
throw new RuntimeException('No s\'ha trobat la comanda al CSV');
}
$alreadyUpdated = (string)($order['stock_updated'] ?? '') === '1';
$stockResult = null;
$mailResult = null;
$analyticsResult = null;
if ($paymentStatus === 'paid' && !$alreadyUpdated) {
$stockResult = kapvoe_decrement_sheet_stock($config, $order, $sessionId);
if (!($stockResult['ok'] ?? false)) {
throw new RuntimeException('No s\'ha pogut actualitzar l\'stock al Google Sheet');
}
kapvoe_mark_order_stock_updated($config, $sessionId);
$alreadyUpdated = true;
}
if ($paymentStatus === 'paid') {
$order = kapvoe_get_order_by_session_id($config, $sessionId) ?? $order;
error_log('[KAPVOE WEBHOOK] sending_order_notifications session_id=' . $sessionId . ' customer_email=' . (string)($order['email'] ?? ''));
$mailResult = kapvoe_send_order_notifications($config, $order, $sessionId);
error_log('[KAPVOE WEBHOOK] mail_result session_id=' . $sessionId . ' result=' . json_encode($mailResult, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$analyticsResult = kapvoe_track_analytics_event($config, kapvoe_build_payment_success_event($order, $sessionId));
error_log('[KAPVOE WEBHOOK] analytics_result session_id=' . $sessionId . ' result=' . ($analyticsResult ? '1' : '0'));
}
http_response_code(200);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'ok' => true,
'handled' => $type,
'session_id' => $sessionId,
'payment_intent_id' => $paymentIntentId,
'already_updated' => $alreadyUpdated,
'stock_result' => $stockResult,
'mail_result' => $mailResult,
'analytics_result' => $analyticsResult,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
default:
http_response_code(200);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'ok' => true,
'ignored' => $type
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
} catch (Throwable $e) {
error_log('[KAPVOE WEBHOOK] ERROR ' . $e->getMessage());
http_response_code(500);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'ok' => false,
'error' => $e->getMessage()
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}