switched to paddle inline checkout, removed paypal and most of stripe. added product sync between app and paddle.
This commit is contained in:
245
app/Services/Paddle/PaddleCatalogService.php
Normal file
245
app/Services/Paddle/PaddleCatalogService.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Paddle;
|
||||
|
||||
use App\Models\Package;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PaddleCatalogService
|
||||
{
|
||||
public function __construct(private readonly PaddleClient $client) {}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function fetchProduct(string $productId): array
|
||||
{
|
||||
return $this->extractEntity($this->client->get("/products/{$productId}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function fetchPrice(string $priceId): array
|
||||
{
|
||||
return $this->extractEntity($this->client->get("/prices/{$priceId}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createProduct(Package $package, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildProductPayload($package, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->post('/products', $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function updateProduct(string $productId, Package $package, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildProductPayload($package, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->patch("/products/{$productId}", $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createPrice(Package $package, string $productId, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildPricePayload($package, $productId, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->post('/prices', $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function updatePrice(string $priceId, Package $package, array $overrides = []): array
|
||||
{
|
||||
$payload = $this->buildPricePayload($package, $overrides['product_id'] ?? $package->paddle_product_id, $overrides);
|
||||
|
||||
return $this->extractEntity($this->client->patch("/prices/{$priceId}", $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function buildProductPayload(Package $package, array $overrides = []): array
|
||||
{
|
||||
$payload = array_merge([
|
||||
'name' => $this->resolveName($package, $overrides),
|
||||
'description' => $this->resolveDescription($package, $overrides),
|
||||
'tax_category' => $overrides['tax_category'] ?? 'standard',
|
||||
'type' => $overrides['type'] ?? 'standard',
|
||||
'custom_data' => $this->buildCustomData($package, $overrides['custom_data'] ?? []),
|
||||
], Arr::except($overrides, ['tax_category', 'type', 'custom_data']));
|
||||
|
||||
return $this->cleanPayload($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function buildPricePayload(Package $package, string $productId, array $overrides = []): array
|
||||
{
|
||||
$unitPrice = $overrides['unit_price'] ?? [
|
||||
'amount' => (string) $this->priceToMinorUnits($package->price),
|
||||
'currency_code' => Str::upper((string) ($package->currency ?? 'EUR')),
|
||||
];
|
||||
|
||||
$payload = array_merge([
|
||||
'product_id' => $productId,
|
||||
'description' => $this->resolvePriceDescription($package, $overrides),
|
||||
'unit_price' => $unitPrice,
|
||||
'custom_data' => $this->buildCustomData($package, $overrides['custom_data'] ?? []),
|
||||
], Arr::except($overrides, ['unit_price', 'description', 'custom_data']));
|
||||
|
||||
return $this->cleanPayload($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $response
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function extractEntity(array $response): array
|
||||
{
|
||||
return Arr::get($response, 'data', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $extra
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function buildCustomData(Package $package, array $extra = []): array
|
||||
{
|
||||
$base = [
|
||||
'fotospiel_package_id' => (string) $package->id,
|
||||
'slug' => $package->slug,
|
||||
'type' => $package->type,
|
||||
'features' => $package->features,
|
||||
'limits' => array_filter([
|
||||
'max_photos' => $package->max_photos,
|
||||
'max_guests' => $package->max_guests,
|
||||
'gallery_days' => $package->gallery_days,
|
||||
'max_tasks' => $package->max_tasks,
|
||||
'max_events_per_year' => $package->max_events_per_year,
|
||||
], static fn ($value) => $value !== null),
|
||||
'translations' => array_filter([
|
||||
'name' => $package->name_translations,
|
||||
'description' => $package->description_translations,
|
||||
], static fn ($value) => ! empty($value)),
|
||||
];
|
||||
|
||||
return array_merge($base, $extra);
|
||||
}
|
||||
|
||||
protected function resolveName(Package $package, array $overrides): string
|
||||
{
|
||||
if (isset($overrides['name']) && is_string($overrides['name'])) {
|
||||
return $overrides['name'];
|
||||
}
|
||||
|
||||
if (! empty($package->name)) {
|
||||
return $package->name;
|
||||
}
|
||||
|
||||
$translations = $package->name_translations ?? [];
|
||||
|
||||
return $translations['en'] ?? $translations['de'] ?? $package->slug;
|
||||
}
|
||||
|
||||
protected function resolveDescription(Package $package, array $overrides): string
|
||||
{
|
||||
if (array_key_exists('description', $overrides)) {
|
||||
$value = is_string($overrides['description']) ? trim($overrides['description']) : null;
|
||||
|
||||
if ($value !== null && $value !== '') {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($package->description)) {
|
||||
return strip_tags((string) $package->description);
|
||||
}
|
||||
|
||||
$translations = $package->description_translations ?? [];
|
||||
|
||||
$fallback = $translations['en'] ?? $translations['de'] ?? null;
|
||||
|
||||
if ($fallback !== null) {
|
||||
$fallback = trim(strip_tags((string) $fallback));
|
||||
if ($fallback !== '') {
|
||||
return $fallback;
|
||||
}
|
||||
}
|
||||
|
||||
return sprintf('Fotospiel package %s', $package->slug ?? $package->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $overrides
|
||||
*/
|
||||
protected function resolvePriceDescription(Package $package, array $overrides): string
|
||||
{
|
||||
if (array_key_exists('description', $overrides)) {
|
||||
$value = is_string($overrides['description']) ? trim($overrides['description']) : null;
|
||||
|
||||
if ($value !== null && $value !== '') {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($package->description)) {
|
||||
return strip_tags((string) $package->description);
|
||||
}
|
||||
|
||||
$translations = $package->description_translations ?? [];
|
||||
$fallback = $translations['en'] ?? $translations['de'] ?? null;
|
||||
|
||||
if ($fallback !== null) {
|
||||
$fallback = trim(strip_tags((string) $fallback));
|
||||
if ($fallback !== '') {
|
||||
return $fallback;
|
||||
}
|
||||
}
|
||||
|
||||
$name = $package->name ?? $package->getNameForLocale('en');
|
||||
|
||||
if ($name) {
|
||||
return sprintf('%s package', trim($name));
|
||||
}
|
||||
|
||||
return sprintf('Package %s', $package->slug ?? $package->id);
|
||||
}
|
||||
|
||||
protected function priceToMinorUnits(mixed $price): int
|
||||
{
|
||||
$value = is_string($price) ? (float) $price : (float) ($price ?? 0);
|
||||
|
||||
return (int) round($value * 100);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user