Skip to main content
UPG has three different failure paths. Treating them as one creates unsafe retries and confusing buyer messages:
  1. Availability is a successful, browser-safe preflight response. It tells you not to begin checkout.
  2. SDK exceptions mean the request did not complete successfully. Handle them on your backend by exception type and request ID.
  3. Completion results can be valid but non-final. A pending, failed, cancelled, or unknown result is not an exception and must not be treated as a successful order.
Never return a signed completion context, gateway credentials, raw callback body, native provider response, or exception->getPayload() to the buyer. Store the request ID in protected backend logs and show the buyer only a safe next step.

The API error envelope

For a non-2xx API response, the PHP SDK throws a typed exception. The source response uses this shape:
request_id, error.code, and the HTTP status are stable backend diagnostic inputs. The human-readable message and optional details can change as validation improves, so do not build application logic around exact message text.

Start with availability, not an error

Call availability() before rendering a new checkout. It returns PaymentAvailability, not an exception, when an active UPG slot or usable configuration is absent. Its payload is public and can safely be sent to Payment Elements. project_paused is also part of the public availability-reason enum, but a paused project is normally rejected by project authentication with HTTP 503 before UPG availability can be returned. Because the PHP SDK maps its UPG-specific error code before general HTTP status, it surfaces as PaymentAccessException.
SDK response — unavailable availability result:
Refresh availability from your backend if the buyer leaves checkout open for a long time. A UPG slot or gateway configuration can change after a page first rendered. Do not use a cached method list to bypass the new-checkout authorization check.

PHP SDK exception mapping

Every SDK-specific exception extends ApixException. You can catch that base class for logging, but payment flows should first handle the more specific type below. The PHP SDK maps by payment error-code prefix before its general HTTP-status mapping. payment_validation_error begins with payment_, so the current PHP SDK maps it to PaymentProviderException even when the HTTP response is 422. This is intentional: use getErrorCode() rather than assuming a type from the status code alone.

Handle a new-checkout exception safely

Create a provider checkout session only on your backend. Do not automatically repeat a failed createOrder() call after a timeout or network error: the provider may have received the first request even if your application did not receive its response.
Your application response — safe buyer-facing result:
The example intentionally keeps the gateway error code and request ID on the backend. Your application can show a friendly unavailable or retry-later message without exposing configuration or provider diagnostics.

Completion can be valid but non-final

Completion is different from new checkout. A valid completion context issued before a slot is released can still be verified so an existing payment is not abandoned. completePayment() may return a valid PaymentCompletionResult instead of throwing an exception.
SDK response — non-final completion result:
nativeOperations and include are server-only response fields. The normal default is the short response; never forward full() or provider-native included fields to a browser.

Callback verification failures

If completePayment() throws PaymentVerificationException, do not retry the same modified callback or mark the order paid. It represents a payment_callback_* error such as a malformed callback, invalid callback signature, or callback/order mismatch. Some gateways report signature failures under other payment_* codes and therefore surface as PaymentProviderException. The safe response is the same: keep the order unfulfilled, preserve the original evidence only in protected backend diagnostics, and investigate with the request ID.

Retry rules

What to log and what to show

Log only on the backend: request ID, stable error code, HTTP status, gateway code, your own pending-order ID, and safe reconciliation metadata. Keep callback signatures, completion contexts, raw bodies, provider-native fields, credentials, and customer/payment data out of logs unless a protected incident process explicitly requires them. For buyers, use short messages such as “Payment methods are unavailable”, “Please try again later”, “Your payment is still being confirmed”, or “This payment was not completed.” Do not expose a gateway-specific failure reason or imply success until verified is true and paymentStatus is succeeded.
Last modified on October 1, 2026