implemented event package addons with filament resource, event-admin purchase path and notifications, showing up in purchase history
This commit is contained in:
137
app/Services/Paddle/PaddleAddonCatalogService.php
Normal file
137
app/Services/Paddle/PaddleAddonCatalogService.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Paddle;
|
||||
|
||||
use App\Models\PackageAddon;
|
||||
use App\Services\Paddle\Exceptions\PaddleException;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class PaddleAddonCatalogService
|
||||
{
|
||||
public function __construct(private readonly PaddleClient $client) {}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createProduct(PackageAddon $addon, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildProductPayload($addon, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->post('/products', $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function updateProduct(string $productId, PackageAddon $addon, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildProductPayload($addon, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->patch("/products/{$productId}", $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createPrice(PackageAddon $addon, string $productId, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildPricePayload($addon, $productId, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->post('/prices', $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function updatePrice(string $priceId, PackageAddon $addon, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildPricePayload($addon, $overrides['product_id'] ?? '', $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->patch("/prices/{$priceId}", $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function buildProductPayload(PackageAddon $addon, array $overrides = []): array
|
||||
{
|
||||
$payload = array_merge([
|
||||
'name' => $overrides['name'] ?? $addon->label,
|
||||
'description' => $overrides['description'] ?? sprintf('Fotospiel Add-on: %s', $addon->label),
|
||||
'tax_category' => $overrides['tax_category'] ?? 'standard',
|
||||
'type' => $overrides['type'] ?? 'standard',
|
||||
'custom_data' => array_merge([
|
||||
'addon_key' => $addon->key,
|
||||
'increments' => $addon->increments,
|
||||
], $overrides['custom_data'] ?? []),
|
||||
], Arr::except($overrides, ['tax_category', 'type', 'custom_data', 'name', 'description']));
|
||||
|
||||
return $this->cleanPayload($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function buildPricePayload(PackageAddon $addon, string $productId, array $overrides = []): array
|
||||
{
|
||||
$unitPrice = $overrides['unit_price'] ?? $this->defaultUnitPrice($addon);
|
||||
|
||||
$payload = array_merge([
|
||||
'product_id' => $productId,
|
||||
'description' => $overrides['description'] ?? $addon->label,
|
||||
'unit_price' => $unitPrice,
|
||||
'custom_data' => array_merge([
|
||||
'addon_key' => $addon->key,
|
||||
], $overrides['custom_data'] ?? []),
|
||||
], Arr::except($overrides, ['unit_price', 'description', 'custom_data', 'product_id']));
|
||||
|
||||
return $this->cleanPayload($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function extractEntity(array $payload): array
|
||||
{
|
||||
return Arr::get($payload, 'data', $payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function cleanPayload(array $payload): array
|
||||
{
|
||||
$filtered = collect($payload)
|
||||
->reject(static fn ($value) => $value === null || $value === '' || $value === [])
|
||||
->all();
|
||||
|
||||
if (array_key_exists('custom_data', $filtered)) {
|
||||
$filtered['custom_data'] = collect($filtered['custom_data'])
|
||||
->reject(static fn ($value) => $value === null || $value === '' || $value === [])
|
||||
->all();
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function defaultUnitPrice(PackageAddon $addon): array
|
||||
{
|
||||
$metaPrice = $addon->metadata['price_eur'] ?? null;
|
||||
|
||||
if (! is_numeric($metaPrice)) {
|
||||
throw new PaddleException('No unit price specified for addon. Provide metadata[price_eur] or overrides.unit_price.');
|
||||
}
|
||||
|
||||
$amountCents = (int) round(((float) $metaPrice) * 100);
|
||||
|
||||
return [
|
||||
'amount' => (string) $amountCents,
|
||||
'currency_code' => 'EUR',
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user