Facturación
Plan y uso para un producto de IA, al estilo de Cursor, Claude y Vercel. Un medidor de uso dividido por modelo que proyecta el final del ciclo y avisa antes de que se agoten los créditos, un gráfico diario por el que puedes desplazarte, un límite de gasto con alertas que puedes previsualizar en el medidor, cambios de plan con prorrateo exacto, un formulario de tarjeta con validación real y facturas descargables en PDF.
Billing es la sección de plan y uso de los ajustes de un producto de IA. Se integra en una sección de SettingsShell y cubre lo que la gente viene a buscar a esa página: cuánto ha usado, si le alcanzará, qué paga y cómo cambiarlo.
El medidor de uso se llena por modelo, con una extensión más clara que muestra dónde terminará probablemente el ciclo al ritmo de los últimos 7 días. Cuando eso supera los créditos incluidos, una nota discreta dice cuándo: «At this pace you’ll run out around Oct 24, 4 days before your credits reset», con formas de activar el uso adicional o ver los planes. Debajo, un gráfico de barras diario basado en Chart cubre todo el ciclo: los días pasados, hoy con toda su intensidad, el resto del ciclo como barras tenues proyectadas a tu ritmo reciente, y una línea discontinua para el ritmo uniforme que duraría todo el ciclo. Pasa el cursor o enfócalo y usa las teclas de flecha para leer cualquier día.
Los límites son un borrador, como en el resto de secciones de ajustes. Arrastra el umbral de alerta o activa el uso adicional y los marcadores se mueven al instante en los medidores, el medidor de uso adicional se desliza hacia dentro y aparece la barra de guardado. Un límite inferior a lo ya gastado en este ciclo se rechaza indicando la cantidad.
Las mejoras muestran el prorrateo exacto antes de cobrar nada: el plan nuevo por los días restantes, los días sin usar del actual y «You’ll pay $13.33 today». Las rebajas esperan al final del periodo y enumeran lo que se pierde. Cancelar es una confirmación honesta sin ofertas, el plan sigue activo hasta que termina el periodo y Keep Pro lo deshace hasta entonces.
El formulario de tarjeta da formato a los números mientras escribes sin mover el cursor, los comprueba con Luhn, detecta la marca y valida la caducidad y el código de seguridad. Las facturas tienen insignias de estado, Pay now para las fallidas y se descargan como archivos PDF reales.
Añade el registro Pro a components.json
components.json Añade tu token
Crea un token en tu página de cuenta y colócalo en
.env.localcomoHEXTAUI_PRO_TOKEN.Añade el bloque
pnpm dlx shadcn@latest add @hextaui-pro/billing
Conéctalo a tu API
BillingSettings muestra los datos que le pasas y te llama de vuelta con cada cambio. Devuelve un valor o lanza un error desde un callback: el mensaje lanzado se muestra en el diálogo que lo pidió, y nada cambia hasta que pases nuevas props.
Actualizaciones de tarjeta
onUpdatePaymentMethod recibe los dígitos limpios, la caducidad, el código de seguridad y la marca una vez que el formulario supera sus comprobaciones. Lanza un error para mostrar un rechazo en el diálogo. En producción, entrega los datos a la tokenización de tu proveedor de pagos y nunca los almacenes tú mismo.
Tus propios archivos de factura
Las facturas se descargan como PDF generados en el navegador a partir de los datos de la factura. Devuelve un Blob desde onDownloadInvoice para servir tu propio archivo, o asigna un href a una factura.
Anatomía
Las partes que compones, de fuera hacia dentro.
| Parte | Descripción |
|---|---|
BillingSettings | El contenido de la sección: resumen del plan, medidores de uso y el Chart diario, límites, planes, pago, facturas y cancelación, con sus diálogos. |
BillingSettingsSkeleton | Un marcador de carga con la forma de la sección. Pásalo al skeleton de SettingsSection. |
prorate | El cálculo de prorrateo detrás del diálogo de mejora, para tu servidor o tus pruebas. |
forecastUsage | La proyección detrás del medidor y la nota de agotamiento. |
createInvoicePdf | Construye el PDF de la factura como un Blob. |
BillingSettings
Los precios están en céntimos y las fechas son días ISO como 2026-10-28. Omite un callback para ocultar su acción.
| Prop | Tipo | Predeterminado |
|---|---|---|
plans{ id, name, price, included, description?, features }. Las features son listas completas por plan, para que una rebaja pueda enumerar lo que falta. Un plan con price 0 es el plan al que pasa la gente cuando cancela. | BillingPlan[] | – |
subscription{ planId, periodStart, periodEnd, status?, cancelAtPeriodEnd?, scheduledPlanId? }. | BillingSubscription | – |
usage{ models: { id, name, used }[], daily: { date, used }[], extraRate, unit? }. extraRate son los céntimos por unidad por encima de lo incluido. unit es "credits" por defecto. | BillingUsage | – |
spendLimit{ enabled, limit, alertAt }. limit está en céntimos y alertAt es un porcentaje. | BillingSpendLimit | – |
paymentMethod{ brand, last4, expMonth, expYear, name? }. | BillingPaymentMethod | null | – |
invoices{ id, number, date, description, amount, status, href?, lines?, paidWith? }. status es paid, open, failed, refunded o void. | BillingInvoice[] | [] |
todayEl día que tu servidor considera hoy. Se usa para el prorrateo, las proyecciones y la caducidad de la tarjeta, de modo que servidor y navegador coincidan. | string | the last daily date |
currencyCualquier código de moneda ISO. | string | "USD" |
sellerEl nombre en la parte superior de las facturas generadas. | string | "Hexta" |
customerSe imprime bajo Bill to en las facturas generadas. | { name?, email? } | – |
onChangePlanSe llama con { planId, when, amountDue }. when es «now» para mejoras y «period_end» para rebajas de plan. | (change) => void | Promise | – |
onCancelPlanCancelar al final del periodo. | () => void | Promise | – |
onResumePlanDeshace una cancelación o una rebaja de plan programada. | () => void | Promise | – |
onSpendLimitChangeGuarda los límites. Devuelve { limit: message } para mostrar un error de campo. | (limit) => void | errors | Promise | – |
onUpdatePaymentMethodSe llama con { number, expMonth, expYear, cvc, name, brand } una vez que el formulario es válido. Lanza un error para mostrar un rechazo. | (card) => void | Promise | – |
onPayInvoiceAñade Pay now a las facturas abiertas y fallidas. | (invoice) => void | Promise | – |
onDownloadInvoiceDevuelve un Blob para descargar tu propio archivo, o nada si lo gestionaste tú. Sin esto, se genera un PDF a partir de la factura. | (invoice) => Blob | void | Promise | – |
prorate
Devuelve { kind, amountDue, charge, credit, daysLeft, totalDays, effectiveDate, nextBillingDate }.
| Prop | Tipo | Predeterminado |
|---|---|---|
optionsLas mejoras cobran la diferencia de precio por los días restantes, redondeada una sola vez. Las rebajas no cobran nada y empiezan en periodEnd. Salir de un plan gratuito cobra un mes completo desde hoy. | { from, to, periodStart, periodEnd, today } | – |
| Key | Acción |
|---|---|
| ←→ | Con el gráfico diario enfocado, mueve el tooltip al día anterior o siguiente. |
| Enter | En el formulario de tarjeta, revisa los datos y guarda. |
| ⌘S | Guarda los límites modificados. Ctrl+S en Windows y Linux. |
- Los medidores usan role meter con un texto de valor que incluye la proyección y el umbral de alerta, y el desglose por modelo es una lista real.
- El gráfico diario es una figure llamada «Daily usage this cycle», descrita por un resumen con el total, la media diaria reciente, el día de más actividad y el ritmo uniforme. Una tabla oculta visualmente enumera cada día, con los días proyectados marcados como estimaciones.
- Los cambios de plan, cancelaciones, actualizaciones de tarjeta y descargas se anuncian de forma polite. Los fallos se muestran en el diálogo que lo pidió, como una alerta, y el diálogo permanece abierto con lo que escribiste.
- Los campos de la tarjeta usan los tokens de autocomplete estándar, así que los navegadores y gestores de contraseñas pueden rellenarlos. El primer campo inválido recibe el foco.
- Los inputs son de 16px en pantallas táctiles para que iOS no haga zoom, y los botones crecen hasta 44px.
- Los números y las fechas se formatean en inglés con zonas horarias fijas, así que el servidor y el navegador renderizan el mismo texto.
Construido con
Los componentes gratuitos de HextaUI con los que está hecho Billing. Cada uno se instala por separado.
Código
4 archivos, añadidos a components/blocks/billing.