Skip to Content
WorkerPagos con PayPal

Pagos con PayPal

El flujo de pago usa la API REST de PayPal directamente (sin el SDK de servidor). El worker actúa como intermediario para mantener las credenciales de PayPal fuera del navegador.

Ambos endpoints requieren autenticación (Authorization: Bearer <token>).


Flujo completo

Frontend Worker PayPal API │ │ │ ├─ POST /create-order ──►│ │ │ ├─ POST /oauth2/token ────►│ │ │◄─ access_token ──────────┤ │ ├─ POST /v2/orders ────────►│ │ │◄─ { id: "ORDER-ID" } ────┤ │◄─ { orderID } ─────────┤ │ │ │ │ │ [usuario aprueba en la UI de PayPal] │ │ │ │ ├─ POST /capture-order ─►│ │ │ { orderID, ├─ POST /orders/:id/ │ │ reservationId } │ capture ──────────────►│ │ │◄─ { status: COMPLETED } ─┤ │ │ │ │ ├─ UPDATE reservations (Supabase) │ ├─ POST email de confirmación (Resend) │◄─ { status: completed }┤

Endpoints

POST /api/paypal/create-order

Crea una orden de pago en PayPal.

Body:

{ "amount": 800, "currency": "MXN" }

Respuesta exitosa (200):

{ "data": { "orderID": "PAYPAL-ORDER-ID" } }

El orderID se pasa al componente <PayPalButtons> de @paypal/react-paypal-js via la función createOrder.


POST /api/paypal/capture-order

Captura el pago de una orden aprobada. Este endpoint también actualiza la reservación en Supabase y envía el email de confirmación.

Body:

{ "orderID": "PAYPAL-ORDER-ID", "reservationId": "uuid-de-la-reservacion" }

Respuesta exitosa (200):

{ "data": { "orderID": "PAYPAL-ORDER-ID", "status": "completed" } }

Si PayPal rechaza el pago:

{ "data": { "orderID": "PAYPAL-ORDER-ID", "status": "failed" } }

En ambos casos la reservación se actualiza en Supabase con el estado correspondiente.


Variables de entorno

VariableDevProd
PAYPAL_CLIENT_IDSandbox client IDLive client ID
PAYPAL_CLIENT_SECRETSandbox secretLive secret
PAYPAL_API_URLhttps://api-m.sandbox.paypal.comhttps://api-m.paypal.com

PAYPAL_API_URL se configura en wrangler.toml por entorno (no es un secret).


Email de confirmación

Al capturar un pago exitoso, el worker:

  1. Consulta la reservación → obtiene clerk_user_id y event_id
  2. Consulta el usuario → obtiene full_name y email
  3. Consulta el evento → obtiene title y event_date
  4. Envía email via Resend con template HTML

El template está en apps/worker/src/email.ts como función que retorna HTML puro (sin dependencias de React — incompatible con el edge runtime).

Remitente: AsamaMX <hello@asamamx.com>

Asunto: Tu lugar en {eventTitle} está confirmado

Last updated on