Skip to content

Callbacks & Status ​

Every gateway notifies your server of the payment result. handleCallback() verifies the gateway's signature and returns a PaymentCallback. Pass it the Laravel request as is: signatures are checked against the exact body the gateway sent.

Production setup

For production, follow Handling Webhooks (recommended): verify, store the call, acknowledge immediately, then process it once in the background with retries. The example below handles everything inline to show the API.

Every callback goes through the same steps; KBZ Pay is shown here.

Handling a KBZ Pay callbackYour appKBZ PayPayment notificationPOST to callbackUrlVerify the signaturekbzPay()->handleCallback()Invalid: 400, never fulfillSignatureVerificationExceptionFind the orderby $callback->orderIdFulfill onceskip if paid, match the amountAcknowledge: plain successacknowledge($callback)No acknowledgement? Retryafter 60 s, then 600 s
Handling a KBZ Pay callback
php
use Illuminate\Http\Request;
use Laranex\LaravelMyanmarPayments\Facades\MyanmarPayments;
use Laranex\PhpMyanmarPayments\Amount;

Route::post('/payments/kbz/callback', function (Request $request) {
    $callback = MyanmarPayments::kbzPay()->handleCallback($request);

    $order = Order::where('reference', $callback->orderId)->firstOrFail();

    // $order->amount is a string such as "10000"; compare by value, not floats
    $paid = Amount::parse($order->amount)->equals($callback->amount);

    if ($callback->isSuccessful() && ! $order->isPaid() && $paid) {
        $order->markAsPaid($callback->gatewayReference);
    }

    return MyanmarPayments::acknowledge($callback);
})->name('payments.kbz.callback');

Gateways post from their own servers, so exclude callback routes from CSRF verification.

Callback Helpers ​

HelperWhat it does
kbzPay()->handleCallback($request)Verifies the callback. Takes the Laravel Request as is, or the SDK's CallbackRequest
MyanmarPayments::handleCallback($gateway, $request)The same, by gateway name, for one route that serves every gateway; see Handling Webhooks
MyanmarPayments::gateway($name)The gateway for kbz-pay, wave-money, aya-pay, yoma-mmqr or cyber-source (gateways() lists them). An unknown name throws InvalidArgumentException
MyanmarPayments::acknowledge($callback)The response the gateway expects, as a Responsable. Without a callback, an empty 200
ayaPay()->verifyRedirect($request)Verifies AYA's browser return; see AYA Pay

Signatures are computed over the exact bytes the gateway sent; the package reads them from $request->getContent(), so don't rewrite the body in middleware before the callback route. A body is read as JSON only when it is a single JSON object; any other body is read as a urlencoded form.

Rules ​

  • Verify, then trust. A callback that fails verification throws SignatureVerificationException, and so does one whose signed or hashed field holds an object or array instead of a single value, since no gateway signs nested values. Never act on its payload; it carries the unverified data in $e->raw for logging only.
  • Check the amount. Compare $callback->amount (as the gateway sent it, a string) with your order before fulfilling. A gateway may format it differently from your order (10000 or 10000.00); Amount::parse($order->amount)->equals($callback->amount) compares decimal strings exactly.
  • Be idempotent. Gateways retry and may deliver the same callback more than once.
  • Acknowledge. MyanmarPayments::acknowledge($callback) returns the response the gateway expects, e.g. KBZ Pay's plain success. Without it, gateways keep retrying.

PaymentStatus ​

Every gateway's own status values are mapped onto one enum. The original value stays in $callback->gatewayStatus.

CaseMeaning
PaymentStatus::SuccessfulThe customer paid. The only status that means money was collected.
PaymentStatus::PendingStill in progress or waiting on the customer.
PaymentStatus::FailedAttempted and failed or rejected.
PaymentStatus::CanceledCanceled or closed before completing.
PaymentStatus::ExpiredThe payment window ran out.
PaymentStatus::UnknownA status this package does not recognize yet. Inspect gatewayStatus.

$status->isFinal() is false for Pending and Unknown. Unknown statuses never throw.

Each gateway page lists its exact mapping.

Status Checks ​

When a callback is late, ask KBZ Pay, AYA or Yoma directly; Wave Money and CyberSource have no status API.

Checking the status when the callback is lateYour appKBZ PayCallback late or missingAsk for the order statuskbzPay()->status($orderId)PaymentStatusResulttrade_status, e.g. PAY_SUCCESSSuccessful? Fulfill oncesame checks as the callbackNot final? Check again later$result->status->isFinal()
Checking the status when the callback is late

When a callback is late or missing, ask the gateway directly. Status checks return a PaymentStatusResult with the same status, gatewayStatus, gatewayReference and amount fields.

GatewayCall
KBZ PayMyanmarPayments::kbzPay()->status($orderId)
AYA Payment GatewayMyanmarPayments::ayaPay()->status($orderId)
Yoma MMQRMyanmarPayments::yomaMmqr()->status($payment->reference)
Wave MoneyNo status API: rely on the callback
CyberSourceNo status API: rely on the callback
php
$result = MyanmarPayments::kbzPay()->status('ORDER_'.$order->id);

if ($result->isSuccessful()) {
    // ...
}

See PaymentCallback & Status for every property.

Released under the MIT License, except where a package says otherwise.