Toku · Eventos (pagos / cobranza)
Webhooks de Toku (pagos/cobranza) → Cloud Run valida la firma HMAC y publica a Pub/Sub por tipo de evento → otro Cloud Run escribe directo a BigQuery
solvento-data-prod.toku.*(sin Dataflow). Volumen bajo, streaming.
¿Llegaste hasta acá desde…?
| Si ves… | Eso sale de… | La lógica está en… |
|---|---|---|
| Transacciones / pagos de Toku en análisis | solvento-data-prod.toku.transaction · toku.payment · toku.payment_intent |
Ingesta directa (sin lógica de negocio); ver "Paso a paso" |
| Liquidaciones / payouts de Toku | solvento-data-prod.toku.settlement (eventos payout_mx.*) |
toku-write-bigquery → cloud_run/app.py (remapea payout_mx → tabla settlement) |
| Clientes / suscripciones / facturas de Toku | solvento-data-prod.toku.customer · toku.subscription · toku.invoice |
Ingesta directa por categoría de event_type |
Resumen
| Campo | Valor |
|---|---|
| Origen | Webhook de Toku (pagos / cobranza) |
| Patrón | Event-driven (Cloud Run → Pub/Sub → Cloud Run → BigQuery directo, sin Dataflow) |
| Destino | solvento-data-prod.toku.* (una tabla por categoría de evento) |
| Frecuencia | Streaming (insert por evento) |
| Criticidad | 🟢 Baja (volumen bajo) |
| Dueño | Martin (data eng) |
| Repos | webhook_toku · toku-write-bigquery |
Diagrama de linaje
graph LR
TOKU[["📨 Toku<br/>webhook pagos/cobranza"]]
subgraph rcv["1 · Recepción + ruteo"]
CR1["Cloud Run<br/>webhook-toku-inline-prod<br/><i>valida HMAC · enruta por event_type</i>"]
T1(["Pub/Sub<br/>TOKU_PAYMENT_INTENT_TOPIC"])
T2(["Pub/Sub<br/>TOKU_TRANSACTION_TOPIC"])
T3(["Pub/Sub<br/>TOKU_PAYOUT_MX_TOPIC"])
T4(["Pub/Sub<br/>otros TOKU_*_TOPIC"])
end
subgraph wr["2 · Escritura directa a BigQuery"]
CR2["Cloud Run<br/>toku-write-bigquery-prod<br/>POST / (push) · insert_rows_json"]
BQ[("solvento-data-prod.toku.*<br/>customer · payment · payment_intent<br/>transaction · subscription · invoice · settlement")]
end
TOKU -->|HTTPS| CR1
CR1 --> T1 --> CR2
CR1 --> T2 --> CR2
CR1 --> T3 --> CR2
CR1 --> T4 --> CR2
CR2 --> BQ
classDef src fill:#fde68a,stroke:#b45309,color:#000;
classDef store fill:#bfdbfe,stroke:#1e40af,color:#000;
class TOKU src;
class BQ store;
Paso a paso
- Toku emite un webhook por cada evento (pagos / cobranza). El
event_typeviene en el payload (ej.payment_intent.succeeded,transaction.success,payout_mx.success,customer.created,subscription.updated,invoice.created). - Cloud Run
webhook-toku-inline-prod(webhook_toku,cloud_run/app.py) recibe el POST en/toku(y/webhook/toku):- Valida la firma HMAC-SHA256: lee el header
Toku-Signature(t=<timestamp>,s=<firma>), verifica que el timestamp no tenga más de 300 s (anti-replay) y compara la firma conhmac.compare_digestusando el secretoTOKU_WEBHOOK_SECRET. Mismatch → 401. - Enruta por tipo: toma la categoría antes del primer punto del
event_type(payment_intent.succeeded→payment_intent) y publica al topic cuyo nombre vive en la env varTOKU_<CATEGORÍA>_TOPIC(ej.TOKU_PAYMENT_INTENT_TOPIC,TOKU_TRANSACTION_TOPIC,TOKU_PAYOUT_MX_TOPIC,TOKU_CUSTOMER_TOPIC,TOKU_SUBSCRIPTION_TOPIC,TOKU_INVOICE_TOPIC,TOKU_PAYMENT_TOPIC). Sin categoría reconocida →TOKU_UNKNOWN_EVENTS_TOPIC. Los valores literales de los topics se inyectan al desplegar; ver env del servicio en GCP (confirmar nombres exactos).
- Valida la firma HMAC-SHA256: lee el header
- Pub/Sub desacopla: una suscripción push por topic entrega al siguiente servicio.
- Cloud Run
toku-write-bigquery-prod(toku-write-bigquery,cloud_run/app.py) recibe el push enPOST /, decodificamessage.data(base64) y escribe directo a BigQuery coninsert_rows_json(streaming insert; no hay Dataflow ni Beam). La tabla se elige por la categoría del evento víaTABLE_CONFIG; crea la tabla si no existe (CREATE TABLE IF NOT EXISTS, columnaload_dts TIMESTAMP DEFAULT CURRENT_TIMESTAMP()).- Dataset por defecto
BIGQUERY_DATASET_ID=toku, proyectoGOOGLE_CLOUD_PROJECT=solvento-data-prod. - Errores no recuperables (base64/JSON inválido) → 200 (ack, no reintenta). Errores transitorios de BigQuery → 500 (Pub/Sub reintenta).
- Dataset por defecto
Tablas que alimenta
| Tabla | Contenido | Job que la carga |
|---|---|---|
solvento-data-prod.toku.customer |
Eventos customer.* |
toku-write-bigquery-prod |
solvento-data-prod.toku.payment_intent |
Eventos payment_intent.* |
toku-write-bigquery-prod |
solvento-data-prod.toku.payment |
Eventos payment.* |
toku-write-bigquery-prod |
solvento-data-prod.toku.transaction |
Eventos transaction.* (incluye payment_instrument, customer, payment_intents, wallet_movements) |
toku-write-bigquery-prod |
solvento-data-prod.toku.subscription |
Eventos subscription.* |
toku-write-bigquery-prod |
solvento-data-prod.toku.invoice |
Eventos invoice.* |
toku-write-bigquery-prod |
solvento-data-prod.toku.settlement |
Eventos payout_mx.* (liquidaciones; el servicio remapea la categoría payout_mx → tabla settlement) |
toku-write-bigquery-prod |
Cada fila lleva además
id,event_type,webhook_uuidyload_dts.
Consumo aguas abajo
- Analítica / Metabase sobre
solvento-data-prod.toku.*para pagos y cobranza (confirmar uso concreto). Cualquier transformación dbt vive endbt-etls; criticidad baja, no se rastrean modelos en esta ficha.
Si falla 🛠️
Impacto: bajo (volumen bajo). Si cae el webhook o el writer, dejan de llegar eventos de Toku a BigQuery. Mitigante: Pub/Sub reintenta los push fallidos.
| Síntoma | Dónde mirar | Acción |
|---|---|---|
| No llegan eventos nuevos de Toku | Logs Cloud Run webhook-toku-inline-prod |
Ver 401 (firma) o errores; si fue un deploy → rollback |
| Eventos clasificados como "unknown" | Logs del webhook + env var TOKU_<CATEGORÍA>_TOPIC faltante |
Falta el topic de esa categoría; revisar config del servicio |
| Llega al topic pero la tabla no avanza | Logs Cloud Run toku-write-bigquery-prod; backlog de la suscripción |
Errores BQ → 500 reintenta solo; persistente → escalar |
| Falla la firma HMAC (401 masivos) | TOKU_WEBHOOK_SECRET en el servicio |
Verificar el secreto productivo |
Escalación: SQL / Metabase → Diego · Airbyte → Gero · resto → Martin.
Enlaces
- 📊 Estado en vivo: dashboard "Data Processes" (Cloud Monitoring)
- 📦 Recepción/firma:
webhook_toku· Escritura BQ:toku-write-bigquery
Última actualización: 2026-06-21 · Si cambia el flujo, los topics o el esquema de los eventos, actualizar esta ficha en el mismo MR.