requestAutocomplete

Pegue meu dinheiro, não meu tempo

Jake archibald
Jake Archibald

Introdução

Eu gosto da Web. No geral, acho que é uma boa ideia. Por isso, entro em debates sobre a Web e os nativos. Não demora muito para a outra pessoa começar a falar sobre a facilidade de pagamentos por meio de sistemas nativos. Minha resposta normal é jogar uma bomba de fumaça e correr para fora da sala rindo maníaca, porque não é um argumento que eu posso vencer. O abandono do carrinho de compras na Web para dispositivos móveis pode chegar a 97%. Imagine isso no mundo real. Imagine 97% das pessoas em um supermercado, com um carrinho cheio de coisas que elas querem, virando o carrinho e saindo. Agora, algumas dessas pessoas estão com preços altos e nunca tiveram a intenção de comprar, mas a terrível experiência do usuário de comprar na Web é uma contribuição significativa. Estamos ofendendo os usuários com tributos sobre a sanidade deles. Pense em uma experiência de pagamento agradável que você teve na Web, especialmente em dispositivos móveis. É uma app store, certo? Ou pelo menos um sistema fechado semelhante que já tenha suas informações de pagamento. Isso é um problema. Ela exige que os sites se comprometam com um provedor de pagamento específico com o qual o usuário já precisa ter uma conta e estar conectado, ou que se comprometam com uma plataforma que exija que os usuários façam login em um provedor de pagamento específico, como lojas de aplicativos que exigem que você codifique somente para essa plataforma. Se você não fizer uma dessas coisas, o usuário estará fadado a tocar na tela ou no teclado até que todos os toques desapareçam ou ele desista. Precisamos corrigir isso.

requestAutocomplete

Em um mundo de WebGL, WebRTC e outras APIs da Web sofisticadas que começam com "Web", o requestAutocomplete é um pouco sem graça. No entanto, é um super-herói em roupas bege. Uma API minúscula e entediante que pode desafiar o coração do vampiro do tempo dos pagamentos na Web.

Em vez de depender de um provedor de pagamento específico, o site solicita os detalhes da forma de pagamento ao navegador, que os armazena em nome do usuário. A versão do Chrome do requestAutocomplete() também se integra à Carteira do Google para usuários dos EUA (atualmente). Faça um teste no nosso site de teste.

form.requestAutocomplete

Os elementos do formulário têm um único método novo, o requestAutocomplete, que pede ao navegador para preencher o formulário. O navegador exibirá uma caixa de diálogo pedindo permissão e permitindo que o usuário selecione quais detalhes ele quer fornecer. Você não pode chamá-lo sempre que quiser. Ele precisa ser chamado durante a execução de eventos de interação específicos, como eventos de mouse para cima/para baixo, clique, tecla e toque. Essa é uma restrição de segurança deliberada.

button.addEventListener('click', function(event) {
  form.requestAutocomplete();
  event.preventDefault();
});

// TODO: listen for autocomplete events on the form

Antes de analisarmos os eventos, precisamos verificar se o navegador compreende os campos do formulário...

Requisitos do formulário

Quando a Internet estava em preto e branco, o Internet Explorer 5 adotou um novo atributo, autocomplete, em elementos de entrada de formulário. Pode ser definido como “desativado” para que o navegador não ofereça sugestões, e é isso. Essa API foi estendida para que você possa especificar o conteúdo esperado do campo sem modificar o atributo “name”. É isso que o requestAutocomplete usa para vincular campos de formulário aos dados do usuário.

<input name="fullname" autocomplete="name">

Como especificação, requestAutocomplete não é específico para pagamentos, mas a implementação atual do Chrome é. No futuro, espera-se que os navegadores consigam lidar com outros tipos de dados, como detalhes de login e gerador de senhas, informações de passaporte e até mesmo fazer upload de um avatar.

No Chrome, o requestAutocomplete reconhece o seguinte:

Pagamento

  • email
  • cc-name - nome no cartão
  • cc-number: número do cartão
  • cc-exp-month – mês de vencimento do cartão em dois dígitos
  • cc-exp-year - ano de vencimento do cartão como quatro dígitos
  • cc-csc: código de segurança do cartão de três a quatro 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">

Os atributos “nome” usados acima são apenas exemplos. Não é necessário usar valores específicos. Se você for reutilizar o formulário para usuários sem o requestAutocomplete, que é o ideal, adicione rótulos, layout e validação básica de HTML5.

Você também não precisa usar elementos de entrada. É possível usar qualquer tipo de entrada de formulário. Por exemplo, você pode usar <select> para os campos de validade do cartão.

Mensagem detalhada do console.
Mensagem detalhada do console

Endereço

  • nome - nome completo. Usar um nome completo como um único campo é muito melhor do que usar vários campos. Vários campos, como nome e sobrenome, mostram um viés ocidental e podem não fazer sentido para outras culturas, além de facilitar a digitação em um único campo.

  • tel - número de telefone completo, incluindo o código do país, pode ser dividido em

    • tel-country-code, por exemplo, +44
    • tel-nacional - as outras
  • Street-address - endereço completo com componentes separados por vírgula, pode ser dividido em

    • linha de endereço1
    • address-line2: pode estar em branco
  • localidade - cidade/município

  • região - código do estado, condado ou cantão

  • postal-code - CEP, código postal, CEP

  • country [país]

