> ## 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.

# PayHere

> Use PayHere checkout and advanced payment operations through the AvraAPI Universal Payment Gateway.

## When to use PayHere

Use PayHere for LKR or USD one-time checkout, a PayHere overlay, or advanced operations such as retrieval, refunds, recurring billing, preapprovals, authorizations, token charges, and captures.

Every operation on this page runs from your backend. Your browser must never receive a PayHere Merchant Secret, Merchant API App Secret, access token, customer token, authorization token, or UPG `completionContext`.

| Capability | Support |
| - | - |
| One-time checkout | `redirect`, `overlay` |
| Currency | LKR and USD |
| PHP SDK | Released for all functions below |
| Laravel SDK | Released through the `AvraAPI::payment()` Facade accessor |
| Node.js SDK | Released: retrieval, refunds, recurring, subscriptions, preapprovals, authorizations, token charges, and captures. |
| Payment Elements | Standard redirect hand-off and PayHere overlay |

<Note>
  Common `availability()`, `createOrder()`, and `completePayment()` are documented in [Quick Setup](/universal-payment-gateway/quick-setup). This page documents PayHere-specific functions only.
</Note>

## Shared data for session-creating functions

Recurring, preapproval, and authorization functions create a `PaymentSession`. Its public `checkout` instructions may be sent to the browser. Its `completionContext` is server-only and must be saved with your pending order.

```json theme={null}
{
  "gateway": "payhere",
  "mode": "redirect",
  "status": "prepared",
  "expires_at": "2026-09-28T12:30:00+00:00",
  "checkout": {
    "type": "redirect_form"
  },
  "request_id": "01j...",
  "flow": "preapproval",
  "binding": {
    "order_id": "ORDER-2026-000184"
  },
  "verification": {
    "callback_signature_required": true
  }
}
```

The SDK maps this response to `PaymentSession`: `$session->gateway`, `$session->mode`, `$session->status`, `$session->checkout`, `$session->requestId`, `$session->flow`, `$session->binding`, `$session->verification`, and `$session->completionContext`.

## Retrieve payments by order ID

