baseUrl = rtrim((string) ($cfg['base_url'] ?? 'https://api.nowpayments.io/v1'), '/'); $this->apiKey = (string) ($dbSettings['api_key'] ?? $cfg['api_key'] ?? ''); $this->jwtToken = (string) ($dbSettings['jwt_token'] ?? $cfg['jwt_token'] ?? ''); $this->timeout = (float) ($cfg['timeout'] ?? 10.0); } private function client(bool $useJwt = false) { $headers = [ 'x-api-key' => $this->apiKey, 'Accept' => 'application/json', 'Content-Type' => 'application/json', ]; if ($useJwt && $this->jwtToken) { $headers['Authorization'] = 'Bearer ' . $this->jwtToken; } return Http::timeout($this->timeout) ->retry(2, 150, throw: false) ->baseUrl($this->baseUrl) ->withHeaders($headers); } public function listCurrencies(): array { $res = $this->client()->get('/currencies'); if (!$res->ok()) { Log::warning('NOWPayments listCurrencies failed', ['status' => $res->status(), 'body' => $res->body()]); return []; } $json = $res->json(); return is_array($json) ? ($json['currencies'] ?? $json) : []; } /** * Get available checked currencies (merchant/coins) * https://api.nowpayments.io/v1/merchant/coins */ public function getAvailableCoins(): array { $res = $this->client()->get('/merchant/coins'); if (!$res->ok()) { Log::warning('NOWPayments getAvailableCoins failed', ['status' => $res->status(), 'body' => $res->body()]); return []; } $json = $res->json(); return is_array($json) ? ($json['selectedCurrencies'] ?? $json) : []; } public function estimate(float $priceAmount, string $priceCurrency, string $payCurrency): ?array { $payload = [ 'amount' => $priceAmount, 'currency_from' => strtoupper($priceCurrency), 'currency_to' => strtoupper($payCurrency), ]; $res = $this->client()->post('/estimate', $payload); if (!$res->ok()) { Log::warning('NOWPayments estimate failed', ['status' => $res->status(), 'body' => $res->body(), 'payload' => $payload]); return null; } return $res->json(); } /** * Get the minimum payment amount * https://api.nowpayments.io/v1/min-amount?currency_from=eth¤cy_to=trx */ public function getMinAmount(string $currencyFrom, string $currencyTo, ?string $fiatEquivalent = null, bool $isFixedRate = false, bool $isFeePaidByUser = false): ?array { $query = [ 'currency_from' => strtolower($currencyFrom), 'currency_to' => strtolower($currencyTo), 'is_fixed_rate' => $isFixedRate ? 'True' : 'False', 'is_fee_paid_by_user' => $isFeePaidByUser ? 'True' : 'False', ]; if ($fiatEquivalent) { $query['fiat_equivalent'] = strtolower($fiatEquivalent); } $res = $this->client()->get('/min-amount', $query); if (!$res->ok()) { Log::warning('NOWPayments getMinAmount failed', ['status' => $res->status(), 'body' => $res->body(), 'query' => $query]); return null; } return $res->json(); } public function createInvoice(array $data): ?array { // Expected keys: price_amount, price_currency, pay_currency, order_id, order_description, success_url, cancel_url, ipn_callback_url $res = $this->client()->post('/invoice', $data); if (!$res->ok()) { Log::error('NOWPayments createInvoice failed', ['status' => $res->status(), 'body' => $res->body(), 'data' => $data]); return null; } return $res->json(); } /** * Get payment status * https://api.nowpayments.io/v1/payment/:payment_id */ public function getPayment(string $paymentId): ?array { $res = $this->client()->get('/payment/' . urlencode($paymentId)); if (!$res->ok()) { Log::warning('NOWPayments getPayment failed', ['status' => $res->status(), 'body' => $res->body(), 'payment_id' => $paymentId]); return null; } return $res->json(); } /** * Get list of payments * https://api.nowpayments.io/v1/payment/?limit=10&page=0&sortBy=created_at&orderBy=asc&dateFrom=2020-01-01&dateTo=2021-01-01&invoiceId=6200264890 */ public function listPayments(array $params = []): ?array { $res = $this->client()->get('/payment/', $params); if (!$res->ok()) { Log::warning('NOWPayments listPayments failed', ['status' => $res->status(), 'body' => $res->body(), 'params' => $params]); return null; } return $res->json(); } public function getInvoice(string $invoiceId): ?array { $res = $this->client()->get('/invoice/' . urlencode($invoiceId)); if (!$res->ok()) { Log::warning('NOWPayments getInvoice failed', ['status' => $res->status(), 'body' => $res->body(), 'invoice_id' => $invoiceId]); return null; } return $res->json(); } /** * Validate address * https://api.nowpayments.io/v1/payout/validate-address */ public function validateAddress(string $currency, string $address, ?string $extraId = null): ?array { $payload = [ 'currency' => strtolower($currency), 'address' => $address, ]; if ($extraId !== null) { $payload['extra_id'] = $extraId; } // According to NOWPayments docs, this uses the standard client $res = $this->client()->post('/payout/validate-address', $payload); if (!$res->ok()) { Log::warning('NOWPayments validateAddress failed', ['status' => $res->status(), 'body' => $res->body(), 'payload' => $payload]); return null; } return $res->json(); } /** * Verify payout * https://api.nowpayments.io/v1/payout/:batch-withdrawal-id/verify */ public function verifyPayout(string $batchWithdrawalId, string $verificationCode): ?array { $payload = [ 'verification_code' => $verificationCode ]; $res = $this->client(true)->post('/payout/' . urlencode($batchWithdrawalId) . '/verify', $payload); if (!$res->ok()) { Log::warning('NOWPayments verifyPayout failed', ['status' => $res->status(), 'body' => $res->body(), 'batch_id' => $batchWithdrawalId]); return null; } return $res->json(); } /** * List of payouts * https://api.nowpayments.io/v1/payout */ public function listPayouts(array $params = []): ?array { $res = $this->client(true)->get('/payout', $params); if (!$res->ok()) { Log::warning('NOWPayments listPayouts failed', ['status' => $res->status(), 'body' => $res->body(), 'params' => $params]); return null; } return $res->json(); } }