Communitygithub.com

Stripe Connect y Suscripciones

Habilidad de agente: construye liquidación de marketplace con Stripe Connect y facturación de suscripciones de plataforma — cargos y transferencias separados, incorporación de cuentas conectadas, depósitos en garantía y reservas renovables, webhooks idempotentes, reintento y reversión de transferencias, cobros fuera de sesión, conciliación de libros mayores — en Next.js App Router

¿Qué es Stripe Connect y Suscripciones?

Esta habilidad de agente proporciona una arquitectura completa para gestionar dos flujos de dinero en una sola cuenta de Stripe: un marketplace que cobra a un comprador y distribuye los ingresos a múltiples vendedores (Connect, cargos y transferencias separados), y una suscripción de plataforma que cobra a esos vendedores una tarifa recurrente fuera de sesión (Billing). Es crucial entender que el cargo del comprador y los pagos a los vendedores fallan de forma independiente; para cuando se ejecuta la liquidación, el dinero ya se ha movido, por lo que una transferencia rechazada nunca debe fallar el cargo ni el webhook, y debe poder reintentarse más tarde sin pagar a nadie dos veces. La habilidad soporta plataformas como Claude Code, Cursor y Codex, y se describe en detalle en su archivo SKILL.md, que incluye reglas estrictas, diagramas de arquitectura, referencias a implementaciones concretas y un contrato de adaptación para integrarse en aplicaciones existentes. Está diseñada para ser utilizada en Next.js App Router y requiere el uso de Stripe Connect con cargos y transferencias separados, nunca cargos con destino único.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add timerise-ai/stripe-connect-subscriptions

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Stripe Connect y Facturación de Suscripciones

Dos flujos de dinero en una sola cuenta de Stripe. Un marketplace cobra al comprador una vez y distribuye los ingresos a muchos comerciantes (Connect, cargos y transferencias separados). Una suscripción de plataforma cobra a esos comerciantes una tarifa recurrente fuera de sesión (Billing). Comparten un cliente, un par de webhooks y un tipo de dinero.

La idea clave que lo define todo: el cargo del comprador y los pagos a los comerciantes fallan de forma independiente. Para cuando se ejecuta la liquidación, el dinero ya se ha movido, por lo que una transferencia rechazada nunca debe fallar el cargo ni el webhook, y debe poder reintentarse más tarde sin pagar a nadie dos veces.

Cuándo usarlo

  • Un pago se divide entre varios vendedores, y la plataforma se queda con una comisión.
  • Los vendedores se incorporan a Connect y reciben pagos con retraso (depósitos en garantía, reservas, KYC).
  • La plataforma cobra a sus propios vendedores una tarifa recurrente con una tarjeta guardada.
  • Una cuenta conectada parece activa pero nunca ha recibido dinero.

Cuándo NO usarlo

No estoUsa en su lugar
Pago de un solo vendedor, sin divisiónStripe Checkout / Payment Element directamente
Incorporación y pagos de PayPal MarketplaceUna habilidad de PayPal; solo los puntos en común se comparten
UI de tarjeta, estilo de Payment ElementTu sistema de diseño; esta habilidad es del lado del servidor

Arquitectura

comprador ──cargo (cuenta de plataforma, transfer_group = orderId)──▶ balance de plataforma
                │  liquidación (webhook O sincronización de lectura; reclamo arrendado)
   ┌────────────┴──┬────────────────────────┬────────────────┐
   ▼               ▼                        ▼                ▼
transferencia:vendedor  transferencia:socio    depósito garantía    reserva renovable
(source_transaction = el cargo)      (release_at)    (% retenido)
   │                                        │  cron de liberación
   ▼                                        ▼
balance conectado ◀── reintento-transfs  balance pagadero ──▶ pago (controlado por KYC/riesgo)
                      (tramos no financiados)

plataforma ──PaymentIntent off_session (customer + PM guardada)──▶ factura de suscripción
             cobros: 3 intentos, 3 días de diferencia, luego suspender

Hechos críticos

  1. Cargos y transferencias separados, nunca cargos con destino. Un cargo tiene un único destination; un carrito con varios vendedores necesita N transferencias bajo un mismo transfer_group, por lo que application_fee_amount es inutilizable.
  2. Una transferencia sin source_transaction se carga del balance disponible y se rechaza mientras el cargo aún se está liquidando; en una cuenta de plataforma joven, esto ocurre en cada transferencia. Esta única bandera es lo que permite dividir los fondos mientras el cargo aún se está liquidando.
  3. Las transferencias de Stripe transfronterizas solo funcionan dentro de EE.UU./Canadá/Reino Unido/EEE/Suiza. Una plataforma en otro lugar paga a cuentas conectadas solo en su propio país. Stripe aplica esto al momento de la transferencia, no al de la incorporación, por lo que las plantillas aplican la regla de región en la incorporación.
  4. Los eventos de Connect usan un secreto de firma diferente al de los eventos de la plataforma. Dos endpoints, dos secretos, una URL — verifica contra ambos.
  5. El país de una cuenta conectada es inmutable — un país incorrecto significa volver a incorporar, no una corrección.
  6. El dinero nunca es un número de coma flotante — cadenas numeric(19,4) de principio a fin, matemáticas con bigint, unidades menores solo en el límite del SDK.

