ProvenPin Install

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
pinned versions3
stripe@23.0.0tsx@4.23.15@types/node@24.19.2
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
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.

package.json
{
  "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"
  }
}
src/checkout.ts
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
}
test/checkout.test.ts
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.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.