# Guion del vídeo, para comentar o para lo que necesites.
# Es una PROYECCIÓN del nuestro: lleva el contenido —qué se dice, qué se ve, en
# qué orden y cuánto dura— y no la maquinaria que lo convierte en vídeo.
id: productos-webhooks
title: 'Webhooks: cómo te avisa SPIDI'
audience: Desarrollador que va a montar el receptor de avisos de SPIDI
objetivo: >
  Al terminar, el espectador sabe qué trae un aviso, cuáles son los cinco eventos, y se lleva la
  trampa que hace fallar en silencio: dos de ellos NO se llaman como el contrato los titula. Además
  sabe que solo dos se han observado, cuántos llegan en un split, y que si SPIDI se rinde no hay
  reenvío.
cta: 'Siguiente: ''Manejar notificaciones'', para montar el receptor.'
target_duration_s: 227
storyboard:
  - 'n': 1
    on_screen: Cómo te enteras sin preguntar
    narracion: >-
      Un pago ocurre en dos fases, y las dos te importan. Un webhook es cómo te enteras de cada una
      sin tener que preguntar: un aviso que SPIDI te envía en cuanto algo pasa, sin depender de que
      la persona vuelva a tu sitio.
    visual: Dos fases de un pago, y un aviso saliendo de cada una hacia el servidor del integrador.
    duracion_s: 17
  - 'n': 2
    on_screen: Qué trae un aviso
    narracion: >-
      Llega por POST a tu URL de webhook, con un cuerpo JSON y tres cabeceras. Un sello HMAC-SHA256,
      calculado sobre la marca de tiempo, un punto, y el cuerpo crudo, con el secreto de tu cuenta.
      Esa misma marca de tiempo, que entra en el cálculo de la firma: sin ella no se puede verificar
      nada. Y una clave de idempotencia, para deduplicar reintentos.
    visual: >-
      El sobre abierto con sus tres cabeceras: el sello, la marca de tiempo y la clave de
      idempotencia.
    duracion_s: 25
  - 'n': 3
    on_screen: El campo `event` es lo que tu código mira
    narracion: >-
      Y dentro del cuerpo hay un campo que manda sobre todos los demás: event. Es lo que tu código
      compara para decidir qué hacer, y todo lo que viene ahora gira alrededor de él.
    visual: El cuerpo del aviso con el campo event resaltado por encima de todo lo demás.
    duracion_s: 13
  - 'n': 4
    on_screen: Los cinco eventos del contrato
    narracion: >-
      El contrato declara cinco. Uno cuando la sesión se crea, antes de la fase uno. Uno cuando el
      débito sale bien, que es la fase uno. Y tres de la fase dos: cuando terminan las
      acreditaciones, cuando se acredita a un receptor del reparto, y cuando esa acreditación a un
      receptor falla. En un pago sin reparto verás dos: pagado y acreditado.
    visual: >-
      Los cinco eventos en una línea de tiempo, repartidos entre antes de la fase 1, la fase 1 y la
      fase 2.
    duracion_s: 24
  - 'n': 5
    on_screen: La trampa de los nombres
    visual: Lámina de sección, sin voz.
    duracion_s: 3
  - 'n': 6
    on_screen: Dos no se llaman como el contrato los titula
    narracion: >-
      Y aquí está la trampa. La clave que titula cada webhook en la especificación es una etiqueta
      del documento: no viaja por el cable. Y en dos casos no coincide con lo que llega. El que el
      contrato titula payment_completed llega como payment_session.paid. Y el que titula
      accreditations_completed llega como payment_session.accredited.
    visual: Dos claves del contrato enfrentadas a los dos valores que viajan de verdad.
    duracion_s: 20
  - 'n': 7
    on_screen: Y el fallo es silencioso
    narracion: >-
      Lo grave no es el despiste, es cómo falla. Un switch escrito leyendo los títulos del contrato
      no entra nunca en esas dos ramas: los avisos llegan, tu endpoint responde 2xx, y tu lógica no
      se ejecuta. Nada da error. Compara siempre contra el campo event del cuerpo.
    visual: Un switch que nunca entra en dos ramas, con los avisos llegando y respondiendo 2xx igualmente.
    duracion_s: 18
  - 'n': 8
    on_screen: Cinco declarados, dos observados
    narracion: >-
      Otra cosa que conviene saber: los cinco están en el contrato, pero solo hemos visto llegar
      dos, pagado y acreditado, y el simulador solo emite esos. Los otros tres están ahí porque el
      contrato los declara y tu receptor puede recibirlos. Ante un evento que no conozcas, ignóralo
      y responde 2xx: nunca rompas.
    visual: >-
      Cinco eventos declarados, dos con marca de observado, y un receptor que ignora lo desconocido
      sin romperse.
    duracion_s: 20
  - 'n': 9
    on_screen: El que más conviene escuchar
    narracion: >-
      Y de esos tres, hay uno que conviene mirar por encima de los demás: el de acreditación fallida
      a un receptor. Es el único que dice que el dinero no llegó a alguien, y no tiene equivalente
      en la consulta de estado. Si no lo escuchas, un reparto fallido se te queda invisible.
    visual: >-
      El evento de acreditación fallida, marcado como el único que no tiene equivalente en la
      consulta de estado.
    duracion_s: 20
  - 'n': 10
    on_screen: Cómo se entrega
    visual: Lámina de sección, sin voz.
    duracion_s: 3
  - 'n': 11
    on_screen: Reintentos e idempotencia
    narracion: >-
      Queda cómo se entrega. Si tu endpoint no responde 2xx a tiempo, SPIDI reintenta con la misma
      clave de idempotencia, y por eso tu receptor tiene que deduplicar: procesar una vez aunque
      llegue varias. No escribas lógica que dependa de cuántos reintentos hay ni de cuánto esperan
      entre uno y otro. Diseña para recibir el mismo aviso un número indeterminado de veces, que es
      la única suposición que no se rompe.
    visual: >-
      Un mismo aviso llegando varias veces con la misma clave, y un receptor que lo procesa una
      sola.
    duracion_s: 27
  - 'n': 12
    on_screen: Si SPIDI se rinde, no hay reenvío
    narracion: >-
      Y si tu servidor estuvo caído demasiado tiempo, SPIDI se rinde: no hay reenvío. Cuando vuelvas
      no habrá un aviso esperándote, habrá una sesión que puedes consultar. Pero no hay forma de
      listar tus sesiones, así que sin el identificador guardado no tienes por dónde entrar.
    visual: Un servidor que vuelve y no encuentra ningún aviso esperando, pero sí una sesión consultable.
    duracion_s: 18
  - 'n': 13
    on_screen: El aviso es el atajo, no la única fuente
    narracion: >-
      Y con eso, la idea que conviene llevarse: el aviso es el atajo, no la única fuente. Las dos
      fases se consultan también en la sesión, con la consulta de estado: la fase uno en el campo
      status, y la fase dos en receiver_credits. El webhook solo te ahorra preguntar.
    visual: Cierre de marca; el aviso y la consulta como dos caminos al mismo dato.
    duracion_s: 19
