PHP code example of gopaycommunity / gopay-php-api-v4

1. Go to this page and download the library: Download gopaycommunity/gopay-php-api-v4 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/ */

    

gopaycommunity / gopay-php-api-v4 example snippets


use GoPay\Payments\GoPayClient;
use GoPay\Payments\Config;
use GoPay\Payments\Environment;
use GoPay\Payments\Generated\Model\ChargeState;

// 1. Initialize the client
$sdk = new GoPayClient(new Config(
    environment: Environment::Sandbox,
    shareableKey: 'YOUR_SHAREABLE_KEY', // optional — for browser SDK initialisation
));

// 2. Authenticate (stored internally; token refreshes automatically)
$sdk->authenticate('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET', 'payment:write payment:read');

// 3. Create a payment
$payment = $sdk->createPayment('YOUR_GOID', [
    'amount'       => 1000,             // 10.00 CZK (in minor units / haléře)
    'currency'     => 'CZK',
    'order_number' => 'ORDER-001',
    'customer'     => ['email' => '[email protected]'],
    'callback'     => [
        'notification_url' => 'https://yourshop.com/notify',
        'return_url'       => 'https://yourshop.com/return',
    ],
]);

// 4. Charge using a card token from the browser iframe
//    (browser SDK's mountCardForm() → user enters card → iframe returns token)
$charge = $sdk->chargePayment($payment->getId(), [
    'payment_instrument' => [
        'payment_instrument' => 'PAYMENT_CARD',
        'input' => [
            'input_type' => 'CARD_TOKEN',
            'card_token' => $cardToken, // from the browser SDK iframe
        ],
        'browser_data' => [
            // EMV 3DS device data — collect in the browser, POST to your server.
            'language'           => $browserData['language'],      // e.g. 'cs-CZ'
            'timezone'           => $browserData['timezone'],      // e.g. -60
            'screen_width'       => $browserData['screen_width'],  // e.g. 1920
            'screen_height'      => $browserData['screen_height'], // e.g. 1080
            'color_depth'        => $browserData['color_depth'],   // e.g. 24
            'javascript_enabled' => $browserData['javascript_enabled'], // e.g. true
            // ip, user_agent and accept_header are the three the browser cannot
            // determine itself. The browser fetches them from
            // GET /cards/browser-data (shareable_key auth) right before the charge
            // and POSTs them to you with the rest — see the note below.
            'ip'                 => $browserData['ip'],            // e.g. '192.0.2.42'
            'user_agent'         => $browserData['user_agent'],
            'accept_header'      => $browserData['accept_header'],
        ],
    ],
]);

// 5. The POST response is not the outcome — the charge usually is still
//    PROCESSING and a 3DS challenge shows up only on a later poll. Poll until
//    it is decided: returns on SUCCEEDED or ACTION_REQUIRED, throws on FAILED
//    (CHARGE_FAILED) or if it stays undecided (CHARGE_TIMEOUT).
$final = $sdk->awaitChargeState($payment->getId());

// 5a. 3DS 

use GoPay\Payments\Config;
use GoPay\Payments\Environment;

$config = new Config(
    environment:         Environment::Production, // Environment::Sandbox (default)
    baseUrl:             null,          // override base URL (e.g. staging); null = use environment
    debugLoggingEnabled: false,         // log request/response to error_log (default false)
    onError:             null,          // callable(\Throwable): void — called before throwing
    shareableKey:        null,          // shareable key for browser SDK initialisation
);

use GoPay\Payments\GoPayClient;
use GoPay\Payments\Config;

$sdk = new GoPayClient(
    config:          new Config(),
    httpClient:      $myPsr18Client,        // Psr\Http\Client\ClientInterface
    requestFactory:  $myRequestFactory,     // Psr\Http\Message\RequestFactoryInterface
    streamFactory:   $myStreamFactory,      // Psr\Http\Message\StreamFactoryInterface
);

// Authenticate (client_credentials grant)
$sdk->authenticate(string $clientId, string $clientSecret, string $scope): void

// Check if a token is stored
$sdk->isAuthenticated(): bool

