Storefront
Sell your JamiDev products from your own website — no secret in the browser, money straight into your Jami wallet.
The storefront SDK (jami-sdk ≥ 0.4.0) lets you sell your published products from
your own site, settling money into your Jami wallet — with no API secret in the
browser and no server in the middle for card checkout.
It ships two ways:
- a drop-in
<script>that exposes aJamiStoreglobal, and - an importable module:
import { JamiStorefront, mountStorefront } from 'jami-sdk/storefront'.
How it works
- Hosted checkout (card): the SDK redirects the buyer to Jami's hosted checkout page
for a public product token (
p_…) or checkout-link token (cl_…). Nothing secret is needed, so this runs entirely in the browser. - Pay with Jami wallet: the SDK redirects to a small confidential server you host
(
walletPay) that runs the buyer's Sign in with Jami and awallet:send.wallet:sendis a confidential-client scope, so a browser can never hold it — that step needs a server.
Drop-in script
<script src="https://cdn.jsdelivr.net/npm/jami-sdk@0.4.0/dist/jami-storefront.global.js"></script>
<div id="shop"></div>
<script>
const { JamiStorefront, mountStorefront } = window.JamiStore;
const store = new JamiStorefront({
// Omit walletPay to offer hosted card checkout only.
walletPay: { endpoint: 'https://your-server.com/pay/wallet', recipient: 'yourhandle' },
});
// Built-in, dependency-free product grid…
mountStorefront('#shop', {
storefront: store,
returnUrl: location.origin + '/thanks',
products: [
{ token: 'p_AbC123', title: 'Leather Bag', priceEtb: 2500, image: 'https://…' },
{ token: 'p_XyZ789', title: 'Canvas Tote', priceEtb: 900, image: 'https://…' },
],
});
</script>Get each product's public p_… token from Developer → Products (publish the product
first — only published products resolve at checkout). Products are yours to supply; the
storefront never calls a product-list API and never needs your token.
Your own UI
Skip mountStorefront and drive the redirects yourself:
import { JamiStorefront } from 'jami-sdk/storefront';
const store = new JamiStorefront({
walletPay: { endpoint: 'https://your-server.com/pay/wallet', recipient: 'yourhandle' },
});
store.checkout('p_AbC123'); // → hosted checkout
store.payWithWallet({ amountMinor: 250000, reference: 'p_AbC123' }); // → wallet server
// Or build URLs without redirecting (e.g. for an <a href>):
store.getCheckoutUrl('cl_LinkToken', { returnUrl: 'https://shop.example/thanks' });Amounts are integer ETB minor units (santim): 250000 = 2,500.00 ETB.
Options
new JamiStorefront({
issuer?: string, // default 'https://jami.bio'
walletPay?: {
endpoint: string, // your confidential wallet-pay server (absolute URL)
recipient: string, // the receiving Jami handle or user id
},
});store.walletEnabled reflects whether walletPay was configured; the built-in grid only
renders a wallet button when it is (and the product has a price).
Wallet-pay endpoint contract
When walletPay is set, the wallet button sends the buyer to:
GET {endpoint}?recipient=<handle>&amountMinor=<santim>&reference=<token>&return_url=<url>Your server (a confidential OAuth client) must:
- Start Sign in with Jami with scope
wallet:send, persistingstate+ the PKCEcode_verifier. - On the callback, exchange the code and call
wallet.sendtorecipientforamountMinor(idempotency key advised). - Record the order and redirect the buyer back to
return_url(e.g. with?status=paid).
Card checkout needs no such server — only the wallet button does.
Notes
- Only public tokens are accepted (
p_…,cl_…); raw product ObjectIds are rejected so real ids never appear in shareable URLs. - Redirect helpers (
checkout,payWithWallet) require a browser; the URL builders (getCheckoutUrl,getWalletPayUrl) work anywhere. - For order fulfilment, subscribe to
order.completedwebhooks — hosted checkouts create JamiDev orders; wallet transfers are recorded by your wallet-pay server.
