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

# Stripe

> Use Stripe Checkout redirect sessions with raw webhook verification and bound session reconciliation.

## When to use Stripe

The released Stripe integration uses a server-created Stripe Checkout Session and a hosted redirect. It is not Stripe Elements. AvraAPI Payment Elements can display a Stripe card and hand the customer to the prepared Checkout URL, but all provider authentication, session creation, webhook verification, and completion stay on your backend.

| Capability | Support |
| - | - |
| Checkout mode | `redirect` only |
| PHP SDK | Stripe webhook and browser-return payload wrappers released |
| Laravel SDK | Released through the `AvraAPI::payment()` Facade accessor |
| Node.js SDK | Released: Stripe webhook and browser-return payload wrappers. |
| Payment Elements | Standard Stripe Checkout redirect hand-off |
| Completion rule | Bound Checkout Session retrieval is always required; a valid webhook is an additional signed observation |
| Not part of this release | Stripe Elements, embedded Checkout, Connect, Billing, refunds, subscriptions, payouts, and direct card collection |

<Note>
  The shared UPG lifecycle—availability, `createOrder()`, and `completePayment()`—is documented in [Quick Setup](/universal-payment-gateway/quick-setup). This page covers only Stripe-specific callback and return handling for the released Checkout flow.
</Note>

## SDK Functions

<Tabs>
  <Tab title="PHP SDK">
    | Function | Purpose |
    | - | - |
    | `new StripeWebhookPayload(...)->toArray()` | Preserves exact webhook evidence as Base64-encoded raw bytes and the `Stripe-Signature` header. |
    | `new StripeReturnPayload(...)->toArray()` | Wraps a returned Stripe Checkout Session ID as an untrusted completion trigger. |
    | `payment()->completePayment(...)` | Verifies the supported webhook event when present and retrieves the exact bound Checkout Session. |
  </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 |
    | - | - |
    | `new StripeWebhookPayload(...).toPayload()` | Preserves exact raw webhook evidence and the `Stripe-Signature` header. |
    | `new StripeReturnPayload(...).toPayload()` | Wraps an untrusted returned Checkout Session ID. |
    | `client.payment().completePayment(...)` | Verifies supported evidence and retrieves the bound Checkout Session. |
  </Tab>
</Tabs>

## Preserve a signed Stripe webhook

Stripe signature verification depends on the unchanged raw request bytes. Read the body before parsing JSON and pass the exact `Stripe-Signature` header. The wrapper Base64-encodes the raw bytes only for safe JSON transport to AvraAPI; it does not alter the bytes used for verification.

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

    $payload = new StripeWebhookPayload(
        rawBody: (string) file_get_contents('php://input'),
        stripeSignature: (string) ($_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''),
    );
    ```

    **SDK response** — `StripeWebhookPayload::toArray()`:

    ```json theme={null}
    {
      "webhook": {
        "raw_body_base64": "eyJpZCI6ImV2dF8xMjMifQ==",
        "stripe_signature": "t=...,v1=..."
      }
    }
    ```

    The original body and signature remain server-only. Do not parse then re-encode the body, and do not send it to a browser, log it, or store it in analytics.
  </Tab>

  <Tab title="Laravel SDK">
    ```php theme={null}
    use Avraapi\Apix\Payments\Stripe\StripeWebhookPayload;

    $payload = new StripeWebhookPayload(
        rawBody: (string) file_get_contents('php://input'),
        stripeSignature: (string) ($_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''),
    );
    ```
  </Tab>

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

    const rawBody = await readRawRequestBody(request); // Your server helper.
    const payload = new StripeWebhookPayload(
      rawBody,
      String(request.headers['stripe-signature'] ?? ''),
    ).toPayload();
    ```
  </Tab>
</Tabs>

## Prepare a Stripe browser-return payload

