Search by

nzovopay / noderpay-php

sendzovo

Official PHP SDK for the NoderPay API

Package info

github.com/nzovopay/noderpay-php

Homepage

pkg:composer/nzovopay/noderpay-php

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-16 11:24 UTC

This package is not auto-updated.

Last update: 2026-09-16 14:57:44 UTC


README

Official framework-independent PHP SDK for the NoderPay API.

This package has no dependency on Laravel or any other framework. For Laravel integration (service provider, facade, Artisan command), see the separate nzovopay/noderpay-laravel package.

Requirements

  • PHP 8.1+
  • Composer 2.x

Installation

composer require nzovopay/noderpay-php

Quick start

use NoderPay\NoderPay;

$noderpay = new NoderPay(
    apiKey: getenv('NODERPAY_API_KEY'),
    storeId: getenv('NODERPAY_STORE_ID'),
);

$invoice = $noderpay->invoices()->create([
    'amount' => 49.00,
    'currency' => 'USD',
    'order_id' => 'ORD-123',
    'metadata' => [
        'customer_id' => '12345',
    ],
    'redirect_url' => 'https://example.com/payment/success',
]);

echo $invoice->id;
echo $invoice->checkoutUrl;
echo $invoice->status;

By default, requests go to https://api.noderpay.com. To point at a different environment:

$noderpay = new NoderPay(
    apiKey: $apiKey,
    storeId: $storeId,
    baseUrl: 'https://api.noderpay.com',
);

Implemented resources

Only methods backed by a confirmed NoderPay production endpoint are implemented. See CHANGELOG.md for the full list of what's stubbed pending endpoint confirmation.

Invoices

$invoice = $noderpay->invoices()->create([
    'amount' => 49.00,
    'currency' => 'USD',
    'order_id' => 'ORD-123',
    'buyer_email' => 'customer@example.com',
    'metadata' => ['customer_id' => '12345'],
    'redirect_url' => 'https://example.com/payment/success',
    'redirect_automatically' => true,
]);

$invoice = $noderpay->invoices()->get('SGutkUiQyJEANnk5GG89yq');

$invoices = $noderpay->invoices()->list(['page' => 1]);

foreach ($invoices as $invoice) {
    echo $invoice->id . ': ' . $invoice->status . PHP_EOL;
}

echo 'Total: ' . $invoices->total();

The Invoice DTO exposes:

  • id
  • internalInvoiceId
  • storeId
  • orderId
  • amount
  • paidAmount
  • currency
  • status (the API's local_status)
  • internalStatus
  • additionalStatus
  • checkoutUrl
  • redirectUrl
  • buyerEmail
  • paidAt
  • settledAt
  • expiresAt
  • createdAt
  • metadata
  • destination

It also provides:

  • isPaid()
  • isExpired()
  • raw — the full decoded API response for anything not yet mapped to a named property.

Stores

$store = $noderpay->stores()->get('DW44tD21vha6kG5UAZVE2VnuQAaZqd28tXcrHSY4i1jD');

echo $store->isActive() ? 'Active' : 'Inactive';

Webhooks

$raw = file_get_contents('php://input');

$signature = $_SERVER['HTTP_MERCHANT_SIG'] ?? '';

if (!$noderpay->webhooks()->verify($raw, $signature, $secret)) {
    http_response_code(401);
    exit('Invalid signature');
}

$event = $noderpay->webhooks()->parse($raw);

if ($event->type === 'InvoiceSettled' && $event->invoice !== null) {
    // Look up your local order by $event->invoice->orderId,
    // confirm it matches, then mark it paid.
    //
    // Never treat the checkout redirect alone as proof of payment.
}

See examples/webhook.php for a runnable version of this pattern.

Signature format

NoderPay signs webhooks with the Merchant-Sig header in the form:

sha256=<hex digest>

This SDK verifies it as an HMAC-SHA256 of the raw request body using your webhook secret.

The header name and algorithm are confirmed; the exact signing input has not been independently verified beyond "the raw body." If verification unexpectedly fails for real webhook traffic, confirm with NoderPay support exactly what is signed.

Exceptions

use NoderPay\Exceptions\ValidationException;
use NoderPay\Exceptions\RateLimitException;
use NoderPay\Exceptions\NoderPayException;

try {
    $invoice = $noderpay->invoices()->create($payload);
} catch (ValidationException $e) {
    $errors = $e->errors();
} catch (RateLimitException $e) {
    $seconds = $e->retryAfter();
} catch (NoderPayException $e) {
    // Generic SDK/API failure.
    // $e->getStatusCode()
    // $e->getRequestId()
    // $e->getBody()
}
HTTP status Exception
401 AuthenticationException
403 AuthorizationException
404 ResourceNotFoundException
422 ValidationException (has errors())
429 RateLimitException (has retryAfter())
5xx ApiException
Network/timeout/DNS ConnectionException

No exception ever includes your API key or webhook secret in its message.

Timeouts and retries

  • Default connect timeout: 5 seconds.
  • Default total timeout: 25 seconds.
  • Both are configurable via the NoderPay constructor.
  • GET/HEAD requests are automatically retried, with a default maximum of 2 attempts, on connection failures, 429, and 5xx responses.
  • Exponential backoff plus jitter is used.
  • Retry-After is honored when present.
  • POST requests are never automatically retried.

NoderPay's support for idempotency keys has not been confirmed. Retrying an unconfirmed invoice-creation request could create a duplicate invoice.

If NoderPay adds idempotency key support, this SDK should be updated to expose it and enable safe POST retries.

Security

  • API keys, webhook secrets, and full Authorization headers are never logged or included in exception messages.
  • HTTP debug mode (debug: true) is opt-in and should only be used locally.
  • TLS certificate verification is never disabled.
  • This SDK never accepts or transmits wallet seed phrases or private keys.
  • Treat any wallet public key material (XPUB/ZPUB) your integration handles as privacy-sensitive, even though it does not permit spending funds.

Testing this package

composer install

composer test

composer analyse

Tests run entirely against a mocked HTTP handler. No live NoderPay credentials or network access are required.

License

MIT. See LICENSE.