Files
fotospiel-app/app/Http/Controllers/PayPalController.php

235 lines
9.0 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Models\PackagePurchase;
use App\Models\Tenant;
use App\Models\TenantPackage;
use App\Models\Package;
use PaypalServerSdkLib\PaypalServerSdkClientBuilder;
use PaypalServerSdkLib\Auth\ClientCredentialsAuthCredentialsBuilder;
use PaypalServerSdkLib\Environment;
use PaypalServerSdkLib\Logging\LoggingConfigurationBuilder;
use PaypalServerSdkLib\Logging\RequestLoggingConfigurationBuilder;
use PaypalServerSdkLib\Logging\ResponseLoggingConfigurationBuilder;
use PaypalServerSdkLib\Logging\LogLevel;
use PaypalServerSdkLib\Orders\OrderRequestBuilder;
use PaypalServerSdkLib\Orders\CheckoutPaymentIntent;
use PaypalServerSdkLib\Orders\PurchaseUnitRequestBuilder;
use PaypalServerSdkLib\Orders\AmountWithBreakdownBuilder;
use PaypalServerSdkLib\Orders\ApplicationContextBuilder;
use PaypalServerSdkLib\Subscriptions\SubscriptionRequestBuilder;
use PaypalServerSdkLib\Subscriptions\SubscriberBuilder;
use PaypalServerSdkLib\Subscriptions\NameBuilder;
use PaypalServerSdkLib\Subscriptions\ApplicationContextSubscriptionBuilder;
use PaypalServerSdkLib\Subscriptions\ShippingPreference;
class PayPalController extends Controller
{
private $client;
public function __construct()
{
$clientId = config('services.paypal.client_id');
$clientSecret = config('services.paypal.secret');
$this->client = PaypalServerSdkClientBuilder::init()
->clientCredentialsAuthCredentials(
ClientCredentialsAuthCredentialsBuilder::init($clientId, $clientSecret)
)
->environment(config('app.env') === 'production' ? Environment::PRODUCTION : Environment::SANDBOX)
->loggingConfiguration(
LoggingConfigurationBuilder::init()
->level(LogLevel::INFO)
->requestConfiguration(RequestLoggingConfigurationBuilder::init()->body(true))
->responseConfiguration(ResponseLoggingConfigurationBuilder::init()->headers(true))
)
->build();
}
public function createOrder(Request $request)
{
$request->validate([
'tenant_id' => 'required|exists:tenants,id',
'package_id' => 'required|exists:packages,id',
]);
$tenant = Tenant::findOrFail($request->tenant_id);
$package = Package::findOrFail($request->package_id);
$ordersController = $this->client->getOrdersController();
$requestBody = OrderRequestBuilder::init(CheckoutPaymentIntent::CAPTURE)
->purchaseUnits([
PurchaseUnitRequestBuilder::init()
->amount(
AmountWithBreakdownBuilder::init('EUR', number_format($package->price, 2, '.', ''))
->build()
)
->description('Package: ' . $package->name)
->customId($tenant->id . '_' . $package->id . '_endcustomer_event')
->build()
])
->applicationContext(
ApplicationContextBuilder::init()
->shippingPreference(ShippingPreference::NO_SHIPPING)
->userAction('PAY_NOW')
->build()
)
->build();
$collect = [
'body' => $requestBody,
'prefer' => 'return=representation'
];
try {
$response = $ordersController->createOrder($collect);
if ($response->statusCode === 201) {
$result = $response->result;
$approveLink = collect($result->links)->first(fn($link) => $link->rel === 'approve')?->href;
return response()->json([
'id' => $result->id,
'approve_url' => $approveLink,
]);
}
Log::error('PayPal order creation failed', ['response' => $response]);
return response()->json(['error' => 'Order creation failed'], 400);
} catch (\Exception $e) {
Log::error('PayPal order creation exception', ['error' => $e->getMessage()]);
return response()->json(['error' => 'Order creation failed'], 500);
}
}
public function captureOrder(Request $request)
{
$request->validate(['order_id' => 'required']);
$ordersController = $this->client->getOrdersController();
$collect = [
'id' => $request->order_id,
'prefer' => 'return=representation'
];
try {
$response = $ordersController->captureOrder($collect);
if ($response->statusCode === 201) {
$result = $response->result;
$customId = $result->purchaseUnits[0]->customId ?? null;
if ($customId) {
[$tenantId, $packageId, $type] = explode('_', $customId);
$tenant = Tenant::findOrFail($tenantId);
$package = Package::findOrFail($packageId);
PackagePurchase::create([
'tenant_id' => $tenant->id,
'package_id' => $package->id,
'provider_id' => $result->id,
'price' => $result->purchaseUnits[0]->amount->value,
'type' => $type ?? 'endcustomer_event',
'purchased_at' => now(),
'refunded' => false,
]);
Log::info('PayPal order captured and purchase created: ' . $result->id);
}
return response()->json(['status' => 'captured', 'order' => $result]);
}
Log::error('PayPal order capture failed', ['response' => $response]);
return response()->json(['error' => 'Capture failed'], 400);
} catch (\Exception $e) {
Log::error('PayPal order capture exception', ['error' => $e->getMessage()]);
return response()->json(['error' => 'Capture failed'], 500);
}
}
public function createSubscription(Request $request)
{
$request->validate([
'tenant_id' => 'required|exists:tenants,id',
'package_id' => 'required|exists:packages,id',
'plan_id' => 'required', // PayPal plan ID for the package
]);
$tenant = Tenant::findOrFail($request->tenant_id);
$package = Package::findOrFail($request->package_id);
$subscriptionsController = $this->client->getSubscriptionsController();
$requestBody = SubscriptionRequestBuilder::init()
->planId($request->plan_id)
->subscriber(
SubscriberBuilder::init()
->name(
NameBuilder::init()
->givenName($tenant->name ?? 'Tenant')
->build()
)
->emailAddress($tenant->email)
->build()
)
->customId($tenant->id . '_' . $package->id . '_reseller_subscription')
->applicationContext(
ApplicationContextSubscriptionBuilder::init()
->shippingPreference(ShippingPreference::NO_SHIPPING)
->userAction('SUBSCRIBE_NOW')
->build()
)
->build();
$collect = [
'body' => $requestBody,
'prefer' => 'return=representation'
];
try {
$response = $subscriptionsController->createSubscription($collect);
if ($response->statusCode === 201) {
$result = $response->result;
$subscriptionId = $result->id;
TenantPackage::create([
'tenant_id' => $tenant->id,
'package_id' => $package->id,
'purchased_at' => now(),
'expires_at' => now()->addYear(),
'active' => true,
]);
PackagePurchase::create([
'tenant_id' => $tenant->id,
'package_id' => $package->id,
'provider_id' => $subscriptionId,
'price' => $package->price,
'type' => 'reseller_subscription',
'purchased_at' => now(),
]);
$approveLink = collect($result->links)->first(fn($link) => $link->rel === 'approve')?->href;
return response()->json([
'subscription_id' => $subscriptionId,
'approve_url' => $approveLink,
]);
}
Log::error('PayPal subscription creation failed', ['response' => $response]);
return response()->json(['error' => 'Subscription creation failed'], 400);
} catch (\Exception $e) {
Log::error('PayPal subscription creation exception', ['error' => $e->getMessage()]);
return response()->json(['error' => 'Subscription creation failed'], 500);
}
}
}