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:
@@ -4,14 +4,17 @@ namespace App\Services\Payments;
|
||||
|
||||
use App\Contracts\Payments\PaymentProviderContract;
|
||||
use App\Models\Coupon;
|
||||
use App\Models\CouponUsage;
|
||||
use App\Models\Plan;
|
||||
use App\Models\Subscription;
|
||||
use App\Models\SubscriptionChange;
|
||||
use App\Models\TrialExtension;
|
||||
use App\Models\User;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PaymentOrchestrator
|
||||
{
|
||||
@@ -588,16 +591,41 @@ class PaymentOrchestrator
|
||||
*/
|
||||
protected function getProviderForPlan(Plan $plan, ?string $providerName = null): PaymentProviderContract
|
||||
{
|
||||
Log::info('PaymentOrchestrator: Getting provider for plan', [
|
||||
'plan_id' => $plan->id,
|
||||
'requested_provider' => $providerName,
|
||||
]);
|
||||
|
||||
if ($providerName) {
|
||||
$provider = $this->providerRegistry->get($providerName);
|
||||
Log::info('PaymentOrchestrator: Checking specific provider', [
|
||||
'provider_name' => $providerName,
|
||||
'provider_exists' => $provider ? true : false,
|
||||
'provider_active' => $provider?->isActive(),
|
||||
'provider_supported' => $provider ? $this->isProviderSupportedForPlan($provider, $plan) : false,
|
||||
]);
|
||||
|
||||
if ($provider && $provider->isActive() && $this->isProviderSupportedForPlan($provider, $plan)) {
|
||||
Log::info('PaymentOrchestrator: Using requested provider', [
|
||||
'provider' => $providerName,
|
||||
]);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the first active provider that supports this plan
|
||||
foreach ($this->providerRegistry->getActiveProviders() as $provider) {
|
||||
Log::info('PaymentOrchestrator: Checking fallback provider', [
|
||||
'provider' => $provider->getName(),
|
||||
'supported' => $this->isProviderSupportedForPlan($provider, $plan),
|
||||
]);
|
||||
|
||||
if ($this->isProviderSupportedForPlan($provider, $plan)) {
|
||||
Log::info('PaymentOrchestrator: Using fallback provider', [
|
||||
'provider' => $provider->getName(),
|
||||
]);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
}
|
||||
@@ -625,10 +653,13 @@ class PaymentOrchestrator
|
||||
*/
|
||||
protected function isProviderSupportedForPlan(PaymentProviderContract $provider, Plan $plan): bool
|
||||
{
|
||||
// Check if plan has provider-specific configuration
|
||||
$providerConfig = $plan->details['providers'][$provider->getName()] ?? null;
|
||||
// Use the same approach as Plan::supportsProvider() - check database relationship
|
||||
$isSupported = $plan->planProviders()
|
||||
->where('provider', $provider->getName())
|
||||
->where('is_enabled', true)
|
||||
->exists();
|
||||
|
||||
if (! $providerConfig || ! ($providerConfig['enabled'] ?? false)) {
|
||||
if (! $isSupported) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user