// Clear tokens
$sdk->logout(): void

// Store shareable key for browser SDK
$sdk->setShareableKey(string $key): void

// Return shareable_key + client_id for browser SDK init (safe to expose to the browser)
$sdk->getBrowserKeys(): array{shareable_key: string, client_id: string}

// Create a payment session
$sdk->createPayment(string $goid, array $params): PaymentDetails

// Get payment status
$sdk->getPaymentStatus(string $paymentId): PaymentDetails

// Cancel a payment that has not been charged yet (only in CREATED; 409 otherwise)
$sdk->cancelPayment(string $paymentId): void

// Charge a payment (card token / Google Pay / Apple Pay)
$sdk->chargePayment(string $paymentId, array $params): PaymentChargeResponse

// Get charge state (poll manually)
$sdk->getChargeState(string $paymentId): PaymentChargeStatusResponse

// Poll charge state until SUCCEEDED or ACTION_REQUIRED (3DS redirect);
// throws on FAILED / timeout. Call it right after chargePayment().
// WARNING: blocks the PHP process — see "Production deployment" below.
$sdk->awaitChargeState(
    string $paymentId,
    int $timeoutSeconds = 30,
    int $pollIntervalMs = 1_000,
): PaymentChargeStatusResponse

// Google Pay configuration (pre-filled paymentDataRequest)
$sdk->getGooglePayInfo(string $paymentId): array

// Apple Pay configuration (applepayVersion, applePayPaymentRequest)
$sdk->getApplePayInfo(string $paymentId): array

// Apple Pay merchant validation (server-side; forward validationURL from browser)
$sdk->validateApplePayMerchant(string $paymentId, ?array $body = null, ?string $origin = null): array

// QR payment information (recipient details + base64 QR image)
$sdk->getQrPaymentInfo(string $paymentId, ?string $format = null): QRPaymentDetails

// Get stored card details
$sdk->getCardDetails(string $cardId): PermanentCardTokenDetails

// Delete a stored card
$sdk->deleteCard(string $cardId): void

// Tokenize JWE payload from the browser iframe (returns permanent token)
$sdk->tokenizeEncryptedCard(string $payload): PermanentCardTokenDetails

// Refund a payment; pass the full amount for a full refund
$sdk->refundPayment(string $paymentId, array $params): RefundDetails

// List all refunds for a payment
$sdk->listRefunds(string $paymentId): list<RefundDetails>

// Get a single refund by its own ID
$sdk->getRefund(string $refundId): RefundDetails

// Poll a refund until it reaches SUCCESS or FAILED
$sdk->awaitRefundState(string $refundId, int $timeoutSeconds = 30, int $pollIntervalMs = 1000): RefundDetails

$refund = $sdk->refundPayment($paymentId, ['amount' => 10000]);
echo $refund->getState();   // 'REQUESTED' — refunds are asynchronous

// Poll until it settles; awaitRefundState does the loop for you
$settled = $sdk->awaitRefundState($refund->getId());
echo $settled->getState();  // 'SUCCESS' | 'FAILED'

// Create a link; `payment` is  $goid, array $params): LinkDetails

// Read a link's current settings and state
$sdk->linkStatus(string $goid, string $linkId): LinkDetails

// Disable a link so it can no longer start a new payment
$sdk->disableLink(string $goid, string $linkId): void

$link = $sdk->createPaymentLink($goid, [
    'expires_in' => 3600,   // omit for a link that never expires
    'reusable'   => false,  // one-shot; default is true
    'payment'    => [
        'amount'       => 15000,
        'currency'     => 'CZK',
        'order_number' => '2026-00042',
        'customer'     => ['email' => '[email protected]'],
        'callback'     => [
            'notification_url' => 'https://yourshop.example.com/gopay/notify',
            'return_url'       => 'https://yourshop.example.com/gopay/return',
        ],
    ],
]);

echo $link->getUrl();   // share this with the customer
echo $link->getId();    // use this on linkStatus() / disableLink()

// Create a recurrence; returned in state NEW, no payment exists yet
$sdk->createRecurrence(string $goid, array $params): RecurrenceDetails

