Files
BetiX/app/Services/NowPaymentsClient.php
Dolo 0280278978
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Initialer Laravel Commit für BetiX
2026-04-04 18:01:50 +02:00

214 lines
7.5 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class NowPaymentsClient
{
private string $baseUrl;
private string $apiKey;
private string $jwtToken; // Added for operations that might need JWT auth (payouts)
private float $timeout;
public function __construct()
{
$cfg = config('services.nowpayments');
// Prefer DB-stored API key from admin settings over config/env
$dbSettings = \App\Models\AppSetting::get('payments.nowpayments', []);
$this->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&currency_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();
}
}