Use retrieval when your backend needs a privacy-safe projection of payments associated with one of your own order IDs. It is read-only and does not replace `completePayment()` for a newly received callback.

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

    $payments = $apix->payment()
        ->payhere()
        ->retrieval()
        ->findByOrderId(
            orderId: 'ORDER-2026-000184',
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response** — a list of safe payment projections:

    ```json theme={null}
    [
      {
        "provider_reference": "320000000000",
        "order_id": "ORDER-2026-000184",
        "status": "SUCCESS",
        "amount": "12000.00",
        "currency": "LKR"
      }
    ]
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $payments = AvraAPI::payment()
        ->payhere()
        ->retrieval()
        ->findByOrderId(
            orderId: 'ORDER-2026-000184',
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

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

    const payments = await client.payment().payhere().retrieval().findByOrderId(
      'ORDER-2026-000184',
      GatewayEnvironment.Sandbox,
    );
    ```
  </Tab>
</Tabs>

## Create a full or partial refund

Use this backend-only command to refund a settled PayHere payment or to release an authorization. Provide **exactly one** of `paymentId` or `authorizationToken`, a clear `description`, a durable idempotency key, and `confirmRefund: true`.

* Omit `amount` for a full refund.
* Set `amount` to a positive decimal string, such as `'100.50'`, for a partial refund.
* Reuse the same idempotency key if your application timed out and the outcome is unknown. A different key is a new financial command.

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

    // Full refund: omit amount.
    $fullRefund = $apix->payment()
        ->payhere()
        ->refunds()
        ->create(
            idempotencyKey: 'refund-order-2026-000184-v1',
            paymentId: '320000000000',
            authorizationToken: null,
            description: 'Customer-requested return',
            confirmRefund: true,
            amount: null,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );

    // Partial refund: set amount explicitly.
    $partialRefund = $apix->payment()
        ->payhere()
        ->refunds()
        ->create(
            idempotencyKey: 'refund-order-2026-000184-partial-v1',
            paymentId: '320000000000',
            authorizationToken: null,
            description: 'Partial item return',
            confirmRefund: true,
            amount: '100.50',
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response** — AvraAPI returns a safe command projection, not PayHere's raw OAuth response:

    ```json theme={null}
    {
      "command_accepted": true,
      "provider_status": "1",
      "provider_reference": "560034010257"
    }
    ```

    `provider_status` reflects PayHere's status value. PayHere documents `1` as success, `0` as an initiation error, and `-1` as a failed refund; inspect your controlled error handling for rejected requests.
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    // Full refund: omit amount.
    $fullRefund = AvraAPI::payment()
        ->payhere()
        ->refunds()
        ->create(
            idempotencyKey: 'refund-order-2026-000184-v1',
            paymentId: '320000000000',
            authorizationToken: null,
            description: 'Customer-requested return',
            confirmRefund: true,
            amount: null,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );

    // Partial refund: set amount explicitly.
    $partialRefund = AvraAPI::payment()
        ->payhere()
        ->refunds()
        ->create(
            idempotencyKey: 'refund-order-2026-000184-partial-v1',
            paymentId: '320000000000',
            authorizationToken: null,
            description: 'Partial item return',
            confirmRefund: true,
            amount: '100.50',
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

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

    const refund = await client.payment().payhere().refunds().create({
      idempotencyKey: 'refund-order-2026-000184-v1',
      paymentId: '320000000000',
      description: 'Customer-requested return',
      confirmRefund: true,
      amount: '100.50', // Omit for a full refund.
      gatewayEnvironment: GatewayEnvironment.Sandbox,
    });
    ```
  </Tab>
</Tabs>

<Warning>
  Do not generate a refund idempotency key from a timestamp alone, and never make this call from browser code.
</Warning>

## Create a recurring checkout session

Use a recurring session to obtain the buyer's approval for scheduled PayHere subscription payments. `recurrence` accepts values such as `'1 Month'`; `duration` accepts `'Forever'` or a value such as `'1 Year'`.

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

    $session = $apix->payment()
        ->payhere()
        ->recurring()
        ->create(new RecurringOrderOptions(
            gateway: GatewayCode::PayHere,
            mode: CheckoutMode::Redirect,
            orderId: 'SUB-2026-000184',
            items: 'Premium membership',
            amount: '2500.00',
            currency: 'LKR',
            customer: $customer,
            urls: $urls,
            recurrence: '1 Month',
            duration: '1 Year',
            startupFee: null,
            recurringStartDate: null,
            autoCancel: true,
            maxRetries: 3,
            isRecoveryDue: null,
            merchantDomain: 'shop.example.com',
        ));
    ```

    **SDK response** — `PaymentSession`. See the shared session response above. Save `$session->completionContext`; send only `$session->checkout` to the buyer.
  </Tab>

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

    use Avraapi\Apix\Payments\CheckoutMode;
    use Avraapi\Apix\Payments\GatewayCode;
    use Avraapi\Apix\Payments\RecurringOrderOptions;

    $session = AvraAPI::payment()
        ->payhere()
        ->recurring()
        ->create(new RecurringOrderOptions(
            gateway: GatewayCode::PayHere,
            mode: CheckoutMode::Redirect,
            orderId: 'SUB-2026-000184',
            items: 'Premium membership',
            amount: '2500.00',
            currency: 'LKR',
            customer: $customer,
            urls: $urls,
            recurrence: '1 Month',
            duration: '1 Year',
            startupFee: null,
            recurringStartDate: null,
            autoCancel: true,
            maxRetries: 3,
            isRecoveryDue: null,
            merchantDomain: 'shop.example.com',
        ));
    ```
  </Tab>

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

    const session = await client.payment().payhere().recurring().create(
      new RecurringOrderOptions({
        gateway: GatewayCode.PayHere,
        mode: CheckoutMode.Redirect,
        orderId: 'SUB-2026-000184', items: 'Premium membership',
        amount: '2500.00', currency: 'LKR', customer, urls,
        recurrence: '1 Month', duration: '1 Year', autoCancel: true, maxRetries: 3,
        merchantDomain: 'shop.example.com',
      }),
    );
    ```
  </Tab>
</Tabs>

## Create a preapproval session

Use preapproval to obtain a PayHere customer token for a later backend-only automated charge. The token is returned in the verified provider callback; your application is responsible for storing it securely. AvraAPI does not retain it.

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

    $session = $apix->payment()
        ->payhere()
        ->preapprovals()
        ->create(new PreapprovalOptions(
            orderId: 'PREAPPROVAL-2026-000184',
            items: 'Premium membership',
            currency: 'LKR',
            customer: $customer,
            urls: $urls,
            amount: '2500.00', // Optional. Omit to use PayHere's preapproval amount.
            merchantDomain: 'shop.example.com',
        ));
    ```

    **SDK response** — `PaymentSession` with `flow: 'preapproval'`. The authorization result and customer token are received later through the verified callback; they are not part of the checkout-session response.
  </Tab>

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

    use Avraapi\Apix\Payments\PreapprovalOptions;

    $session = AvraAPI::payment()
        ->payhere()
        ->preapprovals()
        ->create(new PreapprovalOptions(
            orderId: 'PREAPPROVAL-2026-000184',
            items: 'Premium membership',
            currency: 'LKR',
            customer: $customer,
            urls: $urls,
            amount: '2500.00', // Optional. Omit to use PayHere's preapproval amount.
            merchantDomain: 'shop.example.com',
        ));
    ```
  </Tab>

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

    const session = await client.payment().payhere().preapprovals().create(
      new PreapprovalOptions({
        orderId: 'PREAPPROVAL-2026-000184', items: 'Premium membership',
        currency: 'LKR', amount: '2500.00', customer, urls,
        merchantDomain: 'shop.example.com',
      }),
    );
    ```
  </Tab>
</Tabs>

## Create an authorization hold session

Use authorization when you need to hold a customer's funds and capture the full or lower approved amount later. PayHere sends the authorization token through its verified `notify_url` callback; use that token only from your backend.

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

    $session = $apix->payment()
        ->payhere()
        ->authorizations()
        ->create(new AuthorizationOptions(
            new CreateOrderOptions(
                gateway: GatewayCode::PayHere,
                mode: CheckoutMode::Redirect,
                orderId: 'AUTH-2026-000184',
                items: 'Hotel reservation hold',
                amount: '12000.00',
                currency: 'LKR',
                customer: $customer,
                urls: $urls,
                merchantDomain: 'shop.example.com',
            ),
        ));
    ```

    **SDK response** — `PaymentSession` with `flow: 'authorization'`. A verified authorization callback can later contain the merchant-owned authorization token. Browser return data does not prove the hold was authorised.
  </Tab>

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

    use Avraapi\Apix\Payments\AuthorizationOptions;
    use Avraapi\Apix\Payments\CheckoutMode;
    use Avraapi\Apix\Payments\CreateOrderOptions;
    use Avraapi\Apix\Payments\GatewayCode;

    $session = AvraAPI::payment()
        ->payhere()
        ->authorizations()
        ->create(new AuthorizationOptions(
            new CreateOrderOptions(
                gateway: GatewayCode::PayHere,
                mode: CheckoutMode::Redirect,
                orderId: 'AUTH-2026-000184',
                items: 'Hotel reservation hold',
                amount: '12000.00',
                currency: 'LKR',
                customer: $customer,
                urls: $urls,
                merchantDomain: 'shop.example.com',
            ),
        ));
    ```
  </Tab>

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

    const session = await client.payment().payhere().authorizations().create(
      new AuthorizationOptions(new CreateOrderOptions({
        gateway: GatewayCode.PayHere, mode: CheckoutMode.Redirect,
        orderId: 'AUTH-2026-000184', items: 'Hotel reservation hold',
        amount: '12000.00', currency: 'LKR', customer, urls,
        merchantDomain: 'shop.example.com',
      })),
    );
    ```
  </Tab>
</Tabs>

## List subscriptions

Use this read-only function to list the safe subscription projections available to the configured PayHere profile.

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

    $subscriptions = $apix->payment()
        ->payhere()
        ->subscriptions()
        ->all(GatewayEnvironment::Sandbox);
    ```

    **SDK response** — a list of `SubscriptionSummary` objects:

    ```json theme={null}
    [
      {
        "subscription_id": "123",
        "order_id": "SUB-2026-000184",
        "status": "ACTIVE",
        "amount": "2500.00",
        "currency": "LKR",
        "recurrence": "1 Month"
      }
    ]
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $subscriptions = AvraAPI::payment()
        ->payhere()
        ->subscriptions()
        ->all(GatewayEnvironment::Sandbox);
    ```
  </Tab>

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

    const subscriptions = await client.payment().payhere().subscriptions().all(
      GatewayEnvironment.Sandbox,
    );
    ```
  </Tab>
</Tabs>

## Get one subscription

Use this read-only function for one known PayHere numeric subscription ID.

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

    $subscription = $apix->payment()
        ->payhere()
        ->subscriptions()
        ->find('123', GatewayEnvironment::Sandbox);
    ```

    **SDK response** — one `SubscriptionSummary` object:

    ```json theme={null}
    {
      "subscription_id": "123",
      "order_id": "SUB-2026-000184",
      "status": "ACTIVE",
      "amount": "2500.00",
      "currency": "LKR",
      "recurrence": "1 Month"
    }
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $subscription = AvraAPI::payment()
        ->payhere()
        ->subscriptions()
        ->find('123', GatewayEnvironment::Sandbox);
    ```
  </Tab>

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

    const subscription = await client.payment().payhere().subscriptions().find(
      '123', GatewayEnvironment.Sandbox,
    );
    ```
  </Tab>
</Tabs>

## List payments for a subscription

Use this read-only function to inspect privacy-safe payment projections for one known PayHere subscription.

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

    $payments = $apix->payment()
        ->payhere()
        ->subscriptions()
        ->payments('123', GatewayEnvironment::Sandbox);
    ```

    **SDK response**:

    ```json theme={null}
    [
      {
        "provider_reference": "320000000001",
        "order_id": "SUB-2026-000184",
        "status": "SUCCESS",
        "amount": "2500.00",
        "currency": "LKR"
      }
    ]
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $payments = AvraAPI::payment()
        ->payhere()
        ->subscriptions()
        ->payments('123', GatewayEnvironment::Sandbox);
    ```
  </Tab>

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

    const payments = await client.payment().payhere().subscriptions().payments(
      '123', GatewayEnvironment.Sandbox,
    );
    ```
  </Tab>
</Tabs>

## Retry a subscription payment

This is a state-changing command. It requires a durable idempotency key and `confirmRetry: true`.

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

    $result = $apix->payment()
        ->payhere()
        ->subscriptions()
        ->retry(
            idempotencyKey: 'subscription-retry-123-v1',
            subscriptionId: '123',
            confirmRetry: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response** — `SubscriptionCommandResult`:

    ```json theme={null}
    {
      "accepted": true,
      "provider_status": "1",
      "subscription_id": "123"
    }
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $result = AvraAPI::payment()
        ->payhere()
        ->subscriptions()
        ->retry(
            idempotencyKey: 'subscription-retry-123-v1',
            subscriptionId: '123',
            confirmRetry: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

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

    const result = await client.payment().payhere().subscriptions().retry({
      idempotencyKey: 'subscription-retry-123-v1', subscriptionId: '123',
      confirmRetry: true, gatewayEnvironment: GatewayEnvironment.Sandbox,
    });
    ```
  </Tab>
</Tabs>

## Cancel a subscription

This is a state-changing command. It requires a durable idempotency key and `confirmCancel: true`.

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

    $result = $apix->payment()
        ->payhere()
        ->subscriptions()
        ->cancel(
            idempotencyKey: 'subscription-cancel-123-v1',
            subscriptionId: '123',
            confirmCancel: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response** — `SubscriptionCommandResult`:

    ```json theme={null}
    {
      "accepted": true,
      "provider_status": "1",
      "subscription_id": "123"
    }
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $result = AvraAPI::payment()
        ->payhere()
        ->subscriptions()
        ->cancel(
            idempotencyKey: 'subscription-cancel-123-v1',
            subscriptionId: '123',
            confirmCancel: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

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

    const result = await client.payment().payhere().subscriptions().cancel({
      idempotencyKey: 'subscription-cancel-123-v1', subscriptionId: '123',
      confirmCancel: true, gatewayEnvironment: GatewayEnvironment.Sandbox,
    });
    ```
  </Tab>
</Tabs>

## Create an automated token charge

Use this backend-only command after your application has safely stored a PayHere customer token received from a verified preapproval callback. It requires an enabled Automated Charging permission, a durable idempotency key, and `confirmCharge: true`.

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

    $charge = $apix->payment()
        ->payhere()
        ->charges()
        ->create(
            idempotencyKey: 'charge-order-2026-000185-v1',
            orderId: 'ORDER-2026-000185',
            items: 'Annual membership renewal',
            currency: 'LKR',
            amount: '12000.00',
            customerToken: $customerToken,
            confirmCharge: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response**:

    ```json theme={null}
    {
      "command_accepted": true,
      "provider_status": "1",
      "provider_reference": "320000000001",
      "order_id": "ORDER-2026-000185",
      "amount": "12000.00",
      "currency": "LKR"
    }
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $charge = AvraAPI::payment()
        ->payhere()
        ->charges()
        ->create(
            idempotencyKey: 'charge-order-2026-000185-v1',
            orderId: 'ORDER-2026-000185',
            items: 'Annual membership renewal',
            currency: 'LKR',
            amount: '12000.00',
            customerToken: $customerToken,
            confirmCharge: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

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

    const charge = await client.payment().payhere().charges().create({
      idempotencyKey: 'charge-order-2026-000185-v1', orderId: 'ORDER-2026-000185',
      items: 'Annual membership renewal', currency: 'LKR', amount: '12000.00',
      customerToken, confirmCharge: true, gatewayEnvironment: GatewayEnvironment.Sandbox,
    });
    ```
  </Tab>
</Tabs>

## Capture an authorization

Use this backend-only command to capture an existing PayHere authorization. The requested capture amount cannot exceed `expectedAuthorizedAmount`. Bind the command to the expected order, currency, and authorisation details to prevent a mismatched capture.

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

    $capture = $apix->payment()
        ->payhere()
        ->captures()
        ->create(
            idempotencyKey: 'capture-auth-2026-000184-v1',
            authorizationToken: $authorizationToken,
            amount: '10000.00',
            expectedAuthorizedAmount: '12000.00',
            expectedOrderId: 'AUTH-2026-000184',
            currency: 'LKR',
            deductionDetails: 'Final reservation amount',
            confirmCapture: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```

    **SDK response**:

    ```json theme={null}
    {
      "command_accepted": true,
      "provider_status": "1",
      "provider_reference": "320000000002",
      "order_id": "AUTH-2026-000184",
      "amount": "10000.00",
      "currency": "LKR"
    }
    ```
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayEnvironment;

    $capture = AvraAPI::payment()
        ->payhere()
        ->captures()
        ->create(
            idempotencyKey: 'capture-auth-2026-000184-v1',
            authorizationToken: $authorizationToken,
            amount: '10000.00',
            expectedAuthorizedAmount: '12000.00',
            expectedOrderId: 'AUTH-2026-000184',
            currency: 'LKR',
            deductionDetails: 'Final reservation amount',
            confirmCapture: true,
            gatewayEnvironment: GatewayEnvironment::Sandbox,
        );
    ```
  </Tab>

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

    const capture = await client.payment().payhere().captures().create({
      idempotencyKey: 'capture-auth-2026-000184-v1', authorizationToken,
      amount: '10000.00', expectedAuthorizedAmount: '12000.00',
      expectedOrderId: 'AUTH-2026-000184', currency: 'LKR',
      deductionDetails: 'Final reservation amount', confirmCapture: true,
      gatewayEnvironment: GatewayEnvironment.Sandbox,
    });
    ```
  </Tab>
</Tabs>

## Payment Elements

Payment Elements can render PayHere as a redirect method or provider overlay. It does not expose PayHere advanced Merchant API commands to browser code.

```js theme={null}
elements.renderMethods('#payment-methods', {
  methods: [{
    gateway: 'payhere',
    mode: 'overlay',
    label: 'Credit or debit card — PayHere',
    description: 'Secure payment opens in a provider overlay.',
  }],
});
```

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

## Gateway-specific options

For one-time PayHere checkout, `providerOptions` can include `delivery_address`, `delivery_city`, `delivery_country`, `custom_1`, `custom_2`, and `payment_method`. These are non-secret, server-validated provider fields. Do not use them for merchant secrets, App Secrets, access tokens, customer tokens, authorization tokens, callback URLs, or payment status.

## Completion, webhooks, and safety

PayHere's `notify_url` is the authoritative payment signal for checkout, recurring sessions, preapprovals, and authorization holds. Preserve callback fields and call common `completePayment()` using the pending order's stored completion context. A browser return or Payment Elements event can update the UI but cannot mark an order paid.

For provider API background and provider response codes, see PayHere's official [Refund API](https://support.payhere.lk/api-%26-mobile-sdk/refund-api), [Retrieval API](https://support.payhere.lk/api-%26-mobile-sdk/retrieval-api), [Recurring API](https://support.payhere.lk/api-%26-mobile-sdk/recurring-api), [Preapproval API](https://support.payhere.lk/api-%26-mobile-sdk/preapproval-api), [Authorize API](https://support.payhere.lk/api-%26-mobile-sdk/authorize-api), [Subscription Manager API](https://support.payhere.lk/api-%26-mobile-sdk/subscription-manager-api), [Charging API](https://support.payhere.lk/api-%26-mobile-sdk/charging-api), and [Capture API](https://support.payhere.lk/api-%26-mobile-sdk/capture-api) documentation.


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