> ## Documentation Index
> Fetch the complete documentation index at: https://docs.avraapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MarxPay

> Use MarxPay redirect checkout, configured tender variants, return binding, initiation, and order-summary retrieval.

## When to use MarxPay

MarxPay is a one-time, redirect-only checkout for a project that has MarxPay tender variants enabled in its Gateway Vault. Use the shared `createOrder()` function to prepare checkout; use the functions below only on your backend to bind and inspect a MarxPay return safely.

| Capability | Support |
| - | - |
| Checkout mode | `redirect` only |
| Tender variants | `OTHER`, `AMEX`, `OTHER_USD`, `AMEX_USD`, `PAY_BY_BANK_ACCOUNT` |
| PHP SDK | Return verification, initiation, and order-summary retrieval released |
| Laravel SDK | Released through the `AvraAPI::payment()` Facade accessor |
| Node.js SDK | Released: return verification, payment initiation, and order-summary retrieval. |
| Payment Elements | Separate cards for enabled tender variants, followed by a redirect hand-off |

<Note>
  The shared UPG lifecycle—availability, `createOrder()`, and `completePayment()`—is documented in [Quick Setup](/universal-payment-gateway/quick-setup). This page covers only MarxPay-specific functions.
</Note>

## SDK Functions

<Tabs>
  <Tab title="PHP SDK">
    | Function | Purpose |
    | - | - |
    | `payment()->marxpay()->verifyReturn()` | Confirms returned `merchantRID` and `trId` match the binding saved with your pending order. |
    | `payment()->marxpay()->initiatePayment()` | Starts the provider-side payment only for a verified, bound MarxPay transaction. |
    | `payment()->marxpay()->retrieveOrderSummary()` | Retrieves the safe current summary for a known, bound MarxPay transaction. |
  </Tab>

  <Tab title="Laravel SDK">
    | Function | Purpose |
    | - | - |
    | Laravel Facade | Use `AvraAPI::payment()` with the released typed helpers shown in the Laravel samples below. |
  </Tab>

  <Tab title="Node.js SDK">
    | Function | Purpose |
    | - | - |
    | `client.payment().marxpay().verifyReturn()` | Verifies returned transaction binding before initiation. |
    | `client.payment().marxpay().initiatePayment()` | Initiates the verified MarxPay transaction. |
    | `client.payment().marxpay().retrieveOrderSummary()` | Retrieves one provider order summary. |
  </Tab>
</Tabs>

## Verify a browser return

The browser return contains `merchantRID` and `trId`. Those values are identifiers, not payment proof. Compare them against the pair your backend saved when it created the checkout session before doing anything else.

<Tabs>
  <Tab title="PHP SDK">
    ```php theme={null}
    use Avraapi\Apix\Payments\GatewayEnvironment;
    use Avraapi\Apix\Payments\MarxPay\MarxPayReturnVerificationOptions;

    $verification = $apix->payment()
        ->marxpay()
        ->verifyReturn(new MarxPayReturnVerificationOptions(
            returnedMerchantRid: (string) ($_GET['merchantRID'] ?? ''),
            returnedTrId: (string) ($_GET['trId'] ?? ''),
            expectedMerchantRid: $order->merchant_rid,
            expectedTrId: $order->marxpay_tr_id,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        ));
    ```

    **SDK response** — `MarxPayReturnVerification`:

    ```json theme={null}
    {
      "verified": true,
      "merchant_rid": "ORDER-2026-000184",
      "tr_id": "MP-320000000000",
      "request_id": "01j..."
    }
    ```

    The SDK exposes these as `$verification->verified`, `$verification->merchantRid`, `$verification->trId`, and `$verification->requestId`. A mismatch raises an exception; do not change order state.
  </Tab>

  <Tab title="Laravel SDK">
    ```php theme={null}
    use Avraapi\Laravel\Facades\AvraAPI;

    use Avraapi\Apix\Payments\GatewayEnvironment;
    use Avraapi\Apix\Payments\MarxPay\MarxPayReturnVerificationOptions;

    $verification = AvraAPI::payment()
        ->marxpay()
        ->verifyReturn(new MarxPayReturnVerificationOptions(
            returnedMerchantRid: (string) ($_GET['merchantRID'] ?? ''),
            returnedTrId: (string) ($_GET['trId'] ?? ''),
            expectedMerchantRid: $order->merchant_rid,
            expectedTrId: $order->marxpay_tr_id,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        ));
    ```
  </Tab>

  <Tab title="Node.js SDK">
    ```ts theme={null}
    import {
      GatewayEnvironment,
      MarxPayReturnVerificationOptions,
    } from '@avraapi/node-sdk';

    const verifiedReturn = await client.payment().marxpay().verifyReturn(
      new MarxPayReturnVerificationOptions({
        returnedMerchantRid: String(request.query.merchantRID ?? ''),
        returnedTrId: String(request.query.trId ?? ''),
        expectedMerchantRid: order.id,
        expectedTrId: order.gatewayTransactionId,
        gatewayEnvironment: GatewayEnvironment.Sandbox,
      }),
    );
    ```
  </Tab>
</Tabs>

## Initiate a verified MarxPay payment

Use this function only after `verifyReturn()` succeeds for the same saved `merchantRID` and `trId`. It asks MarxPay to initiate the bound transaction. It does not replace the final common UPG completion step.

