Browse project documentation

Redirect & Callback

Pardakhtv1.0.0-beta.4View sourceEnglish / Persian

After a successful purchase() call, you need to redirect the user to the gateway’s payment page and handle the callback when they return.

RedirectResponse

The purchase() method returns a RedirectResponse with two possible redirect types:

GET Redirect (REST Gateways)

REST gateways (Zarinpal, IDPay, Zibal, etc.) provide a URL for a simple HTTP redirect:

$response = $gateway->purchase($request);

header('Location: ' . $response->getUrl());
exit;

POST Form (SOAP Gateways)

SOAP bank gateways (Mellat, Saman, Parsian) require submitting a POST form with hidden fields to the bank’s payment page:

$response = $gateway->purchase($request);

echo $response->renderAutoSubmitForm();

The generated HTML includes a form with hidden fields and a JavaScript snippet that auto-submits it. A <noscript> fallback button is included for users without JavaScript.

Handling Both Types

$response = $gateway->purchase($request);

if ($response->isPost()) {
    echo $response->renderAutoSubmitForm('Redirecting to bank...');
} else {
    header('Location: ' . $response->getUrl());
    exit;
}

RedirectResponse API

$response->getUrl();         // Gateway payment page URL
$response->getMethod();      // "GET" or "POST"
$response->getReferenceId(); // Gateway reference (Authority, RefId, etc.)
$response->getFormData();    // POST fields (empty for GET)
$response->isPost();         // true for SOAP gateways

$response->renderAutoSubmitForm(
    string $submitText = 'Redirecting...'
): string;

Reference ID

The referenceId returned by purchase() is the gateway’s identifier for this payment attempt. Save it to your database — you’ll need it to correlate the callback.

Handling the Callback

After the user completes (or cancels) the payment, the gateway redirects them back to your callbackUrl.

Auto-Detection

By default, verify() reads callback data from $_POST or $_GET automatically:

$transaction = $gateway->verify();

Explicit Data

In frameworks where superglobals aren’t used directly, pass the callback data explicitly:

// Laravel
$transaction = $gateway->verify($request->all());

// Symfony
$transaction = $gateway->verify($request->query->all());

Transaction Result

After successful verification:

$transaction->getId();           // TransactionId value object
$transaction->getGatewayName();  // "zarinpal"
$transaction->getAmount();       // Amount value object
$transaction->getStatus();       // TransactionStatus::Verified
$transaction->getReferenceId();  // Gateway reference
$transaction->getTrackingCode(); // User-facing tracking code (or null)
$transaction->getCardNumber();   // Payer's card number (or null)
$transaction->getExtra();        // Additional gateway-specific data

Complete Flow Example

// === Purchase page ===
$pardakht = new Pardakht();
$gateway = $pardakht->create('zarinpal', new ZarinpalConfig('merchant-id'));

$response = $gateway->purchase(new PurchaseRequest(
    amount: Amount::fromToman(50_000),
    callbackUrl: 'https://example.com/payment/callback',
    orderId: 'ORDER-123',
));

// Save to database
save_payment($response->getReferenceId(), 'ORDER-123', 'pending');

// Redirect
header('Location: ' . $response->getUrl());
exit;

// === Callback handler ===
$gateway = $pardakht->create('zarinpal', new ZarinpalConfig('merchant-id'));

try {
    $transaction = $gateway->verify();
    update_payment($transaction->getReferenceId(), 'verified');
    show_success_page($transaction->getTrackingCode());
} catch (VerificationException $e) {
    update_payment_failed($e->getErrorCode());
    show_failure_page();
}

Search documentation

Search across all projects. Close this window to return to your guide.

Tab to navigate · Enter to openEsc to close