ElebneElebneDocs
SDKs

Angular SDK

Angular web SDK for Elebne Pay checkout — a standalone component that renders the hosted embed, re-verifies the result server-side, and shows a success screen. Three integration flows.

Angular SDK

@elebne/pay-angular is the client SDK for Elebne Pay on Angular. It wraps the hosted /embed surface: you supply (or mint) a clientSecret, the SDK renders the payment iframe, re-verifies the result server-side, and shows a success screen. It never handles a secret key.

It shares its core with @elebne/pay-react — same flows, same guarantees, Angular idioms on top: one standalone component, signal inputs and outputs, and a provide* function.

Install

npm install @elebne/pay-angular

@angular/core, @angular/common and @angular/platform-browser (20, 21 or 22) are peer dependencies. The SDK holds all its state in signals, so it runs zoneless as happily as it runs with zone.js.

@elebne/pay-angular is at 0.1.0. While it is being published to npm it is also available via the Elebne private registry — request access from dev@elebne.ai.

Setup

Register the environment once, then drop the component wherever you need a checkout:

import { bootstrapApplication } from '@angular/platform-browser';
import { provideElebnePay } from '@elebne/pay-angular';

bootstrapApplication(AppComponent, {
  providers: [provideElebnePay({ env: 'production' })],
});

provideElebnePay() is optional — every checkout also accepts its own [config], merged over the global one.

The three flows

Merchant backend (recommended). Your server creates the intent with its sk_ key (PHP / Java) and returns the clientSecret. The SDK never sees a secret key.

import { Component } from '@angular/core';
import {
  ElebneEmbedCheckoutComponent,
  type CheckoutOptions,
  type CheckoutSession,
  type ElebnePayError,
} from '@elebne/pay-angular';

@Component({
  selector: 'app-checkout',
  imports: [ElebneEmbedCheckoutComponent],
  template: `
    <elebne-embed-checkout
      [options]="options"
      presentation="modal"
      (paid)="onPaid($event)"
      (cancelled)="onCancelled($event)"
      (errored)="onError($event)" />
  `,
})
export class CheckoutPage {
  readonly options: CheckoutOptions = {
    fetchClientSecret: async () => (await createIntentOnMyServer()).clientSecret,
  };

  onPaid(session: CheckoutSession) { console.log('paid', session.referenceNumber); }
  onCancelled(session: CheckoutSession) { console.log('cancelled', session.referenceNumber); }
  onError(error: ElebnePayError) { console.error(error.code); }
}

If you already have the clientSecret at render time, pass it directly instead:

<elebne-embed-checkout [options]="{ clientSecret: 'cs_live_…' }" (paid)="onPaid($event)" />

No backend (stored price). Define a price in the Elebne dashboard; the SDK mints the intent with a publishable key.

<elebne-embed-checkout
  [options]="{ publishableKey: 'pk_live_…', priceId: 'abc123', quantity: 2 }"
  presentation="inline"
  (paid)="onPaid($event)" />

Optional price fields: merchantOrderId, returnUrl, cancelUrl, label.

Verify callback (legacy). Verify an out-of-band payment against your own order reference.

<elebne-embed-checkout
  [options]="{ publishableKey: 'pk_live_…', merchantOrderId: 'ORDER-1', flow: 'verify' }"
  (paid)="onPaid($event)" />

<elebne-embed-checkout> inputs

The most common inputs — see the package README for the exhaustive list.

InputTypeDefaultDescription
optionsCheckoutOptions (required)—One of the flows above. Read once, on init
configProviderConfig—env, baseUrl, embedUrl; merged over provideElebnePay()
presentation'inline' | 'modal''inline'Modal adds a centered overlay with a close button
showSuccessbooleantrueShow the built-in terminal success screen
successTemplateTemplateRef<{ $implicit: CheckoutSession }>—Replace the default success screen
pollbooleantruePolling fallback (disable in tests)
cancelOnClosebooleanfalseIn modal mode, cancel the intent when closed

<elebne-embed-checkout> outputs

OutputPayloadDescription
readyvoidThe embed signalled elebne:loaded
paidCheckoutSessionServer re-verification confirmed PAID
cancelledCheckoutSessionServer re-verification confirmed CANCELLED
expired / failedCheckoutSessionFire on the corresponding terminal status
erroredElebnePayErrorNon-recoverable errors
doneCheckoutSessionUser clicked "Continuer" on the success screen
closedvoidThe modal close button or backdrop was clicked

Angular convention drops the on prefix: (paid) here is onPaid in the React SDK.

Guarantees

  • Server re-verification — the iframe postMessage is only a hint; the SDK calls GET /checkout/session and emits paid / cancelled / expired / failed only when the server confirms a terminal status.
  • Origin-checked — messages from any origin other than the embed base URL are silently ignored.
  • No secret leakage — the clientSecret travels only in the URL fragment; no sk_ key ever touches the SDK.
  • Idempotent minting — when the SDK mints an intent (Flow B / C), one idempotency key is generated per checkout instance, so change detection never creates duplicates.
  • Fail-closed polling — a 401 or any 4xx on re-verification aborts the flow instead of retrying every tick.

Imperative control

The component exposes its state as signals. Grab it with a template reference variable:

<elebne-embed-checkout #checkout [options]="options" />

<p>Statut : {{ checkout.status() }}</p>
<button (click)="checkout.cancel()">Annuler</button>

status(), session(), error() and clientSecret() are read-only signals; cancel() cancels the current intent. For a headless integration (your own UI, no iframe), inject ElebneCheckoutService directly.

Error handling

All SDK errors are ElebnePayError instances with a .code string:

onError(e: ElebnePayError) {
  console.error(e.code, e.message); // INVALID_CLIENT_SECRET, NETWORK_ERROR, …
}

Environments & sandbox

{ env: 'production' }   // https://api.elebne.ai/api/v1 + https://elebne.ai/embed
{ env: 'staging' }      // https://api.staging.elebne.ai/api/v1 + https://pay.staging.elebne.ai/embed

// Local dev only — override both endpoints
{ baseUrl: 'http://localhost:3000/api/v1', embedUrl: 'http://localhost:3100/embed' }

Sandbox vs live is decided by the key: a pk_test_ / sk_test_ key yields a sandbox intent (surfaced as session.sandbox). There is no separate sandbox hostname.

Next steps

Was this page helpful?

On this page