*/ public function createDiscount(Coupon $coupon): array { $existing = $this->findExistingDiscount($coupon->code); if ($existing !== null) { return $existing; } $payload = $this->buildDiscountPayload($coupon); $response = $this->client->post('/discounts', $payload); return Arr::get($response, 'data', $response); } /** * @return array */ public function updateDiscount(Coupon $coupon): array { if (! $coupon->paddle_discount_id) { return $this->createDiscount($coupon); } $payload = $this->buildDiscountPayload($coupon); $response = $this->client->patch('/discounts/'.$coupon->paddle_discount_id, $payload); return Arr::get($response, 'data', $response); } public function archiveDiscount(Coupon $coupon): void { if (! $coupon->paddle_discount_id) { return; } $this->client->delete('/discounts/'.$coupon->paddle_discount_id); } /** * @param array $items * @param array{currency?: string, address?: array{country_code: string, postal_code?: string}, customer_id?: string, address_id?: string} $context * @return array */ public function previewDiscount(Coupon $coupon, array $items, array $context = []): array { $payload = [ 'items' => $items, 'discount_id' => $coupon->paddle_discount_id, ]; if (isset($context['currency'])) { $payload['currency_code'] = Str::upper($context['currency']); } if (isset($context['address'])) { $payload['address'] = $context['address']; } if (isset($context['customer_id'])) { $payload['customer_id'] = $context['customer_id']; } if (isset($context['address_id'])) { $payload['address_id'] = $context['address_id']; } $response = $this->client->post('/transactions/preview', $payload); return Arr::get($response, 'data', $response); } /** * @return array|null */ protected function findExistingDiscount(?string $code): ?array { $normalized = Str::upper(trim((string) $code)); if ($normalized === '') { return null; } $response = $this->client->get('/discounts', [ 'code' => $normalized, 'per_page' => 1, ]); $items = Arr::get($response, 'data', []); if (! is_array($items) || $items === []) { return null; } $match = Collection::make($items)->first(static function ($item) use ($normalized) { $codeValue = Str::upper((string) Arr::get($item, 'code', '')); return $codeValue === $normalized ? $item : null; }); return is_array($match) ? $match : null; } /** * @return array */ protected function buildDiscountPayload(Coupon $coupon): array { $payload = [ 'code' => $coupon->code, 'type' => $this->mapType($coupon->type), 'amount' => $this->formatAmount($coupon), 'currency_code' => Str::upper((string) ($coupon->currency ?? config('app.currency', 'EUR'))), 'enabled_for_checkout' => $coupon->enabled_for_checkout, 'description' => $this->resolveDescription($coupon), 'mode' => $coupon->paddle_mode ?? 'standard', 'usage_limit' => $coupon->usage_limit, 'maximum_recurring_intervals' => null, 'recur' => false, 'restrict_to' => $this->resolveRestrictions($coupon), 'expires_at' => optional($coupon->ends_at)?->toIso8601String(), ]; if ($payload['type'] === 'percentage') { unset($payload['currency_code']); } return Collection::make($payload) ->reject(static fn ($value) => $value === null || $value === '') ->all(); } protected function formatAmount(Coupon $coupon): string { if ($coupon->type === CouponType::PERCENTAGE) { return (string) $coupon->amount; } return (string) ((int) round($coupon->amount * 100)); } protected function mapType(CouponType $type): string { return match ($type) { CouponType::PERCENTAGE => 'percentage', CouponType::FLAT => 'flat', CouponType::FLAT_PER_SEAT => 'flat_per_seat', }; } protected function resolveRestrictions(Coupon $coupon): ?array { $packages = ($coupon->relationLoaded('packages') ? $coupon->packages : $coupon->packages()->get()) ->whereNotNull('paddle_price_id'); if ($packages->isEmpty()) { return null; } $prices = $packages->pluck('paddle_price_id')->filter()->values(); return $prices->isEmpty() ? null : $prices->all(); } protected function resolveDescription(Coupon $coupon): string { $description = trim((string) ($coupon->description ?? '')); if ($description !== '') { return $description; } $name = trim((string) ($coupon->name ?? '')); if ($name !== '') { return $name; } $code = trim((string) ($coupon->code ?? '')); if ($code !== '') { return sprintf('Coupon %s', $code); } return sprintf('Coupon %d', $coupon->id); } }