The platform's Stripe payment extension is the canonical way to accept payments in Internet Computer apps. It wraps Checkout Sessions, webhook verification, subscription management, and usage metering — all orchestrated through the Caffeine extension layer, without you having to build a payment backend from scratch.
Choose your billing model first — it determines which Stripe resources you configure and which webhook events you must handle.
> THREE BILLING MODELS
One-time payments
Customers pay once for a product or a digital goods delivery — no subscription, no automatic renewal.
When: When you sell a fixed product: e-book, course, software license, NFT mint, one-off donation.
Example: Scenario: A builder sells a Caffeine prompt pack for $9 — customer checks out once, receives an instant download link.
Recurring subscriptions
Customers are billed automatically at regular intervals — monthly, yearly, or custom — until they cancel.
When: When you deliver ongoing value: SaaS tools, premium communities, hosted apps, content memberships.
Example: Scenario: A hosted ICP app builder offers a Studio plan at $25/month — Stripe auto-renews, webhook revokes access on cancellation.
Usage-based billing
Customers pay based on actual consumption — API calls, bytes processed, tokens generated, records stored.
When: When value varies per unit: API services, AI inference, storage backends, compute platforms.
Example: Scenario: An AI writing service charges $0.02 per 1,000 generated tokens — Stripe meters usage and invoices a lump sum at month end.
> QUICK START PROMPT
Copy this prompt and paste it into your own Caffeine build to add Stripe payments right away — Checkout Sessions, webhook verification, and a success page are all included. Adjust the product name, price, and currency to match your offering.
Add Stripe payments to my project using the Stripe extension:
- Create a Checkout Session for one-time payments (product: "Premium Prompt Pack", price: $9.00 USD) and redirect the customer to Stripe-hosted Checkout.
- Handle the checkout.session.completed webhook: verify the signature with the webhook secret, then grant the customer access to the purchased content.
- Show a success page after payment confirmation and a cancel page if the customer abandons checkout.
- Store payment status in canister state so access survives reloads.
- Use test mode keys during development and switch to live keys at deploy time.> MODEL COMPARISON
> CREATE A CHECKOUT SESSION
Redirect the customer to a Stripe Checkout Session. The platform extension wraps the API call; you pass the product ID, success, and cancel URLs.
import { createActor } from "@/backend";
import { useActor } from "@caffeineai/core-infrastructure";
// Frontend: request a Checkout Session URL from the canister
// (the Stripe extension signs the request server-side).
async function startCheckout(productId: string) {
const { actor } = useActor(createActor);
if (!actor) throw new Error("actor not ready");
const result = await actor.createCheckoutSession({
productId,
successUrl: `${window.location.origin}/success`,
cancelUrl: `${window.location.origin}/cancel`,
mode: "payment", // "payment" | "subscription"
});
if ("ok" in result) {
// Redirect the browser to Stripe-hosted Checkout
window.location.href = result.ok.url;
} else {
throw new Error(result.err);
}
}> VERIFY & PROCESS A WEBHOOK
Stripe sends events to your canister. Always verify the signature with the webhook secret before running business logic — never trust client-side payment confirmation.
// Backend (Motoko): the Stripe extension exposes a typed handler.
// Verify the signature, then match on the event type.
public shared func handleStripeWebhook(
payload : Text,
signature : Text,
) : async Text {
// 1. Verify signature — throws if invalid
let event = await Stripe.verifyWebhook(payload, signature);
// 2. Dispatch on event type
switch (event.type) {
case ("checkout.session.completed") {
let session = event.data.session;
// Fulfill the order: grant access, send email, mint NFT...
await fulfillOrder(session);
};
case ("invoice.paid") {
// Recurring subscription renewal succeeded
await renewAccess(event.data.invoice);
};
case ("customer.subscription.deleted") {
// Subscription cancelled — revoke access
await revokeAccess(event.data.subscription);
};
case (_) {
// Unhandled event — log and acknowledge
};
};
return "ok";
}[THE EXTENSION DOES THE HEAVY LIFTING]
[ALWAYS VERIFY WEBHOOK SIGNATURES]
// Stripe Payments Checklist
- Choose your billing model — one-time, recurring, or usage-based — matching your product
- Configure the platform's Stripe extension (API keys, webhook secret, create products in Stripe)
- Request a Checkout Session from the frontend and redirect the customer to Stripe-hosted Checkout
- Implement a webhook handler — verify the signature and react to checkout.session.completed
- Test end-to-end in test mode before going live — test cards, subscription renewals, refunds
