Add PayPal support for add-on and gift voucher checkout
This commit is contained in:
117
app/Services/Addons/EventAddonPurchaseService.php
Normal file
117
app/Services/Addons/EventAddonPurchaseService.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Addons;
|
||||
|
||||
use App\Models\EventPackage;
|
||||
use App\Models\EventPackageAddon;
|
||||
use App\Notifications\Addons\AddonPurchaseReceipt;
|
||||
use App\Notifications\Ops\AddonPurchased;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class EventAddonPurchaseService
|
||||
{
|
||||
public function __construct(private readonly EventAddonCatalog $catalog) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
*/
|
||||
public function complete(
|
||||
EventPackageAddon $addon,
|
||||
array $payload,
|
||||
?string $transactionId,
|
||||
?string $checkoutId,
|
||||
?float $amount,
|
||||
?string $currency,
|
||||
array $metadata = [],
|
||||
): void {
|
||||
if ($addon->status === 'completed') {
|
||||
return;
|
||||
}
|
||||
|
||||
$increments = $this->resolveAddonIncrements($addon, $addon->addon_key);
|
||||
|
||||
DB::transaction(function () use ($addon, $payload, $transactionId, $checkoutId, $amount, $currency, $metadata, $increments) {
|
||||
$addon->forceFill([
|
||||
'transaction_id' => $transactionId ?? $addon->transaction_id,
|
||||
'checkout_id' => $addon->checkout_id ?: $checkoutId,
|
||||
'status' => 'completed',
|
||||
'amount' => $amount ?? $addon->amount,
|
||||
'currency' => $currency ?? $addon->currency,
|
||||
'metadata' => array_merge($addon->metadata ?? [], array_filter([
|
||||
'payment_payload' => $payload,
|
||||
]), $metadata),
|
||||
'purchased_at' => now(),
|
||||
])->save();
|
||||
|
||||
/** @var EventPackage $eventPackage */
|
||||
$eventPackage = EventPackage::query()
|
||||
->lockForUpdate()
|
||||
->find($addon->event_package_id);
|
||||
|
||||
if (! $eventPackage) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eventPackage->forceFill([
|
||||
'extra_photos' => ($eventPackage->extra_photos ?? 0) + (int) ($increments['extra_photos'] ?? 0) * $addon->quantity,
|
||||
'extra_guests' => ($eventPackage->extra_guests ?? 0) + (int) ($increments['extra_guests'] ?? 0) * $addon->quantity,
|
||||
'extra_gallery_days' => ($eventPackage->extra_gallery_days ?? 0) + (int) ($increments['extra_gallery_days'] ?? 0) * $addon->quantity,
|
||||
]);
|
||||
|
||||
if (($increments['extra_gallery_days'] ?? 0) > 0) {
|
||||
$base = $eventPackage->gallery_expires_at ?? now();
|
||||
$eventPackage->gallery_expires_at = $base->copy()->addDays((int) ($increments['extra_gallery_days'] ?? 0) * $addon->quantity);
|
||||
}
|
||||
|
||||
$eventPackage->save();
|
||||
|
||||
$tenant = $addon->tenant;
|
||||
if ($tenant) {
|
||||
Notification::route('mail', [$tenant->contact_email ?? $tenant->user?->email])
|
||||
->notify(new AddonPurchaseReceipt($addon));
|
||||
|
||||
$opsEmail = config('mail.ops_address');
|
||||
if ($opsEmail) {
|
||||
Notification::route('mail', $opsEmail)->notify(new AddonPurchased($addon));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
*/
|
||||
public function fail(EventPackageAddon $addon, string $reason, array $payload = []): void
|
||||
{
|
||||
$addon->forceFill([
|
||||
'status' => 'failed',
|
||||
'error' => $reason,
|
||||
'metadata' => array_merge($addon->metadata ?? [], array_filter([
|
||||
'payment_payload' => $payload,
|
||||
])),
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, int>
|
||||
*/
|
||||
private function resolveAddonIncrements(EventPackageAddon $addon, string $addonKey): array
|
||||
{
|
||||
$stored = Arr::get($addon->metadata ?? [], 'increments', []);
|
||||
|
||||
if (is_array($stored) && $stored !== []) {
|
||||
$filtered = collect($stored)
|
||||
->map(fn ($value) => is_numeric($value) ? (int) $value : 0)
|
||||
->filter(fn ($value) => $value > 0)
|
||||
->all();
|
||||
|
||||
if ($filtered !== []) {
|
||||
return $filtered;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->catalog->resolveIncrements($addonKey);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user