As informações acima devem ser usadas em combinação com: - faturamento - frete

<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">
…

Mais uma vez, os atributos de nome são exemplos. Você pode usar o que quiser. Obviamente, nem todos os formulários precisam solicitar um endereço de entrega.Por exemplo, não pergunte onde eu gostaria que meu quarto de hotel fosse entregue. A localização atual geralmente é o ponto de venda. Já temos nosso formulário e sabemos como solicitar autocompletion. Mas...

Quando o requestAutocomplete deve ser chamado?

O ideal é mostrar a caixa de diálogo requestAutocomplete em vez de carregar a página que exibe o formulário de finalização de compra. Se tudo correr bem, o usuário não verá o formulário.

Fluxo de pagamentos

Um padrão comum é ter uma página de carrinho com um botão "Finalizar a compra" que leva você ao formulário de detalhes de pagamento. Nessa situação, você quer carregar o formulário de faturamento na página do carrinho, mas ocultá-lo do usuário e chamar requestAutocomplete nele quando ele pressionar o botão "Finalizar a compra". Lembre-se de que é necessário veicular a página do carrinho por SSL para evitar o aviso Skeletor. Para começar, devemos ocultar nosso botão para que o usuário não possa clicar nele até que esteja tudo pronto, mas queremos fazer isso somente para usuários com JavaScript. Então, no cabeçalho da sua página:

<script>document.documentElement.className += ' js';</script>

No seu CSS:

.js #checkout-button,
#checkout-form.for-autocomplete {
  display: none;
}

Precisamos incluir o formulário de faturamento na página do carrinho. Isso pode ser acessado em qualquer lugar. O CSS acima garante que o site não esteja visível para o usuário.

<form id="checkout-form" class="for-autocomplete" action="/checkout" method="post">
  …fields for payment, billing address &amp; shipping if relevant…
</form>

Agora, o JavaScript pode começar a configurar tudo:

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
}

Você chamaria enhanceForm na página do carrinho, logo após o botão e o formulário de finalização de compra. Navegadores compatíveis com requestAutocomplete terão uma nova e sofisticada experiência rápida, enquanto outros navegadores voltarão ao seu formulário de pagamento normal. Para pontos de bônus, carregue o formulário HTML via XHR como parte de enhanceForm. Isso significa que é possível carregar o formulário somente em navegadores compatíveis com requestAutocomplete, e não é necessário adicionar o formulário a cada página em que você pode chamar enhanceForm. Veja como funciona o site de demonstração.

Você chamou "requestAutocomplete". E agora?

O processo de preenchimento automático é assíncrono, e requestAutocomplete retorna imediatamente. Para saber como foi, ouvimos alguns eventos novos:

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
  }
});

Se tudo funcionar, você poderá fazer o que quiser com os dados. O mais simples é enviar o formulário. O servidor pode validar os dados e fornecer ao usuário uma página de confirmação, incluindo o custo de entrega. Se os dados forem inválidos, você pode mostrar o formulário e destacar os campos que o usuário precisa corrigir. Outra opção é enviar o formulário e deixar a validação normal do lado do servidor assumir o controle. Se o usuário cancelou o processo, você não precisa fazer nada. Se o recurso estiver desativado, encaminhe o usuário para o formulário normal. Na maioria dos casos, os ouvintes vão ficar assim...

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/';
  }
});

Onde o navegador armazena meus dados?

A especificação não determina onde os dados são armazenados, permitindo que os navegadores inovem. Se você fizer login no Chrome, terá a opção de armazenar detalhes na Carteira do Google. Assim, eles podem ser acessados em outros dispositivos em que você fizer login. Se você armazenar seus dados na Carteira, o número real do seu cartão não será revelado até requestAutocomplete, o que aumenta a segurança. Se você não fez login no Chrome ou optar por não usar a Carteira do Google, seus dados podem ser armazenados localmente no navegador para reutilização. Este é o estado atual, mas no futuro o Chrome e outros navegadores poderão adotar outros provedores de pagamento.

Como facilitar os pagamentos

É até ridículo que os usuários precisem inserir suas informações de pagamento várias vezes sempre que quiserem fazer uma compra. Tudo fica mais fácil quando um site armazena seus detalhes de pagamento. Fico um pouco preocupado com quantos sites armazenam os detalhes do meu cartão. Esse é um problema perfeito para os padrões da Web. O requestAutocomplete pode trazer os pagamentos com um clique para toda a Web, sem dependência de serviços ou plataformas, e também em pouco tempo.

Rodada bônus: gerenciamento de formulários com várias páginas

É muito melhor ligar para requestAutocomplete uma vez e coletar todos os dados necessários. Se não for possível modificar seu servidor para receber todos esses dados de uma vez, tudo bem. Basta extrair os dados do formulário preenchido e enviá-los como for melhor para você. Você pode usar essa pouca função para capturar todos os dados compatíveis no momento como um objeto simples, sem precisar criar um formulário. Assim que tiver os dados, você poderá transformar em qualquer formato de que seu servidor precisar e postá-los em várias etapas.

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
    });
  });
});