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; } }