Add PayPal webhook handling
This commit is contained in:
@@ -31,7 +31,7 @@ class CouponRedemptionService
|
||||
return;
|
||||
}
|
||||
|
||||
$transactionId = Arr::get($payload, 'id') ?? $session->lemonsqueezy_order_id;
|
||||
$transactionId = $this->resolveTransactionId($session, $payload);
|
||||
|
||||
$context = $this->resolveRequestContext($session);
|
||||
$fraudSnapshot = $this->buildFraudSnapshot($context);
|
||||
@@ -48,6 +48,7 @@ class CouponRedemptionService
|
||||
'metadata' => array_filter([
|
||||
'session_snapshot' => $session->coupon_snapshot,
|
||||
'payload' => $payload,
|
||||
'provider' => $session->provider,
|
||||
'fraud' => $fraudSnapshot,
|
||||
]),
|
||||
'redeemed_at' => now(),
|
||||
@@ -74,6 +75,7 @@ class CouponRedemptionService
|
||||
|
||||
$context = $this->resolveRequestContext($session);
|
||||
$fraudSnapshot = $this->buildFraudSnapshot($context);
|
||||
$transactionId = $this->resolveTransactionId($session);
|
||||
|
||||
CouponRedemption::query()->updateOrCreate(
|
||||
[
|
||||
@@ -84,13 +86,14 @@ class CouponRedemptionService
|
||||
'tenant_id' => $session->tenant_id,
|
||||
'user_id' => $session->user_id,
|
||||
'package_id' => $session->package_id,
|
||||
'lemonsqueezy_order_id' => $session->lemonsqueezy_order_id,
|
||||
'lemonsqueezy_order_id' => $transactionId,
|
||||
'status' => CouponRedemption::STATUS_FAILED,
|
||||
'failure_reason' => $reason,
|
||||
'amount_discounted' => $session->amount_discount,
|
||||
'currency' => $session->currency ?? 'EUR',
|
||||
'metadata' => array_filter([
|
||||
'session_snapshot' => $session->coupon_snapshot,
|
||||
'provider' => $session->provider,
|
||||
'fraud' => $fraudSnapshot,
|
||||
]),
|
||||
]),
|
||||
@@ -109,6 +112,24 @@ class CouponRedemptionService
|
||||
], static fn ($value) => $value !== null && $value !== '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
*/
|
||||
private function resolveTransactionId(CheckoutSession $session, array $payload = []): ?string
|
||||
{
|
||||
if ($session->provider === CheckoutSession::PROVIDER_PAYPAL) {
|
||||
$paypalId = $session->paypal_capture_id
|
||||
?? $session->paypal_order_id
|
||||
?? Arr::get($payload, 'id');
|
||||
|
||||
return is_string($paypalId) && $paypalId !== '' ? $paypalId : null;
|
||||
}
|
||||
|
||||
$lemonsqueezyId = Arr::get($payload, 'id') ?? $session->lemonsqueezy_order_id;
|
||||
|
||||
return is_string($lemonsqueezyId) && $lemonsqueezyId !== '' ? $lemonsqueezyId : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{ip_address?: string|null, device_id?: string|null, user_agent?: string|null} $context
|
||||
* @return array<string, mixed>|null
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Services\Coupons;
|
||||
|
||||
use App\Enums\CouponStatus;
|
||||
use App\Enums\CouponType;
|
||||
use App\Models\CheckoutSession;
|
||||
use App\Models\Coupon;
|
||||
use App\Models\CouponRedemption;
|
||||
use App\Models\Package;
|
||||
@@ -18,11 +19,11 @@ class CouponService
|
||||
/**
|
||||
* @return array{coupon: Coupon, pricing: array<string, mixed>, source: string}
|
||||
*/
|
||||
public function preview(string $code, Package $package, ?Tenant $tenant = null): array
|
||||
public function preview(string $code, Package $package, ?Tenant $tenant = null, ?string $provider = null): array
|
||||
{
|
||||
$coupon = $this->findCouponForCode($code);
|
||||
|
||||
$this->ensureCouponCanBeApplied($coupon, $package, $tenant);
|
||||
$this->ensureCouponCanBeApplied($coupon, $package, $tenant, $this->resolveProvider($provider));
|
||||
|
||||
$pricing = $this->buildPricingBreakdown($coupon, $package, $tenant);
|
||||
|
||||
@@ -33,9 +34,9 @@ class CouponService
|
||||
];
|
||||
}
|
||||
|
||||
public function ensureCouponCanBeApplied(Coupon $coupon, Package $package, ?Tenant $tenant = null): void
|
||||
public function ensureCouponCanBeApplied(Coupon $coupon, Package $package, ?Tenant $tenant = null, ?string $provider = null): void
|
||||
{
|
||||
if (! $coupon->lemonsqueezy_discount_id) {
|
||||
if ($provider !== CheckoutSession::PROVIDER_PAYPAL && ! $coupon->lemonsqueezy_discount_id) {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => __('marketing.coupon.errors.not_synced'),
|
||||
]);
|
||||
@@ -75,6 +76,17 @@ class CouponService
|
||||
}
|
||||
}
|
||||
|
||||
protected function resolveProvider(?string $provider): ?string
|
||||
{
|
||||
if ($provider && $provider !== '') {
|
||||
return $provider;
|
||||
}
|
||||
|
||||
$default = config('checkout.default_provider');
|
||||
|
||||
return is_string($default) && $default !== '' ? $default : null;
|
||||
}
|
||||
|
||||
protected function findCouponForCode(string $code): Coupon
|
||||
{
|
||||
$normalized = Str::upper(trim($code));
|
||||
|
||||
Reference in New Issue
Block a user