feat(webhooks): enhance Polar webhook processing with proper event handling

- Add support for subscription.uncanceled webhook event
  - Fix spelling mismatch for subscription.canceled (Polar) vs subscription.cancelled (code)
  - Implement proper cancel_at_period_end handling in subscription.canceled events
  - Add cancelled_at field updates for subscription.updated events
  - Handle Polar's spelling variants (canceled_at vs cancelled_at) consistently
  - Remove non-existent pause_reason column from subscription uncanceled handler
  - Enhance webhook logging with detailed field update tracking
  - Add comprehensive cancellation metadata storage in provider_data
  - Gracefully handle null provider_subscription_id in payment confirmation polling

  All Polar webhook events now properly sync subscription state including
  cancellation timing, reasons, and billing period details.
This commit is contained in:
idevakk
2025-12-07 00:57:46 -08:00
parent 289baa1286
commit 1b438cbf89
4 changed files with 182 additions and 11 deletions

View File

@@ -117,7 +117,19 @@ class PaymentConfirmation extends Component
'poll_count' => $this->pollCount,
]);
// Check status via provider
// Check status via provider (only if we have a provider subscription ID)
if (empty($this->subscription->provider_subscription_id)) {
Log::info('PaymentConfirmation: Skipping provider status check - no provider subscription ID yet', [
'subscription_id' => $this->subscription->id,
'provider' => $this->subscription->provider,
'provider_checkout_id' => $this->subscription->provider_checkout_id,
'poll_count' => $this->pollCount,
]);
// Don't update status, just continue polling
return;
}
$statusResult = $orchestrator->checkSubscriptionStatus(
$user,
$this->subscription->provider,
@@ -157,6 +169,19 @@ class PaymentConfirmation extends Component
return;
}
} else {
// Handle status check failure
Log::warning('PaymentConfirmation: Provider status check failed', [
'error' => $statusResult['error'] ?? 'Unknown error',
'subscription_id' => $this->subscription->id,
'retry_suggested' => $statusResult['retry_suggested'] ?? false,
]);
// If retry is suggested (e.g., webhook not processed yet), continue polling
if (! ($statusResult['retry_suggested'] ?? false)) {
// If retry is not suggested, we might want to show an error
// but for now, continue polling to be safe
}
}
// Continue polling if not active and max polls not reached