Svelte
Wajub Components for Svelte and SvelteKit — complete examples with server endpoints, hosted checkout, and payment fields.
16 min read
Install:
npm install @wajub/svelte @wajub/jsSvelteKit — full example
Server endpoint
import { json, error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { WAJUB_SECRET_KEY } from '$env/static/private';
export const POST: RequestHandler = async ({ request }) => {
const { cartId } = await request.json();
const res = await fetch('https://api.wajub.com/payments', {
method: 'POST',
headers: {
Authorization: WAJUB_SECRET_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 25000,
currency: 'XAF',
customer: { email: 'buyer@example.com' },
metadata: { cart_id: cartId },
}),
});
if (!res.ok) throw error(502, 'Payment init failed');
const { authorization_token } = await res.json();
return json({ sessionId: authorization_token });
};Checkout page
<script lang="ts">
import { onMount } from 'svelte';
import { WajubProvider, CheckoutEmbed } from '@wajub/svelte';
let sessionId: string | null = null;
let loadError: string | null = null;
onMount(async () => {
try {
const res = await fetch('/api/checkout/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ cartId: 'cart_123' }),
});
const data = await res.json();
sessionId = data.sessionId;
} catch {
loadError = 'Could not start checkout';
}
});
</script>
{#if loadError}
<p>{loadError}</p>
{:else if !sessionId}
<p>Loading checkout…</p>
{:else}
<WajubProvider>
<CheckoutEmbed
{sessionId}
layout="tabs"
appearance={{ primaryColor: '#6366f1' }}
onSuccess={() => (window.location.href = '/order/complete')}
onError={(e) => { loadError = e.message; }}
/>
</WajubProvider>
{/if}export const ssr = false; // or use a client-only wrapperHosted checkout — minimal
<script lang="ts">
import { WajubProvider, CheckoutEmbed } from '@wajub/svelte';
export let sessionId: string;
</script>
<WajubProvider>
<CheckoutEmbed {sessionId} onSuccess={() => (window.location.href = '/thanks')} />
</WajubProvider>Payment fields
<script lang="ts">
import type { ComponentInstance } from '@wajub/js';
import { WajubProvider, PaymentComponent, useConfirmPayment } from '@wajub/svelte';
export let sessionId: string;
const confirm = useConfirmPayment(sessionId);
let paymentRef: ComponentInstance | null = null;
let paying = false;
async function pay() {
if (!paymentRef) return;
paying = true;
try {
await confirm(paymentRef);
} finally {
paying = false;
}
}
</script>
<WajubProvider>
<PaymentComponent
{sessionId}
collectAddress="shipping"
collectName
layout="tabs"
on:instance={(e) => { paymentRef = e.detail; }}
/>
<button disabled={paying || !paymentRef} on:click={pay}>
{paying ? 'Processing…' : 'Pay'}
</button>
</WajubProvider>Events
Svelte components dispatch standard events:
| Event | Detail |
|---|---|
on:ready | ComponentInstance |
on:instance | ComponentInstance | null |
onSuccess / onError | Callback props on CheckoutEmbed |
Listen to on:instance before calling useConfirmPayment().
Live appearance updates
CheckoutEmbed remounts when sessionId changes. Payment field
components call update() when appearance, locale, or
layout props change. For live hosted-checkout styling, use onReady
and call instance.update().
API reference
| Export | Description |
|---|---|
WajubProvider | Loads SDK once for the subtree |
CheckoutEmbed | Full hosted checkout inline |
CardComponent | Card fields only |
PaymentComponent | Method selector + form |
AddressComponent | Shipping / billing address |
MobileMoneyComponent | Mobile money form |
WalletComponent | Apple Pay / Google Pay |
useWajub() | Access loaded SDK |
useWajubOptional() | Safe access (null during SSR) |
useConfirmPayment() | Submit a mounted component |
SvelteKit tips
- Set
export const ssr = falseon checkout routes, or mount inside a client-only wrapper. - Create sessions in
+server.ts— never exposesk_…to the client. - Wrap with
WajubProvideronce per checkout flow.