101 lines
3.6 KiB
PHP
101 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Requests\LemonSqueezy\LemonSqueezyCheckoutRequest;
|
|
use App\Models\CheckoutSession;
|
|
use App\Models\Package;
|
|
use App\Services\Checkout\CheckoutSessionService;
|
|
use App\Services\Coupons\CouponService;
|
|
use App\Services\LemonSqueezy\LemonSqueezyCheckoutService;
|
|
use App\Support\CheckoutRequestContext;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class LemonSqueezyCheckoutController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly LemonSqueezyCheckoutService $checkout,
|
|
private readonly CheckoutSessionService $sessions,
|
|
private readonly CouponService $coupons,
|
|
) {}
|
|
|
|
public function create(LemonSqueezyCheckoutRequest $request): JsonResponse
|
|
{
|
|
$data = $request->validated();
|
|
|
|
$user = Auth::user();
|
|
$tenant = $user?->tenant;
|
|
|
|
if (! $tenant) {
|
|
throw ValidationException::withMessages(['tenant' => 'Tenant context missing.']);
|
|
}
|
|
|
|
$package = Package::findOrFail((int) $data['package_id']);
|
|
|
|
if (! $package->lemonsqueezy_variant_id) {
|
|
throw ValidationException::withMessages(['package_id' => 'Package is not linked to a Lemon Squeezy variant.']);
|
|
}
|
|
|
|
$session = $this->sessions->createOrResume($user, $package, array_merge(
|
|
CheckoutRequestContext::fromRequest($request),
|
|
[
|
|
'tenant' => $tenant,
|
|
]
|
|
));
|
|
|
|
$this->sessions->selectProvider($session, CheckoutSession::PROVIDER_LEMONSQUEEZY);
|
|
|
|
$now = now();
|
|
|
|
$session->forceFill([
|
|
'accepted_terms_at' => $now,
|
|
'accepted_privacy_at' => $now,
|
|
'accepted_withdrawal_notice_at' => $now,
|
|
'digital_content_waiver_at' => null,
|
|
'legal_version' => $this->resolveLegalVersion(),
|
|
])->save();
|
|
|
|
$couponCode = Str::upper(trim((string) ($data['coupon_code'] ?? '')));
|
|
|
|
if ($couponCode !== '') {
|
|
$preview = $this->coupons->preview($couponCode, $package, $tenant);
|
|
$this->sessions->applyCoupon($session, $preview['coupon'], $preview['pricing']);
|
|
}
|
|
|
|
$checkout = $this->checkout->createCheckout($tenant, $package, [
|
|
'success_url' => $data['success_url'] ?? null,
|
|
'return_url' => $data['return_url'] ?? null,
|
|
'metadata' => [
|
|
'checkout_session_id' => $session->id,
|
|
'coupon_code' => $couponCode ?: null,
|
|
'legal_version' => $session->legal_version,
|
|
'accepted_terms' => true,
|
|
],
|
|
'discount_code' => $couponCode ?: null,
|
|
'customer_email' => $user?->email,
|
|
'customer_name' => trim(($user?->first_name ?? '').' '.($user?->last_name ?? '')) ?: ($user?->name ?? null),
|
|
]);
|
|
|
|
$session->forceFill([
|
|
'lemonsqueezy_checkout_id' => $checkout['id'] ?? $session->lemonsqueezy_checkout_id,
|
|
'provider_metadata' => array_merge($session->provider_metadata ?? [], array_filter([
|
|
'lemonsqueezy_checkout_id' => $checkout['id'] ?? null,
|
|
'lemonsqueezy_checkout_url' => $checkout['checkout_url'] ?? null,
|
|
'lemonsqueezy_expires_at' => $checkout['expires_at'] ?? null,
|
|
])),
|
|
])->save();
|
|
|
|
return response()->json(array_merge($checkout, [
|
|
'checkout_session_id' => $session->id,
|
|
]));
|
|
}
|
|
|
|
protected function resolveLegalVersion(): string
|
|
{
|
|
return config('app.legal_version', now()->toDateString());
|
|
}
|
|
}
|