Webhooks
Entrantes — los que recibimos
Genius Checkout
URL: POST /functions/v1/gc-webhook
GC publica eventos por cada cambio de estado de suscripción (created, charged, paused, cancelled, payment_failed). Cada publicación lleva:
X-GC-Signature— HMAC-SHA256 sobre el cuerpo crudo usando elwebhook_secretde tu organización.Idempotency-Key— GC reintenta respuestas 5xx no firmadas durante ~24 horas, así que protégete contra duplicados de tu lado.
Verificamos la firma, buscamos la fila correspondiente de recurring_donations por gateway_subscription_id y actualizamos su estado. El payload completo se registra en donation_payment_webhook_log para que puedas reproducirlo si una escritura falla.
Respuestas entrantes de WAHA / WhatsApp
URL: POST /functions/v1/wacrm-webhook
WAHA publica JSON por cada mensaje entrante de WhatsApp + acuse de entrega. Normalizamos el número de teléfono (solo dígitos, sin +), lo cotejamos contra members.primary_phone y añadimos el mensaje al hilo de conversación existente (o creamos uno nuevo).
Reembolsos + notificaciones de PowerTranz
URL: POST /functions/v1/powertranz-webhook
Usado para confirmaciones asíncronas de reembolso + notificaciones de pago recurrente. El mismo patrón HMAC que GC.
Salientes — los que puedes configurar
Webhooks por evento
Ve a Ajustes → Integraciones → Webhooks y agrega una URL. Elige entre:
| Evento | Se dispara cuando |
|---|---|
member.created | Se agrega un nuevo miembro (manualmente, en masa o vía formulario de visitante) |
member.lost | Un miembro se marca como perdido |
donation.recorded | Se inserta una fila de donación (manual o en línea) |
attendance.marked | Se inserta una fila de asistencia |
workflow.completed | Una ejecución de workflow termina |
Cada publicación incluye:
X-GCM-Signature— HMAC-SHA256 del cuerpo usando un secreto que tú estableces.- Un cuerpo JSON con la fila afectada + delta.
Zapier
Incluimos una integración con Zapier (busca "Genius Church Manager" en Zapier). Úsala para automatizaciones low-code. Por debajo es el mismo endpoint de webhook saliente.
Verificando firmas
Pseudocódigo (el mismo algoritmo funciona en Node, Python, PHP, Go):
expected = HMAC_SHA256(secret, raw_body).hex()
got = request_header('X-GCM-Signature')
if not constant_time_compare(expected, got):
return 401WARNING
No uses == — solo comparación en tiempo constante. Stripe y Slack publican guías más detalladas, ambas aplican aquí.
Reintentos
Reintentamos publicaciones fallidas (status ≠ 2xx, o sin respuesta en 10s) con backoff exponencial hasta 24 horas, luego marcamos la entrega como permanently_failed. Revisa el historial de entrega en Ajustes → Integraciones → Logs de Webhook.
