1. Go to this page and download the library: Download comfino/php-api-client 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/ */
comfino / php-api-client example snippets
use Comfino\Api\Client;
use Nyholm\Psr7\Factory\Psr17Factory;
use Sunrise\Http\Client\Curl\Client as CurlClient;
$psr17Factory = new Psr17Factory();
$client = new Client(
httpClient: new CurlClient($psr17Factory),
requestFactory: $psr17Factory,
streamFactory: $psr17Factory,
apiKey: 'your-api-key' // Private - keep server-side only.
);
$client->enableSandboxMode(); // Omit or call disableSandboxMode() for production.
// Submit a loan application.
$response = $client->createOrder($order); // $order implements OrderInterface
header('Location: ' . $response->applicationUrl);
// Override the default user agent.
$client->setCustomUserAgent('my-plugin/1.0.0');
// Set the API language (ISO 639-1) and currency (ISO 4217).
$client->setApiLanguage('pl');
$client->setApiCurrency('PLN');
// Add a custom HTTP header (e.g., for platform identification).
$client->addCustomHeader('X-Shop-Platform', 'WooCommerce/8.5');
// Use a different API endpoint (e.g., staging). Accepted destinations are ComfinoPay
// domains over HTTPS, plus private/loopback IPs, single-label hosts and `.test`
// domains for local development.
$client->setCustomApiBaseUrl('https://api-ecommerce.craty.pl');
use Comfino\Api\Dto\Payment\LoanQueryCriteria;
use Comfino\Enum\LoanType;
use Comfino\Enum\ProductListType;
// List all products for a 1 500 PLN cart (amounts in grosz).
$criteria = new LoanQueryCriteria(loanAmount: 150000);
$response = $client->getFinancialProducts($criteria);
foreach ($response->financialProducts as $product) {
echo $product->name . ' - ' . $product->instalmentAmount . " grosz/month\n";
}
// Filter by product type.
$criteria = new LoanQueryCriteria(
loanAmount: 150000,
loanType: LoanType::INSTALLMENTS_ZERO_PERCENT
);
// Get detailed information about a specific financial product (e.g., for a product detail page).
$details = $client->getFinancialProductDetails($criteria, $cart); // $cart implements CartInterface
// Get available product types configured for this shop account (for promotional banner widget at shop product page).
$types = $client->getProductTypes(ProductListType::WIDGET);
// Create a loan application - $order implements Comfino\Shop\Order\OrderInterface.
$createResponse = $client->createOrder($order);
$applicationUrl = $createResponse->applicationUrl;
// Validate an order without submitting it.
$validateResponse = $client->validateOrder($order);
// Cancel an order.
$client->cancelOrder('ORDER-123');
use Comfino\Api\Dto\Account\UserRegistration;
$client = new Client($httpClient, $requestFactory, $streamFactory, null);
// Fetch the legal agreements to present as consent checkboxes.
$agreements = $client->fetchAgreements()->agreements;
// Register the shop, echoing back the IDs of the agreements the owner accepted.
$registration = new UserRegistration(
name: 'shop.example.com',
webSiteUrl: 'https://shop.example.com',
contactName: 'Jane Doe',
contactEmail: '[email protected]',
contactPhone: '500600700',
platformId: 16,
agreements: array_map(static fn ($agreement) => $agreement->id, array_filter(
$agreements,
static fn ($agreement) => $agreement->
// Check that the API key belongs to an active account.
$isActive = $client->isShopAccountActive();
// Retrieve the widget key (public) for use in frontend scripts (e.g., promotional banner).
$widgetKey = $client->getWidgetKey();
// List available widget types.
$widgetTypes = $client->getWidgetTypes();
use Comfino\Api\Dto\Plugin\ShopPluginError;
// Report a plugin error for remote diagnostics (e.g., from an exception handler).
$client->sendLoggedError(new ShopPluginError(
host: 'myshop.example.com',
platform: 'ExampleEcommercePlatform',
environment: ['php' => PHP_VERSION, 'plugin' => '2.0.0'],
errorCode: 'API_ERROR',
errorMessage: 'Unexpected API response.',
stackTrace: $exception->getTraceAsString()
));
// Notify ComfinoPay when the payment plugin is uninstalled.
$client->notifyPluginRemoval();
// Notify ComfinoPay of an abandoned cart event.
$client->notifyAbandonedCart('checkout_abandoned');
use Comfino\Auth\WebhookSignatureVerifier;
$verifier = new WebhookSignatureVerifier();
$signature = $_SERVER['HTTP_CR_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
if (!$verifier->verify($signature, 'your-api-key', $payload)) {
http_response_code(401);
exit;
}
// Process verified payload.
$data = json_decode($payload, true);
use Comfino\Auth\PaywallAuthKeyGenerator;
$generator = new PaywallAuthKeyGenerator();
// $widgetKey - public, obtained via $client->getWidgetKey() and stored in shop config
// $apiKey - private, never sent to the browser
$authKey = $generator->generateAuthKey(widgetKey: $widgetKey, apiKey: $apiKey);
// Pass only $authKey to the frontend widget initialization script served from the ComfinoPay CDN (part of the official ComfinoPay Web Frontend SDK).
use Comfino\Api\ApiContext;
use Comfino\Api\RequestOptions;
use Comfino\Api\SharedClient;
// Register this once, as a service. It is stateless and safe to share.
$client = new SharedClient(
httpClient: $httpClient,
requestFactory: $requestFactory,
streamFactory: $streamFactory,
retryExecutor: new RetryExecutor($retryPolicy)
);
// Build one context per merchant, per request. Immutable, so it cannot be mutated out from under a call.
$context = new ApiContext(
apiKey: $merchant->apiKey,
sandboxMode: $merchant->isSandbox,
tenantKey: $merchant->id // Partitions the limiter, the breaker, and your own metrics.
);
$products = $client->getFinancialProducts($context, $criteria, RequestOptions::attempts(2));
$order = $client->createOrder($context, $order, RequestOptions::failFast());
use Comfino\Api\Client;
use Comfino\Api\Retry\ExponentialBackoffRetryPolicy;
use Comfino\Api\Retry\RetryExecutor;
use Comfino\Api\Retry\TimeoutConfig;
$retryPolicy = new ExponentialBackoffRetryPolicy(
timeoutConfig: new TimeoutConfig(connectionTimeout: 5, transferTimeout: 15),
maxAttempts: 3,
maxTotalTransferTimeout: 15, // Budget shared by every attempt; null restores unbounded escalation.
baseDelayMs: 100, // 0 disables the delay entirely
maxDelayMs: 2000
);
$client = new Client(
httpClient: $httpClient,
requestFactory: $requestFactory,
streamFactory: $streamFactory,
apiKey: 'your-api-key',
retryExecutor: new RetryExecutor($retryPolicy)
);
// One attempt, no delay: surface the failure and let the shopper pick another method.
$policy = ExponentialBackoffRetryPolicy::failFast(new TimeoutConfig(1, 3));
// Retries, but never sleeping.
$policy = ExponentialBackoffRetryPolicy::withoutDelay(new TimeoutConfig(1, 3), maxAttempts: 2);
final class RegisterSomething extends Request
{
public function isIdempotent(): bool
{
return false; // No dedup key server-side, so never replay it.
}
// ...
}
use Comfino\Api\Retry\CallbackTimeoutAwareClient;
use Comfino\Api\Retry\TimeoutConfig;
use Symfony\Component\HttpClient\Psr18Client;
$transport = new CallbackTimeoutAwareClient(
fn (TimeoutConfig $t) => new Psr18Client(
$symfonyHttpClient->withOptions(['timeout' => $t->connectionTimeout, 'max_duration' => $t->transferTimeout])
),
new TimeoutConfig(connectionTimeout: 1, transferTimeout: 3)
);
use Comfino\Api\CircuitBreaker\CircuitBreaker;
use Comfino\Api\RateLimit\TokenBucketRateLimiter;
use Comfino\Api\RateLimit\TwoTierRateLimiter;
$client = new SharedClient(
httpClient: $httpClient,
requestFactory: $requestFactory,
streamFactory: $streamFactory,
retryExecutor: new RetryExecutor($retryPolicy),
rateLimiter: new TwoTierRateLimiter(
perTenantLimiter: new TokenBucketRateLimiter(capacity: 20, refillTokensPerSecond: 5),
globalLimiter: new TokenBucketRateLimiter(capacity: 200, refillTokensPerSecond: 50)
),
circuitBreaker: new CircuitBreaker()
);
use Comfino\Api\OnLimit;
// Checkout: surface ServiceUnavailable and let the shopper choose another method.
$client->getFinancialProducts($context, $criteria, (new RequestOptions())->andOnLimit(OnLimit::FailFast));
// Worker: catch RateLimitExceeded, read getRetryAfterMs(), and put the call back on your queue.
$client->cancelOrder($context, $orderId, (new RequestOptions())->andOnLimit(OnLimit::Queue));
final class MetricsObserver implements RequestObserverInterface
{
public function onResponse(ApiContext $c, RequestInterface $rq, ResponseInterface $rs, float $durationMs): void
{
$this->histogram->observe($durationMs, ['tenant' => $c->tenantKey, 'status' => $rs->getStatusCode()]);
}
// onRequest() and onFailure() omitted for brevity.
}
use Comfino\Api\Request\CustomRequest;
// Free-form JSON in, free-form JSON out - no Request/Response subclass needed.
$response = $client->sendCustomRequest(
new CustomRequest(method: 'POST', endpointPath: 'orders/ORDER-123/notes', body: ['note' => 'Called back, will retry payment.'])
);
$response->body; // Deserialized response body, verbatim (array|string|bool|int|float|null)