request()->get('/customers/'.$customerID); if (! $response->successful()) { return null; } $data = $response->json('data'); return is_array($data) ? $data : null; } public function updateSubscriptionPrice(string $subscriptionID, string $priceID): array { $this->requireWritableConfiguration(); $response = $this->request()->patch('/subscriptions/'.$subscriptionID, [ 'proration_billing_mode' => 'prorated_immediately', 'items' => [[ 'price_id' => $priceID, 'quantity' => 1, ]], ]); return $this->subscriptionData($response, 'Paddle could not update the subscription.'); } public function cancelSubscriptionImmediately(string $subscriptionID): array { $this->requireWritableConfiguration(); $response = $this->request()->post('/subscriptions/'.$subscriptionID.'/cancel', [ 'effective_from' => 'immediately', ]); return $this->subscriptionData($response, 'Paddle could not cancel the subscription.'); } private function request() { return Http::baseUrl((string) config('rsync-studio.paddle.api_url')) ->withToken((string) config('rsync-studio.paddle.api_key')) ->acceptJson() ->timeout(15); } private function requireWritableConfiguration(): void { if (trim((string) config('rsync-studio.paddle.api_key')) === '') { throw new RuntimeException('Paddle subscription management is not configured.'); } } private function subscriptionData(Response $response, string $fallback): array { if (! $response->successful()) { $detail = trim((string) ($response->json('error.detail') ?? '')); throw new RuntimeException($detail !== '' ? $detail : $fallback); } $data = $response->json('data'); if (! is_array($data)) { throw new RuntimeException($fallback); } return $data; } }