<Tabs>
  <Tab title="PHP SDK">
    ```php theme={null}
    use Avraapi\Apix\Payments\GatewayEnvironment;
    use Avraapi\Apix\Payments\MarxPay\MarxPayInitiatePaymentOptions;

    $result = $apix->payment()
        ->marxpay()
        ->initiatePayment(new MarxPayInitiatePaymentOptions(
            trId: $order->marxpay_tr_id,
            merchantRid: $order->merchant_rid,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        ));
    ```

    **SDK response** — `MarxPayPaymentResult`:

    ```json theme={null}
    {
      "merchant_rid": "ORDER-2026-000184",
      "tr_id": "MP-320000000000",
      "payment_status": "pending",
      "provider_status": "PENDING",
      "amount": "12000.00",
      "currency": "LKR",
      "payment_method": "OTHER",
      "expires_at": "2026-09-28T12:30:00+00:00",
      "request_id": "01j..."
    }
    ```

    The PHP object properties are `$result->merchantRid`, `$result->trId`, `$result->paymentStatus`, `$result->providerStatus`, `$result->amount`, `$result->currency`, `$result->paymentMethod`, `$result->expiresAt`, and `$result->requestId`. `payment_status` can be `succeeded`, `pending`, `failed`, or `unknown`; a started payment is not automatically a completed payment.
  </Tab>

  <Tab title="Laravel SDK">
    ```php theme={null}
    use Avraapi\Laravel\Facades\AvraAPI;

    use Avraapi\Apix\Payments\GatewayEnvironment;
    use Avraapi\Apix\Payments\MarxPay\MarxPayInitiatePaymentOptions;

    $result = AvraAPI::payment()
        ->marxpay()
        ->initiatePayment(new MarxPayInitiatePaymentOptions(
            trId: $order->marxpay_tr_id,
            merchantRid: $order->merchant_rid,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        ));
    ```
  </Tab>

  <Tab title="Node.js SDK">
    ```ts theme={null}
    import { MarxPayInitiatePaymentOptions } from '@avraapi/node-sdk';

    const payment = await client.payment().marxpay().initiatePayment(
      new MarxPayInitiatePaymentOptions({
        trId: verifiedReturn.trId,
        merchantRid: verifiedReturn.merchantRid,
      }),
    );
    ```
  </Tab>
</Tabs>

## Retrieve an order summary

Use this read-only function to retrieve the current safe summary for the same transaction. It validates that the returned provider data belongs to the supplied `merchantRid` and `trId` before mapping the result.

<Tabs>
  <Tab title="PHP SDK">
    ```php theme={null}
    use Avraapi\Apix\Payments\GatewayEnvironment;

    $summary = $apix->payment()
        ->marxpay()
        ->retrieveOrderSummary(
            trId: $order->marxpay_tr_id,
            merchantRid: $order->merchant_rid,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response** — `MarxPayPaymentResult`:

    ```json theme={null}
    {
      "merchant_rid": "ORDER-2026-000184",
      "tr_id": "MP-320000000000",
      "payment_status": "succeeded",
      "provider_status": "SUCCESS",
      "amount": "12000.00",
      "currency": "LKR",
      "payment_method": "OTHER",
      "expires_at": "2026-09-28T12:30:00+00:00",
      "request_id": "01j..."
    }
    ```

    This is a safe SDK projection. Raw MarxPay gateway and card data are intentionally not returned.
  </Tab>

  <Tab title="Laravel SDK">
    ```php theme={null}
    use Avraapi\Laravel\Facades\AvraAPI;

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $summary = AvraAPI::payment()
        ->marxpay()
        ->retrieveOrderSummary(
            trId: $order->marxpay_tr_id,
            merchantRid: $order->merchant_rid,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

  <Tab title="Node.js SDK">
    ```ts theme={null}
    import { GatewayEnvironment } from '@avraapi/node-sdk';

    const summary = await client.payment().marxpay().retrieveOrderSummary(
      order.gatewayTransactionId,
      order.id,
      GatewayEnvironment.Sandbox,
    );
    ```
  </Tab>
</Tabs>

## Payment Elements

When server-side availability returns more than one enabled MarxPay tender, Payment Elements renders each one as a separate method card. Each card keeps `gateway: 'marxpay'` and `mode: 'redirect'`, then sends the selected tender as `providerOptions.payment_method` to your backend.

```js theme={null}
elements.renderMethods('#payment-methods', {
  methods: [{
    gateway: 'marxpay',
    mode: 'redirect',
    label: 'Cards — USD',
    description: 'Visa, Mastercard, or UnionPay in USD.',
    providerOptions: { payment_method: 'OTHER_USD' },
  }],
});
```

For rendering, events, visual customization, and checkout lifecycle details, see [More Payment Elements features](/universal-payment-gateway/payment-elements/overview).

## Gateway-specific options

`providerOptions.payment_method` accepts only `OTHER`, `AMEX`, `OTHER_USD`, `AMEX_USD`, and `PAY_BY_BANK_ACCOUNT`.

* `OTHER` and `AMEX` are LKR-only.
* `OTHER_USD` and `AMEX_USD` are USD-only.
* `PAY_BY_BANK_ACCOUNT` is available only if the connected MarxPay merchant account enables it.
* Omitting the option defaults to `OTHER` for LKR and `OTHER_USD` for USD.

AvraAPI validates the tender against the order currency and enabled Gateway Vault payment methods. A browser selection never overrides that check.

## Completion, webhooks, and safety

Even after a successful return binding or order-summary call, a browser return is not payment proof. Preserve the original server-only completion context and call common `completePayment()` for the final reconciliation and canonical payment result. Do not send `merchantRID`, `trId`, or summary data into client-controlled state.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.