Reglas estrictas

Nunca permitas que una transferencia fallida haga fallar la liquidación. Registra el tramo como no financiado y continúa. El cargo ya ha tenido éxito, por lo que el webhook también debe tener éxito; el cron de reintento financia el tramo más tarde.

Nunca trates una inserción duplicada de webhook como "ya manejada". La inserción es un reclamo; el reintento después de que una entrega fallara a medio camino vuelve a ejecutar los manejadores, por lo que cada evento se ejecuta hasta completarse exactamente una vez.

Nunca reenvíes una transferencia sin preguntar a Stripe si ya existe. Un tramo registrado como no financiado porque la respuesta se perdió paga dos veces una vez que pasa la ventana de idempotencia de 24 horas de Stripe.

Nunca derives exclusividad de liquidación de una bandera de estado escrita al final. Dos llamadas alcanzan la liquidación de forma rutinaria; un reclamo arrendado atómicamente es lo que hace que el inventario y las transferencias ocurran una vez.

Nunca reviertas más que el margen restante de una transferencia. Las reversiones apiladas (tarifa de pasarela, luego un reembolso) se rechazan más allá del monto original.

Inicio rápido

  1. Modela el dinero — money.md, data-model.md, store.md.
  2. Cliente, secretos duales de webhook, entorno — stripe-adapter.md.
  3. Incorpora cuentas; verifica la regla de región primero — connect-accounts.md.
  4. Recibe eventos de forma idempotente — webhooks.md.
  5. Liquida: reclama, distribuye, depósito en garantía, reserva — settlement.md.
  6. Convierge: reintenta tramos, concilia tarifas — reconciliation.md.
  7. Factura a los inquilinos — subscriptions.md; ejecuta con operations.md.

Adáptalo a tu aplicación con adaptation.md; el registro de la auditoría está en provenance.md.

Contrato de adaptación

Punto de integraciónLa habilidad proporcionaEl anfitrión proporciona
Entidades de dominioTenant (organización vendedora), Order, VendorOrder, PartnerSu propio vocabulario
Ámbito del inquilinoUn tenantId derivado del servidororg / workspace / vendedor
Guardia de autenticaciónUna firma de adaptador por rutaClerk, NextAuth, Supabase, personalizado
Acceso a datosUn contrato PaymentsStore + SQLSu ORM o SDK
Auditoría + notificacionesSitios de llamada, nombres de eventos, formas de carga útilSu tabla de auditoría / bandeja de salida
Trabajo en segundo planoCuatro crons y su cadenciaSu planificador
ValidaciónUna forma de esquema por cuerpo de rutazod / valibot / yup
UINada — esta habilidad es del lado del servidorTodo

Directorio de referencias

EscenarioPalabras clave de activaciónReferencia
Por qué este modelo de dinerocargos y transferencias separados, cargo destino, application_fee_amount, transfer_group, libro mayorarchitecture.md
Tablas, columnas, RLSesquema, migración, payment_intents, transfers, escrow_holds, webhook_eventsdata-model.md
El contrato de acceso a datosstore, repositorio, reclamo atómico, actualización condicional, ORMstore.md
Montos y redondeonumeric, bigint, unidades menores, distribuir, resto mayoritario, centavosmoney.md
Código de cliente y adaptadorstripeClient, apiVersion, constructEvent, whsec_, PaymentIntent, refund, payoutstripe-adapter.md
Incorporación, estado de cuentaExpress, Accounts v2, account.updated, charges_enabled, acct_, country, regionconnect-accounts.md
Recibir eventos de forma seguraidempotencia, duplicado, repetición, cuerpo sin procesar, firma, invalid_signaturewebhooks.md
Dividir un pedido pagadoliquidación, distribución, source_transaction, depósito garantía, reserva, single-flightsettlement.md
Arreglar lo que no llegóreintento, no financiado, backoff, adopt, tarifa de pasarela, clawback, reversión, margenreconciliation.md
Tarifas recurrentes de plataformaSetupIntent, off_session, tarjeta guardada, dunning, invoice, past_due, suspendsubscriptions.md
Configuración, entorno, crons, depuraciónSTRIPE_SECRET_KEY, endpoint webhook, stripe listen, cron, "el comerciante nunca pagó"operations.md
Adaptarlo a esta aplicaciónadaptar, sonda del anfitrión, renombrar, ORM, guardia de autenticación, puertoadaptation.md
El registro de auditoríaprocedencia, desviación, mantenido, añadido, no verificadoprovenance.md

Skills relacionados