-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstripe_webhook.php
More file actions
124 lines (114 loc) · 4.6 KB
/
stripe_webhook.php
File metadata and controls
124 lines (114 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/helpers.php';
require_once __DIR__ . '/stripe_lib.php';
require_once __DIR__ . '/provision_storefront.php';
require_once __DIR__ . '/admin_notifications_lib.php';
$pdo = db();
$cfg = gc_stripe_runtime_settings();
$secret = trim((string)($cfg['webhook_secret'] ?? ''));
$payload = file_get_contents('php://input') ?: '';
$sig = (string)($_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '');
if ($secret === '') {
http_response_code(500);
echo 'Stripe webhook secret not configured.';
exit;
}
if (!stripe_verify_webhook_signature($payload, $sig, $secret)) {
http_response_code(400);
echo 'Invalid signature.';
exit;
}
$event = json_decode($payload, true);
if (!is_array($event)) {
http_response_code(400);
echo 'Invalid JSON.';
exit;
}
$eventId = (string)($event['id'] ?? '');
if ($eventId === '') {
http_response_code(400);
echo 'Missing event id.';
exit;
}
try {
$pdo->prepare("INSERT INTO payment_webhook_events (provider, event_id) VALUES ('stripe', ?)")->execute([$eventId]);
} catch (Throwable $e) {
http_response_code(200);
echo 'duplicate';
exit;
}
$type = (string)($event['type'] ?? '');
$obj = $event['data']['object'] ?? [];
if (!is_array($obj)) $obj = [];
function gc_stripe_order_id_from_meta(array $obj): int {
$meta = (array)($obj['metadata'] ?? []);
$id = (int)($meta['order_id'] ?? 0);
if ($id > 0) return $id;
$cr = (int)($obj['client_reference_id'] ?? 0);
return $cr > 0 ? $cr : 0;
}
try {
switch ($type) {
case 'checkout.session.completed':
$orderId = gc_stripe_order_id_from_meta($obj);
$subscriptionId = '';
if (is_array($obj['subscription'] ?? null)) $subscriptionId = (string)($obj['subscription']['id'] ?? '');
else $subscriptionId = (string)($obj['subscription'] ?? '');
if ($orderId > 0 && $subscriptionId !== '') {
$subscription = is_array($obj['subscription'] ?? null) ? $obj['subscription'] : stripe_get_subscription($subscriptionId);
gc_sync_stripe_subscription_from_order($pdo, $orderId, $subscription);
}
break;
case 'invoice.paid':
$subscriptionId = (string)($obj['subscription'] ?? '');
if ($subscriptionId !== '') {
$subscription = stripe_get_subscription($subscriptionId);
$meta = (array)($subscription['metadata'] ?? []);
$orderId = (int)($meta['order_id'] ?? 0);
if ($orderId < 1) {
$st = $pdo->prepare("SELECT id FROM orders WHERE stripe_subscription_id=? ORDER BY id ASC LIMIT 1");
$st->execute([$subscriptionId]);
$orderId = (int)($st->fetchColumn() ?: 0);
}
if ($orderId > 0) {
$userId = gc_sync_stripe_subscription_from_order($pdo, $orderId, $subscription, (string)($obj['id'] ?? ''));
$billingReason = strtolower((string)($obj['billing_reason'] ?? ''));
if ($billingReason !== 'subscription_create') {
$amount = ((int)($obj['amount_paid'] ?? 0)) / 100;
$currency = strtoupper((string)($obj['currency'] ?? 'USD'));
$item = $subscription['items']['data'][0] ?? [];
$priceId = (string)($item['price']['id'] ?? '');
gc_record_stripe_renewal_order($pdo, $orderId, $userId, (int)($meta['plan_id'] ?? 0 ?: 0) ?: (int)(gc_storefront_load_order($pdo, $orderId)['plan_id'] ?? 0), (string)($obj['id'] ?? ''), $subscriptionId, (string)($subscription['customer'] ?? ''), $priceId, (float)$amount, $currency);
}
}
}
break;
case 'invoice.payment_failed':
$subscriptionId = (string)($obj['subscription'] ?? '');
if ($subscriptionId !== '') {
try {
admin_notifications_broadcast($pdo, 'payment', 'Stripe renewal failed', 'Subscription ' . $subscriptionId . ' had a failed renewal invoice.', '/admin/billing_reports.php', 'stripefail:' . $subscriptionId . ':' . (string)($obj['id'] ?? ''));
} catch (Throwable $t) {}
}
break;
case 'customer.subscription.updated':
case 'customer.subscription.deleted':
$subscription = $obj;
$meta = (array)($subscription['metadata'] ?? []);
$orderId = (int)($meta['order_id'] ?? 0);
if ($orderId < 1) {
$st = $pdo->prepare("SELECT id FROM orders WHERE stripe_subscription_id=? ORDER BY id ASC LIMIT 1");
$st->execute([(string)($subscription['id'] ?? '')]);
$orderId = (int)($st->fetchColumn() ?: 0);
}
if ($orderId > 0) gc_sync_stripe_subscription_from_order($pdo, $orderId, $subscription);
break;
}
} catch (Throwable $e) {
http_response_code(500);
echo 'Webhook error: ' . $e->getMessage();
exit;
}
http_response_code(200);
echo 'ok';