Skip to main content
completePayment() turns authenticated provider evidence into one gateway-neutral payment result. It is the only result your application should use when deciding whether to fulfil an order. The integration rules on this page apply to every AvraAPI SDK. Laravel 1.2.0 uses AvraAPI::payment() and Node.js SDK 1.2.0 uses client.payment() with the same typed payment options, completion result, and server-only safety rules.
A redirect return, an overlay event, or a browser success screen is not payment proof. Do not mark an order paid until your backend receives and evaluates completePayment().

The completion sequence

  1. Look up the pending order using a trusted provider reference or an opaque return token that your backend created.
  2. Load the stored completionContext for that exact order.
  3. Preserve provider callback or return data in its gateway-required format.
  4. Call completePayment() from the webhook, callback, or server return handler.
  5. Fulfil only a verified result with paymentStatus === PaymentStatus::Succeeded.
  6. Make the order update idempotent because providers can send the same callback more than once.

1. Set the GatewayCode

Use the gateway stored with the pending order. Do not trust a browser query parameter to choose it.

2. Load the saved completionContext

The context returned by createOrder() is signed, server-only evidence that binds completion to one prepared payment session. Load it from protected order storage.
Never rebuild, guess, expose, or accept this value from a browser request.

3. Preserve the provider payload exactly

Each gateway has its own callback or return shape. Preserve raw bodies and signature headers where the provider requires them, then use the gateway-specific SDK payload wrapper. Do not parse and re-encode signed provider data before the wrapper receives it. For the required payload type and exact callback/return handling for each gateway, see Gateway-wise Functions.

4. Response option: PaymentResponseOptions::short()

short() is the default and recommended production response. It returns the normalized payment result needed for fulfilment without provider-native diagnostic bodies.

Actual response shape

This is the raw HTTP response envelope returned by AvraAPI to the SDK transport. Values such as order IDs, provider statuses, and references vary per real payment; the field names and nesting below are the actual completion contract.
success: true means AvraAPI processed the completion request successfully. It does not mean the buyer paid. Always decide what to do from data.verified and data.payment_status.

Failed, cancelled, pending, and unknown responses

The normalized payment_status is the same across released gateways, while provider_status remains gateway-specific. The following are representative, verified PayHere short() envelopes. Other gateways use the same field names but return their own provider status values and reconciliation details.
The callback is authentic, but the payment failed. Mark the merchant order failed without fulfilment.

The object returned by completePayment()

SDK developers do not read $response['data']. The SDK reads the raw envelope internally, extracts data and request_id, then returns a PaymentCompletionResult object. SDK integrations use object properties such as $result->amount and $result->paymentStatus->value. For example, this is the gateway-neutral result that an application can deliberately create from the SDK object for its own protected order record:
The resulting application-owned JSON can safely have this shape:

5. Response option: PaymentResponseOptions::full()

full() adds the exact provider-native operation bodies under native_operations. Use it only in a protected server-side diagnostic workflow when there is a genuine integration or support need.

Actual additional response data

full() preserves the normalized fields from short() and adds native_operations. The following is the actual PayHere callback operation structure used by the response projector; provider-native fields differ by gateway and flow.
In the PHP SDK, read this additional data through $diagnosticResult->nativeOperations, not through a data array.
full() can contain provider-native customer, masked-card, or detailed transaction fields. Do not return it to a browser, public return page, logs, analytics, cache, queue payload, or unapproved support tool.

6. Response option: PaymentResponseOptions::include()

include() returns only exact provider-native paths requested by your server. It is safer than full() when a protected workflow needs a small known set of fields.

Actual additional response data

include() preserves the normalized result, returns only selected provider data in native_operations, and reports exactly which requested paths were recognised.
Include paths must be non-empty strings and are valid only for include() mode. Use only paths documented for that gateway, and apply the same server-only handling rules as full(). In the PHP SDK, the metadata is available through $selectedResult->include and the selected operation body through $selectedResult->nativeOperations.

7. reconcileProvider option

reconcileProvider is an optional boolean on PaymentCompletionOptions. It defaults to true. When a gateway supports a secondary authenticated status observation, UPG compares it with the callback or return evidence to reduce mismatches.
Do not disable reconciliation for speed because a buyer returned to your site, closed a checkout window, or your frontend wants an earlier response. Browser events are never authoritative payment proof.
When a supported secondary provider read agrees with authenticated callback evidence, the actual reconciliation field has this shape:
If reconciliation conflicts, is unavailable, or the final state remains pending or unknown, do not fulfil. Retain the pending order and follow the gateway’s retry or support process.

Disabled — only where the gateway permits it

For a permitted PayHere signed-callback flow, disabling the optional retrieval produces this actual reconciliation shape:
This flag never bypasses signature verification or a mandatory provider lifecycle. In particular, WebXPay, OnePay, and Stripe always perform their required provider verification; MarxPay uses its mandatory provider completion lifecycle. Gateway-wise pages will document gateway-specific rules for PayHere, PayPlus, KOKO, and all future adapters.

8. Handle every outcome and fulfil exactly once

Fulfil only a verified terminal success. Your order update must be idempotent so duplicated callbacks cannot create duplicate delivery, credit, invoice, or balance changes. A verified failed or cancelled result is still useful business evidence, but it must never trigger fulfilment.
For failed and cancelled, update the pending order without fulfilment. For pending and unknown, retain the order and wait for a webhook, retry according to the provider’s rules, or send it to a controlled reconciliation workflow.

Handle completion errors without fulfilment

The SDK throws typed exceptions for unsuccessful HTTP responses. Catch them in your backend, record only safe correlation details, and leave the order unfulfilled.
See UPG Errors for error meanings and customer-safe handling guidance.

Return a safe webhook acknowledgement

After the result is processed, return a short acknowledgement to the provider. Do not echo completionContext, raw provider data, nativeOperations, or include data.
Store your merchant order ID, the provider reference, and AvraAPI request ID together. They are the useful support and reconciliation correlation records; provider secrets and raw sensitive payloads are not.
Continue to Redirect Checkout or In-page Checkout.
Last modified on October 1, 2026