Angular
Angular uses @sanwohq/web directly — no framework-specific wrapper needed. Angular’s dependency injection, lifecycle hooks, and template syntax work naturally with the createSanwo API.
Installation
Section titled “Installation”npm i @sanwohq/web @sanwohq/paystackReplace @sanwohq/paystack with whichever provider you need (@sanwohq/flutterwave, @sanwohq/razorpay, etc.).
Quick start
Section titled “Quick start”import { Component, OnDestroy } from "@angular/core";import { createSanwo, type SanwoInstance } from "@sanwohq/web";import { paystackProvider } from "@sanwohq/paystack";
@Component({ selector: "app-root", standalone: true, template: ` <button (click)="pay()" [disabled]="isLoading"> {{ isLoading ? 'Processing…' : 'Pay ₦5,000' }} </button> `,})export class AppComponent implements OnDestroy { private sanwo: SanwoInstance; isLoading = false;
constructor() { this.sanwo = createSanwo({ provider: paystackProvider, publicKey: "pk_test_xxxxxxxxxxxx", }); }
async pay() { this.isLoading = true; const result = await this.sanwo({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" }, }); this.isLoading = false;
if (result.status === "successful") { console.log("Paid!", result.reference); } }
ngOnDestroy() { this.sanwo.destroy(); }}Creating a reusable service
Section titled “Creating a reusable service”Wrap createSanwo in an Angular service so any component can inject it.
import { Injectable, OnDestroy } from "@angular/core";import { createSanwo, type SanwoInstance } from "@sanwohq/web";import { paystackProvider } from "@sanwohq/paystack";import type { CheckoutOptions, CheckoutResult } from "@sanwohq/types";
@Injectable({ providedIn: "root" })export class SanwoService implements OnDestroy { private sanwo: SanwoInstance;
constructor() { this.sanwo = createSanwo({ provider: paystackProvider, publicKey: "pk_test_xxxxxxxxxxxx", }); }
checkout(options: CheckoutOptions): Promise<CheckoutResult> { return this.sanwo(options); }
ngOnDestroy() { this.sanwo.destroy(); }}import { Component } from "@angular/core";import { SanwoService } from "./sanwo.service";
@Component({ selector: "app-checkout", standalone: true, template: ` <button (click)="pay()" [disabled]="isLoading"> {{ isLoading ? 'Processing…' : 'Pay ₦5,000' }} </button> <p *ngIf="message">{{ message }}</p> `,})export class CheckoutComponent { isLoading = false; message = "";
constructor(private sanwo: SanwoService) {}
async pay() { this.isLoading = true; const result = await this.sanwo.checkout({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" }, }); this.isLoading = false;
switch (result.status) { case "successful": this.message = `Paid! Ref: ${result.reference}`; break; case "cancelled": this.message = "Payment cancelled."; break; case "failed": this.message = `Payment failed: ${result.error}`; break; } }}Switching providers at runtime
Section titled “Switching providers at runtime”Create a new SanwoInstance when the provider changes and destroy the old one.
import { Component, OnDestroy } from "@angular/core";import { createSanwo, type SanwoInstance } from "@sanwohq/web";import { paystackProvider } from "@sanwohq/paystack";import { flutterwaveProvider } from "@sanwohq/flutterwave";
@Component({ selector: "app-multi-provider", standalone: true, template: ` <select (change)="switchProvider($event)"> <option value="paystack">Paystack</option> <option value="flutterwave">Flutterwave</option> </select> <button (click)="pay()">Pay</button> `,})export class MultiProviderComponent implements OnDestroy { private sanwo: SanwoInstance;
private providers = { paystack: { provider: paystackProvider, key: "pk_test_xxx" }, flutterwave: { provider: flutterwaveProvider, key: "FLWPUBK-xxx" }, };
constructor() { this.sanwo = this.buildInstance("paystack"); }
switchProvider(event: Event) { const id = (event.target as HTMLSelectElement).value; this.sanwo.destroy(); this.sanwo = this.buildInstance(id); }
async pay() { const result = await this.sanwo({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" }, }); console.log(result); }
ngOnDestroy() { this.sanwo.destroy(); }
private buildInstance(id: string): SanwoInstance { const config = this.providers[id as keyof typeof this.providers]; return createSanwo({ provider: config.provider, publicKey: config.key, }); }}Handling results
Section titled “Handling results”The checkout returns a CheckoutResult — a discriminated union on status:
const result = await this.sanwo({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" },});
switch (result.status) { case "successful": // result.reference, result.providerResponse break; case "cancelled": // user closed the checkout break; case "failed": // result.error break; case "pending": // result.reference — verify server-side break;}Environment configuration
Section titled “Environment configuration”Store your keys in Angular’s environment files:
export const environment = { paystackPublicKey: "pk_test_xxxxxxxxxxxx",};import { environment } from "../environments/environment";
this.sanwo = createSanwo({ provider: paystackProvider, publicKey: environment.paystackPublicKey,});Full example
Section titled “Full example”A complete checkout form with scenario picker, form inputs, and result display:
import { Component, OnDestroy } from "@angular/core";import { CommonModule } from "@angular/common";import { FormsModule } from "@angular/forms";import { createSanwo, type SanwoInstance } from "@sanwohq/web";import type { CheckoutResult } from "@sanwohq/types";import { paystackProvider } from "@sanwohq/paystack";
@Component({ selector: "app-checkout", standalone: true, imports: [CommonModule, FormsModule], template: ` <div *ngIf="result"> <h2>{{ result.status === 'successful' ? 'Payment Successful' : 'Payment ' + result.status }}</h2> <button (click)="result = null">Make another payment</button> </div>
<form *ngIf="!result" (ngSubmit)="pay()"> <input [(ngModel)]="email" name="email" type="email" placeholder="customer@example.com" required /> <input [(ngModel)]="amount" name="amount" type="number" placeholder="1000.00" required min="1" step="0.01" /> <button type="submit" [disabled]="isLoading"> {{ isLoading ? 'Processing…' : 'Pay with Paystack' }} </button> </form>
<p *ngIf="error" style="color: red">{{ error }}</p> `,})export class CheckoutComponent implements OnDestroy { private sanwo: SanwoInstance; email = ""; amount = ""; isLoading = false; error: string | null = null; result: CheckoutResult | null = null;
constructor() { this.sanwo = createSanwo({ provider: paystackProvider, publicKey: "pk_test_xxxxxxxxxxxx", }); }
async pay() { this.isLoading = true; this.error = null;
try { this.result = await this.sanwo({ amount: Math.round(parseFloat(this.amount) * 100), currency: "NGN", customer: { email: this.email }, }); } catch (err) { this.error = err instanceof Error ? err.message : String(err); } finally { this.isLoading = false; } }
ngOnDestroy() { this.sanwo.destroy(); }}See the Angular example app for a multi-provider demo with Paystack, Flutterwave, Razorpay, Monnify, and Interswitch.