coinpay / php-integration
php package for coin payment finance
Package info
github.com/coinpay-finance/php-integration-package
pkg:composer/coinpay/php-integration
Requires
- php: ^7.0|^8.0
- ext-curl: *
- ext-json: *
This package is not auto-updated.
Last update: 2026-08-13 11:29:17 UTC
README
Safe, fast and instant payments; Anytime, anywhere with CoinPay.
This is CoinPay's official framework-agnostic PHP SDK — plain PHP, zero third-party
dependencies (only ext-curl and ext-json). If you're on Laravel, use
coinpay/laravel-integration instead.
Installation
Install with composer:
composer require coinpay/php-integration
Requires PHP 7.4+ or 8.0+, with the curl and json extensions.
Creating a payment
use Coinpay\Finance\CoinPayGateway; use Coinpay\Finance\Exceptions\CoinPayException; $gateway = new CoinPayGateway('###COINPAY_API_KEY###'); try { $response = $gateway->createPayment( 1.0, // The amount to be paid (in Dollar - $). 'https://your-callback.url', // The URL the user will be redirected to after payment. 'ref123', // A unique reference ID for tracking the transaction. 'payer@example.com', // The identity of the payer (email or phone number). 'Alimo', // Full name of the payer. 'Test Payment', // Description of the payment (e.g. "Payment for order #123"). '1234567890' // National identification code of the payer. ); echo "Payment URL: " . $response->url . PHP_EOL; // Redirect the user to this URL echo "Transaction ID: " . $response->transactionId . PHP_EOL; // Store this ID if you need it later } catch (CoinPayException $e) { // $e->getHttpStatusCode() — HTTP status code, or 0 if the request never got a response // $e->getResponseBody() — decoded (array) or raw (string) response body, if any // $e->isNetworkError() — true for connection/timeout failures rather than API rejections echo "Error: " . $e->getMessage() . PHP_EOL; }
Checking a payment's status
use Coinpay\Finance\CoinPayGateway; use Coinpay\Finance\Exceptions\CoinPayException; $gateway = new CoinPayGateway('###COINPAY_API_KEY###'); try { $status = $gateway->checkStatus('transaction-id-from-createPayment'); echo $status->status . PHP_EOL; // e.g. "completed", "pending", "failed" echo $status->amount . PHP_EOL; echo $status->transactionId . PHP_EOL; echo $status->reason . PHP_EOL; echo $status->transactionHash . PHP_EOL; echo $status->network . PHP_EOL; } catch (CoinPayException $e) { echo "Error: " . $e->getMessage() . PHP_EOL; }
Verifying webhooks
CoinPay notifies your application asynchronously about payment status changes. Since this
package targets plain PHP with no framework/router to pass you a parsed request, read the
raw request body yourself with file_get_contents('php://input') and pull the relevant
headers, then verify before trusting anything in the payload.
Two verification schemes exist:
Current: HMAC-SHA256 signature (X-Coinpay-Signature)
The request carries three headers — X-Coinpay-Signature: v1=<hex-hmac-sha256>,
X-Coinpay-Timestamp: <unix-seconds>, and X-Coinpay-Delivery: <uuid> — and the signature
covers "{timestamp}.{deliveryId}.{rawBody}". CoinPayWebhookVerifier::verify() recomputes
the digest, compares it with hash_equals(), and rejects the request if the timestamp is
more than 300 seconds old or in the future.
use Coinpay\Finance\CoinPayWebhookVerifier; $rawBody = file_get_contents('php://input'); $timestamp = $_SERVER['HTTP_X_COINPAY_TIMESTAMP'] ?? ''; $deliveryId = $_SERVER['HTTP_X_COINPAY_DELIVERY'] ?? ''; $signature = $_SERVER['HTTP_X_COINPAY_SIGNATURE'] ?? null; $secret = '###YOUR_COINPAY_WEBHOOK_SECRET###'; if (!CoinPayWebhookVerifier::verify($rawBody, $timestamp, $deliveryId, $secret, $signature)) { http_response_code(403); exit; } $payload = json_decode($rawBody, true); // $payload['status'], $payload['reason'], $payload['transaction_id'], // $payload['amount'], $payload['transaction_hash'] http_response_code(200);
Legacy: static shared-secret header (SECRET) — deprecated
Older deliveries may still arrive with a plain SECRET header instead of a signature. This
scheme is deprecated (no payload binding, no timestamp, no replay protection) but CoinPay
still accepts it during the transition window, so a merchant that wants to keep working
without gaps should check for it as a fallback when X-Coinpay-Signature is absent:
use Coinpay\Finance\CoinPayWebhookVerifier; $rawBody = file_get_contents('php://input'); $secret = '###YOUR_COINPAY_WEBHOOK_SECRET###'; $signature = $_SERVER['HTTP_X_COINPAY_SIGNATURE'] ?? null; $verified = $signature !== null ? CoinPayWebhookVerifier::verify( $rawBody, $_SERVER['HTTP_X_COINPAY_TIMESTAMP'] ?? '', $_SERVER['HTTP_X_COINPAY_DELIVERY'] ?? '', $secret, $signature ) : CoinPayWebhookVerifier::verifyLegacy($secret, $_SERVER['HTTP_SECRET'] ?? null); if (!$verified) { http_response_code(403); exit; }
Prefer the HMAC path for any new integration; only fall back to the legacy path if you need to support deliveries that predate signature verification.
Exceptions
Every failure — a rejected API request or a network/timeout failure — is thrown as
Coinpay\Finance\Exceptions\CoinPayException, which extends \Exception and additionally
exposes:
getHttpStatusCode(): int— the HTTP status code, or0if no response was ever received.getResponseBody()— the decoded (array) or raw (string) response body, if any.isNetworkError(): bool—truefor connection/timeout failures rather than API rejections.getCurlErrno(): ?int— the curl error number, whenisNetworkError()istrue.
Testing
composer install
composer test