nzovopay / noderpay-php
Official PHP SDK for the NoderPay API
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.8
- psr/log: ^3.0
- symfony/deprecation-contracts: ^3.7
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
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:
idinternalInvoiceIdstoreIdorderIdamountpaidAmountcurrencystatus(the API'slocal_status)internalStatusadditionalStatuscheckoutUrlredirectUrlbuyerEmailpaidAtsettledAtexpiresAtcreatedAtmetadatadestination
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
NoderPayconstructor. GET/HEADrequests are automatically retried, with a default maximum of 2 attempts, on connection failures,429, and5xxresponses.- Exponential backoff plus jitter is used.
Retry-Afteris honored when present.POSTrequests 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
Authorizationheaders 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.