// Read its current state and the payment it last created
$sdk->recurrenceStatus(string $recId): RecurrenceDetails

// Stop it permanently
$sdk->stopRecurrence(string $recId): void

// Create the first payment — the one the customer pays to activate the recurrence
$sdk->startRecurrence(string $recId, ?array $params = null): PaymentDetails

// Create a further payment, once the recurrence is STARTED
$sdk->recurrenceNext(string $recId, ?array $params = null): PaymentDetails

// AUTO — GoPay creates a payment every month
$recurrence = $sdk->createRecurrence($goid, [
    'type'               => 'AUTO',
    'schedule'           => ['period' => 'MONTH', 'cycle' => 1],
    'recurrence_date_to' => '2027-09-04',
    'payment'            => [
        'amount'       => 1500,
        'currency'     => 'CZK',
        'order_number' => '2025010199',
        'customer'     => ['email' => '[email protected]'],
        'callback'     => [
            'notification_url' => 'https://yourshop.example.com/gopay/notify',
            'return_url'       => 'https://yourshop.example.com/gopay/return',
        ],
    ],
]);

// ON_DEMAND — no schedule; you call recurrenceNext() when you want the next payment
$recurrence = $sdk->createRecurrence($goid, [
    'type'               => 'ON_DEMAND',
    'recurrence_date_to' => '2027-09-04',
    'payment'            => [ /* same shape, no schedule anywhere */ ],
]);

$recurrence = $sdk->createRecurrence($goid, [...]);   // state NEW

$first = $sdk->startRecurrence($recurrence->getId()); // state REQUESTED, not STARTED
header('Location: ' . $first->getGwUrl());            // the customer pays this one

// …once the customer has paid it, the recurrence becomes STARTED
$next = $sdk->recurrenceNext($recurrence->getId());   // 409 before that point

$payment = $sdk->recurrenceNext($recId, [
    'amount'       => 2500,                      // this instalment only
    'order_number' => '2026-00042',
    'customer'     => ['first_name' => 'Jane'],  // merged, not replaced
]);

> $sdk->startRecurrence($recId, ['customer' => (object) []]);   // {"customer":{}}  → 201
> $sdk->startRecurrence($recId, ['customer' => []]);            // {"customer":[]}  → 400
> 

$payment = $sdk->createPayment($goid, [...]);
echo $payment->getId();     // unique payment ID
echo $payment->getState();  // 'CREATED', 'PAID', etc.
echo $payment->getAmount(); // amount in minor units (int)

$charge = $sdk->chargePayment($payment->getId(), [...]);
echo $charge->getState(); // usually 'PROCESSING' — not the outcome yet, see below

$final = $sdk->awaitChargeState($payment->getId());
echo $final->getState();                    // 'SUCCEEDED' or 'ACTION_REQUIRED'
echo $final->getAction()?->getRedirectUrl(); // 3DS URL on ACTION_REQUIRED, otherwise null

$card = $sdk->tokenizeEncryptedCard($jwePayload);
echo $card->getToken();     // permanent card token for future charges
echo $card->getMaskedPan(); // '411111******1111'

use GoPay\Payments\Generated\Model\ChargeState;

$sdk->chargePayment($paymentId, $params);

// Returns on SUCCEEDED or ACTION_REQUIRED; throws CHARGE_FAILED / CHARGE_TIMEOUT
$final = $sdk->awaitChargeState($paymentId);

