baseUrl = rtrim($baseUrl, '/'); } public function createInvoice(string $requestId, string $amountRial, ?int $ttlMinutes = null, string $presentation = "hosted"): array { return $this->request('POST', '/api/v1/invoices', [ 'request_id' => $requestId, 'amount_rial' => $amountRial, 'ttl_minutes' => $ttlMinutes, 'presentation' => $presentation, ]); } public function getInvoice(string $invoiceId): array { if (!preg_match('/^[0-9a-f-]{36}$/D', $invoiceId)) { throw new InvalidArgumentException('Invalid invoice ID.'); } return $this->request('GET', '/api/v1/invoices/' . $invoiceId); } public function getPaymentData(string $invoiceId): array { if (!preg_match('/^[0-9a-f-]{36}$/D', $invoiceId)) throw new InvalidArgumentException('Invalid invoice ID.'); return $this->request('GET', '/api/v1/invoices/' . $invoiceId . '/payment-data'); } public function getWallet(): array { return $this->request('GET', '/api/v1/wallet'); } private function request(string $method, string $path, ?array $body = null): array { $curl = curl_init($this->baseUrl . $path); if ($curl === false) { throw new RuntimeException('Could not initialize cURL.'); } try { curl_setopt_array($curl, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 20, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $this->apiKey, 'Accept: application/json', 'Content-Type: application/json'], ]); if ($body !== null) { curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body, JSON_THROW_ON_ERROR)); } $raw = curl_exec($curl); $status = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($raw === false) { throw new RuntimeException('Didban connection failed; check invoice status before retrying the same order.'); } $result = json_decode($raw, true, 64, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING); if (!is_array($result) || $status < 200 || $status >= 300) { throw new RuntimeException('Didban request failed (HTTP ' . $status . ').'); } return $result; } finally { curl_close($curl); } } }