PHP code example of qbitflow / qbitflow-php

1. Go to this page and download the library: Download qbitflow/qbitflow-php library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

qbitflow / qbitflow-php example snippets


use QBitFlow\QBitFlow;

$client = new QBitFlow('your-api-key');

use QBitFlow\Dto\Session\CreatePaymentSessionDto;

$payment = $client->oneTimePayments->createSession(new CreatePaymentSessionDto(
    productId: 1,
    customerUUID: 'customer-uuid',
    successUrl: 'https://example.com/success',
    cancelUrl: 'https://example.com/cancel',
));

// Send this link to your customer
echo $payment->link;

use QBitFlow\Dto\Session\CreateSubscriptionSessionDto;
use QBitFlow\Support\Duration;

$subscription = $client->subscriptions->createSession(new CreateSubscriptionSessionDto(
    frequency: Duration::months(1),     // bill monthly
    productId: 1,
    trialPeriod: Duration::days(7),     // optional 7-day trial
    customerUUID: 'customer-uuid',
));

echo $subscription->link;

use QBitFlow\Enums\TransactionType;

$status = $client->transactionStatus->get('transaction-uuid', TransactionType::ONE_TIME_PAYMENT);

if ($status->isCompleted()) {
    echo 'Paid. Transaction hash: ', $status->txHash;
} elseif ($status->isFailed()) {
    echo 'Not paid: ', $status->message;
}

$client = new QBitFlow(
    apiKey: 'your-api-key',
    timeout: 10.0,
    maxRetries: 5,
);

$client = new QBitFlow(
    apiKey: 'your-api-key',
    httpClient: new GuzzleHttp\Client(['timeout' => 5, 'http_errors' => false]),
);

use QBitFlow\QBitFlow;

final class CheckoutController
{
    public function __construct(private readonly QBitFlow $qbitflow) {}

    public function store(Request $request)
    {
        $payment = $this->qbitflow->oneTimePayments->createSession(new CreatePaymentSessionDto(
            reference: $request->user()->currentOrder()->id,
            productId: 1,
        ));

        return redirect($payment->link);
    }
}

use QBitFlow\Laravel\Facades\QBitFlow;

$products = QBitFlow::products()->getAll();

