Connexion tocken, stripe 3D, tracking analytic
This commit is contained in:
1 parent
1deb30fcd1
commit
bd311da711
17 files changed
+3324
-455
No files matched your search
+54
-42
@@ -644,36 +644,13 @@ if (in_array($type, $checkoutEvents, true) && $obj) {
|
||||
'last_event_id' => $eventId,
|
||||
]);
|
||||
|
||||
// 1) Aligner praticien (abonnement_id + date_expiration)
|
||||
if ($praticien_id && $abonnement_id && $current_period_end && colExists($pdo, 'praticien', 'date_expiration')) {
|
||||
$pdo->prepare("UPDATE praticien SET abonnement_id = ?, date_expiration = ? WHERE id = ?")
|
||||
->execute([(int) $abonnement_id, (string) $current_period_end, (int) $praticien_id]);
|
||||
} elseif ($praticien_id && $abonnement_id && $current_period_end && colExists($pdo, 'praticien', 'abonnement_expire_le')) {
|
||||
$pdo->prepare("UPDATE praticien SET abonnement_id = ?, abonnement_expire_le = ? WHERE id = ?")
|
||||
->execute([(int) $abonnement_id, (string) $current_period_end, (int) $praticien_id]);
|
||||
}
|
||||
// IMPORTANT:
|
||||
// Ne pas activer/prolonger l'accès ici.
|
||||
// L'accès réel est accordé uniquement sur invoice.paid.
|
||||
|
||||
// 2) Créer le paiement même si invoice.paid est arrivé avant (robuste aux webhooks désordonnés)
|
||||
try {
|
||||
if ($sub_id) {
|
||||
$subLatest = $stripe->subscriptions->retrieve((string) $sub_id, []);
|
||||
$latestInvoiceId = stripeId($subLatest->latest_invoice ?? null);
|
||||
|
||||
if ($latestInvoiceId) {
|
||||
$invLatest = $stripe->invoices->retrieve((string) $latestInvoiceId, []);
|
||||
insertPaiementFromInvoice($pdo, $configAll, $stripe, $invLatest, (int) $praticien_id, (int) $abonnement_id, (string) $sub_id, $eventId);
|
||||
|
||||
// Optionnel: stocker last_invoice_id dans billing
|
||||
$upsertBilling([
|
||||
'praticien_id' => $praticien_id,
|
||||
'last_invoice_id' => (string) $latestInvoiceId,
|
||||
'last_event_id' => $eventId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
wh_log('WARN checkout-sub latest_invoice insert paiement failed: ' . $e->getMessage());
|
||||
}
|
||||
// IMPORTANT:
|
||||
// Ne pas créer de ligne paiement ici pour un abonnement.
|
||||
// La création du paiement réel se fait uniquement sur invoice.paid.
|
||||
|
||||
http_response_code(200);
|
||||
echo 'ok-checkout-subscription';
|
||||
@@ -810,6 +787,7 @@ if (in_array($type, $checkoutEvents, true) && $obj) {
|
||||
$billingEvents = [
|
||||
'invoice.paid',
|
||||
'invoice.payment_failed',
|
||||
'invoice.payment_action_required',
|
||||
'invoice_payment.paid', // type vu chez toi (non standard)
|
||||
'customer.subscription.updated',
|
||||
'customer.subscription.deleted',
|
||||
@@ -822,7 +800,12 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
}
|
||||
|
||||
// ---------- invoice.* ----------
|
||||
if ($type === 'invoice.paid' || $type === 'invoice.payment_failed' || $type === 'invoice_payment.paid') {
|
||||
if (
|
||||
$type === 'invoice.paid' ||
|
||||
$type === 'invoice.payment_failed' ||
|
||||
$type === 'invoice.payment_action_required' ||
|
||||
$type === 'invoice_payment.paid'
|
||||
) {
|
||||
|
||||
// invoice_payment.paid => récupérer la vraie invoice
|
||||
if ($type === 'invoice_payment.paid') {
|
||||
@@ -870,18 +853,30 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
$amount_cent = is_numeric($inv->amount_due ?? null) ? (int) $inv->amount_due : null;
|
||||
}
|
||||
|
||||
// Price/Product depuis lignes
|
||||
$provider_plan_id = null;
|
||||
$provider_product_id = null;
|
||||
// Price/Product + période depuis lignes
|
||||
$provider_plan_id = null;
|
||||
$provider_product_id = null;
|
||||
$invoice_period_start = null;
|
||||
$invoice_period_end = null;
|
||||
try {
|
||||
if (isset($inv->lines->data) && is_array($inv->lines->data) && ! empty($inv->lines->data)) {
|
||||
$line0 = $inv->lines->data[0];
|
||||
|
||||
if (isset($line0->price)) {
|
||||
$provider_plan_id = stripeId($line0->price);
|
||||
if (is_object($line0->price) && isset($line0->price->product)) {
|
||||
$provider_product_id = stripeId($line0->price->product);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($line0->period)) {
|
||||
if (isset($line0->period->start)) {
|
||||
$invoice_period_start = dtFromUnix($line0->period->start);
|
||||
}
|
||||
if (isset($line0->period->end)) {
|
||||
$invoice_period_end = dtFromUnix($line0->period->end);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
wh_log('WARN invoice lines parse: ' . $e->getMessage());
|
||||
@@ -1046,7 +1041,14 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Pour un renouvellement, la période portée par la facture est souvent
|
||||
// la source la plus fiable pour prolonger l'accès.
|
||||
if ($invoice_period_start) {
|
||||
$current_period_start = $invoice_period_start;
|
||||
}
|
||||
if ($invoice_period_end) {
|
||||
$current_period_end = $invoice_period_end;
|
||||
}
|
||||
wh_log("BILL ev=$eventId $type inv=" . ($invoice_id ?: 'null') . " sub=" . ($sub_id ?: 'null') . " cust=" . ($cust_id ?: 'null') . " pid=" . ($praticien_id ?: 'null') . " aid=" . ($abonnement_id ?: 'null') . " cps=" . ($current_period_start ?: 'null') . " cpe=" . ($current_period_end ?: 'null') . " status=" . ($sub_status ?: ''));
|
||||
|
||||
// Upsert billing_subscriptions (NE PAS écraser avec null)
|
||||
@@ -1059,7 +1061,11 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
'provider_subscription_id' => $sub_id,
|
||||
'provider_plan_id' => $provider_plan_id,
|
||||
'provider_product_id' => $provider_product_id,
|
||||
'status' => $sub_status ?? ($type === 'invoice.payment_failed' ? 'payment_failed' : 'paid'),
|
||||
'status' => $sub_status ?? (
|
||||
$type === 'invoice.payment_failed'
|
||||
? 'payment_failed'
|
||||
: ($type === 'invoice.payment_action_required' ? 'action_required' : 'paid')
|
||||
),
|
||||
'current_period_start' => $current_period_start,
|
||||
'current_period_end' => $current_period_end,
|
||||
'cancel_at_period_end' => (int) $cancel_at_period_end,
|
||||
@@ -1068,7 +1074,12 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
'last_event_id' => $eventId,
|
||||
'last_invoice_id' => $invoice_id,
|
||||
]);
|
||||
|
||||
if ($type === 'invoice.payment_action_required') {
|
||||
wh_log("ACTION_REQUIRED inv=" . ($invoice_id ?: 'null') . " sub=" . ($sub_id ?: 'null') . " cust=" . ($cust_id ?: 'null') . " pid=" . ($praticien_id ?: 'null'));
|
||||
http_response_code(200);
|
||||
echo 'ok-invoice-action-required';
|
||||
exit;
|
||||
}
|
||||
// invoice.paid => insert paiement + update praticien si pid/aid OK
|
||||
if ($type === 'invoice.paid') {
|
||||
if (! $praticien_id || ! $abonnement_id) {
|
||||
@@ -1092,7 +1103,7 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
$prix = is_numeric($amount_cent) ? ((int) $amount_cent) / 100.0 : 0.0;
|
||||
$statut = pickStatut($pdo, 'payé');
|
||||
|
||||
$date_expiration = $current_period_end;
|
||||
$date_expiration = $invoice_period_end ?: $current_period_end;
|
||||
if (! $date_expiration) {
|
||||
[$cpsF, $cpeF] = periodFallbackFromPlan($pdo, (int) $abonnement_id);
|
||||
$date_expiration = $cpeF ?: (new DateTime('now'))->modify("+30 days")->format('Y-m-d H:i:s');
|
||||
@@ -1135,6 +1146,9 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
if (colExists($pdo, 'praticien', 'date_expiration')) {
|
||||
$pdo->prepare("UPDATE praticien SET abonnement_id = ?, date_expiration = ? WHERE id = ?")
|
||||
->execute([(int) $abonnement_id, (string) $date_expiration, (int) $praticien_id]);
|
||||
} elseif (colExists($pdo, 'praticien', 'abonnement_expire_le')) {
|
||||
$pdo->prepare("UPDATE praticien SET abonnement_id = ?, abonnement_expire_le = ? WHERE id = ?")
|
||||
->execute([(int) $abonnement_id, (string) $date_expiration, (int) $praticien_id]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
@@ -1276,11 +1290,9 @@ if (in_array($type, $billingEvents, true) && $obj) {
|
||||
'last_event_id' => $eventId,
|
||||
]);
|
||||
|
||||
// align expiration praticien
|
||||
if ($praticien_id && $current_period_end && colExists($pdo, 'praticien', 'date_expiration')) {
|
||||
$pdo->prepare("UPDATE praticien SET date_expiration = ? WHERE id = ?")
|
||||
->execute([(string) $current_period_end, (int) $praticien_id]);
|
||||
}
|
||||
// IMPORTANT:
|
||||
// Ne pas modifier praticien.date_expiration ici.
|
||||
// Seul invoice.paid doit prolonger l'accès effectif.
|
||||
|
||||
http_response_code(200);
|
||||
echo 'ok-sub';
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user