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.

Quellinformationen

Repository
stacksjs/postline
Letzte Quellaktivität
3. August 2026 um 19:34
Erkannte Sprache von SKILL.md
Englisch
Sterne
2
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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 ```
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen