Server-side SDK for RideBuilder's FirstParty affiliate program. It does two things:
- Capture the
click_ida shopper arrives with, so your backend can bind it to the cart/order. - Report checkout and return postbacks to RideBuilder (auth, retries, idempotency handled).
Mirrors the Node/.NET/Python SDKs — same contract, verified by the shared conformance suite.
composer require ridebuilder/affiliateRequires PHP 8.1+ and ext-curl (bundled with virtually every PHP). No third-party runtime dependencies —
the default transport uses cURL. To run from source without Composer, require 'sdk/php/autoload.php'.
Capture the click_id on landing, store it with the cart, and send it at purchase.
use RideBuilder\Affiliate\{RideBuilderClient, Capture, CheckoutInput};
// 1. On landing, read a validated click_id off the request URL and persist it onto YOUR cart record.
$clickId = Capture::fromUrl($_SERVER['REQUEST_URI']);
if ($clickId !== null) {
$cart->ridebuilderClickId = $clickId;
}
// 2. At order time, send the postback from your backend.
$rb = new RideBuilderClient(apiKey: getenv('RIDEBUILDER_API_KEY'));
$rb->reportCheckout(new CheckoutInput(
orderId: $order->id,
subtotal: '199.99', // major units; string keeps it exact
currency: 'USD',
clickId: $order->ridebuilderClickId,
));Store the API key server-side (env/secrets) — never in frontend code.
If the frontend is separate, the browser snippet captures the click_id into a first-party cookie, and
you get it to your backend one of two ways:
// Same registrable domain — the cookie rides along; read it off the Cookie header:
$clickId = Capture::fromCookieHeader($_SERVER['HTTP_COOKIE'] ?? null);
// Cross-domain / mobile — the frontend forwards it in the checkout call:
$clickId = Capture::fromHeaders(getallheaders()); // default header: X-RideBuilder-Click-IdEither way, reportCheckout is unchanged — that's the SDK's real value in a decoupled setup.
$rb->reportReturn(new ReturnInput(
returnId: $refund->id, orderId: $order->id, refundAmount: '49.95', currency: 'USD',
));$rb = new RideBuilderClient(apiKey: $apiKey, environment: 'production'); // or 'sandbox'
$reg = $rb->register(); // handshake on install/startup; returns a stable integration id
$rb->verify(); // deploy/CI self-test — throws RideBuilderException on a bad/rotated key
$rb->heartbeat(); // periodic liveness (call from cron; PHP has no persistent process)The SDK reports its own type (php_sdk), version, and default capabilities.
All validate ref == "ridebuilder" and the UUID-v4 click_id, returning null otherwise:
Capture::fromUrl($url)— from an absolute or relative URL.Capture::fromQuery($query)— from a decoded query map.Capture::fromCookieHeader($cookieHeader)— recover it from theridebuilder_attributioncookie.Capture::fromHeaders($headers, $name = 'X-RideBuilder-Click-Id')— from a forwarding header (decoupled path).
new RideBuilderClient(
apiKey: $key,
baseUrl: null, // defaults to https://api.ridebuilder.com/v1
maxRetries: 3, // retries on network errors, timeouts, 5xx, 429
timeoutMs: 10000, // per-attempt timeout
environment: 'production',
transport: null, // inject a RideBuilder\Affiliate\Transport\Transport (e.g. wrap a PSR-18 client)
);reportCheckout / reportReturn return PostbackResult(accepted, status) (202 = accepted, validated
asynchronously). Invalid input throws a non-retryable RideBuilderException; auth/size failures (401,
413) throw with ->status and ->errorCode. Amounts must be > 0 with at most 2 decimal places (pass a
string to avoid float rounding) or the call throws up front.
Plain PHP, no PHPUnit/Composer required:
php tests/conformance.php # the shared cross-language fixtures
php tests/unit.php # validation, capture, money, retry/error, identityWraps the RideBuilder affiliate REST contract — POST /v1/postback/checkout, /postback/return,
/postback/health, the /integration/* endpoints, the /redirect link format, and API-key provisioning.
Verified byte-for-byte against the Node/.NET/Python SDKs by the shared conformance fixtures.