@pylonsync/stripe replaces the ~400 lines every Pylon app rewrites when it adds Stripe billing: customer creation, checkout session creation, billing portal, webhook signature verification, plan derivation, and subscription state. One stripe({plans, hooks}) block returns a manifest fragment and handler factories.
Install
Config
Wrapper files
Pylon loads function handlers by file. Create one-line wrappers underfunctions/:
billing.handlers (cancelSubscription, restoreSubscription, stripeWebhook, plus the _pylonStripe* internals).
Required env
Webhook endpoint
Configure in Stripe Dashboard → Developers → Webhooks → Add endpoint:whsec_...). Set it as STRIPE_WEBHOOK_SECRET on your Pylon machine.
Lifecycle hooks
RBAC
TheauthorizeReference hook gates subscription mutations. Defaults:
referenceType: "org": the caller must be the org’s owner or admin.referenceType: "user": the caller must be the user.referenceType: "custom": you must supply your ownresolveCustomerhook, which mapsreferenceIdto a Stripe customer ID and creates one if needed.customhas no default authorization, so supplyauthorizeReferencetoo.
Security
- Constant-time signature verification with a 5-minute replay window. The
Stripe-Signatureheader can carry multiplev1=signatures (Stripe emits several during a signing-secret rotation). The verifier accepts a match against any of them. - URL allowlist derived automatically from
PYLON_PUBLIC_URLandPYLON_CORS_ORIGIN. No hardcoded host strings. - Three-signal plan resolver: it matches on lookup_key, then nickname, then price ID match. Stripe sometimes omits the first two on webhook payloads.
- Double-trial guard: a prior
Subscriptionrow for the same reference disables the trial period, regardless of plan config. - Idempotent webhook upsert via
stripeSubscriptionIdlookup, so Stripe retries produce the same state.