Download the PHP package qbitflow/qbitflow-php without Composer

On this page you can find all versions of the php package qbitflow/qbitflow-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package qbitflow-php

QBitFlow PHP SDK

License: MPL-2.0

Official PHP SDK for QBitFlow โ€” non-custodial cryptocurrency payment processing and on-chain subscriptions. Feature-equivalent to the Python and JavaScript SDKs.

Works in any PHP project, with first-class Laravel integration.

Features

Table of Contents

Requirements

Installation

Laravel

That's the whole install. Laravel's HTTP client depends on Guzzle, which satisfies the PSR-18 and PSR-17 requirements, so nothing else is pulled in โ€” the SDK is the only package added. The service provider and QBitFlow facade register themselves through package discovery; there is nothing to add to config/app.php or bootstrap/providers.php.

Then run the installer and check your key:

Everywhere else

The SDK speaks PSR-18, so it uses whatever HTTP client your project already has. If you don't have one, install Guzzle alongside it:

composer.json requires psr/http-client-implementation and psr/http-factory-implementation, so if your project has no implementation at all Composer refuses the install and names what's missing โ€” rather than letting it fail later on the first API call. Guzzle, Symfony HTTP Client, Nyholm, Laminas Diactoros and Slim PSR-7 are all detected automatically.

Quick Start

1. Get your API key

Sign up at QBitFlow and copy your API key from the dashboard. A test key keeps every action on blockchain testnets, with data kept entirely separate from live mode.

2. Create a client

In Laravel, skip this โ€” set QBITFLOW_API_KEY in .env and resolve the client from the container or the facade instead. See Laravel Integration.

3. Take a payment

Webhook URLs are configured in the dashboard, under Settings โ†’ Webhooks, with separate Test and Live endpoints. They can no longer be set per session. See Webhooks.

4. Start a subscription

5. Check where a transaction stands

Configuration

Argument Type Default Description
$apiKey string (required) Your QBitFlow API key
$baseUrl string https://api.qbitflow.app/v1 API base URL; also read from QBITFLOW_BASE_URL
$timeout float 30 Request timeout in seconds
$maxRetries int 3 Retry attempts for server and network failures
$httpClient ClientInterface auto-discovered Your own PSR-18 client

โš ๏ธ timeout is in seconds, unlike the JavaScript SDK, which uses milliseconds. PHP HTTP clients work in seconds, so this one does too.

Bring your own HTTP client

Pass any PSR-18 client and the SDK will use it as-is. Configure the timeout on that client โ€” the SDK's $timeout only applies to a client it builds itself.

Set 'http_errors' => false on a Guzzle client you supply: the SDK classifies non-2xx responses itself and needs to see them.

Laravel Integration

The service provider and facade register themselves through package discovery โ€” there is nothing to add to config/app.php or bootstrap/providers.php.

Set up

This publishes config/qbitflow.php, adds a QBITFLOW_API_KEY placeholder to .env and .env.example if they don't have one, and prints what to do next. It never overwrites a key you have already set, so it is safe to re-run.

You can also do it by hand โ€” the only thing the SDK truly needs is the key:

Check it works

It calls GET /user and reports who the key belongs to, its role, and your organization โ€” so you find out now, rather than on your first checkout. It distinguishes a rejected key from an unreachable API, and warns you if the key is user-level (which means onBehalfOf() will 403). Handy after rotating keys, and in CI.

Use it

Inject the client wherever you need it:

Or use the facade:

Every service is reachable both as a property ($client->products) and as a method ($client->products()); the facade forwards to the method form.

Supplying your own HTTP client

Bind a PSR-18 client in the container and the SDK uses it instead of auto-detecting one โ€” useful for an outbound proxy, request logging, or your own retry middleware:

PSR-17 factories are picked up from the container the same way (RequestFactoryInterface, StreamFactoryInterface). Bind nothing and the SDK detects Guzzle on its own.

Testing

Swap the client for one backed by a mock transport, and no test touches the network:

Acting on Behalf of a User

With an organization (admin or owner) API key you can run any request as one of your users, without storing a key per user. Funds route to that user's wallet and your platform fee is applied, exactly as if you had used their own key.

Every service exposes onBehalfOf(). It returns a scoped copy โ€” your base client keeps operating at the organization level.

Requires an admin- or owner-level key. A regular user key gets a 403 (ForbiddenException).

One-Time Payments

Create a session

Identify the product in one of three ways:

Use your own identifiers

Rather than storing QBitFlow's UUIDs, pass your own. Set reference to your order or invoice ID; use productReference and customerReference to select an existing product or customer by your identifier. If no customer matches, one is created during checkout.

reference comes back on the resulting Payment and in webhook payloads.

Read payments

Subscriptions

A subscription always bills against an existing product, so supply either productId or productReference.

Duration accepts seconds, minutes, hours, days, weeks, months and years, via named constructors (Duration::months(1)) or directly (new Duration(1, DurationUnit::MONTHS)).

Manage subscriptions

Transaction Status

The API also exposes a status WebSocket. This SDK does not wrap it โ€” a long-lived socket has no place in a typical PHP request. Use webhooks, which are the recommended way to learn that a payment settled, or poll the method above.

Webhooks

Verifying a webhook signature

