vault backup: 2026-05-15 16:27:02

This commit is contained in:
Vadym Samoilenko 2026-05-15 16:27:02 +01:00
parent 946d68d739
commit 865b8a5c69
4 changed files with 161 additions and 1 deletions

View file

@ -35,7 +35,7 @@ This 3-hop pattern works for hundreds of articles without vector search.
| [[wiki/reports/_index\|reports/]] | Weekly and monthly summaries — generate: `uv run python scripts/report-generator.py --weekly` | 1 |
| [[wiki/infrastructure/_index\|infrastructure/]] | Server inventory: all 10 SSH hosts — optical, optical-dev, optical-prod, baic, librechat, modocmms, box-cli, aimpress, pve | 12 |
| [[wiki/testing/_index\|testing/]] | Web app testing: functional, performance, security, UI types; TDD/BDD/Agile methodologies; Selenium/Cypress/Playwright/JMeter/OWASP ZAP tools | 1 |
| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 120 |
| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 121 |
| [[wiki/shared-patterns/_index\|shared-patterns/]] | Oliver Agency standard library patterns: httpx, structlog, pydantic-settings, alembic — reuse before writing from scratch | 4 |
| [[wiki/mistakes/_index\|mistakes/]] | Anti-patterns extracted from sessions — per-stack running lists (fastapi, react, docker, postgres, general) — injected at session start | 5 |

View file

@ -122,3 +122,5 @@
| [[wiki/payloadcms/plugin-redirects\|Redirects Plugin]] | Managed `redirects` collection (from/to + doc reference), redirect types (301/302), overrides pattern, frontend integration (Next.js middleware/redirects()) | raw/plugins__redirects.md | 2026-05-15 |
| [[wiki/payloadcms/plugin-search\|Search Plugin]] | First-party search index: static `search` collection, hook-free queries, priority sorting, `beforeSync`/`skipSync`, on-demand reindex | raw/plugins__search.md | 2026-05-15 |
| [[wiki/payloadcms/plugin-sentry\|Sentry Plugin]] | Sentry error tracking + performance monitoring: Next.js setup prerequisite, Postgres pg driver injection for DB traces, captureErrors, context callback | raw/plugins__sentry.md | 2026-05-15 |
| [[wiki/payloadcms/plugin-seo\|SEO Plugin]] | `meta` field group (title/description/image) on collections/globals, auto-generate functions, real-time search preview, custom fields (og:title, json-ld), tabbedUI gotcha, direct field imports | raw/plugins__seo.md | 2026-05-15 |
| [[wiki/payloadcms/plugin-stripe\|Stripe Plugin]] | Two-way Stripe↔Payload sync, webhook handlers, REST proxy (dev-only), `sync` auto-hooks, serverless `waitUntil` fix, `skipSync` loop prevention | raw/plugins__stripe.md | 2026-05-15 |

View file

