Receta: vende membresías mensuales
Un gimnasio, una academia o un SaaS con planes mensuales: registra clientes, cobra cada mes por enlace o con débito automático y mantén el acceso al día con los pagos, paso a paso.
Lo que vas a construir
Un negocio de membresías: “Básico” a $15 y “Pro” a $25 al mes. Los miembros se registran en tu sitio, pagan cada mes en bolívares y solo pierden el acceso después de que VEX Pay intentó cobrar durante 3 días. Quien lo prefiera paga con débito automático.
| Paso | Haces | Listo cuando |
|---|---|---|
| 1 | Crea tus planes | Tienes dos ids price_… |
| 2 | Escucha los webhooks de facturación | Tu endpoint verifica customer.subscription.created |
| 3 | Registra un miembro | Recibe la primera factura y la paga |
| 4 | Mantén el acceso al día | El acceso sigue a invoice.paid y customer.subscription.deleted |
| 5 | Ofrece débito automático | A un miembro de prueba se le debita sin pagar a mano |
| 6 | Sal a producción | Tu primer miembro real se renueva |
Paso 01
Crea tus planes
curl --request POST "${API_URL}/v1/products" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "name": "Membresía", "priceUsd": "15.00" }'
curl --request POST "${API_URL}/v1/prices" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "product": "PRODUCT_ID", "unitAmountUsd": 15, "recurring": { "interval": "month" }, "nickname": "Básico" }'
curl --request POST "${API_URL}/v1/prices" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "product": "PRODUCT_ID", "unitAmountUsd": 25, "recurring": { "interval": "month" }, "nickname": "Pro" }'Punto de control: guarda los dos ids price_… en tu configuración. Los planes se crean una sola vez, no por cada miembro.
Paso 02
Escucha los webhooks de facturación
Registra (o actualiza) tu endpoint de webhooks con los eventos de facturación y verifica las firmas como en Webhooks. Guarda el id sub_… en el registro del miembro.
curl --request POST "${API_URL}/v1/webhooks" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"url": "https://example.com/webhooks/vexpay",
"events": ["customer.subscription.created", "customer.subscription.updated", "customer.subscription.deleted",
"customer.subscription.reactivated", "invoice.paid", "invoice.payment_failed"]
}'Paso 03
Registra un miembro
Cuando alguien elige un plan, crea el cliente y la suscripción desde tu servidor. Pon tu propio id de usuario en metadata para relacionar cada webhook con el miembro.
curl --request POST "${API_URL}/v1/customers" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "name": "Ana Pérez", "email": "ana@example.com", "phone": "04141234567", "idNumber": "V12345678", "metadata": { "userId": "u_981" } }'
curl --request POST "${API_URL}/v1/subscriptions" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "customer": "CUSTOMER_ID", "price": "PRICE_PRO", "metadata": { "userId": "u_981" } }'
# Lleva al miembro directo a su primera factura:
curl "${API_URL}/v1/invoices?subscription=SUBSCRIPTION_ID" --header "x-api-key: ${VEXPAY_API_KEY}"
# → items[0].hostedInvoiceUrlPunto de control: redirige al miembro a hostedInvoiceUrl (también le llega por correo; en modo de prueba solo si su correo es el de tu perfil de negocio), págala con un método de prueba y comprueba que llegue invoice.paid. ¿Prefieres ofrecer una prueba? Agrega "trialPeriodDays": 7 y no se emite factura hasta que termine.
Paso 04
Mantén el acceso al día con los pagos
| Evento | Tu app |
|---|---|
invoice.paid | Acceso activo (o extendido) hasta el currentPeriodEnd de la suscripción |
customer.subscription.updated con status: past_due | Mantén el acceso y muestra un aviso de “pago pendiente” con el enlace de la factura |
customer.subscription.deleted | Quita el acceso. Si cancellationReason es payment_failed, avísale que pagar la factura lo reactiva |
customer.subscription.reactivated | Vuelve a dar acceso |
Para un botón de “Cancelar membresía”, llama a POST /v1/subscriptions/:id con { "cancelAtPeriodEnd": true }: el miembro conserva lo que ya pagó y no se le vuelve a cobrar.
Paso 05
Ofrece débito automático
Para los miembros que no quieren pagar a mano nunca más, crea una sesión de autorización, envíales el enlace y cambia la suscripción cuando autoricen (payment_method.attached). Todos los detalles: Débito automático.
curl --request POST "${API_URL}/v1/setup-sessions" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "customer": "CUSTOMER_ID", "successUrl": "https://example.com/cuenta" }'
# → envía "url" al miembro
curl --request POST "${API_URL}/v1/subscriptions/SUBSCRIPTION_ID" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "collectionMethod": "charge_automatically" }'Punto de control (modo de prueba): autoriza con un teléfono que termine en 0000: la siguiente factura se debita y se paga sola. Prueba con 0002 para ver un fallo insufficient_funds y el reintento del día siguiente. Con un precio de prueba diario no tienes que esperar un mes por la siguiente factura.
Paso 06
Sal a producción
- Completa tu perfil de negocio (nombre, logo, correo): es lo que ven tus miembros en las facturas y los correos.
- Vuelve a crear tus planes con la clave de producción (los objetos de prueba y de producción son independientes) y cambia tu servidor a esa clave.
- Elige tus intentos de cobro por defecto en Portal → Billing → Settings.
- Si ofreces débito automático, pídele a VEX Pay que lo habilite en tu cuenta de producción; mientras tanto, en producción las sesiones de autorización y
charge_automaticallyrespondenautomatic_charging_unavailable, ysend_invoicefunciona como siempre.