Download the PHP package comfino/php-api-client without Composer

On this page you can find all versions of the php package comfino/php-api-client. 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 php-api-client

ComfinoPay PHP API client

Latest Version PHP Version Build Status Total Downloads API Documentation

ComfinoPay PHP API client library

A portable, PSR-compliant PHP protocol layer for the ComfinoPay payment gateway REST API. This library handles all HTTP communication with the ComfinoPay API: creating and managing loan applications (orders), querying available financial products, verifying webhook signatures, and generating paywall iframe authentication tokens for the shop checkout page. It imposes no concrete HTTP client, serializer, or framework dependency — bring your own PSR-18 client and PSR-17 factories.

Features

Requirements

Installation

Suggested companion packages:

Quick start

The API key is issued by ComfinoPay when your shop signs a merchant contract. It authenticates all server-to-server API calls and must be kept secret — never expose it in frontend code, browser requests, or public repositories.

Usage

Client configuration

Plain HTTP for local development

Cleartext http:// is refused by default, including for private IPs and Docker service names: the API key travels as a request header, so an http destination hands it to anyone on the path. It is enabled by COMFINO_DEV_ENV — the same server-set variable the ComfinoPay plugins already gate their dev overrides on:

With it set, http://localhost:8080, http://comfino-api and http://shop.test become valid destinations. It never widens the host allowlist — a public IP or a spoofed domain stays refused — and the real API always requires HTTPS. Do not set it in production.

Querying financial products

Order management

See request-signing.md for details on how request signatures are computed automatically for order creation.

Shop owner registration

createUser() and fetchAgreements() are the one pair of calls made before an API key exists — construct the client with a null key (or, for SharedClient, an ApiContext whose apiKey is ''):

A shop already registered under webSiteUrl throws Comfino\Api\Exception\Conflict (HTTP 409); its message carries the field-level reason from the API.

Account and widget

The widget key is a public identifier associated with the ComfinoPay merchant account pointed to by the API key. Unlike the API key, it is safe to embed in frontend scripts — it is used by the ComfinoPay Web Frontend SDK to render the promotional banner widget and the paywall iframe at the shop checkout page.

Notifications (fire-and-forget)

These methods catch all exceptions internally and return bool. They are safe to call without a try/catch block.

Webhook signature verification

ComfinoPay signs status-update webhook requests with a CR-Signature header. Verify it before processing:

See webhook-verification.md for comprehensive webhook handling patterns, including framework integration, multiple API keys, replay attack prevention, and troubleshooting.

Paywall authentication token

The ComfinoPay paywall iframe embedded at the shop checkout page requires a short-lived signed token. Generate one server-side per page render using the public widget key and the private API key, then pass only the resulting token to the frontend — the API key never leaves the server:

Tokens are valid for 15 minutes (enforced server-side).

Serving many merchants from one process

Comfino\Api\Client holds one merchant's credentials as mutable state, which is right for a shop plugin and wrong for a long-lived service that handles many merchants in sequence. For that, use SharedClient: it stores no credential at all, so a single instance — one transport, one connection pool, one retry executor — can serve every tenant.

Keep the PSR-18 transport shared. The credential is a header, not a connection property, so one TLS pool serving every tenant is both safe and the point — giving each merchant its own transport costs a handshake per merchant per request.

Already have code written against the mutable surface? SharedClient::bind($context) returns a BoundClient implementing the same ClientInterface, one binding per tenant, with the credential still off anything shared.

Retry, backoff and timeout escalation

Wrap the client with a RetryExecutor to retry transient failures with exponentially growing, jittered delays:

Two schedules grow per attempt, and they answer different failures. The timeout doubles, which is the right answer to a slow far side. The delay doubles with full jitter, which is the right answer to a refused connection — and to not turning every tenant on a node into one synchronized retry wave. Both are bounded: the escalation by maxTotalTransferTimeout, the delay by maxDelayMs. They bound different clocks, so getWorstCaseWallClockMs() reports the sum, which is the number to size a request latency budget against.

On a path that cannot absorb a sleep, say so rather than sleeping in it:

Retryable failures are transport errors, HTTP 429, 502, 503 and 504, plus 500 for requests that are safe to replay. A Retry-After header is honored in both of its RFC 9110 forms and clamped, so a wrong header cannot park a worker.

Order creation is safe to retry and needs no idempotency key. The API deduplicates a replayed POST /orders by orderId — mandatory, and unique per shop — plus the hash of the request body: a request for an id that already exists with the same body is answered with the existing order at 201 Created rather than creating a second loan application, and a differing body under the same id is rejected as a validation error. The one thing this asks of a caller is not to vary the body between attempts; the client builds each request once and reuses it across attempts, so that holds automatically.

