Playbook
Diseño de instantáneas de pago inmutable: la decisión que congela el carrito (Diseno DE Instantaneas DE Pago Inmutable La Decision Que Congela El Carrito)
Leer el carrito en vivo cuando comienza el pago deja indeciso el monto y la moneda. La finalización no funcionará de manera confiable sin una instantánea que se congele en el momento de la intención.
Motor de pago distribuido
Parte 4 de 22
Una serie de arquitecturas de pago distribuidas que cierran la brecha entre la captura y la finalización.
La canasta es un objetivo en movimiento.
Cuando un cliente llega a la pantalla de pago, el precio, la campaña y la información de stock en el carrito aún están sujetos a cambios: la campaña puede caducar, el precio puede actualizarse, el mismo cliente puede cambiar el carrito en otra pestaña. Si no congela esta información en el momento en que se crea la intención de pago, el monto que se destina al PSP y el monto esperado al finalizar pueden representar dos realidades diferentes.```text Sepet (canlı, değişken) --intent anında--> Payment Snapshot (donmuş, değişmez) ↓ PSP'ye gönderilen tutar = snapshot'taki tutar
## Conceptos en la primera mención```text
📦 Payment Intent
Müşterinin ödeme yapma niyetini temsil eden, PSP'ye gönderilecek tutarı ve para birimini taşıyan kayıt.
📦 Snapshot
Bir anlık gerçeğin (fiyat, miktar, vergi, indirim) o an olduğu haliyle donmuş, sonradan değişmeyen kopyası.
📦 Price-at-Intent
Ödeme başlatıldığı anda geçerli olan fiyatın, sonraki kampanya veya fiyat değişikliklerinden bağımsız olarak korunması ilkesi.
📦 Basket Drift
Sepetin, ödeme süreci ilerlerken (kullanıcı başka bir sekmede değişiklik yaparak veya arka plan işleriyle) snapshot'tan farklılaşması.
📦 Amount Reconciliation
PSP'den gelen gerçek tahsilat tutarının, snapshot'taki beklenen tutarla karşılaştırılması.
```La instantánea no es una “foto” del carrito; El estado actual de la cesta se congela como un registro legal que no se puede modificar posteriormente.
## Por qué leer canastas en vivo es engañoso
Algunos sistemas miran el carrito nuevamente para obtener el "monto actual" durante la fase de finalización después de que se crea la intención de pago. Este enfoque parece atractivo porque da la sensación de que se utilizan “los datos más actualizados”; pero en realidad confunde dos realidades diferentes en dos momentos diferentes del tiempo.```text
t0: Müşteri ödeme başlatır → Sepet: 3 ürün, 450 TL, kampanya aktif
t1: PSP'ye 450 TL isteği gider
t2: Kampanya süresi dolar, sepet artık 480 TL gösterir
t3: Finalization, sepete tekrar bakar → 480 TL bekler ama PSP 450 TL tahsil etmiştir
```Esta incompatibilidad deja a la saga de finalización en una situación en la que no puede decidir qué cantidad considerar como “correcta”. El resultado: revisión manual, queja del cliente o registro financiero silenciosamente incorrecto.
## Problema resuelto por instantánea
El enfoque correcto es congelar el estado actual del carrito en el momento en que se crea la intención de pago (monto, moneda, artículos en línea, impuestos, descuento) como un registro separado e inmutable. Este registro es independiente de la tabla de canasta; Incluso si cambia la cesta, finaliza la campaña o se actualiza el precio del producto, la instantánea sigue siendo la misma.```text
PaymentSnapshot
amount: 450.00
currency: TRY
lines: [...]
createdAt: t0
(sepet t1, t2, t3'te değişse de bu kayıt asla değişmez)
```La cantidad enviada a la PSP siempre se lee desde la instantánea, no desde el carrito en vivo. La saga Finalization siempre hace referencia a esta instantánea en los pasos de caída de existencias, registro financiero y confirmación de pedido. De esta manera, sea cual sea el futuro del carrito, todas las decisiones relacionadas con el pago se basan en la misma verdad fija.
## Verificación de monto y moneda
La instantánea no sólo se congela; También debe verificar el monto de cobro real devuelto por el PSP. Si el monto en la respuesta del PSP no coincide con el monto en la instantánea (por ejemplo, una diferencia de redondeo, un error de conversión de moneda o un defecto de integración), este evento no debe marcarse automáticamente como "completado"; debería caer en una cola de disputas.```text
PSP cevabı: amount=450.00, currency=TRY
Snapshot: amount=450.00, currency=TRY
→ eşleşti, işleme devam
PSP cevabı: amount=449.99, currency=TRY
Snapshot: amount=450.00, currency=TRY
→ eşleşmedi, finalization DURDURULUR, inceleme kuyruğuna düşer
```Este paso de verificación detecta tempranamente tanto los errores de integración como los posibles escenarios de manipulación.
## Señuelo “Volver al carro vivo”
Incluso después de que se establece el mecanismo de instantáneas, algunos equipos regresan a la canasta durante la finalización diciendo "pero las acciones pueden haber cambiado, veamos los datos actuales". Esto socava el propósito de la instantánea: el control de existencias debe tratarse como un paso separado (y con su propia lógica de fracaso/compensación); La decisión sobre el monto y la moneda nunca debe depender de datos en vivo. Confundirlos es como reabrir un expediente legal congelado para la discusión.
## Los enfrentamientos más confusos de este episodio.```text
❌ Finalization'da sepete tekrar bakmak, “en güncel veri” kullanmaktır
✓ Finalization'da sepete tekrar bakmak, iki farklı zaman noktasındaki gerçeği karıştırmaktır
❌ Snapshot sadece bir loglama/audit kaydıdır
✓ Snapshot, ödeme ve finalization kararlarının tek referans kaynağıdır
❌ PSP'den gelen tutar her zaman beklenen tutarla eşleşir, doğrulama gereksizdir
✓ Tutar/para birimi uyuşmazlığı otomatik değil, kuyruğa düşen bir olay olmalıdır
❌ Stok güncelliği ile ödeme tutarı aynı mekanizmayla kontrol edilebilir
✓ Stok kontrolü ayrı bir adımdır; tutar kararı asla canlı veriye dönmemelidir
Haz una instantánea de tu lista de verificación de diseño
- ¿La cantidad que enviaste a PSP se lee del carrito en vivo o de un registro instantáneo congelado?
- ¿De qué fuente (instantánea o tabla en vivo) se lee el monto/monto en cada paso de la saga de Finalización?
- ¿Qué sucede si el monto devuelto por PSP no coincide con el monto que aparece en la instantánea? ¿Pasa automáticamente o se detiene?
- ¿Ha probado que la instantánea no cambia incluso si la tabla de la cesta cambia después de crear la instantánea?
- ¿El campo de moneda de la instantánea es siempre el mismo que el de la moneda enviada al PSP? Si hay una conversión, ¿dónde se registra este paso?
Si no puede responder claramente ni siquiera a una de estas cinco preguntas, probablemente exista el riesgo de una “desviación silenciosa de cantidades” en su sistema.
Cosas para recordar de esta sección
- Tan pronto como se crea la intención de pago, el monto del carrito, las líneas y la moneda deben congelarse como una instantánea separada e inmutable.
- La saga Finalización no debe regresar al carrito en vivo en ningún paso; Cada decisión debe hacer referencia a la instantánea.
- El monto real devuelto por el PSP debe compararse con el monto esperado en la instantánea; La disputa no debe resolverse automáticamente, sino que debe estar sujeta a revisión.
- El control de la actualización de existencias es responsabilidad separada; No confundir con la decisión de cantidad/moneda.
La canasta es un modelo para el futuro; El pago es una decisión congelada en el pasado. Leer estos dos de un mismo registro es hacer que dos tiempos diferentes parezcan una sola realidad.
FAQ
Frequently asked questions
¿Qué es la intención de pago?
Un registro que representa la intención de pago del cliente y lleva el monto y la moneda que se enviará al PSP.
¿Qué es la instantánea?
Una copia congelada de una realidad momentánea (precio, cantidad, impuesto, descuento) tal como es en ese momento, que no cambia después.
¿Es cierto que "Volver a mirar el carrito en Finalización significa utilizar los" datos más actuales "?
Mirar de nuevo la canasta en Finalización confunde la realidad en dos momentos diferentes en el tiempo
¿Qué soluciona esta sección?
Esta sección explica por qué "volver al carrito en vivo" es un riesgo, no un atajo, y cómo la instantánea inmutable lo resuelve. Tan pronto como se crea la intención de pago, el monto del carrito, las líneas y la moneda deben congelarse como una instantánea separada e inmutable. Cuando un cliente llega a la pantalla de pago, el precio, la campaña y la información de stock en el carrito aún están sujetos a cambios: la campaña puede caducar, el precio puede actualizarse, el mismo cliente puede cambiar el carrito en otra pestaña. Si no congela esta información en el momento en que se crea la intención de pago, el monto que se destina al PSP y el monto esperado al finalizar pueden representar dos realidades diferentes.
Principios de ingeniería aprendidos
- Tan pronto como se produce la intención de pago, el monto de la cesta, las líneas y la moneda deben congelarse como una instantánea inmutable.
- Las decisiones de finalización nunca deben volver al carrito en vivo; siempre debe hacer referencia a la instantánea.
- Si el monto devuelto por la PSP y la instantánea no coinciden, esto no debería ser un evento automático sino que debería estar sujeto a revisión.
Continuar leyendo
Continuar leyendo
Siguiente en la serie
Idempotencia (transacción segura repetible) más allá de la solicitud de API (interfaz de programación de aplicaciones)
La idempotencia no es un único encabezado. Es una pila de defensa que debe configurarse por separado en cinco capas diferentes, desde la clave API hasta el…
Siguiente en la serie
¿Por qué la recopilación (captura) es fácil pero la finalización es difícil?
Es sólo un paso para que PSP consiga el dinero. Terminar el pedido; Es una saga que requiere pasos de inventario, finanzas, informes y limpieza para que…
Misma serie
Fiabilidad del webhook en sistemas de pago
Los webhooks se repiten, desaparecen, llegan desordenados y con retraso. Verifique la firma, proporcione ACK rápido, nunca ejecute trabajos pesados…