Skip to main content

stacks-payments

Use when implementing payment processing in Stacks — Stripe charges, subscriptions, checkout sessions, customer management, payment methods, invoices, coupons, promo codes, products, prices, webhooks, or the Payment facade. Covers @stacksjs/payments and config/payment.ts.

Datos de origen

Repositorio
stacksjs/postline
Última actividad en el origen
3 de agosto de 2026 a las 19:34
Idioma detectado de SKILL.md
inglés
Estrellas
2
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
stacks-payments
description
Use when implementing payment processing in Stacks — Stripe charges, subscriptions, checkout sessions, customer management, payment methods, invoices, coupons, promo codes, products, prices, webhooks, or the Payment facade. Covers @stacksjs/payments and config/payment.ts.
license
MIT
compatibility
Bun >= 1.3.0, TypeScript
allowed-tools
Read Edit Write Bash Grep Glob
# Stacks Payments Full Stripe integration via the Payment facade. Uses Stripe API version `2026-01-28.clover`. The Stripe SDK is initialized from `services.stripe.secretKey` (sourced from `config/payment.ts`). ## Key Paths - Core package: `storage/framework/core/payments/src/` - Payment facade: `storage/framework/core/payments/src/payment.ts` - Stripe driver: `storage/framework/core/payments/src/drivers/stripe.ts` - Billable modules: `storage/framework/core/payments/src/billable/` - Configuration: `config/payment.ts` - SaaS config: `config/saas.ts` - Default billing functions: `storage/framework/defaults/functions/billing/payments.ts` ## Package Exports - `Payment` (default) -- facade object with all payment methods - All individual functions (`charge`, `subscribe`, `checkout`, etc.) - All billable modules (`manageCharge`, `manageCustomer`, `manageSubscription`, etc.) - `stripe` -- raw Stripe SDK instance - `Stripe` -- re-exported Stripe types namespace ## Payment Facade The `Payment` object aggregates all payment operations. Every method is also available as a standalone export. ### Charges ```typescript import { Payment } from '@stacksjs/payments' // Create and confirm a charge (creates PaymentIntent with confirm: true) const intent = await Payment.charge(user, 2999, 'pm_xxx', { currency: 'usd' }) // Create PaymentIntent without confirming (for client-side confirmation) const intent = await Payment.createPayment(user, 2999, { currency: 'usd' }) // Refund -- partial const refund = await Payment.refund('pi_xxx', 1000) // Refund -- full (omit amount) const refund = await Payment.refund('pi_xxx') ``` `charge()` sets `confirmation_method: 'automatic'`, `confirm: true`, attaches the payment method, and delegates to `createPayment()`. If the user has a `stripe_id`, it is set as the customer on the PaymentIntent. Default currency is `'usd'`. The `manageCharge` module also exposes `findPayment(id)` which retrieves a PaymentIntent by ID, returning `null` on failure. ### Checkout Sessions ```typescript // One-time payment checkout const session = await Payment.checkout(user, [ { price: 'price_xxx', quantity: 1 } ], { success_url: '/success', cancel_url: '/cancel' }) // Subscription checkout const subSession = await Payment.subscriptionCheckout(user, 'price_xxx', { success_url: '/success', cancel_url: '/cancel' }) ``` Both methods require the user to have a `stripe_id` (throws if missing). `checkout()` sets `mode: 'payment'`, `subscriptionCheckout()` sets `mode: 'subscription'`. ### Subscriptions ```typescript // Create -- uses lookup_key to resolve the Stripe Price const sub = await Payment.subscribe(user, 'premium-monthly') // Cancel at period end (prorate: true) const cancelled = await Payment.cancelSubscription('sub_xxx') // Cancel immediately (invoice_now: true, prorate: false) const cancelled = await Payment.cancelSubscription('sub_xxx', true) // Check active subscription const hasActive = await Payment.hasActiveSubscription(user, 'default') // Change plan -- swaps the subscription item's price const changed = await Payment.changeSubscription(user, 'enterprise-monthly') ``` `subscribe()` calls `managePrice.retrieveByLookupKey(lookupKey)` to find the price, then creates the subscription with `payment_behavior: 'allow_incomplete'` and `expand: ['latest_invoice.payment_intent']`. It stores the subscription in the `subscriptions` database table. `isValid()` returns `true` if the subscription status is `'active'` or `'trialing'`. `isIncomplete()` checks for `'incomplete'` status. `cancel()` calls `stripe.subscriptions.cancel()` and updates `provider_status` to `'canceled'` in the database. `update()` retrieves the active subscription via `user.activeSubscription()`, finds the new price by lookup key, updates the subscription item, and stores the updated price in the database. ### Customers ```typescript // Get existing or create new Stripe customer const customer = await Payment.getOrCreateCustomer(user, { name: 'John' }) // Update customer details in Stripe const updated = await Payment.updateCustomer(user, { name: 'Jane' }) // Delete from Stripe and clear stripe_id on user model const deleted = await Payment.deleteCustomer(user) ``` `createOrGetStripeUser()` checks `user.stripe_id` first. If the user has one, it retrieves the customer from Stripe. If the customer was deleted (404 or `deleted: true`), it creates a new one. On creation, it auto-fills `name` and `email` from the user model and calls `user.update({ stripe_id: customer.id })`. Additional methods on `manageCustomer`: - `stripeId(user)` -- returns `user.stripe_id` - `hasStripeId(user)` -- boolean check - `createStripeCustomer(user, options)` -- throws if user already has a stripe_id - `createOrUpdateStripeUser(user, options)` -- creates or updates - `retrieveStripeUser(user)` -- returns customer or undefined - `syncStripeCustomerDetails(user, options)` -- updates Stripe with user's name, email, address, locales, metadata ### Payment Methods ```typescript // Add a payment method to the customer const pm = await Payment.addPaymentMethod(user, 'pm_xxx') // Set as default (by Stripe payment method ID string) const customer = await Payment.setDefaultPaymentMethod(user, 'pm_xxx') // Remove a payment method (by database record ID number) const removed = await Payment.removePaymentMethod(user, paymentMethodDbId) // Create a setup intent for collecting payment methods const intent = await Payment.createSetupIntent(user, { payment_method_types: ['card'] }) ``` `addPaymentMethod()` accepts a string (Stripe PM ID) or Stripe.PaymentMethod object. It attaches the PM to the customer if not already attached, then stores it in the `payment_methods` table with `type`, `last_four`, `brand`, `exp_year`, `exp_month`, `user_id`, `provider_id`. `setUserDefaultPayment()` accepts a Stripe PM ID string, clears existing `is_default` flags, sets the new default in the database, and updates `invoice_settings.default_payment_method` on the Stripe customer. `setDefaultPaymentMethod()` accepts a database record ID number. Additional methods on `managePaymentMethod`: - `updatePaymentMethod(user, pmId, params)` -- updates PM in Stripe - `listPaymentMethods(user)` -- queries `payment_methods` table by `user_id` - `retrievePaymentMethod(user, pmId)` -- by database ID - `retrieveDefaultPaymentMethod(user)` -- finds where `is_default: true` ### Invoices ```typescript const invoices = await Payment.getInvoices(user) // lists with expanded payment_intent.payment_method const invoice = await Payment.createInvoice('cus_xxx', { description: 'Custom invoice' }) const paid = await Payment.payInvoice('inv_xxx') ``` `getInvoices()` requires the user to have a `stripe_id` and expands `data.payment_intent.payment_method`. ### Products & Prices ```typescript // Create a product with its price const { product, price } = await Payment.createProduct('Pro Plan', 2999, { currency: 'usd', interval: 'month', description: 'Pro features' }) // Get a price by Stripe lookup_key const price = await Payment.getPrice('premium-monthly') // List active products const products = await Payment.listProducts({ limit: 10 }) ``` `createProduct()` creates the Stripe product, then creates a price linked to it. If `interval` is provided, the price gets `recurring: { interval }`. Additional methods on `manageProduct`: - `create(params)`, `retrieve(productId)`, `update(productId, params)` - `archive(productId)` -- sets `active: false` - `search(query, params)` -- Stripe product search - `list(params)` -- defaults to `active: true` Additional methods on `managePriceExtended`: - `create(params)`, `retrieve(priceId)`, `update(priceId, params)` - `list(params)` -- defaults to `active: true` - `listByProduct(productId, params)` -- prices for a specific product - `search(query, params)` -- Stripe price search - `archive(priceId)` -- sets `active: false` ### Coupons & Promo Codes ```typescript const coupon = await Payment.createCoupon({ percentOff: 20, duration: 'once', name: 'Holiday Sale', maxRedemptions: 100 }) // Or amount-based: { amountOff: 500, currency: 'usd', duration: 'forever' } const promo = await Payment.createPromoCode('coupon_xxx', 'SAVE20') const valid = await Payment.validatePromoCode('SAVE20') // returns PromotionCode | null ``` `createCoupon()` supports `percentOff`, `amountOff`, `currency`, `duration` ('forever' | 'once' | 'repeating'), `durationInMonths`, `name`, `maxRedemptions`. Additional methods on `manageCoupon`: - `retrieve(couponId)`, `update(couponId, params)`, `delete(couponId)`, `list(params)` - `createPromotionCode(params)` -- wraps `stripe.promotionCodes.create()` - `retrievePromotionCode(code)` -- lists active promotion codes matching the code string ### Transactions ```typescript import { manageTransaction } from '@stacksjs/payments' const tx = await manageTransaction.store(user, productId, { brand: 'visa', provider_id: 'pi_xxx', description: 'Purchase', type: 'one-time' }) const txList = await manageTransaction.list(user) ``` Transactions are stored in the `payment_transactions` table with `name` (from product), `amount` (from product `unit_price`), `brand`, `type`, `provider_id`, `user_id`. ### Webhooks ```typescript import { Payment } from '@stacksjs/payments' // Register handlers Payment.onPaymentIntent({ succeeded: async (event) => { /* ... */ }, failed: async (event) => { /* ... */ }, created: async (event) => { /* ... */ }, canceled: async (event) => { /* ... */ }, }) Payment.onSubscription({ created: async (event) => { /* ... */ }, updated: async (event) => { /* ... */ }, deleted: async (event) => { /* ... */ }, trialWillEnd: async (event) => { /* ... */ }, }) Payment.onInvoice({ paid: async (event) => { /* ... */ }, paymentFailed: async (event) => { /* ... */ }, created: async (event) => { /* ... */ }, finalized: async (event) => { /* ... */ }, }) Payment.onCheckout({ completed: async (event) => { /* ... */ }, expired: async (event) => { /* ... */ }, }) Payment.onCharge({ succeeded: async (event) => { /* ... */ }, failed: async (event) => { /* ... */ }, refunded: async (event) => { /* ... */ }, disputed: async (event) => { /* ... */ }, }) // Process incoming webhook request const result = await Payment.processWebhook(rawPayload, signatureHeader, { secret: 'whsec_xxx', tolerance: 300 }) // Returns: { success: boolean, eventType?: string, error?: string } // Low-level: register any event type Payment.webhook.onWebhookEvent('payment_method.attached', handler) Payment.webhook.registerWebhookHandlers({ 'payment_intent.succeeded': handler }) // Event data extractors import { getPaymentIntent, getSubscription, getInvoice, getCheckoutSession, getCharge, getCustomer } from '@stacksjs/payments' ``` Supported webhook event types: `payment_intent.succeeded`, `payment_intent.payment_failed`, `payment_intent.created`, `payment_intent.canceled`, `customer.subscription.created/updated/deleted`, `customer.subscription.trial_will_end`, `customer.created/updated/deleted`, `invoice.paid/payment_failed/finalized/created`, `checkout.session.completed/expired`, `charge.succeeded/failed/refunded`, `charge.dispute.created/closed`, `payment_method.attached/detached`, `setup_intent.succeeded/setup_failed`, plus any string. ### Setup Products from SaaS Config ```typescript import { createStripeProduct } from '@stacksjs/payments' const result = await createStripeProduct() // Creates Stripe products and prices from config/saas.ts plans ```
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub