Planteamiento y alcance
Una plataforma de pagos multimerciante desea que los compradores confirmen el beneficiario, el monto y la moneda en el checkout y generen evidencia criptográfica que un banco o servicio de pagos pueda verificar. El equipo está evaluando el W3C Secure Payment Confirmation Candidate Recommendation Draft publicado el 2 de julio de 2026. La página del comerciante, el orquestador de pagos y la página de autenticación del emisor pueden tener orígenes diferentes, mientras que los navegadores más antiguos deben conservar la ruta de autenticación existente.
Diseña el sistema desde el registro de credenciales SPC hasta la verificación de aserciones. Explica cómo un tercero puede iniciar la autenticación para una parte usuaria (relying party), qué campos debe vincular el servidor y cómo manejar la indisponibilidad de la API, la cancelación, el pago duplicado y el rollback. La especificación sigue siendo un borrador; no trates ese estado como compatibilidad universal del navegador.
Qué evalúa el entrevistador
El entrevistador quiere ver si vinculas los detalles de la transacción mostrados al usuario, la orden aprobada por el servidor y la aserción de autenticación a un único intento de pago. Debes explicar la relación entre SPC y WebAuthn, así como las implicaciones de seguridad de la invocación de origen cruzado.
Una respuesta sólida también cubre la Permission Policy payment, los límites de privacidad de securePaymentConfirmationAvailability(), la separación de credenciales, las claves de idempotencia, el fallback basado en riesgos, la retención de evidencia y un despliegue reversible en lugar de limitarse a describir un diálogo biométrico.
Aclaraciones que conviene hacer primero
- ¿Quién registra la credencial SPC y está separada de la credencial de inicio de sesión?
- ¿Cuáles son los orígenes del emisor, el comerciante y el orquestador de pagos, y qué parte es la WebAuthn Relying Party?
- ¿Debe la información de autenticación incluir monto, beneficiario, moneda, ID de orden y vencimiento?
- ¿Puede una ruta de autenticación existente asumir el control de forma segura cuando SPC no esté disponible o se cancele?
- ¿Qué evidencia se requiere para reintentos, callbacks duplicados, reembolsos y disputas?
Una respuesta de 30 segundos
“Crearía un intento de pago inmutable en el servidor antes de la autenticación, registraría una credencial SPC específica para pagos y restringiría los orígenes de llamada permitidos. El servidor emite un challenge de un solo uso y el digest de la orden; el comerciante pasa únicamente los datos de pago aprobados por el servidor a SPC, y el callback se verifica contra la política de orígenes, el challenge, la credencial, la verificación de usuario y el estado de la orden. La indisponibilidad o cancelación sigue una ruta legacy explícita, nunca un atajo hacia el éxito. Las transiciones de estado utilizan claves de idempotencia. Comenzaría con tráfico de bajo riesgo, mediría fallas de aserción, disputas y fallback, y deshabilitaría nuevos intentos de SPC conservando la evidencia en tránsito si surgen anomalías.”
Solución paso a paso
Definir los orígenes y la propiedad de las credenciales
SPC se basa en WebAuthn, pero permite que un tercero active una ceremonia para una parte usuaria. Utiliza un Relying Party ID específico para pagos o un subdominio de pagos para que las credenciales de inicio de sesión y de pago no sean intercambiables silenciosamente. El registro acepta únicamente tokens de vinculación de usuario y comerciante emitidos por el servidor. Almacena el ID de credencial, el origen, la hora de creación, el estado de revocación y las propiedades de vinculación al dispositivo; nunca confíes en un Relying Party ID provisto por el navegador como autorización.
Vincular el estado de la orden al challenge
Crea un payment_attempt que contenga la versión de la orden, el monto, la moneda, el beneficiario, el challenge, el vencimiento y la clave de idempotencia. Consume cada challenge una sola vez. Una edición de la orden, conversión de moneda o cambio de beneficiario genera un nuevo intento. El monto renderizado al usuario proviene del mismo registro o digest aprobado por el servidor; un comerciante no debe concatenar un valor en el navegador e invocar a SPC directamente.
type PaymentAttempt = {
id: string;
orderVersion: number;
amountMinor: bigint;
currency: string;
payeeOrigin: string;
challenge: Uint8Array;
expiresAt: Date;
status: "created" | "authorizing" | "approved" | "cancelled" | "expired";
};Aplicar el límite de origen cruzado
El cambio importante de SPC es que un tercero puede usar una credencial que pertenece a otra parte usuaria. Incluye el invocador, la parte usuaria, la orden y los orígenes de autenticación permitidos en una política del servidor. Configura la Permission Policy payment antes de incrustar un iframe de pago y valida el origen de nivel superior contra una lista de permisos del comerciante. Después de que retorne una aserción de origen cruzado, el invocador recibe únicamente el resultado necesario para esa transacción; no debe solicitar extensiones WebAuthn arbitrarias ni acceder a credenciales de inicio de sesión.
Detectar la capacidad y elegir un fallback
Prefiere PaymentRequest.securePaymentConfirmationAvailability() y registra available de forma separada de las razones de indisponibilidad; un agente de usuario puede devolver una razón intencionalmente vaga para reducir la huella digital (fingerprinting). La disponibilidad aún no demuestra que exista una credencial en particular. Un fallback basado en riesgos puede seleccionar SPC, autenticación bancaria, un código de un solo uso o revisión manual. Cada ruta vuelve a verificar la orden y el challenge, por lo que un error de SPC no puede convertirse en un pago exitoso.
Verificar la aserción y la semántica de pago
El servidor verifica el origen en client-data, el challenge, el Relying Party ID, la firma, el flag de verificación de usuario, el estado de la credencial y el digest de la orden. Utiliza una actualización condicional para reclamar el intento created antes de realizar el cobro; los callbacks duplicados devuelven el mismo resultado. Una discrepancia en el digest es una falla de seguridad y no debe reintentarse indefinidamente. Una aserción demuestra que la autenticación se completó; no demuestra que los fondos se hayan liquidado.
Manejar cancelación, vencimiento y fallos
La cancelación, la ausencia de autenticador, un navegador cerrado y un timeout del emisor se convierten en estados terminales distintos. Un reintento crea un nuevo intento y challenge. Un timeout de pasarela no debe reutilizar el challenge anterior: consulta primero la clave de idempotencia y luego decide si el resultado está pendiente, fue exitoso o requiere revisión humana. Los eventos entre el servicio de pagos, el comerciante y el emisor llevan versiones para que un evento antiguo no pueda sobrescribir un estado más reciente.
Monitorear el riesgo y retener evidencia
Segmenta la disponibilidad de SPC, la cancelación del usuario, las fallas de aserción, los callbacks duplicados, la tasa de fallback, la latencia de cobro y las disputas por navegador, combinación de orígenes, método de autenticación y nivel de riesgo. Conserva un hash del digest de la orden, un identificador de credencial no reversible, el ID del intento, la versión de la política y el resultado de la verificación; no registres datos biométricos ni claves privadas. Aplica rate limiting a las anomalías de origen cruzado, los intentos repetidos de credenciales y los cambios abruptos de monto.
Desplegar por etapas, probar y hacer rollback
Comienza con comerciantes internos y montos de bajo riesgo, luego expande por navegador, origen y región. Prueba iframes de origen cruzado, ausencia de Permission Policy, rechazo del usuario, credenciales faltantes, repetición de challenges, ediciones de órdenes, callbacks duplicados, timeouts de pasarela y carreras con reembolsos. En caso de rollback, deja de crear nuevos intentos de SPC, permite que las transacciones en curso finalicen mediante la máquina de estados y enruta las nuevas transacciones a la ruta legacy. Conserva las aserciones y la evidencia de la orden para el análisis de disputas.
Respuesta modelo de alta calidad
“SPC genera evidencia de autenticación; no es la liquidación. Vincularía un payment_attempt inmutable a la versión de la orden, monto, beneficiario, challenge, política de orígenes y clave de idempotencia. Las credenciales de pago se separan de las de inicio de sesión, y Permission Policy limita a los invocadores de origen cruzado. Tras la autenticación, el servidor verifica la aserción WebAuthn y el digest de la orden, para luego avanzar condicionalmente el estado del cobro. La indisponibilidad, la cancelación y el timeout utilizan fallbacks explícitos, mientras que los callbacks duplicados devuelven el resultado ya establecido. Durante un despliegue escalonado monitorearía fallas de aserción, fallback, disputas y anomalías de origen cruzado; el rollback detiene nuevos intentos de SPC y preserva la evidencia en tránsito.”
Errores comunes
- Tratar
availablecomo una credencial → es posible que el usuario aún no tenga una credencial utilizable → separa la detección de capacidad de la disponibilidad de credenciales. - Permitir que el navegador elija el monto → la confirmación y el cobro pueden divergir → vincula un digest de orden y un challenge del servidor.
- Tratar una llamada de origen cruzado como un inicio de sesión común → pueden filtrarse credenciales de inicio de sesión o datos de extensiones → separa las credenciales de pago y restringe al invocador.
- Convertir una falla de SPC en un pago exitoso → se confunde la autenticación con la liquidación → modela autenticación, cobro y liquidación por separado.
- Reutilizar un challenge en un reintento → se puede reproducir una aserción → consume una sola vez y emite un nuevo challenge por intento.
- Eliminar registros durante el rollback → las disputas y los cobros duplicados se vuelven irrastreables → congela nuevas solicitudes y retén la evidencia en tránsito.
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: ¿Por qué no reutilizar la passkey de inicio de sesión?
El pago y el inicio de sesión tienen amenazas, orígenes y propósitos de autorización distintos. La especificación permite credenciales WebAuthn en SPC, pero un subdominio de pagos y credenciales separadas reducen la superficie de ataque del inicio de sesión. Si se comparten credenciales, el propósito de la aserción, la Relying Party y las comprobaciones del servidor deben ser explícitos.
Pregunta de seguimiento 2: ¿Cómo evitas que un comerciante muestre un dólar y cobre cien?
La interfaz del comerciante no es la autoridad sobre el monto. El servicio de pagos crea el digest a partir de la versión de la orden, el flujo de autenticación transporta ese digest y el servicio de cobro acepta únicamente el mismo intento. Cualquier cambio de campo crea un nuevo intento.
Pregunta de seguimiento 3: ¿Cuál es el riesgo de devolver una razón de disponibilidad detallada?
Las razones detalladas pueden convertirse en una huella digital del dispositivo o de la configuración, por lo que un agente de usuario puede devolver unavailable-unknown-reason. El negocio utiliza el resultado para la selección de la experiencia, nunca como perfil de usuario, puntaje de riesgo o hecho de autorización.
Pregunta de seguimiento 4: ¿Puede el servicio de pagos llamar a SPC de nuevo después de un timeout?
Primero consulta el estado de cobro y autenticación mediante la clave de idempotencia. Si el intento anterior sigue sin resolverse, no lo reproduzcas a ciegas. Cancélalo o hazlo expirar explícitamente, y luego crea un nuevo intento con un nuevo challenge y digest de orden.