Toma mi dinero, no mi tiempo
Introducción
Me gusta la Web. En general, creo que es una buena idea. Por lo tanto, participo en muchos debates sobre la Web y las apps nativas. La otra persona no tarda en comenzar a hablar sobre la facilidad de los pagos a través de sistemas nativos. Mi respuesta habitual es tirar una bomba de humo y salir corriendo de la habitación riendo de forma maníaca, porque no es un argumento que pueda ganar. El abandono del carrito de compras en la Web móvil puede llegar al 97%. Imagina eso en el mundo real. Imagínate una situación en la cual el 97% de las personas en un supermercado vuelcan sus carritos, después de haberlos cargado por completo con artículos que desean, y se retiran. Ahora bien, algunas de esas personas solo están buscando precios y nunca tuvieron la intención de comprar, pero la experiencia del usuario cuando compra en la Web es un factor importante. Estamos cobrando un impuesto a la cordura de los usuarios. Piensa en una experiencia de pago agradable que hayas tenido en la Web, en especial en dispositivos móviles. Es una tienda de aplicaciones, ¿no? O al menos un sistema cerrado similar que ya tenga tu información de pago. Esto es un problema. Exige que los sitios se comprometan con un proveedor de pagos en particular con el que el usuario ya debe tener una cuenta y haber accedido, o bien que se comprometan con una plataforma que requiera que los usuarios accedan a un proveedor de pagos en particular, como una tienda de aplicaciones que requiera que escribas código solo para esa plataforma. Si no haces una de estas acciones, el usuario estará condenado a presionar la pantalla o el teclado hasta que se le acabe la piel de los dedos o se rinda. Debemos solucionarlo.
requestAutocomplete
En un mundo de WebGL, WebRTC y otras APIs web sofisticadas que comienzan con “Web”, requestAutocomplete
no es muy atractivo. Sin embargo, es un superhéroe con ropa beige. Una API pequeña y aburrida que puede clavar una estaca en el corazón del vampiro de tiempo de los pagos web.
En lugar de que el sitio dependa de un proveedor de pagos en particular, solicita los detalles del pago al navegador, que los almacena en nombre del usuario. La versión de requestAutocomplete() de Chrome también se integra en la Billetera de Google para solo usuarios de EE.UU. (actualmente). Pruébala en nuestro sitio de prueba.
form.requestAutocomplete
Los elementos de formulario tienen un solo método nuevo, requestAutocomplete, que le solicita al navegador que propague el formulario. El navegador mostrará un diálogo al usuario en el que se le solicitará permiso y se le permitirá seleccionar qué detalles desea proporcionar. No puedes llamar a esta función cuando quieras, sino que debes hacerlo durante la ejecución de eventos de interacción específicos, como los eventos de mouse arriba/abajo, clic, tecla y toque. Esta es una restricción de seguridad deliberada.
button.addEventListener('click', function(event) {
form.requestAutocomplete();
event.preventDefault();
});
// TODO: listen for autocomplete events on the form
Antes de analizar los eventos, debemos asegurarnos de que el navegador comprenda los campos de tu formulario…
Requisitos de los formularios
Cuando Internet era en blanco y negro, Internet Explorer 5 adoptó un nuevo atributo, autocomplete
, en los elementos de entrada de formularios. Se podía configurar en “desactivado” para que el navegador dejara de ofrecer sugerencias, y eso era todo. Se amplió esta API para que puedas especificar el contenido esperado del campo sin modificar el atributo "name", y esto es lo que requestAutocomplete
usa para vincular los campos de formulario a los datos del usuario.
<input name="fullname" autocomplete="name">
Como especificación, requestAutocomplete
no es específico de pagos, pero la implementación actual de Chrome sí lo es. En el futuro, es probable que los navegadores puedan manejar otros tipos de datos, como detalles de acceso y generador de contraseñas, información de pasaportes y hasta subir un avatar.
Actualmente, en Chrome, requestAutocomplete
reconoce lo siguiente:
Pago
- correo electrónico
- cc-name - name on card
- cc-number: número de tarjeta
- cc-exp-month: Es el mes de vencimiento de la tarjeta expresado en dos dígitos.
- cc-exp-year: Es el año de vencimiento de la tarjeta expresado en cuatro dígitos.
- cc-csc: Código de seguridad de la tarjeta de 3 o 4 dígitos
<input type="email" autocomplete="email" name="email">
<input type="text" autocomplete="cc-name" name="card-name">
<input type="text" autocomplete="cc-number" name="card-num">
<input type="text" autocomplete="cc-exp-month" name="card-exp-month">
<input type="text" autocomplete="cc-exp-year" name="card-exp-year">
<input type="text" autocomplete="cc-csc" name="card-csc">
Los atributos "name" que usé anteriormente son solo ejemplos. No es necesario usar valores específicos. Si vas a volver a usar este formulario para usuarios sin requestAutocomplete
, que es lo ideal, te recomendamos que agregues etiquetas, diseño y validación básica de HTML5.
Tampoco tienes restricciones en cuanto a los elementos de entrada, puedes usar cualquier tipo de entrada de formulario. Por ejemplo, puedes usar <select>
para los campos de vencimiento de la tarjeta.
Dirección
name: Es el nombre completo. Tomar un nombre completo como un solo campo es mucho mejor que usar varios campos. Varios campos, como nombre y apellido, muestran un sesgo occidental y pueden no tener sentido para otras culturas. Además, es más fácil escribir en un solo campo.
tel: Es el número de teléfono completo, incluido el código de país. Como alternativa, se puede dividir en
- tel-country-code - p.ej., +44
- tel-national: El resto
street-address: Es la dirección completa con componentes separados por comas. Se puede desglosar en las siguientes secciones:
- address-line1
- address-line2: Puede estar vacío.
localidad: ciudad o pueblo
region: Código de estado, condado o cantón
postal-code: Código postal
country
Lo anterior se debe usar en combinación con lo siguiente: - facturación - envío
<input type="text" autocomplete="billing name" required name="billing-name">
<input type="tel" autocomplete="billing tel" required name="billling-tel">
<input type="text" autocomplete="billing address-line1" required name="billing-address1">
<input type="text" autocomplete="billing address-line2" required name="billing-address2">
<input type="text" autocomplete="billing locality" required name="billing-locality">
<input type="text" autocomplete="billing region" required name="billing-region">
<input type="text" autocomplete="billing postal-code" required name="billing-postal-code">
<select autocomplete="billing country" required name="billing-country">
<option value="US">United States</option>
…
</select>
<input type="text" autocomplete="shipping name" name="shipping-name">
…
Una vez más, los atributos de nombre son ejemplos, puedes usar los que quieras.
Obviamente, no todos los formularios deben solicitar una dirección de envío. Por ejemplo, no me preguntes dónde me gustaría que se entregue mi habitación de hotel, ya que su ubicación actual suele ser el punto de venta.
Bien, tenemos nuestro formulario y sabemos cómo solicitar autocompletion
. Pero…
¿Cuándo se debe llamar a requestAutocomplete?
Lo ideal es que muestres el diálogo requestAutocomplete
en lugar de cargar la página que muestra el formulario de confirmación de la compra. Si todo funciona correctamente, el usuario no debería ver el formulario.
Un patrón común es tener una página del carrito con un botón "Confirmar la compra" que te dirija al formulario de detalles del pago. En esta situación, quieres cargar tu formulario de facturación en la página del carrito, pero ocultarlo al usuario y llamar a requestAutocomplete
cuando el usuario presione el botón “Confirmar la compra”. Recuerda que deberás publicar tu página del carrito a través de SSL para evitar la advertencia de Skeletor.
Para comenzar, debemos ocultar nuestro botón de confirmación de la compra para que el usuario no pueda hacer clic en él hasta que todo esté listo, pero solo queremos hacerlo para los usuarios con JavaScript. En el encabezado de tu página, haz lo siguiente:
<script>document.documentElement.className += ' js';</script>
Y en tu CSS:
.js #checkout-button,
#checkout-form.for-autocomplete {
display: none;
}
Debemos incluir el formulario de facturación en nuestra página del carrito. Esto puede ir a cualquier lugar, el CSS anterior se asegura de que no sea visible para el usuario.
<form id="checkout-form" class="for-autocomplete" action="/checkout" method="post">
…fields for payment, billing address & shipping if relevant…
</form>
Ahora, nuestro código JavaScript puede comenzar a configurar todo:
function enhanceForm() {
var button = document.getElementById('checkout-button');
var form = document.getElementById('checkout-form');
// show the checkout button
button.style.display = 'block';
// exit early if there's no requestAutocomplete support
if (!form.requestAutocomplete) {
// be sure to show the checkout button so users can
// access the basic payment form!
return;
}
button.addEventListener('click', function(event) {
form.requestAutocomplete();
event.preventDefault();
});
// TODO: listen for autocomplete events on the form
}
Llamarías a enhanceForm
en la página del carrito, en algún momento después del formulario y el botón de confirmación de la compra.
Los navegadores que admiten requestAutocomplete
obtendrán la nueva experiencia rápida y elegante, mientras que otros navegadores usarán tu formulario de pago normal.
Para obtener puntos de bonificación, te recomendamos que cargues el HTML del formulario a través de XHR como parte de enhanceForm
. Esto significa que puedes cargar el formulario solo en navegadores que admitan requestAutocomplete
y no necesitas recordar agregar el formulario a cada página desde la que llames a enhanceForm
. Así es como funciona el sitio de demostración.
Llamaste a requestAutocomplete. ¿Qué sigue?
El proceso de autocompletado es asíncrono, requestAutocomplete
se muestra de inmediato. Para saber cómo fue, escuchamos un par de eventos nuevos:
form.addEventListener('autocomplete', function() {
// hurrah! You got all the data you needed
});
form.addEventListener('autocompleteerror', function(event) {
if (event.reason == 'invalid') {
// the form was populated, but it failed html5 validation
// eg, the data didn't match one of your pattern attributes
}
else if (event.reason == 'cancel') {
// the user aborted the process
}
else if (event.reason == 'disabled') {
// the browser supports requestAutocomplete, but it's not
// available at this time. Eg, it wasn't called from an
// interaction event or the page is insecure
}
});
Si todo funcionó, puedes hacer lo que quieras con los datos. Lo más sencillo es enviar el formulario. Luego, el servidor puede validar los datos y mostrarle al usuario una página de confirmación con el costo de envío. Si los datos no son válidos, puedes mostrar el formulario y destacar los campos que el usuario debe corregir. Como alternativa, puedes enviar el formulario y permitir que se aplique la validación normal del servidor. Si el usuario canceló el proceso, no es necesario que realices ninguna acción. Si la función está inhabilitada, envía al usuario al formulario normal. Por lo tanto, en la mayoría de los casos, tus objetos de escucha se verán de la siguiente manera:
form.addEventListener('autocomplete', function() {
form.submit();
});
form.addEventListener('autocompleteerror', function(event) {
if (event.reason == 'invalid') {
form.submit();
}
else if (event.reason != 'cancel') {
window.location = '/checkout-page/';
}
});
¿Dónde almacena mis datos el navegador?
La especificación no dicta dónde se almacenan los datos, lo que permite que los navegadores innoven.
Si accediste a Chrome, tienes la opción de almacenar los detalles en la Billetera de Google para que puedas acceder a ellos en otros dispositivos en los que hayas accedido. Si almacenas tus datos en la Billetera, requestAutocomplete
no distribuirá tu número de tarjeta real, lo que aumentará la seguridad.
Si no accediste a Chrome o si eliges no usar la Billetera de Google, tus datos se almacenarán de forma opcional de forma local en el navegador para su reutilización.
Esta es la situación actual, pero es posible que, en el futuro, Chrome y otros navegadores adopten proveedores de pagos adicionales.
Facilita los pagos
Es un poco ridículo que los usuarios tengan que ingresar su información de pago una y otra vez cada vez que quieran realizar una compra. Las cosas son más fáciles cuando un sitio almacena los detalles de tu pago. Me preocupa la cantidad de sitios que almacenan los detalles de mi tarjeta. Este es un problema perfecto para resolver con los estándares web.
requestAutocomplete
puede llevar los pagos con un clic a toda la Web, sin bloqueos de servicios o plataformas, y ya era hora.
Ronda adicional: Cómo manejar formularios de varias páginas
Es mucho mejor llamar a requestAutocomplete
una vez y recopilar todos los datos que necesitas. Si no puedes modificar tu servidor para que reciba todos estos datos a la vez, no te preocupes. Extrae los datos del formulario completado y envíalos de la forma que te resulte más conveniente.
Puedes usar esta pequeña y práctica función para capturar todos los datos admitidos actualmente como un objeto simple, sin tener que crear un formulario por tu cuenta. Una vez que tengas los datos, puedes transformarlos en el formato que necesite tu servidor y publicarlos en varios pasos.
checkoutButton.addEventListener('click', function() {
requestUserData({
billing: true,
shipping: true
}, function(response) {
if (response.err == 'cancel') {
// exit silently
return;
}
if (response.err) {
// fall back to normal form
window.location.href = '/normal-checkout-form/';
return;
}
// the rest is just made-up pseudo code as an example
postToServer(data.shipping).then(function() {
return postToServer(data.billing);
}).then(function() {
return postToServer(data.cc);
}).catch(function() {
// handle error
});
});
});