feat(payment): integrate Polar.sh payment provider with checkout flow

- Build PolarProvider from scratch with proper HTTP API integration
  - Add encrypted configuration loading from payment_providers table via model
  - Implement sandbox/live environment switching with proper credential handling
  - Fix product creation API structure for Polar.sh requirements
  - Add comprehensive error handling and logging throughout checkout flow
  - Fix PaymentController checkout URL handling to support Polar's checkout_url response
  - Add debug logging for troubleshooting checkout session creation
  - Support both regular and trial checkout flows for Polar payments
This commit is contained in:
idevakk
2025-12-04 10:29:25 -08:00
parent c2c18f2406
commit 75086ad83b
6 changed files with 770 additions and 352 deletions

View File

@@ -7,6 +7,7 @@ use App\Models\User;
use App\Services\Payments\PaymentOrchestrator;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
class PaymentController extends Controller
@@ -75,8 +76,23 @@ class PaymentController extends Controller
], 404);
}
Log::info('PaymentController: Creating checkout session', [
'user_id' => $user->id,
'plan_id' => $plan->id,
'requested_provider' => $provider,
'is_trial' => $isTrial,
'options_count' => count($options),
]);
$result = $this->orchestrator->createCheckoutSession($user, $plan, $provider, $options);
Log::info('PaymentController: Returning successful checkout response', [
'result_keys' => array_keys($result),
'has_checkout_url' => isset($result['checkout_url']),
'checkout_url' => $result['checkout_url'] ?? 'missing',
'provider_subscription_id' => $result['provider_subscription_id'] ?? 'missing',
]);
return response()->json([
'success' => true,
'data' => $result,
@@ -277,6 +293,14 @@ class PaymentController extends Controller
'is_trial' => false,
]);
Log::info('PaymentController: enhancedCheckout result', [
'result_keys' => array_keys($result),
'has_redirect_url' => isset($result['redirect_url']),
'has_session_url' => isset($result['session_url']),
'has_checkout_url' => isset($result['checkout_url']),
'checkout_url' => $result['checkout_url'] ?? 'missing',
]);
// Redirect to provider's checkout page
if (isset($result['redirect_url'])) {
return redirect($result['redirect_url']);
@@ -287,6 +311,11 @@ class PaymentController extends Controller
return redirect($result['session_url']);
}
// Polar checkout URL handling
if (isset($result['checkout_url'])) {
return redirect($result['checkout_url']);
}
session()->flash('error', 'Unable to create checkout session. Please try again.');
return redirect()->route('dashboard');
@@ -332,6 +361,14 @@ class PaymentController extends Controller
'trial_requires_payment_method' => $trialConfig?->trial_requires_payment_method ?? true,
]);
Log::info('PaymentController: trialCheckout result', [
'result_keys' => array_keys($result),
'has_redirect_url' => isset($result['redirect_url']),
'has_session_url' => isset($result['session_url']),
'has_checkout_url' => isset($result['checkout_url']),
'checkout_url' => $result['checkout_url'] ?? 'missing',
]);
// Redirect to provider's checkout page
if (isset($result['redirect_url'])) {
return redirect($result['redirect_url']);
@@ -342,6 +379,11 @@ class PaymentController extends Controller
return redirect($result['session_url']);
}
// Polar checkout URL handling
if (isset($result['checkout_url'])) {
return redirect($result['checkout_url']);
}
session()->flash('error', 'Unable to create trial checkout session. Please try again.');
return redirect()->route('dashboard');