Este tutorial es la tercera parte de la siguiente serie de tutoriales que explica el funcionamiento práctico de la nueva API llamada Payment Request para hacer pagos en Internet:
- Primera parte: introducción general y cómo definir las formas de pago disponibles.
- Segunda parte: cómo mostrar los detalles del pago y solicitar información al usuario.
- Tercera parte: cómo completar (o cancelar) el proceso de pago.
- Cuarta parte: cómo solicitar la dirección y forma de envío.
Respondiendo a PaymentRequest.show()
Después de llamar al método show()
, el navegador muestra al usuario todos los
detalles del pago para iniciar el proceso. Los usuarios tienen dos opciones:
ignorar esa información y no completar o rellenar la información solicitada y
pulsa el botón "Pagar".
Si el usuario rellena la información correctamente, la promesa devuelta por
show()
se resuelve,. Si no, la promesa se rechaza:
paymentRequest.show()
.then((paymentResponse) => {
// el usuario ha rellenado la información solicitada y ha realizado
// el pago. Obtener los detalles de `paymentResponse` para completar el pago
return paymentResponse.complete();
})
.catch((err) => {
// hay un error o el usuario ha rechazado el pago
});
Cuando el pago se completa, la promesa show()
recibe un objeto de tipo
PaymentResponse
que contiene la información del usuario que debes enviar al
sistema de procesamiento de pagos que utilices.
Propiedades de PaymentResponse
El objeto PaymentResponse
contiene los siguientes parámetros:
Parámetro | Explicación |
---|---|
methodName |
Método de pago seleccionado por el usuario (por ejemplo basic-card ) |
details |
Contiene los detalles del pago, que dependen de la forma de pago seleccionada. Se explica más adelante con detalle. |
payerName |
Nombre del pagador, que será null a menos que hayas definido requestPayerName a true |
payerPhone |
Teléfono del pagador, que será null a menos que hayas definido requestPayerPhone a true |
payerEmail |
Email del pagador, que será null a menos que hayas definido requestPayerEmail a true |
Shipping Info |
Información sobre la forma de envío. Se explica más adelante con detalle. |
Para los pagos de tipo basic-card
, los detalles están estandarizados y siempre
son billingAddress
, cardNumber
, cardSecurityCode
, cardholderName
,
expiryMonth
y expiryYear
. Cuando se utilizan servicios de terceros como
Google Pay, los detalles serán los que defina cada servicio en su documentación.
Una vez obtenidos los detalles mediante el objeto PaymentResponse
, ya puedes
procesar el pago y completar la transacción llamando al método
paymentResponse.complete()
.
Completando la transacción
Una vez que la promesa de show()
se ha resuelto, el navegador muestra una
imagen animada indicando que se está a la espera de completar el pago. Puedes
dejar esta animación visible o puedes ocultarla y utilizar tu propio diseño
para esta pantalla de espera:
Si quieres ocultar la animación inmediatamente, llama al método
PaymentResponse.complete()
.
paymentRequest.show()
.then((paymentResponse) => {
// cerrar la pantalla de espera
return paymentResponse.complete()
.then(() => {
// TODO: obtener detalles del pago mediante el objeto paymentResponse
// TODO: procesa pago
});
})
.catch((err) => {
console.error('Payment Request API error: ', err);
});
Ejecutar el método complete()
sin argumentos es equivalente a ejecutar
paymentResponse.complete('unknown')
. En otras palabras, al navegador le estás
diciendo que no considere el pago ni como completado ni como erróneo, por lo que
no se muestra ninguna pantalla de espera.
Si quieres mantener la pantalla de espera mientras se completa el pago, no
ejecutes complete()
todavía. Imaginemos que tienes un método llamado
validatePaymentWithBackend()
que comprueba el pago realizando llamadas a tu
servidor y que devuelve una promesa que se resuelve como un valor booleano
(true
si el pago se ha completado y false
en cualquier otro caso). En este
caso, la pantalla de espera se mantendría y la llamada a complete()
se haría
cuando esta nueva promesa se resuelva:
paymentRequest.show()
.then((paymentResponse) => {
return validatePaymentWithBackend(paymentResponse)
.then((success) => {
if (success) {
return paymentResponse.complete('success');
} else {
return paymentResponse.complete('fail');
}
});
})
.catch((err) => {
// hay un error o el usuario ha cancelado el pago
});
En este ejemplo se utilizan las cadenas success
y fail
para indicar al
navegador el estado del pago. Estos valores son estándar y el navegador los usa
para mostrar al usuario si el pago se ha completado con éxito o si ha fallado:
Cosas a tener en cuenta
Devolver un resultado propio
Si no devuelves alguno de los valores definidos en el estándar (unknown
,
success
o fail
) la promesa devuelta por complete()
rechaza el pago y
te devolverá un error como el siguiente:
Failed to execute 'complete' on 'PaymentResponse': The provided value '...' is not a valid enum value of type PaymentComplete.
Completar los pagos rápido
Si no llamas al método complete()
en un tiempo razonable, el navegador
considera que la transacción ha caducado y cerrará la pantalla de pago. Además,
se avisará al usuario de que ha habido un problema con el pago.
Cancelando la transacción
Utiliza el método abort()
para cancelar la transacción actual (porque ha
expirado la sesión, porque el producto que se quiere comprar acaba de agotarse,
etc.)
paymentRequest.show()
.catch((err) => {
console.error('PaymentRequest error: ', err);
});
setTimeout(() => {
paymentRequest.abort()
.then(() => {
// La transacción se ha cancelado correctamente
// TODO: mostrar un mensaje avisando al usuario
})
.catch((err) => {
// No se puede cancelar la transacción
console.log('abort() Error: ', err);
});
}, 4000);
En el ejemplo anterior, si se deja la ventana del pago visible, la promesa
show()
se cancela con el siguiente error:
DOMException: The user aborted a request.
La promesa devuelta por abort()
permite comprobar si la cancelación se ha
completado correctamente o no. La cancelación de la transacción podría fallar
por ejemplo si el usuario cierra la ventana del pago o si el pago se ha
completado mientras se intentaba anular.