token())->acceptJson()->timeout(8) ->get($this->base().'/balance', ['user' => $publicId]); $res->throw(); return (int) ($res->json('balance_minor') ?? 0); } public function canAfford(string $publicId, int $amountMinor): bool { $res = Http::withToken($this->token())->acceptJson()->timeout(8) ->get($this->base().'/can-afford', ['user' => $publicId, 'amount_minor' => $amountMinor]); $res->throw(); return (bool) ($res->json('affordable') ?? false); } /** * Debit the wallet. Returns true on success, false on insufficient balance * (HTTP 402). Idempotent by $reference. */ public function debit(string $publicId, int $amountMinor, string $source, string $reference, ?string $description = null): bool { $res = Http::withToken($this->token())->acceptJson()->timeout(10)->post($this->base().'/debit', array_filter([ 'user' => $publicId, 'amount_minor' => $amountMinor, 'service' => (string) config('billing.service', 'crm'), 'source' => $source, 'reference' => $reference, 'description' => $description, ], static fn ($v) => $v !== null)); if ($res->status() === 402) { return false; } $res->throw(); return true; } /** * @param array $metadata * @return array{checkout_url: string, reference: string} */ public function initiatePlanCheckout( string $publicId, string $plan, int $months, int $amountMinor, string $returnUrl, array $metadata = [], ): array { $res = Http::withToken($this->token())->acceptJson()->timeout(15)->post($this->base().'/plan-checkout', [ 'user' => $publicId, 'app' => (string) config('billing.service', 'queue'), 'plan' => $plan, 'months' => $months, 'amount_minor' => $amountMinor, 'return_url' => $returnUrl, 'metadata' => $metadata, ]); $res->throw(); return [ 'checkout_url' => (string) $res->json('checkout_url'), 'reference' => (string) $res->json('reference'), ]; } /** @return array */ public function verifyPlanCheckout(string $reference): array { $res = Http::withToken($this->token())->acceptJson()->timeout(15)->post($this->base().'/plan-checkout/verify', [ 'reference' => $reference, ]); if ($res->status() === 422) { return ['paid' => false, 'error' => $res->json('error')]; } $res->throw(); return $res->json(); } }