The success URL may return a Stripe Checkout Session ID beginning with `cs_`. That value identifies the prepared session but is not proof of payment. The SDK wrapper accepts only a Checkout Session ID and sends it as the `return` observation for common completion.

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

    $payload = (new StripeReturnPayload(
        sessionId: (string) ($_GET['session_id'] ?? ''),
    ))->toArray();
    ```

    **SDK response** — `StripeReturnPayload::toArray()`:

    ```json theme={null}
    {
      "return": {
        "session_id": "cs_test_..."
      }
    }
    ```

    The wrapper rejects a value that does not start with `cs_`. During completion, AvraAPI checks it against the Checkout Session ID bound when the order was created, then retrieves that session from Stripe.
  </Tab>

  <Tab title="Laravel SDK">
    ```php theme={null}
    use Avraapi\Apix\Payments\Stripe\StripeReturnPayload;

    $payload = (new StripeReturnPayload(
        sessionId: (string) ($_GET['session_id'] ?? ''),
    ))->toArray();
    ```
  </Tab>

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

    const payload = new StripeReturnPayload(
      String(request.query.session_id ?? ''),
    ).toPayload();
    ```
  </Tab>
</Tabs>

## Complete a Stripe payment

Use the stored completion context with the webhook payload or return payload. A supplied valid webhook must be one of the supported Checkout Session events; AvraAPI then retrieves the exact server-created Checkout Session, validates its binding, amount, currency, environment, and payment state, and produces the canonical result. Stripe retrieval cannot be disabled.

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

    $result = $apix->payment()->completePayment(new PaymentCompletionOptions(
        gateway: GatewayCode::Stripe,
        completionContext: $order->completion_context,
        payload: $payload->toArray(),
    ));
    ```

    **SDK response** — `PaymentCompletionResult`:

    ```json theme={null}
    {
      "gateway": "stripe",
      "verified": true,
      "payment_status": "succeeded",
      "provider_status": "paid",
      "order_id": "ORDER-2026-000184",
      "gateway_reference": "pi_...",
      "amount": "12000.00",
      "currency": "LKR",
      "reconciliation": {
        "attempted": true,
        "state": "matched",
        "authority": "provider_status",
        "callback_status": "paid",
        "secondary_status": "paid",
        "retry_recommended": false
      }
    }
    ```

    The result has `$result->gateway`, `$result->verified`, `$result->paymentStatus`, `$result->providerStatus`, `$result->gatewayReference`, and `$result->reconciliation`. A session with `payment_status: unpaid` is `pending` while open, `failed` when complete, or `cancelled` when expired. A retrieval outage is `unknown` and must be retried from your backend.
  </Tab>

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

    use Avraapi\Apix\Payments\GatewayCode;
    use Avraapi\Apix\Payments\PaymentCompletionOptions;

    $result = AvraAPI::payment()->completePayment(new PaymentCompletionOptions(
        gateway: GatewayCode::Stripe,
        completionContext: $order->completion_context,
        payload: $payload->toArray(),
    ));
    ```
  </Tab>

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

    const result = await client.payment().completePayment(
      new PaymentCompletionOptions({
        gateway: GatewayCode.Stripe,
        completionContext: order.completionContext,
        payload,
      }),
    );
    ```
  </Tab>
</Tabs>

## Payment Elements

Payment Elements does not load Stripe.js or Stripe Elements in this integration. It displays a normal redirect method and sends the customer only to the public Stripe Checkout URL created by your backend.

```js theme={null}
elements.renderMethods('#payment-methods', {
  methods: [{
    gateway: 'stripe',
    mode: 'redirect',
    label: 'Pay securely with Stripe',
    description: 'Continue to Stripe Checkout to complete your payment securely.',
  }],
});
```

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

## Gateway-specific options

Stripe payment-method types are configured in the Gateway Vault. When no allowed-type list is configured, Stripe Checkout uses the merchant account's Dashboard defaults. A browser cannot submit a Stripe secret key, webhook signing secret, account context, API version, payment method type, or checkout amount through `providerOptions`.

The success URL and cancel URL are provider configuration resolved by your backend. AvraAPI adds Stripe's Checkout Session placeholder to the configured success return URL and never exposes the server-only completion context.

## Completion, webhooks, and safety

Register a Stripe webhook endpoint for the exact Checkout Session event types supported by this release: `checkout.session.completed`, `checkout.session.async_payment_succeeded`, and `checkout.session.async_payment_failed`. Preserve raw bytes and the `Stripe-Signature` header, then let shared completion verify and reconcile the bound session.

The browser return is informational only. Fulfil only when `verified` is true and `paymentStatus` is `succeeded`; do not trust browser navigation, a `cs_...` value, or a webhook without valid raw-body signature verification.


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