El pago de licencias
Cómo vende el sitio web sus dos licencias: el pago, las propias páginas de Stripe y PayPal, el pago de prueba, el webhook, el recibo y su clave de licencia, y cómo cambiar las ofertas o vender a través de una tienda externa.
Para el paquete Full Stack
De una licencia a un recibo
- En la página de precios el comprador pulsa Get single project o Get Studio. El Purchase summary muestra la licencia, lo que cubre y el total, y Continue to checkout abre
/checkout?license=singleo?license=studio. - El pago pide un correo, un nombre completo y un método de pago, Card o PayPal, y la aceptación de los términos de la licencia. Continue to payment los envía a la API, que escribe el pedido (una referencia como
NS-7KQ2-M9XD) a su propio precio: el navegador nunca envía uno. - El comprador paga en la propia página de Stripe o de PayPal, o en el pago de prueba del sitio cuando ese método no tiene claves. Los datos de la tarjeta nunca se escriben en tu sitio.
- La página a la que vuelve el comprador,
/checkout/success, pide a la API que compruebe el pago con el proveedor, y de nuevo cada tres segundos, hasta cinco veces, mientras sigue procesándose. Cuando la API lo ha verificado, el pedido está pagado, el recibo muestra la clave de licencia (comoNSK-4F7Q-2M9X-HB3T-8KRD) con Copy the license key, y el recibo se envía por correo al comprador.
El sitio web nunca decide que un pedido está pagado. Un pedido solo lo paga el webhook firmado de Stripe, la sesión de Stripe que la API lee de vuelta cuando regresa el comprador, o la captura de PayPal que la API hace en ese regreso. Exactamente uno de ellos emite la clave y el correo, lleguen los que lleguen. Un comprador que sale de la página de pago llega a /checkout/cancelled, que dice que no se cobró dinero y ofrece Try again.
Métodos de pago
| Método | Se define en el .env de la API | Cómo funciona |
|---|---|---|
| Tarjeta, en Stripe | STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET | Stripe Checkout en modo pago. El precio viaja con cada sesión, así que no hace falta crear nada antes en Stripe. Stripe devuelve al comprador a /checkout/success o /checkout/cancelled. |
| PayPal | PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET (una aplicación REST de PayPal), PAYPAL_ENV (sandbox por defecto, o live) | La propia página de PayPal. La API captura el pago aprobado cuando el comprador vuelve a /checkout/success. |
| Pago de prueba | nada: acepta cualquier método que no tenga claves | La página /checkout/test del sitio, con Pay y Cancel payment. No cobra a nadie. |
- Cada método va a su proveedor una vez definidas las claves de ese proveedor, y al pago de prueba hasta entonces, así que una instalación nueva puede completar una compra de inmediato.
- Mientras ningún método mueve dinero real (sin claves, una clave
sk_test_de Stripe o el sandbox de PayPal), el pago dice que está en modo de prueba. Con una clave de prueba de Stripe nombra la tarjeta de prueba:4242 4242 4242 4242, cualquier fecha futura y cualquier CVC. - Usa primero claves de prueba: no mueven dinero. Cuando la API inicia, registra para cada proveedor si acepta pagos de prueba o reales.
- Las claves de Stripe son las mismas que usa la facturación de suscripciones del panel.
El webhook de Stripe
Los pedidos de licencias y las suscripciones de los espacios de trabajo comparten un webhook de Stripe. Antes de salir en vivo, regístralo en Stripe con la dirección pública de tu API y pon su secreto de firma en STRIPE_WEBHOOK_SECRET:
https://<your-api>/api/billing/webhooks/stripePara las licencias la API actúa con checkout.session.completed (el pedido está pagado) y checkout.session.expired (el pedido falló). Distingue una sesión de licencia de una de suscripción por los metadatos kind: license de la sesión. PayPal no necesita webhook: la captura ocurre cuando el comprador vuelve.
Con STRIPE_SECRET_KEY definido y STRIPE_WEBHOOK_SECRET vacío, el registro de la API lo indica al iniciar y cada entrega se rechaza con un 400 que nombra la variable. Un pedido con tarjeta solo se paga entonces cuando el comprador vuelve a la página del recibo.
En tu propio equipo Stripe no puede llegar a la API, y un pago de prueba se completa igualmente: la página de retorno pregunta a la API, que lee la sesión de vuelta desde Stripe. Define WEBSITE_URL con la dirección del sitio web, porque cada enlace de retorno que la API da a Stripe y a PayPal se construye a partir de ella, en el idioma del comprador.
Estados del pedido
| Estado | Significado | Qué dice la página del recibo |
|---|---|---|
pending | Escrito, aún sin pagar. | "Checking your payment.", y luego "Your payment is still processing." con Check again. |
paid | Verificado con el proveedor; se emite la clave de licencia. | "Thank you. Studio is yours." (con la licencia comprada), los detalles del pedido y la clave. |
failed | La sesión de Stripe caducó, PayPal rechazó la captura, o no se pudo abrir la página del proveedor. | "The payment did not go through." con Try again. |
cancelled | El comprador salió de la página de pago. | "This order was cancelled." |
El recibo muestra la clave de licencia solo en un pedido pagado, y marca un pedido de prueba con "Test payment: no money moved." Si el webhook de Stripe informa después de un pago de un pedido cancelado o fallido (un comprador que volvió atrás y pagó en otra pestaña), ese pedido pasa a pagado.
Límites y seguridad
- Un pedido se lee solo por su id, 32 caracteres aleatorios que solo llevan los enlaces de retorno del comprador y el correo del recibo. No hay una lista de pedidos para que un visitante la explore.
- Cada envío lleva su propio token, así que pulsar Continue to payment dos veces abre el mismo pedido y la misma página de pago, nunca un segundo cobro.
- Cada dirección puede iniciar diez pagos en una hora; el siguiente dice "Too many attempts from this address. Try again in an hour." Detrás de un proxy inverso, define
TRUST_PROXY=1en el.envde la API, o todos los compradores comparten el cupo del proxy. - No se añade ningún impuesto. Configura los impuestos de tu país antes de aceptar pagos reales; las comisiones propias de Stripe y PayPal son aparte.
El correo del recibo
El correo del pedido pagado da la referencia del pedido, la licencia, el importe, la clave de licencia y un enlace de vuelta al recibo. Se envía mediante SMTP_HOST y los demás ajustes SMTP_*; sin ellos se escribe en el registro de la API. El texto del correo está en inglés en ambos idiomas, en back-end/src/modules/licenses/services/license-checkout.service.ts; el enlace del recibo se abre en el idioma en que pagó el comprador.
Cambiar las licencias y sus precios
El precio se guarda en dos lugares, y deben coincidir:
| Archivo | Qué decide |
|---|---|
back-end/src/modules/licenses/constants/license-offers.ts | Lo que cobra la API, en céntimos (19900 y 39900, dólares estadounidenses), y el nombre en la página del proveedor y en el recibo. |
website/src/config/licenses.ts | Lo que imprime el sitio web, cuántos productos finales cubre cada licencia, qué tarjeta se recomienda y las líneas que lista cada tarjeta (sus textos están bajo PricingPage.licenses en website/messages/pricing/en.json y ar.json). |
Un precio cambiado solo en el sitio web cambia únicamente lo que muestra la página: el comprador sigue pagando el importe de la API. Los dos ids de licencia, single y studio, están escritos en ambos archivos, la petición de pago de la API y los mensajes del sitio web, así que una tercera licencia es un cambio en cada uno de ellos.
Vender a través de una tienda externa
Define NEXT_PUBLIC_PURCHASE_URL_SINGLE y NEXT_PUBLIC_PURCHASE_URL_STUDIO con el pago de la tienda para cada licencia y vuelve a construir el sitio web (con Docker Compose, PURCHASE_URL_SINGLE y PURCHASE_URL_STUDIO en el .env junto a docker-compose.yml). Continue to checkout abre entonces esa dirección en lugar de /checkout. Una licencia que se deja vacía mantiene el pago propio del sitio.
Sin la API
Cuando el sitio web funciona con sus datos de ejemplo integrados, el pago se comprueba y se responde en el navegador: un pedido abre el pago de prueba del propio sitio, Pay emite una clave de licencia en el recibo, y los pedidos se guardan solo en ese navegador. No se cobra ni se envía nada.
En modo demostración
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Cómo se comporta el pago en una demostración pública.
Las rutas que hay detrás
| Ruta | Qué hace |
|---|---|
GET /api/licenses/checkout/options | Los métodos ofrecidos, el proveedor que cobra cada uno (stripe, paypal o simulator) y testMode. |
POST /api/licenses/checkout | license (single o studio), email, name, method (card o paypal), locale (en o ar) y clientToken. Responde con el id del pedido y la página donde pagar; 429 pasado el límite, 503 payment_unavailable cuando no se pudo abrir la página del proveedor. |
GET /api/licenses/orders/:id | El pedido, con su clave de licencia una vez pagado. |
POST /api/licenses/orders/:id/confirm | Pregunta al proveedor si el pago se completó. |
POST /api/licenses/orders/:id/cancel | El comprador salió de la página de pago. |
POST /api/licenses/orders/:id/simulate | El pay o cancel del pago de prueba, para un pedido que tomó el pago de prueba. |
Todos son públicos: el id de un pedido es lo que prueba que quien lee es su comprador. Un id que no tiene 32 caracteres hexadecimales, o que no coincide con ningún pedido, responde 404 order_not_found.