Casa Nokiate Mockup 17 · Integración Uber Direct
Documento técnico · whiteboard

Cómo viaja un pedido

De principio a fin: cliente → nuestro Next.js → Stripe → Uber Direct → cocina → repartidor → cliente. Cada paso muestra la API exacta, el evento que dispara la siguiente acción, y qué se persiste en la base de datos.

Nuestro stack Stripe Uber Direct Caso de error
Cliente
(navegador)
1El cliente escribe su dirección y avanza a "Pagar"

Antes de redirigir a Stripe, llamamos a Uber Direct para pedir cotización. Si Uber dice "no cubrimos", nunca cobramos.

Next.js
→ Uber Direct
2POST /v1/customers/{cid}/delivery_quotes
{
  "pickup_address":  "{...San Bartolomé 14...}",
  "dropoff_address": "{...Hortaleza 42...}",
  "pickup_ready_dt":   "2026-05-11T20:30:00Z",
  "dropoff_deadline_dt":"2026-05-11T21:00:00Z",
  "manifest_total_value": 2150
}
Respuesta: { id:"dqt_8f3a...", fee:450, dropoff_eta:"20:58", expires:"20:35" }
DB: guardamos order.uber_quote_id y delivery_fee_cents = 450 + markup.
Caso límite
3aSi Uber responde address_undeliverable

Renderizamos Mockup 07 · Fuera de zona con alternativas (pickup, Uber Eats app, reserva). Stripe nunca se invoca.

Next.js
→ Stripe
4Creamos sesión de Stripe con metadata order_id

Order ya está en DB con status=pending_payment + el uber_quote_id.

Redirect: el cliente paga en la pantalla hospedada de Stripe (cards / Apple Pay / Google Pay).
Stripe
→ Webhook
5Stripe nos envía checkout.session.completed

Verificamos firma, leemos order_id de metadata, actualizamos a status=received.

Next.js
→ Uber Direct
6POST /v1/customers/{cid}/deliveries usando quote_id
{ "quote_id":"dqt_8f3a...",
  "pickup_name":"Casa Nokiate",
  "pickup_phone_number":"+34646261756",
  "dropoff_name":"María García",
  "dropoff_phone_number":"+34612345678",
  "manifest_items":[
    {"name":"Patatas Nokiate","quantity":1,"price":850},
    {"name":"Croqueta","quantity":4,"price":1000}
  ],
  "external_id":"ord_01JTV3K9..." }
DB: guardamos uber_delivery_id, uber_tracking_url.
Caso límite
6aQuote expiró (lento checkout) → 409

Re-cotizamos: si la nueva tarifa cambia ≤20%, seguimos y registramos el delta. Si cambia más o ya no cubren, marcamos el pedido canceled + reembolso Stripe automático + email de disculpa.

Cocina
(tablet)
7El pedido aparece en Kitchen queue con sonido

El cocinero pulsa "Aceptar" → status preparing. SSE empuja el cambio al cliente en la pantalla de tracking.

Uber Direct
→ Webhook
8POST /api/uber/webhook · event.delivery_status
Uber statusNuestro orders.statusAviso al cliente
pending
pickupaccepted
pickup_completedispatchedWhatsApp + tracking URL
dropoffdispatched
delivereddeliveredWhatsApp "entregado, gracias"
canceled / returnedcanceledEmail + WhatsApp; reembolso Stripe
Verificamos firma X-Uber-Signature: t=…,v1=… (HMAC-SHA256, ventana 5 min). Persistimos cada evento en uber_events con dedupe por event_id.
Cliente
9La página de tracking se actualiza por SSE

Cuando llega pickup_complete, el botón "Ver en Uber" se activa apuntando al tracking_url que devolvió Uber.

Admin
→ Uber Direct
10Cancelación: POST /v1/customers/{cid}/deliveries/{id}/cancel

Permitido sólo mientras Uber esté en pending o pickup. Tras pickup_complete hay que llamar a soporte Uber. La acción dispara reembolso Stripe automáticamente si el pedido estaba pagado.


Resumen visual

Cliente Next.js Stripe Uber Direct Cocina ① address ② quote ④ checkout ⑤ paid ⑥ create ⑦ new ticket ⑧ status ⑨ SSE

Documentación detallada y payloads completos en docs/UBER-DIRECT.md.