Accept crypto payments with PHP

Create crypto deposit addresses and verify TrezorPay callbacks in plain PHP.

Plain PHP 8 with the openssl and curl extensions; no framework or SDK needed.

Create a payment address

create_address.php
<?php
function createAddress(string $ticker, int $orderId, string $wallet): array {
    $query = http_build_query([
        'callback' => "https://shop.example/paid?order={$orderId}",
        'address' => $wallet,
        'pending' => 1,
    ]);
    $body = json_decode(file_get_contents("https://api.trezorpay.com/{$ticker}/create/?{$query}"), true);
    if (($body['status'] ?? '') !== 'success') {
        throw new RuntimeException($body['error'] ?? 'Unknown error');
    }
    return $body; // address_in, minimum_transaction_coin, ...
}

Receive and verify the callback

paid.php
<?php
$pubkey = json_decode(file_get_contents('https://api.trezorpay.com/pubkey/'), true)['pubkey'];

$url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$signature = base64_decode($_SERVER['HTTP_X_CA_SIGNATURE'] ?? '');

if (openssl_verify($url, $signature, $pubkey, OPENSSL_ALGO_SHA256) !== 1) {
    http_response_code(401);
    exit;
}

if (($_GET['pending'] ?? '') === '0') {
    $order = $_GET['order'];
    $amount = $_GET['value_forwarded_coin'];
    // mark the order paid, once per $_GET['uuid']
}

echo '*ok*';

Cache the public key instead of fetching it on every request. For post=1 callbacks, verify file_get_contents('php://input') instead of the URL.

On this page