// AppServiceProvider::register()
$this->app->bind(\Psr\Http\Client\ClientInterface::class, fn () => new \GuzzleHttp\Client([
    'timeout' => 15,
    'proxy' => config('services.proxy'),
    'http_errors' => false,   // 

$this->app->instance(QBitFlow::class, new QBitFlow('test-key', httpClient: $mockPsr18Client));

$userId = 123;

// This user's products
$products = $client->products->onBehalfOf($userId)->getAll();

// A checkout credited to this user
$payment = $client->oneTimePayments->onBehalfOf($userId)->createSession(
    new CreatePaymentSessionDto(productId: 1),
);

// Unaffected — still organization-level
$allProducts = $client->products->getAll();

// 1. By ID
$payment = $client->oneTimePayments->createSession(new CreatePaymentSessionDto(
    productId: 1,
    customerUUID: 'customer-uuid',
));

// 2. By your own product reference
$payment = $client->oneTimePayments->createSession(new CreatePaymentSessionDto(
    productReference: 'PROD-PREMIUM',
    customerReference: 'user-42',
));

// 3. Inline, with no stored product
$payment = $client->oneTimePayments->createSession(new CreatePaymentSessionDto(
    productName: 'Custom Product',
    description: 'One-off charge',
    price: 99.99,               // USD
));

echo $payment->uuid;   // session UUID
echo $payment->link;   // send this to the customer

$payment = $client->oneTimePayments->createSession(new CreatePaymentSessionDto(
    reference: 'order-1234',
    productReference: 'PROD-PREMIUM',
    customerReference: 'user-42',
));

// Later, with nothing of QBitFlow's stored on your side
$settled = $client->oneTimePayments->getByReference('order-1234');

$payment  = $client->oneTimePayments->get('payment-uuid');
$payment  = $client->oneTimePayments->getByReference('order-1234');
$session  = $client->oneTimePayments->getSession('session-uuid');
$customer = $client->oneTimePayments->getCustomerForTransaction('transaction-uuid');

$page = $client->oneTimePayments->getAll(limit: 20);

// One-time payments and subscription billings in one feed
$combined = $client->oneTimePayments->getAllCombined(limit: 20);

foreach ($combined as $entry) {
    echo $entry->isSubscriptionBilling() ? 'renewal' : 'one-off', ': ', $entry->amount, PHP_EOL;
}

use QBitFlow\Support\Duration;

$subscription = $client->subscriptions->createSession(new CreateSubscriptionSessionDto(
    frequency: Duration::months(1),
    productId: 1,
    trialPeriod: Duration::days(7),
    minPeriods: 3,                      // the subscriber commits to 3 periods
    customerUUID: 'customer-uuid',
));

$subscription = $client->subscriptions->get('subscription-uuid');
$subscription = $client->subscriptions->getByReference('sub-1234');

echo $subscription->subscriptionStatus->value;   // active, past_due, trial, …
echo $subscription->nextBillingDate->format('Y-m-d');
echo $subscription->allowance;                   // remaining on-chain allowance, USD

$history = $client->subscriptions->getPaymentHistory('subscription-uuid');

// Cancel immediately, bypassing the usual signed-cancellation flow
$client->subscriptions->forceCancel('subscription-uuid');

// Run a billing cycle now — test-mode subscriptions only
$client->subscriptions->executeTestBilling('subscription-uuid');

use QBitFlow\Enums\TransactionType;
use QBitFlow\Enums\TransactionStatusValue;

$status = $client->transactionStatus->get($uuid, TransactionType::ONE_TIME_PAYMENT);

match (true) {
    $status->isCompleted() => handlePaid($status->txHash),
    $status->isFailed()    => handleFailed($status->message),
    default                => handlePending(),
};

use QBitFlow\Exceptions\ValidationException;
use QBitFlow\Webhooks\WebhookVerifier;

$headers = WebhookVerifier::extractHeaders($_SERVER);
$body = file_get_contents('php://input');

if ($headers['isTest']) {
    http_response_code(200); // connectivity check, nothing to process
    exit;
}

try {
    WebhookVerifier::verify(
        getenv('QBITFLOW_WEBHOOK_SECRET'),
        $headers['timestamp'],
        $headers['signature'],
        $body,
    );
} catch (ValidationException $e) {
    http_response_code(400);
    exit;
}

$event = json_decode($body, true);
http_response_code(200);

// Laravel
public function handle(Request $request)
{
    $headers = WebhookVerifier::extractHeaders($request->headers->all());

    try {
        WebhookVerifier::verify(
            config('services.qbitflow.webhook_secret'),
            $headers['timestamp'],
            $headers['signature'],
            $request->getContent(),
        );
    } catch (ValidationException $e) {
        abort(400);
    }

    // ...
}

WebhookVerifier::verify($secret, $timestamp, $signature, $body, 600);

$ok = $client->webhooks->verify($payload, $signature, $timestamp);

// routes/api.php
Route::qbitflowTransactionWebhook('/webhooks/qbitflow/transaction');
Route::qbitflowSubscriptionWebhook('/webhooks/qbitflow/subscription');

use QBitFlow\Laravel\Events\SubscriptionBilled;
use QBitFlow\Laravel\Events\SubscriptionStatusChanged;
use QBitFlow\Laravel\Events\TransactionWebhookReceived;

class MarkOrderPaid implements ShouldQueue
{
    public function handle(TransactionWebhookReceived $event): void
    {
        $order = Order::where('id', $event->reference())->firstOrFail();

        $event->isSubscription()
            ? $order->startSubscription($event->payload->session->uuid)
            : $order->markPaid($event->payload->status->txHash);
    }
}

class RecordRenewal
{
    public function handle(SubscriptionBilled $event): void
    {
        Renewal::create([
            'subscription_uuid' => $event->billing->subscriptionUUID,
            'amount' => $event->billing->amount,
            'tx_hash' => $event->billing->transactionHash,
        ]);
    }
}

class ReactToStatusChange
{
    public function handle(SubscriptionStatusChanged $event): void
    {
        if ($event->transition->currentStatus === SubscriptionStatus::PAST_DUE) {
            // nudge the customer
        }
    }
}

Route::post('/hooks/qbitflow', MyController::class)->middleware('qbitflow.webhook');

$raw = file_get_contents('php://input');
$webhookId = $_SERVER['HTTP_X_WEBHOOK_ID'] ?? null;

// The dashboard's "Test the endpoint" probe carries fake data
if ($client->webhooks->isTestWebhook($webhookId)) {
    http_response_code(200);
    exit;
}

$valid = $client->webhooks->verify(
    $raw,
    $_SERVER['HTTP_X_WEBHOOK_SIGNATURE_256'] ?? '',
    $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '',
);

if (! $valid) {
    http_response_code(400);
    exit;
}

$event = SessionWebhookResponse::fromArray(json_decode($raw, true));

http_response_code(200);

use QBitFlow\Dto\CreateCustomerDto;
use QBitFlow\Dto\UpdateCustomerDto;

$customer = $client->customers->create(new CreateCustomerDto(
    name: 'John',
    lastName: 'Doe',
    email: '[email protected]',
    phoneNumber: '+1234567890',
    reference: 'CRM-12345',
));

$customer = $client->customers->get('customer-uuid');
$customer = $client->customers->getByEmail('[email protected]');
$customer = $client->customers->getByReference('CRM-12345');

$page = $client->customers->getAll(limit: 50);

// Only the fields you set are sent; everything else is left untouched.
// Note: `reference` is immutable and cannot be updated.
$customer = $client->customers->update('customer-uuid', new UpdateCustomerDto(
    email: '[email protected]',
));

$client->customers->delete('customer-uuid');

use QBitFlow\Dto\CreateProductDto;
use QBitFlow\Dto\UpdateProductDto;

$product = $client->products->create(new CreateProductDto(
    name: 'Premium Plan',
    description: 'Access to all premium features',
    price: 29.99,
    reference: 'PROD-PREMIUM',
));

$product  = $client->products->get(1);
$product  = $client->products->getByReference('PROD-PREMIUM');
$products = $client->products->getAll();

// All three fields replace the current values
// Partial update: omitted fields keep their current value
$product = $client->products->update(1, new UpdateProductDto(price: 39.99));

$product = $client->products->update(1, new UpdateProductDto('Premium Plus', 'More features', 39.99));

$client->products->delete(1);

use QBitFlow\Dto\CreateUserDto;
use QBitFlow\Dto\UpdateUserDto;
use QBitFlow\Enums\UserRole;

$user = $client->users->create(new CreateUserDto(
    name: 'Jane',
    lastName: 'Smith',
    email: '[email protected]',
    role: UserRole::USER,
    organizationFeeBps: 100,        // 1%
));

$me    = $client->users->get();     // the user this API key belongs to
$user  = $client->users->getById(5);
$user  = $client->users->getByEmail('[email protected]');
$users = $client->users->getAll();

// Partial update: omitted fields keep their current value
$client->users->update(5, new UpdateUserDto(name: 'Jane'));

// organizationFeeBps 

$keys = $client->apiKeys->getAll();
$keys = $client->apiKeys->getForUser(42);      // admin or owner only

$currencies = $client->currencies->getAllAvailable();       // native currencies and tokens
$chains     = $client->currencies->getAllMain();            // one per chain, no tokens
$testnets   = $client->currencies->getAllAvailable(test: true);

foreach ($currencies as $currency) {
    printf("%d: %s (%s)%s\n", $currency->id, $currency->name, $currency->symbol,
        $currency->isToken() ? ' — token' : '');
}

$refund = $client->refunds->getByTransaction('transaction-uuid');   // public endpoint
$active = $client->refunds->getAll();                               // awaiting a decision
$page   = $client->refunds->getAllInactive(limit: 20);              // resolved

echo $refund->status->value;   // pending, approved, refused, failed

$events = $client->accounting->exportJson('2026-01-01', '2026-01-31');

foreach ($events as $event) {
    printf("%s | %s | $%.2f net\n", $event->paymentId, $event->type->value, $event->netAmountUsd);
}

file_put_contents('export.csv', $client->accounting->exportCsv('2026-01-01', '2026-01-31'));

$claim = $client->claims->createRequest(42);
// Send $claim->link to the user

$claim = $client->claims->getRequestByUser(42);   // resend an existing link

foreach ($client->claims->getFunds() as $fund) {
    printf("User %d is owed $%.2f (funded: %s)\n",
        $fund->userId, $fund->totalAmountOwed, $fund->funded ? 'yes' : 'no');
}

// Test mode: compute now instead of waiting for the hourly job
$client->claims->triggerTestClaimFunds(42);

$cursor = null;

do {
    $page = $client->oneTimePayments->getAll(limit: 50, cursor: $cursor);

    foreach ($page as $payment) {
        echo $payment->uuid, PHP_EOL;
    }

    $cursor = $page->nextCursor;
} while ($page->hasMore());

use QBitFlow\Exceptions\NotFoundException;
use QBitFlow\Exceptions\QBitFlowException;
use QBitFlow\Exceptions\RateLimitException;

try {
    $payment = $client->oneTimePayments->get($uuid);
} catch (NotFoundException) {
    return null;
} catch (RateLimitException $e) {
    sleep($e->getRetryAfter() ?? 60);
} catch (QBitFlowException $e) {
    Log::error('QBitFlow request failed', [
        'message' => $e->getMessage(),
        'status' => $e->getStatusCode(),
        'response' => $e->getResponse(),
    ]);
    throw $e;
}

$client = new QBitFlow('test-key', httpClient: $yourMockPsr18Client);
bash
composer 
bash
composer 
bash
php artisan qbitflow:install
bash
php artisan vendor:publish --tag=qbitflow-config
bash
php artisan qbitflow:verify