Stripe Node SDK Checkout Sessions with a mocked HTTP client: working versions (tested 2026-10-15)
Create Stripe Checkout Sessions with line items, metadata and idempotency keys, tested offline by plugging a fake fetch into Stripe.createFetchHttpClient.
passed3 passed · 0 failed2026-10-15 13:33 UTC- Status
- passed
- Last passed
- 2026-10-15 13:33 UTC
- Tests
- 3 / 3
- Language
- TypeScript
- Runtime
- node v22.23.3
npm install --no-audit --no-fund --ignore-scripts=false npm test
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38742087302
The code
Exactly the files that passed. Your agent can pull them with get_recipe("stripe-checkout-mocked-http") (install), or see them on GitHub.
{
"name": "stripe-checkout-mocked-http",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"stripe": "23.0.0"
},
"devDependencies": {
"tsx": "4.23.15",
"@types/node": "24.19.2"
}
}
import Stripe from "stripe";
export type CartLine = { priceId: string; qty: number };
export async function createCheckout(stripe: Stripe, orderId: string, lines: CartLine[], baseUrl: string) {
if (!lines.length) throw new Error("empty cart");
return stripe.checkout.sessions.create({
mode: "payment",
line_items: lines.map((l) => ({ price: l.priceId, quantity: l.qty })),
success_url: `${baseUrl}/thanks?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${baseUrl}/cart`,
metadata: { orderId },
}, { idempotencyKey: `checkout-${orderId}` }); // retries never create a second session
}
import { test } from "node:test";
import assert from "node:assert/strict";
import Stripe from "stripe";
import { createCheckout } from "../src/checkout.ts";
function fakeStripe(status: number, body: object, seen: { url: string; headers: Headers; body: URLSearchParams }[]) {
const fetchFn = async (url: any, init: any) => {
seen.push({ url: String(url), headers: new Headers(init.headers), body: new URLSearchParams(init.body) });
return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json", "request-id": "req_1" } });
};
return new Stripe("sk_test_123", { httpClient: Stripe.createFetchHttpClient(fetchFn as any), maxNetworkRetries: 0 });
}
test("sends line items, metadata and idempotency key", async () => {
const seen: any[] = [];
const s = await createCheckout(fakeStripe(200, { id: "cs_test_1", object: "checkout.session", url: "https://checkout.stripe.com/c/pay/cs_test_1" }, seen), "ord_9", [{ priceId: "price_a", qty: 2 }], "https://shop.test");
assert.equal(s.id, "cs_test_1");
const req = seen[0];
assert.match(req.url, /\/v1\/checkout\/sessions$/);
assert.equal(req.body.get("line_items[0][price]"), "price_a");
assert.equal(req.body.get("line_items[0][quantity]"), "2");
assert.equal(req.body.get("metadata[orderId]"), "ord_9");
assert.equal(req.headers.get("idempotency-key"), "checkout-ord_9");
});
test("Stripe errors become typed exceptions", async () => {
const stripe = fakeStripe(400, { error: { type: "invalid_request_error", message: "No such price: 'price_x'", param: "line_items[0][price]" } }, []);
await assert.rejects(createCheckout(stripe, "o1", [{ priceId: "price_x", qty: 1 }], "https://shop.test"), (e: any) => e instanceof Stripe.errors.StripeInvalidRequestError && /No such price/.test(e.message));
});
test("rejects an empty cart before calling Stripe", async () => {
const seen: any[] = [];
await assert.rejects(createCheckout(fakeStripe(200, {}, seen), "o1", [], "https://x"), /empty cart/);
assert.equal(seen.length, 0);
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
Express 5 + Stripe webhook signature verification
Verify Stripe webhook signatures in Express 5 using the raw body, then dispatch on event type. Tested offline with generated test headers.
Next.js App Router + Stripe webhook handler
A Next.js route handler that verifies Stripe webhook signatures from the raw body and handles checkout.session.completed.
FastAPI + Stripe webhook signature verification
Verify Stripe webhook signatures in FastAPI from the raw request body and dispatch on event type. Tested offline with locally signed payloads.