If you write a Request of your own against an endpoint with no such key, say so and it will be sent exactly once:

For per-request timeouts to reach the wire, the transport has to accept them. Implement TimeoutConfigurableClientInterface::withTimeouts(), which returns a configured copy, or wrap a transport whose timeouts are construction options:

The older TimeoutAwareClientInterface::updateTimeouts() is still honored, but it mutates the transport in place and never restores it — on transport shared between tenants, one tenant's escalated budget stays applied to the next tenant's call. Prefer the copy-returning interface.

Circuit breaker and outbound rate limiting

Both are optional and off by default. A breaker stops a ComfinoPay outage from becoming your outage: instead of every worker paying the full timeout on a dead socket, calls fail immediately once a host looks unhealthy.

The limiter is keyed by (tenantKey, endpoint) through RateLimitKey, which drops the query string before building the key: without that, GET /financial-products?loanAmount=130000 and ?loanAmount=130100 are separate buckets, and the endpoint an integration calls most — with the cart total in the query — is the one the limit never reaches. Scheme, host and path are kept, so a merchant's sandbox traffic does not spend its production budget.

The breaker is keyed by (tenantKey, host), and only transport failures and 5xx feed it: one merchant's wrong API key produces 401s, and a breaker opened by those would block every healthy merchant on the same host. The limiter is non-blocking by contract — what happens on rejection is a call-site decision:

Pass a shared store to either one (both take a store interface) when several workers need to agree on what they have learned; the in-memory defaults are per process.

A shared store needs a compare-and-swap to be exact. Reserving a token is a read-modify-write, so two workers over a plain TokenBucketStoreInterface both read the same bucket and the second write erases the first — the limiter then admits one burst per worker. Implement AtomicTokenBucketStoreInterface (and AtomicCircuitBreakerStoreInterface) instead: the limiter switches to a bounded swap loop, and the breaker uses the swap to let exactly one worker claim the half-open probe rather than all of them. TokenBucketRateLimiter::isExact() and CircuitBreaker::isExact() report which path a given wiring took, so it can be asserted in a test — a shared store that cannot swap looks identical to one that can, right up to the load that breaks it. comfino/php-sdk ships PSR-6 implementations of the plain interfaces (Psr6TokenBucketStore, Psr6CircuitBreakerStore) for hosts that want shared state without writing the serialization; PSR-6 itself has no swap, so read their docblocks on which of the two costs that leaves you with.

Observing requests and retries

Implement RequestObserverInterface or RetryObserverInterface to emit per-tenant metrics without patching anything. Both receive the tenant, so nothing has to be inferred:

Custom requests

Call an endpoint that doesn't have a dedicated client method yet with sendCustomRequest(). It reuses the same authentication, track ID, and error-mapping infrastructure as every built-in method:

For a typed response, pass your own Response subclass (see src/Api/Response/GetProductTypes.php for a minimal example) as the second argument:

Error handling

All API errors are thrown as typed exceptions that implement HttpErrorExceptionInterface and preserve the original request and response bodies for debugging:

HTTP status Exception Description
400 Comfino\Api\Exception\RequestValidationError Invalid request data.
401 Comfino\Api\Exception\AuthorizationError Missing or invalid API key.
403 Comfino\Api\Exception\Forbidden Permission issues.
404 Comfino\Api\Exception\NotFound Resource not found.
405 Comfino\Api\Exception\MethodNotAllowed HTTP method not allowed.
409 Comfino\Api\Exception\Conflict Resource state conflict.
5xx Comfino\Api\Exception\ServiceUnavailable Server-side error.
timeout/retry exhausted Comfino\Api\Exception\ConnectionTimeout HTTP client timeout or all retry attempts failed.

Development

The bin/ wrappers delegate to Docker containers when docker-compose is available, or fall back to the host PHP. Two containers are used:

PSR standards

Changelog

See CHANGELOG for recent changes.

License

BSD 3-Clause License. See LICENSE for details.

Support

Bug reports and feature requests: GitHub issue tracker.

Contributing

The GitHub repository is a read-only public mirror that receives automated clean-snapshot releases. Please report bugs and suggest improvements via the issue tracker.


All versions of php-api-client with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
ext-json Version *
ext-sodium Version *
ext-zlib Version *
psr/http-client Version ^1.0
psr/http-factory Version ^1.1
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 comfino/php-api-client contains the following files

Loading the files please wait ...