Every webhook QBitFlow sends carries three headers:

Header Meaning
X-Webhook-Signature-256 HMAC signature, formatted sha256=<hex>
X-Webhook-Timestamp Send time, in unix seconds
X-Webhook-Id Transaction id, e.g. pay@<uuid>

There are two ways to check a webhook is genuine, and you can use either:

Needs the secret Network call Use when
Local yes none Default. Faster, and keeps working if the API is unreachable.
Remote no one per webhook You would rather not hold the secret at all.

Local verification performs the same three checks the server does: the timestamp is within a replay window (5 minutes by default), the HMAC matches, and the comparison is constant-time so a timing side channel cannot be used to guess the signature.

Why the signature covers a canonical rendering, not the raw bytes. JSON object key order is not significant, and proxies, frameworks and logging layers routinely re-serialize a body and reorder keys. Signing raw bytes would reject a payload that is in fact untouched. So both sides sign <timestamp>.<canonical-json>, where canonical means keys sorted at every level and no insignificant whitespace. You do not have to do anything for this โ€” pass the body you received and the SDK handles it.

Get your webhook secret from the QBitFlow dashboard. Treat it like a password: keep it in your environment or secret manager, never in source control.

extractHeaders() takes any array of headers, so it works with $_SERVER (where PHP exposes them as HTTP_X_WEBHOOK_*), getallheaders(), a PSR-7 $request->getHeaders(), or Laravel's $request->headers->all(). Lookup is case-insensitive and tolerates the HTTP_ prefix and underscore spelling.

To widen or narrow the replay window (it must match the server's setting), pass it as the fifth argument:

To verify through the API instead, with no secret in your process:

Configure your endpoints in the dashboard under Settings โ†’ Webhooks. There are two, each with separate Test and Live URLs:

Every delivery carries X-Webhook-Signature-256, X-Webhook-Timestamp and X-Webhook-ID. Always verify before acting, and always answer 200 โ€” anything else makes QBitFlow retry.

In Laravel

Register the routes, and everything above is handled for you:

Put these in routes/api.php. If you prefer routes/web.php, exclude the paths from CSRF protection โ€” QBitFlow does not send a CSRF token.

Each route verifies the signature, answers the dashboard's "Test the endpoint" probe automatically, and dispatches a typed event. Listen for the ones you care about:

Queue your listeners. The route answers 200 as soon as the event is dispatched, so slow work in a synchronous listener risks a timeout and a redelivery.

To verify on a route of your own, apply the middleware directly:

Outside Laravel

Pass the raw body to verify(). Decoding and re-encoding it reorders keys and invalidates the signature.

verify() returns false only when QBitFlow rejects the signature. A network or server failure is rethrown instead, so an outage is never mistaken for a forgery โ€” let it bubble, answer non-200, and the delivery is retried.

Customers

Products

Prices are in USD; QBitFlow converts to crypto at checkout using live rates.

Users

Most of these require an admin or owner key.

No password is set at creation โ€” users set their own through the claim flow.

API Keys

Read-only. Creating and deleting keys requires a dashboard session and cannot be done with an API key; manage them in the dashboard.

Currencies

Public endpoints. Use them to resolve the currency IDs in availableCurrencies on a session, and in currencyId on payments and subscriptions.

Refunds

Accounting Export

export($from, $to, $format) matches the other SDKs and returns either shape; exportJson() and exportCsv() are the same call with a single, definite return type.

Token amounts (grossAmount, netAmount, fees) are decimal strings so no precision is lost; the matching โ€ฆUsd fields are floats.

Claims

Create users whose earnings your organization holds initially. When you are ready, raise a claim request: the user follows the link, sets a password, connects a wallet, and their funds become transferable.

Pagination

List endpoints that can grow return a CursorData page, which is countable and iterable.

Error Handling

Every exception extends QBitFlowException, so one catch covers the SDK.

Exception Raised on
ValidationException 400, and local validation before a request is sent
UnauthorizedException 401 โ€” invalid or missing API key
ForbiddenException 403 โ€” key not allowed to perform the request
NotFoundException 404
RateLimitException 429 โ€” see getRetryAfter()
ServerException 5xx, once retries are exhausted
NetworkException connection failures, DNS errors, timeouts

Retries. Server (5xx) and network failures are retried up to maxRetries times, with the delay growing on each attempt (1s, 2s, 3sโ€ฆ). Client errors (4xx) are never retried โ€” repeating them would not help. Rate limits are not retried automatically either; back off on your own schedule using getRetryAfter().

Coming from the Python or JavaScript SDK

The surface is the same; these are the deliberate differences.

Examples

Runnable examples live in examples/:

Testing

The suite runs against a mock PSR-18 client, so nothing touches the network. To test your own code against the SDK, inject a mock client the same way:

License

TRADEMARKS.md for brand usage, COMPLIANCE.md for compliance posture.

Support


All versions of qbitflow-php with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
ext-json Version *
psr/http-client Version ^1.0
psr/http-client-implementation Version ^1.0
psr/http-factory Version ^1.0
psr/http-factory-implementation Version ^1.0
psr/http-message Version ^1.1 || ^2.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package qbitflow/qbitflow-php contains the following files

Loading the files please wait ...