Caravel Pay Docs

SDKs

PHP SDK

caravelpay/caravel-php signs every request, verifies webhooks in constant time and checks every response before you use it. It runs on PHP 7.4 to 8.5 with only ext-curl and ext-json.

Install#

Download caravel-php-1.0.0.zip, unzip it into your project and load its autoloader. The SDK needs nothing else.

Load the SDK
<?php
require 'caravel-php/autoload.php';

Available at launch. The downloads on this page open when Caravel Pay launches.

Get API keys#

Run this once, then keep the merchant id and secret in your server's environment. Every call creates a new merchant, so to change your wallet or rotate the secret you connect again. See Get your API keys.

Connect once
<?php
require 'caravel-php/autoload.php';

$keys = CaravelPay\Client::connect([
    'site_url' => 'https://shop.example',
    'payout_address' => '0x52908400098527886E0F7030069857D2E4169EE7',
    'email' => 'you@shop.example', // optional
]);
// ['merchant_id' => 'mch_…', 'secret' => '…', 'status' => 'active', 'fee_rate' => '2%']

Create a checkout#

Create a checkout and redirect
<?php
use CaravelPay\Amount;
use CaravelPay\Client;

$caravel = new Client(getenv('CARAVEL_MERCHANT_ID'), getenv('CARAVEL_SECRET'), ['max_retries' => 2]);

$checkout = $caravel->createCheckout([
    'order_id' => '1042',
    'amount' => Amount::normalize($order->total), // "136.41"
    'customer_email' => 'buyer@example.com',      // optional
    'return_url' => 'https://shop.example/thanks',
    'cancel_url' => 'https://shop.example/cart',
    'callback_url' => 'https://shop.example/webhooks/caravel',
]);
header('Location: ' . $checkout['checkout_url'], true, 303);

The same order_id with the same details returns the same checkout. A timeout or 5xx can be retried safely, and with max_retries the SDK does it for you.

Handle the webhook#

webhooks/caravel.php
<?php
use CaravelPay\Checkout;
use CaravelPay\Exception\SignatureVerificationException;
use CaravelPay\Webhook;

try {
    // One secret, or [merchant_id => secret] while old keys are still in use.
    $event = Webhook::verifyCurrentRequest(getenv('CARAVEL_SECRET'), 'https://shop.example/webhooks/caravel');
} catch (SignatureVerificationException $e) {
    http_response_code($e->getHttpStatus()); // 401, or 400 for a malformed event
    exit;
}
if (already_handled($event->id)) {
    http_response_code(200);
    exit;
}
// Re-read the checkout: the webhook says what to look at, the signed API says what is true.
$checkout = $caravel->getCheckout($event->checkoutId());
if (Checkout::isPaid($checkout)) {
    mark_paid($checkout['order_id'], Checkout::txHash($checkout));
}
remember($event->id);
http_response_code(200);

Webhook::verify() checks the timestamp is within 300 seconds and compares the HMAC over POST, the callback path with its query string, and the raw body in constant time. It then checks the event shape. Details: Verify the signature.

Reference#

MethodEndpoint
Client::connect($params)POST /v1/connect, unsigned, never retried
$client->createCheckout($params, ['idempotency_key' => …])POST /v1/checkouts
$client->getCheckout($id)GET /v1/checkouts/{id}
$client->listCheckouts(['limit' => 50, 'cursor' => …]), allCheckouts()GET /v1/checkouts
$client->getMerchant()GET /v1/merchant
$client->createPaymentLink($params), Client::createPaymentLinkWithoutKeys($params)POST /v1/payment-links, signed or without keys
$client->getPaymentLink($id), deactivatePaymentLink($id)GET /v1/payment-links/{id}, POST …/deactivate
Webhook::verify($body, $headers, $secrets, $callbackUrl)Verifies a webhook and returns an Event
Signature::compute(), Signature::signedPath()The signing rules, if you need them directly

Errors are exceptions:

  • ApiException carries getErrorCode(), getHttpStatus(), getParam(), getRetryAfter() and isRetryable(). The codes are listed under Errors.
  • NetworkException means no response arrived.
  • UnexpectedResponseException means a malformed 2xx answer, which is never treated as paid.

To use your platform's HTTP client, implement CaravelPay\Http\TransportInterface.

Coming from PayGate's PHP SDK#

PayGate's SDK builds a payment URL from a wallet-forwarding address. With Caravel Pay you create a checkout per order, redirect to its checkout_url, verify the signed webhook and re-read the checkout before marking the order paid. A short payment comes back as underpaid, so there is no tolerance setting.