Skip to Content
🚀Agentic Commerce Protocol is now live! Instant Checkout is available in ChatGPT. Learn more →
DocumentationCode ExamplesNode.js / Express

Node.js / Express Example

A complete implementation using Node.js, Express, and Stripe.

Setup

npm install express stripe uuid npm install -D typescript @types/express @types/node

Main Server

import express from 'express'; import Stripe from 'stripe'; import crypto from 'crypto'; import { v4 as uuidv4 } from 'uuid'; const app = express(); const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); app.use(express.json()); // In-memory store (use database in production) const sessions = new Map(); // Signature verification middleware function verifySignature(req, res, next) { const signature = req.headers['signature']; const timestamp = req.headers['timestamp']; const expected = crypto .createHmac('sha256', process.env.SIGNING_SECRET!) .update(`${timestamp}.${JSON.stringify(req.body)}`) .digest('base64'); if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { return res.status(401).json({ error: { code: 'invalid_signature' } }); } next(); } // Create session app.post('/checkout_sessions', verifySignature, async (req, res) => { const { cart_items, buyer_context, currency } = req.body; const sessionId = `cs_${uuidv4().replace(/-/g, '')}`; const session = { checkout_session_id: sessionId, state: buyer_context?.shipping_address ? 'ready_for_payment' : 'not_ready_for_payment', cart: { items: cart_items.map(item => ({ ...item, title: 'Product', unit_price: 2999, total: 2999 * item.quantity, }))}, totals: { items_base_amount: 2999, subtotal: 2999, tax: 262, total: 3261, }, expires_at: new Date(Date.now() + 30 * 60000).toISOString(), }; sessions.set(sessionId, session); res.status(201).json(session); }); // Complete checkout app.post('/checkout_sessions/:id/complete', verifySignature, async (req, res) => { const session = sessions.get(req.params.id); if (!session) { return res.status(404).json({ error: { code: 'session_not_found' } }); } const { payment_data } = req.body; try { await stripe.paymentIntents.create({ amount: session.totals.total, currency: 'usd', payment_method: payment_data.token, confirm: true, payment_method_options: { card: { request_delegated_payment: true }, }, }); session.state = 'completed'; session.order = { order_id: `ord_${uuidv4().slice(0, 16)}`, order_number: `ORD-${Date.now()}`, status: 'confirmed', }; res.json(session); } catch (error) { res.status(400).json({ error: { code: 'payment_declined' } }); } }); app.listen(3000, () => console.log('Server running on port 3000'));

Running

# Development npx tsx watch server.ts # HTTPS tunnel for testing ngrok http 3000

Specification maintained by OpenAI and Stripe

AboutPrivacyTermsRSS

Apache 2.0 · Open Source