@ -0,0 +1,158 @@
---
title: "Stripe Plugin"
aliases: [payload-stripe, plugin-stripe, stripe-payments-payload]
tags: [payloadcms, stripe, payments, ecommerce, plugin, webhooks, sync]
sources: [raw/plugins__stripe.md]
created: 2026-05-15
updated: 2026-05-15
---
# Stripe Plugin
Integrates [Stripe](https://stripe.com) billing into Payload CMS — two-way sync, webhook handling, and a proxied Stripe REST API behind Payload access control.
## Installation
```bash
pnpm add @payloadcms/plugin-stripe
```
## Basic Config
```ts
import { stripePlugin } from '@payloadcms/plugin-stripe'
buildConfig({
plugins: [
stripePlugin({
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
}),
],
})
```
## Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `stripeSecretKey` * | string | — | Stripe secret key |
| `stripeWebhooksEndpointSecret` | string | — | Webhook signing secret |
| `rest` | boolean | `false` | Open `/api/stripe/rest` proxy (dev only) |
| `webhooks` | object \| function | — | Webhook event handlers |
| `sync` | array | — | Auto-sync configs between collections and Stripe resources |
| `logs` | boolean | `false` | Log sync events to console |
## Auto-Opened Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/stripe/rest` | POST | Proxied Stripe REST API (behind Payload access control) |
| `/api/stripe/webhooks` | POST | Stripe webhook receiver |
## Webhooks Setup
**Dev:**
```bash
stripe login
stripe listen --forward-to localhost:3000/api/stripe/webhooks
# paste the secret into .env as STRIPE_WEBHOOKS_ENDPOINT_SECRET
```
**Production:** Create webhook in Stripe dashboard → set URL to `YOUR_DOMAIN/api/stripe/webhooks` → paste secret into `.env`.
**Handler config:**
```ts
stripePlugin({
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOKS_ENDPOINT_SECRET,
webhooks: {
'customer.subscription.updated': ({ event, stripe, stripeConfig }) => {
// handle event
},
},
})
```
### Serverless Warning
Stripe expects a `2xx` response within 1020 seconds. The plugin processes webhooks asynchronously — in serverless environments the function instance may close before processing completes, causing duplicate events.
**Vercel fix:** install `@vercel/functions` — the plugin auto-detects it and wraps handlers in `waitUntil()`.
## Sync — Two-Way Auto-Sync
Maps Payload collection fields to Stripe resource properties. Hooks + webhook handlers are created automatically.
```ts
stripePlugin({
sync: [
{
collection: 'customers',
stripeResourceType: 'customers',
stripeResourceTypeSingular: 'customer',
fields: [
{ fieldPath: 'name', stripeProperty: 'name' },
],
},
],
})
```
**What `sync` does automatically:**
- Adds read-only `stripeID` field (Stripe-generated cross-reference)
- Adds direct link to resource on Stripe.com in admin
- Adds read-only `skipSync` flag to prevent infinite loops
- Attaches hooks: `beforeValidate: createNewInStripe`, `beforeChange: syncExistingWithStripe`, `afterDelete: deleteFromStripe`
- Handles webhooks: `STRIPE_TYPE.created/updated/deleted`
> **Limitation:** Only top-level fields supported (Stripe API constraint).
## Server-Side Usage
Prefer direct Stripe SDK on server rather than the REST proxy:
```ts
import Stripe from 'stripe'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: '2022-08-01' })
const customer = await stripe.customers.create({ email: data.email })
```
Or use `stripeProxy` from the plugin:
```ts
import { stripeProxy } from '@payloadcms/plugin-stripe'
const customer = await stripeProxy({
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
stripeMethod: 'customers.create',
stripeArgs: [{ email: data.email }],
})
```
## TypeScript
```ts
import { StripeConfig, StripeWebhookHandler, StripeProxy } from '@payloadcms/plugin-stripe/types'
```
## Key Takeaways
- **Hides Stripe credentials** — client-side calls go through Payload's access control, never directly to Stripe
- **REST proxy (`rest: true`) is dev-only** — opening it in production gives authenticated users full Stripe API access
- **Two-way sync requires webhooks** — set `stripeWebhooksEndpointSecret` or changes from Stripe won't propagate to Payload
- **Serverless + webhooks = `@vercel/functions`** — without it, async webhook handlers may be killed before completing
- **`sync` only works on top-level Stripe fields** — nested fields require manual hooks
- **`skipSync` flag prevents infinite loops** — sync hooks set it before triggering webhooks, webhooks check it before re-syncing
- For e-commerce, pair with [[wiki/payloadcms/ecommerce|Ecommerce Plugin]] or [[wiki/payloadcms/ecommerce-payment-adapters|Payment Adapters]]
## Related
- [[wiki/payloadcms/plugins|Plugins Overview + Official]]
- [[wiki/payloadcms/ecommerce|Ecommerce Plugin]]
- [[wiki/payloadcms/ecommerce-payment-adapters|Ecommerce — Payment Adapters]]
- [[wiki/payloadcms/access-control|Access Control]]
- [[wiki/payloadcms/hooks-collections|Collection Hooks]]
## Sources
- `raw/plugins__stripe.md`
- https://payloadcms.com/docs/plugins/stripe