Stripe Checkout para compras: sesiones con precios del servidor, pedido solo desde el webhook y reembolso automático si se agota
Instalar
genpm add @core/checkoutQué obtienes
- Código en src/lib/checkout/, 8 archivos. (23,9 kB)
- Reglas de IA en src/lib/checkout/AGENTS.md, más archivos de reglas para tu IDE.
- Variables añadidas a .env.example: SITE_URL, STRIPE_TAX, CHECKOUT_ALERT_TO.
- Resuelve @core/cart, @core/catalog, @core/email, @core/jobs, @core/money, @core/orders, @core/shipping, @core/stripe por ti.
README
Este paquete no tiene README.
Esto es exactamente lo que lee tu IA cuando trabaja en src/lib/checkout. No se añade nada más a su contexto.
@core/checkout — rules for AI agents
Purpose
Pays a @core/cart with Stripe Checkout (hosted page: no card data on your server). startCheckout recomputes totals,
blocks carts with issues or without shipping, sends server prices, a one-off coupon for the computed discounts and
the chosen shipping rate, and stores a snapshot. The order (@core/orders) is created ONLY in the Stripe webhook,
idempotently, from that snapshot after checking the charged amount; if the order can never be created (stock ran
out, a variant was withdrawn, invalid address…), the payment is refunded automatically, the customer and the team
are told and the webhook still answers 2xx (transient errors are rethrown so Stripe retries). Open sessions reserve
the discount codes they carry (registerPendingCodeUses of @core/cart); if a concurrent checkout took the last use,
the new session is expired and startCheckout throws issues. Also registers Stripe as the refund provider for the admin.
Map
index.ts— public API:startCheckout,getCheckoutStatus,finalizeSession,stripePaymentProvider,beginCheckoutEvent,purchaseEvent.checkout.ts— logic and webhook handlers (registered on import).schema.ts—checkout_sessions.adapters/hono.ts—checkoutRoutes({ currentUserId }).adapters/next.ts—checkoutRoute,checkoutStatusRoute.
Integration
- Install and wire @core/stripe (one webhook endpoint) with events
checkout.session.completed,checkout.session.async_payment_succeededandcheckout.session.expired. Env:SITE_URL,EMAIL_FROM, optionalCHECKOUT_ALERT_TO(team alerts) andSTRIPE_TAX=1(Stripe Tax; configure it in Stripe first). - Import this module and @core/shipping at startup. Migrations as in
src/lib/db/AGENTS.md; the @core/jobs cron must run. - Cart page → ask country and shipping rate (
setCartMeta), thenPOST /api/checkout {email}→ redirect tourl. - Success page
/checkout/success?session_id=…: pollGET /api/checkout/statusuntilpaid(show the order number),refunded(sold out or order could not be created) or keep "processing" — never trust the URL alone. - Verify locally:
stripe listen --forward-to localhost:3000/api/stripe/webhook, pay with card 4242 4242 4242 4242, an order appears.
Conventions
- Amounts always come from
computeTotals; the snapshot is what the customer saw and paid. - Show delivery estimate, total with shipping and taxes, and legal links before redirecting to Stripe.
- Use
purchaseEvent(order)(sameeventIdin browser and server) for @core/pixels.
Don't
- Don't create or mark orders paid from the success redirect or from client calls.
- Don't send prices, discounts or shipping amounts from the browser to Stripe.
- Don't log card data, full webhook payloads or Stripe keys.
# @core/checkout — rules for AI agents
## Purpose
Pays a @core/cart with Stripe Checkout (hosted page: no card data on your server). `startCheckout` recomputes totals,
blocks carts with issues or without shipping, sends server prices, a one-off coupon for the computed discounts and
the chosen shipping rate, and stores a snapshot. The order (@core/orders) is created ONLY in the Stripe webhook,
idempotently, from that snapshot after checking the charged amount; if the order can never be created (stock ran
out, a variant was withdrawn, invalid address…), the payment is refunded automatically, the customer and the team
are told and the webhook still answers 2xx (transient errors are rethrown so Stripe retries). Open sessions reserve
the discount codes they carry (`registerPendingCodeUses` of @core/cart); if a concurrent checkout took the last use,
the new session is expired and `startCheckout` throws `issues`. Also registers Stripe as the refund provider for the admin.
## Map
- `index.ts` — public API: `startCheckout`, `getCheckoutStatus`, `finalizeSession`, `stripePaymentProvider`, `beginCheckoutEvent`, `purchaseEvent`.
- `checkout.ts` — logic and webhook handlers (registered on import). `schema.ts` — `checkout_sessions`.
- `adapters/hono.ts` — `checkoutRoutes({ currentUserId })`. `adapters/next.ts` — `checkoutRoute`, `checkoutStatusRoute`.
## Integration
1. Install and wire @core/stripe (one webhook endpoint) with events `checkout.session.completed`,
`checkout.session.async_payment_succeeded` and `checkout.session.expired`. Env: `SITE_URL`, `EMAIL_FROM`,
optional `CHECKOUT_ALERT_TO` (team alerts) and `STRIPE_TAX=1` (Stripe Tax; configure it in Stripe first).
2. Import this module and @core/shipping at startup. Migrations as in `src/lib/db/AGENTS.md`; the @core/jobs cron must run.
3. Cart page → ask country and shipping rate (`setCartMeta`), then `POST /api/checkout {email}` → redirect to `url`.
4. Success page `/checkout/success?session_id=…`: poll `GET /api/checkout/status` until `paid` (show the order number),
`refunded` (sold out or order could not be created) or keep "processing" — never trust the URL alone.
5. Verify locally: `stripe listen --forward-to localhost:3000/api/stripe/webhook`, pay with card 4242 4242 4242 4242, an order appears.
## Conventions
- Amounts always come from `computeTotals`; the snapshot is what the customer saw and paid.
- Show delivery estimate, total with shipping and taxes, and legal links before redirecting to Stripe.
- Use `purchaseEvent(order)` (same `eventId` in browser and server) for @core/pixels.
## Don't
- Don't create or mark orders paid from the success redirect or from client calls.
- Don't send prices, discounts or shipping amounts from the browser to Stripe.
- Don't log card data, full webhook payloads or Stripe keys.
El árbol exacto que se inyectará, tras aplicar .genpmignore. Anclado a
// Adaptador Hono: `app.route('/api/checkout', checkoutRoutes({ currentUserId }))`.
import { Hono } from 'hono';
import { type CheckoutPaths, type CurrentUserId, handleCheckoutStatus, handleStartCheckout } from './http.ts';
export function checkoutRoutes(opts: { currentUserId: CurrentUserId; paths?: CheckoutPaths }) {
const paths = opts.paths ?? { success: '/checkout/success', cancel: '/cart' };
return new Hono().post('/', (c) => handleStartCheckout(c.req.raw, opts.currentUserId, paths)).get('/status', (c) => handleCheckoutStatus(c.req.raw));
}
- servidor
- stripe
- comando
- npx -y @stripe/mcp
- entorno
- STRIPE_SECRET_KEY
| Versión | Commit | Publicado | Escaneo |
|---|---|---|---|
| 1.0.1 | 6590fd9 | hace 4 horas | escaneo superado |
- genpm
- @core/cart ^1.1.0@core/catalog ^1.0.0@core/email ^1.0.1@core/jobs ^1.0.0@core/money ^1.0.0@core/orders ^1.0.0@core/shipping ^1.0.0@core/stripe ^1.0.0
- propuesta
- GenPM propone el comando npm y solo lo ejecuta si dices que sí.
- Usado por (1)
- @core/kit-store ^1.0.0
- escaneo
- escaneo superado · 0 hallazgos
- commit
- v1.0.1 → 6590fd9f566c5f55262488b266ce60ce5a433b2b · verificado tras la descarga
- scripts
- Ninguno. GenPM nunca ejecuta código del paquete.
- licencia
- MIT
- Calidad
- 100/100
- Licencia reconocidacumplido
- AGENTS.md explica su propósitocumplido
- AGENTS.md tiene pasos de integracióncumplido
- AGENTS.md lista convenciones o prohibicionescumplido
- Incluye testscumplido
- Escaneo de seguridad superadocumplido
- Publicado en los últimos 6 mesescumplido
- Publicador verificadocumplido
- Resumen y palabras clavecumplido
- reporte
- ¿Ves algo raro?