Skip to content
Payfim - Secure. Simple. Yours.
Platforms

Use the PHP & Laravel SDK

Install the Payfim PHP & Laravel SDK and start accepting crypto in a few minutes.

PFPayfim Team · September 28, 2026 · 6 min read

The SDK is for developers who connect their own PHP application (custom shop, SaaS billing, membership site, Laravel app ...) to the Payfim Gateway. It creates invoices, reads their status and verifies the signed webhooks your gateway sends. The full API reference is in README.md inside the zip; this part shows the four things every integration needs.

Before you start, install your Payfim Gateway and add your wallets (see Install the gateway and Add wallets). Compatibility: PHP 7.4 – 8.4 · Laravel 8+ (optional) · ext-curl, ext-json.

  1. Install the SDK.

    Unzip payfim-php.zip into your project, e.g. packages/payfim-php/, and require it through a Composer path repository:

    "repositories": [{"type": "path", "url": "packages/payfim-php"}],
    "require": {"payfim/payfim-php": "^3.0"}

    then run composer update payfim/payfim-php. No Composer? README.md shows a four-line autoloader. Put the Gateway URL and API key (gateway admin > Integrations) in environment variables:

    $payfim = new Payfim\Client(getenv('PAYFIM_URL'), getenv('PAYFIM_API_KEY'));
    print_r($payfim->ping());   // version, store name, active coins

    Tip: The API key creates invoices and signs webhooks. Use it only on the server - never in JavaScript or a mobile app.

  2. Create an invoice and redirect.

    When the customer chooses crypto, create an invoice from your own order record and send the customer to the hosted checkout. Store the invoice id on the order.

    $invoice = $payfim->createInvoice([
        'order_id'    => (string) $order->id,
        'amount'      => $order->total,        // '49.90'
        'currency'    => $order->currency,     // 'USD'
        'webhook_url' => 'https://shop.example.com/payfim/webhook',
        'return_url'  => 'https://shop.example.com/orders/' . $order->id,
    ]);
    $order->payfim_invoice_id = $invoice->getId();
    header('Location: ' . $invoice->getCheckoutUrl(), true, 303);

    Calling it again for the same open order returns the same invoice. Errors throw Payfim\Exception\ApiException or TransportException - show a friendly "temporarily unavailable" message and log the details.

  3. Handle the webhook.

    Your webhook_url receives a signed POST on every status change. Verify it on the raw body, re-fetch the invoice, check it is yours, then update the order once:

    $event   = $payfim->constructEvent(file_get_contents('php://input'),
                                        $_SERVER['HTTP_X_PAYFIM_SIGNATURE'] ?? '');
    $invoice = $payfim->fetchEventInvoice($event);   // never trust the payload alone
    
    if ($invoice->isPaid() && $order->status !== 'paid'
        && $invoice->matchesAmount($order->total, $order->currency)) {
        $order->markPaid($invoice->getTransactionReference());   // tx hash
    }
    http_response_code(200);

    A bad signature throws SignatureVerificationException (answer 401). Answer 2xx for events you ignore - otherwise the gateway retries for up to 24 hours. examples/plain-php/webhook.php is a complete handler including underpaid and expired invoices.

    Tip: Treat underpaid as "needs review", never as paid, and never mark an order paid just because the customer reached your return page.

  4. Laravel: config, route and events.

    The service provider and the Payfim facade are auto-discovered. Add to .env:

    PAYFIM_URL=https://pay.example.com
    PAYFIM_API_KEY=pf_live_...

    Register the webhook route (signature checked by the VerifyPayfimSignature middleware) and exclude payfim/webhook from CSRF protection:

    Route::payfimWebhook();   // POST /payfim/webhook

    Create invoices with Payfim::createInvoice([...]) and listen for Payfim\Laravel\Events\InvoicePaid (also InvoiceUnderpaid, InvoiceExpired ...). Each event carries $invoice, already re-fetched from the gateway:

    public function handle(InvoicePaid $e): void
    {
        $order = Order::where('payfim_invoice_id', $e->invoice->getId())->first();
        if ($order && $order->status !== 'paid') { $order->markPaid($e->invoice->getTransactionReference()); }
    }

    Optional: php artisan vendor:publish --tag=payfim-config.

  5. Run the tests.

    php tests/run.php runs the built-in test suite (no PHPUnit needed). Point it at your own gateway to run the live tests too:

    PAYFIM_TEST_URL=https://pay.example.com PAYFIM_TEST_KEY=pf_live_... php tests/run.php

    Tip: Everything green? Make a small real payment through your integration (Part 3) and watch the order update.

Troubleshooting

ApiException "Invalid or missing API key" (401)
Copy the key again from the gateway's Integrations page. After 20 failed attempts in 15 minutes the gateway rate-limits API calls (429).
ApiException bad_response
The Gateway URL does not point to the gateway (you got an HTML page). Use the folder that contains api.php, without a trailing /admin.php.
SignatureVerificationException on every webhook
Verify the raw body (php://input / $request->getContent()), not a re-encoded array, and make sure the server clock is correct (tolerance 5 minutes).
Laravel webhook returns 419
The route is protected by CSRF. Exclude payfim/webhook in validateCsrfTokens(except: ...) or register it in routes/api.php (the URL then gets the /api prefix: set PAYFIM_WEBHOOK_PATH=api/payfim/webhook and use Route::payfimWebhook('payfim/webhook')).

Get the Payfim PHP & Laravel SDK - the download includes an illustrated PDF version of this guide.

Accept crypto on your store today

Self-hosted, non-custodial, zero fees. Lifetime license.