Handling Callbacks

Your callback URL receives the payer's browser after Cartino Pay has verified the payment.

GET https://cartino.cloud/payment/callback?payment_id=PAY_01J9…&order_id=CLOUD-12345&status=paid
Query param Meaning
payment_id The Cartino Pay payment
order_id Your reference, as sent at creation
status The payment status at redirect time: usually paid, failed or cancelled; can be pending if the gateway could not be reached

The golden rule

Never fulfil an order based on the query string alone. Anyone can type ?status=paid into a browser.

The redirect is for user experience. The source of truth is:

  1. the signed webhook — preferred, or
  2. GET /api/v1/payments/{payment_id} from your server — always available.

Recommended callback handler

public function callback(Request $request)
{
    $paymentId = $request->query('payment_id');
    $order = Order::where('cartino_payment_id', $paymentId)->firstOrFail();

    // Ask Cartino Pay (server-to-server) — do not trust ?status=
    $payment = CartinoPay::getPayment($paymentId);      // GET /api/v1/payments/{id}

    return match ($payment['status']) {
        'paid'                 => view('checkout.success', ['order' => $order, 'tracking' => $payment['tracking_code']]),
        'pending', 'processing'=> view('checkout.pending', ['order' => $order]),
        default                => view('checkout.failed', ['order' => $order, 'reason' => $payment['failure_reason']]),
    };
}

Fulfilment itself (activate the subscription, ship the goods) should happen in the webhook handler, idempotently. If the webhook has already arrived, the callback page simply shows the result.

Edge cases