*/ public function fetchProduct(string $productId): array { return $this->extractEntity($this->client->get("/products/{$productId}")); } /** * @return array */ public function fetchPrice(string $priceId): array { return $this->extractEntity($this->client->get("/prices/{$priceId}")); } /** * @return array */ public function createProduct(Package $package, array $overrides = []): array { $payload = $this->buildProductPayload($package, $overrides); return $this->extractEntity($this->client->post('/products', $payload)); } /** * @return array */ 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 */ public function createPrice(Package $package, string $productId, array $overrides = []): array { $payload = $this->buildPricePayload($package, $productId, $overrides, includeProduct: true); return $this->extractEntity($this->client->post('/prices', $payload)); } /** * @return array */ public function updatePrice(string $priceId, Package $package, array $overrides = []): array { $payload = $this->buildPricePayload( $package, $overrides['product_id'] ?? $package->paddle_product_id, $overrides, includeProduct: false ); return $this->extractEntity($this->client->patch("/prices/{$priceId}", $payload)); } /** * @return array */ 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 */ public function buildPricePayload(Package $package, string $productId, array $overrides = [], bool $includeProduct = true): array { $unitPrice = $overrides['unit_price'] ?? [ 'amount' => (string) $this->priceToMinorUnits($package->price), 'currency_code' => Str::upper((string) ($package->currency ?? 'EUR')), ]; $base = [ 'description' => $this->resolvePriceDescription($package, $overrides), 'unit_price' => $unitPrice, 'custom_data' => $this->buildCustomData($package, $overrides['custom_data'] ?? []), ]; if ($includeProduct) { $base['product_id'] = $productId; } $payload = array_merge($base, Arr::except($overrides, ['unit_price', 'description', 'custom_data', 'product_id'])); return $this->cleanPayload($payload); } /** * @param array $response * @return array */ protected function extractEntity(array $response): array { return Arr::get($response, 'data', $response); } /** * @param array $payload * @return array */ 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 $extra * @return array */ 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 $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); } }