feat(payments): implement smart Polar subscription sync with checkout tracking

- Add provider_checkout_id column to separate checkout ID from subscription ID
   - Update Polar provider to store checkout ID separately and set subscription ID to null initially
   - Implement smart sync logic that queries Polar API when subscription ID is missing
   - Add fetchPolarSubscriptionId method to find active subscriptions via customer ID
   - Update webhook handlers to use provider_checkout_id for subscription lookup
   - Make makeAuthenticatedRequest public to enable Subscription model API access
   - Support plan metadata matching for accurate subscription identification
   - Add fallback to most recent active subscription when no exact match found

   This resolves sync button issues by properly tracking checkout vs subscription IDs
   and enables automatic subscription ID recovery when webhooks fail.
This commit is contained in:
idevakk
2025-12-06 02:28:40 -08:00
parent 5ee5c5b8dc
commit 0724e6da43
3 changed files with 120 additions and 4 deletions

View File

@@ -132,7 +132,7 @@ class PolarProvider implements PaymentProviderContract
}
}
protected function makeAuthenticatedRequest(string $method, string $endpoint, array $data = []): \Illuminate\Http\Client\Response
public function makeAuthenticatedRequest(string $method, string $endpoint, array $data = []): \Illuminate\Http\Client\Response
{
$url = $this->apiBaseUrl.$endpoint;
@@ -261,7 +261,8 @@ class PolarProvider implements PaymentProviderContract
'stripe_id' => $checkout['id'], // Using stripe_id field for Polar checkout ID
'stripe_status' => 'pending',
'provider' => $this->getName(),
'provider_subscription_id' => $checkout['id'],
'provider_checkout_id' => $checkout['id'], // Store checkout ID separately
'provider_subscription_id' => null, // Will be populated via webhook or sync
'status' => 'pending_payment',
'starts_at' => null,
'ends_at' => null,
@@ -1170,9 +1171,9 @@ class PolarProvider implements PaymentProviderContract
{
$polarSubscription = $webhookData['data']['object'];
// Find and update local subscription
// Find and update local subscription using checkout_id
$localSubscription = Subscription::where('provider', 'polar')
->where('provider_subscription_id', $polarSubscription['checkout_id'])
->where('provider_checkout_id', $polarSubscription['checkout_id'])
->first();
if ($localSubscription) {