Search by

lacasoft / coatipay-sdk

lacasoft

CoatiPay PHP SDK — the open payment network

v0.1.2 2026-08-31 23:07 UTC

README

The CoatiPay PHP SDK — Stripe-compatible payments for the open web. Accept USDC on Base with no gatekeepers: gasless settlement (ERC-3009), webhooks, and x402 micropayments. 1.5% protocol fee (1.05% nodeit / 0.45% treasury), settled trustlessly on-chain.

  • ⛽ Gasless for payers — they sign an ERC-3009 authorization; the nodeit pays the gas.
  • 🧩 Stripe-like DX — paymentIntents->create(...), webhooks->verify(...).
  • 🌐 Open network — no lock-in: any nodeit can settle your payments, and anyone can run one.

Install

composer require lacasoft/coatipay-sdk

Requires PHP ≥ 8.1. Depends on guzzlehttp/guzzle.

Quick start

<?php

require 'vendor/autoload.php';

use CoatiPay\CoatiPay;

// Use a SECRET key, server-side only — never ship it to a client.
$relay = new CoatiPay('sk_live_...');

$intent = $relay->paymentIntents->create(
    amount:   10_000_000,           // 10.00 USDC (6 decimals → 1 USDC = 1_000_000)
    currency: 'usdc',
    chain:    'base',
    metadata: ['order_id' => '123'],
);

echo $intent['id'], ' ', $intent['status'];  // "pi_…", "created"

Other payment-intent methods: retrieve($id), list($limit = 10, $startingAfter = null), cancel($id).

Gasless settlement with ERC-3009

Payers authorize USDC transfers off-chain with an EIP-712 signature. The nodeit pays the gas to settle on-chain.

use CoatiPay\Eip712;

$auth = Eip712::signAuthorization(
    payer:    '0xPayerAddress...',
    amount:   1_000_000,                       // 1.00 USDC
    settlementHub: '0xSettlementHubAddress...',
    chain:    'base',
    intentId: $intent['id'],                    // the "pi_…" the API returned — becomes the nonce
    privateKey: '0x...',                        // payer private key — server-side demo only
);

$relay->paymentIntents->submitAuthorization($intent['id'], $auth);

intentId is required: the authorization's ERC-3009 nonce is that intent. The SettlementHub enforces nonce == keccak256(utf8(intentId)), so a signature can only ever pay the intent it was signed for — the nodeit that submits the transaction cannot redirect it to a different intent.

Pass the plain pi_… id: the SDK derives the on-chain bytes32 for you, so there is no hash to get wrong. If you build the typed data yourself, derive it with the same helper the SDK uses:

$nonce = Eip712::intentIdToBytes32('pi_abc123'); // 0x… (32 bytes)

For batch settlement, pass a list of ['intent_id' => ..., 'authorization' => $auth] items to $relay->paymentIntents->submitAuthorizationBatch($items) (max 50 per batch).

x402 micropayments

Protect a route with a PSR-15 middleware that returns 402 Payment Required when the X-PAYMENT header is missing or invalid.

use CoatiPay\X402\X402Middleware;

$relay = new CoatiPay('sk_live_...', merchantWallet: '0xMerchantWallet...');

$app->add(new X402Middleware($relay, [
    'price'       => 1_000,     // 0.001 USDC
    'currency'    => 'usdc',
    'chain'       => 'base',
    'description' => 'Premium API access',
]));

Webhooks

$event = $relay->webhooks->verify(
    $payload,                                   // raw request body (string)
    $_SERVER['HTTP_X_SIGNATURE'],       // X-Signature header
    'whsec_...',
);

if ($event['type'] === 'payment_intent.settled') {
    fulfillOrder($event['data']['metadata']['order_id']);
}

verify() checks the HMAC-SHA256 signature and rejects payloads whose timestamp is older than 5 minutes (replay protection). It throws \InvalidArgumentException on any mismatch.

Configuration

$relay = new CoatiPay(
    apiKey:         'sk_live_...',                  // required — secret key, server-side only
    baseUrl:        'https://api.coatipay.com',   // optional — your CoatiPay API host
    timeout:        30.0,                           // optional — seconds
    merchantWallet: '0x...',                         // optional — receives x402 payments
);

Economics

The protocol fee is 1.5% (1.05% nodeit / 0.45% treasury), settled on-chain. The API enforces a minimum payment floor (~$0.30) — intents below it are rejected, because around that point the protocol fee stops covering settlement gas reliably, even when batched. Sub-cent x402 micropayments are on the roadmap via off-chain netting (aggregating many tiny payments into one on-chain settlement).

Links