if ($final->getState() === ChargeState::ACTION_REQUIRED) {
    // 3DS authentication 

use GoPay\Payments\PaymentPoller;

// On your return_url handler:
$paymentId = $_GET['payment_id'];

do {
    sleep(2);
    $payment = $sdk->getPaymentStatus($paymentId);
} while (PaymentPoller::isPending($payment->getState()));

if (PaymentPoller::isSuccessful($payment->getState())) {
    // PAID or AUTHORIZED
    echo 'Payment succeeded: ' . $payment->getState();
} else {
    // CANCELED or TIMEOUTED
    echo 'Payment did not complete: ' . $payment->getState();
}

// 1. Create the payment session (same as any other payment)
$payment = $sdk->createPayment($goid, [
    'amount'       => 1990,
    'currency'     => 'CZK',
    'order_number' => 'ORDER-001',
    'customer'     => ['email' => '[email protected]'],
    'callback'     => [
        'notification_url' => 'https://yourshop.com/notify',
        'return_url'       => 'https://yourshop.com/return',
    ],
]);

// 2. Retrieve QR code and recipient details
$qr = $sdk->getQrPaymentInfo($payment->getId());         // 'png' (default) or 'svg'
$imageBase64 = $qr->getQrCode();      // base64-encoded image

// 3. Render to the customer
echo '<img src="data:image/png;base64,' . $imageBase64 . '" alt="QR payment">';
echo 'Amount: ' . $qr->getAmount() . ' ' . $qr->getCurrency();

// 4. Poll until the customer pays (webhook-preferred; polling shown for completeness)
use GoPay\Payments\PaymentPoller;
do {
    sleep(3);
    $status = $sdk->getPaymentStatus($payment->getId());
} while (PaymentPoller::isPending($status->getState()));

echo PaymentPoller::isSuccessful($status->getState()) ? 'Paid' : 'Not paid';

use GoPay\Payments\Exception\GoPaySdkException;
use GoPay\Payments\Exception\GoPayHttpException;
use GoPay\Payments\Exception\ErrorCode;

try {
    $payment = $sdk->createPayment($goid, $params);
} catch (GoPayHttpException $e) {
    echo $e->status;  // e.g. 422
    var_dump($e->body); // decoded JSON or raw string
} catch (GoPaySdkException $e) {
    echo $e->errorCode->value; // e.g. 'AUTH_TOKEN_MISSING'
    echo $e->getMessage();
}

$sdk = new GoPayClient(new Config(
    onError: function (\Throwable $e): void {
        // Fires before every throw — use for logging/monitoring
        $logger->error('GoPay error', ['exception' => $e]);
    },
));

use GoPay\Payments\GoPayClient;
use GoPay\Payments\Config;
use GoPay\Payments\Environment;

function getGoPayClient(): GoPayClient {
    $cacheKey = 'gopay_token_' . md5(CLIENT_ID . SCOPE);
    $sdk = new GoPayClient(new Config(environment: Environment::Production));

    $cached = apcu_fetch($cacheKey, $success);
    if ($success && is_array($cached)) {
        // pseudo-code — getHttp() is not yet public; see note below
        // $sdk->getHttp()->getTokenStore()->setToken($cached['token'], $cached['expires_in']);
        // $sdk->getHttp()->getTokenStore()->setClientCredentials(CLIENT_ID, CLIENT_SECRET, SCOPE);
    } else {
        $sdk->authenticate(CLIENT_ID, CLIENT_SECRET, SCOPE);
    }

    return $sdk;
}

// Server-side (PHP)
$keys = $sdk->getBrowserKeys();
// $keys = ['shareable_key' => '...', 'client_id' => '...']

// Browser posts the JWE payload to your server
$jwePayload = $_POST['payload'];
$card = $sdk->tokenizeEncryptedCard($jwePayload);

// Now charge with the permanent token
$sdk->chargePayment($paymentId, [
    'payment_instrument' => [
        'payment_instrument' => 'PAYMENT_CARD',
        'input' => ['input_type' => 'CARD_TOKEN', 'card_token' => $card->getToken()],
        'browser_data' => [
            // EMV 3DS device data — collect in the browser, POST to your server.
            // ip, user_agent and accept_header come from GET /cards/browser-data,
            // fetched by the browser — never from $_SERVER. See the charge flow above.
            'language'           => $browserData['language'],
            'timezone'           => $browserData['timezone'],
            'screen_width'       => $browserData['screen_width'],
            'screen_height'      => $browserData['screen_height'],
            'color_depth'        => $browserData['color_depth'],
            'javascript_enabled' => $browserData['javascript_enabled'],
            'ip'                 => $browserData['ip'],
            'user_agent'         => $browserData['user_agent'],
            'accept_header'      => $browserData['accept_header'],
        ],
    ],
]);