requestAutocomplete

花钱,不用时间

杰克·阿奇博尔德
Jake Archibald

简介

我喜欢网络。总的来说,我认为这是一个很好的想法。因此,我进行了很多有关网络与原生的争论。很快对方就会开始谈论通过原生系统实现付款的便利性。我通常的回答是放一颗烟弹,然后狂笑地从房间里跑出去,因为这不是我能赢的理由。 移动网站上的购物车放弃率可高达 97%。在现实世界中想象一下。想象一下,超市中 97% 的人,推着满满一购物车他们想买的东西,把购物车翻过来然后走出去。 现在,有些人只是在定价,从来没有购买意向,但在网上购物的糟糕用户体验是非常重要的因素。我们正在对用户的健全度征税。 回想一下您在网络上(尤其是在移动设备上)获得的愉悦付款体验。这是应用商店,对吗?或者至少拥有一个已拥有您的付款信息的类似封闭式系统。 这是一个问题。它要求网站承诺,用户必须已经拥有帐号并登录的特定付款服务机构,或者承诺服务于要求用户登录特定付款服务机构的平台(例如要求您只针对该平台进行编码的应用商店)。如果您未执行上述任一操作,用户就注定要点按屏幕或键盘,直到所有手指的皮肤都消失或放弃。 我们需要解决这个问题。

requestAutocomplete

在 WebGL、WebRTC 和其他以“Web”开头的复杂 Web API 的世界里,requestAutocomplete 相当乏味。不过,在米色服装中,它是一个超级英雄。一个微小而枯燥的 API,可能会根深蒂固地贯穿网络付款的核心。

网站不依赖于特定的付款服务机构,而是向浏览器请求付款详情,由浏览器代表用户存储这些信息。 Chrome 的 requestAutocomplete() 版本还与 Google 钱包集成,仅面向美国用户(目前)在我们的测试网站上试用一下

form.requestAutocomplete

表单元素承载一种新方法 requestAutocomplete,该方法会要求浏览器填充表单。浏览器将向用户显示一个对话框,请求授予权限,并允许用户选择他们想要提供哪些详细信息。 您无法随时调用此方法,而是需要在执行特定互动事件(例如鼠标释放/按下事件、点击事件、按键事件和触摸事件)期间调用。这是故意实施的安全限制。

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

// TODO: listen for autocomplete events on the form

在查看这些事件之前,我们需要确保浏览器了解您的表单字段...

表单要求

早在互联网还处于黑白色时,Internet Explorer 5 对表单输入元素采用了新属性 autocomplete。您可以将其设为“关闭”,以阻止浏览器提供建议,这样就大功告成了。此 API 已经过扩展,因此您无需修改“name”属性即可指定字段的预期内容,requestAutocomplete 也使用此方法将表单字段关联到用户数据。

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

按照规范,requestAutocomplete 并不局限于付款功能,但 Chrome 目前的实现方法基本上是这样的。将来,浏览器能够处理其他类型的数据,希望能够处理其他类型的数据,比如登录详细信息和密码生成器、护照信息,甚至上传头像。

目前,在 Chrome 中,requestAutocomplete 可识别以下内容:

付款

  • email
  • cc-name - 持卡人姓名
  • cc-number - 卡号
  • cc-exp-month - 卡到期月份(两位数)
  • cc-exp-year - 卡到期年份(四位数)
  • cc-csc - 3-4 位数的银行卡安全码
<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">

我在上面使用的“name”属性只是示例,不需要使用特定的值。如果您打算为没有 requestAutocomplete 的用户重复使用此表单(理想情况),则您需要添加标签、布局和基本的 HTML5 验证。

您也不必局限于输入元素,可以使用任何表单输入类型。例如,您可以为卡到期字段使用 <select>

详细的控制台消息。
详细的控制台消息

地址

  • name - 全名。将全名作为单个字段比多个字段要好。名字和姓氏等多个字段表现出西方偏见,可能对其他文化有意义,而且在单个字段中输入内容更方便

  • tel - 包含国家/地区代码的完整电话号码,也可以分解为

    • tel-country-code - 例如 +44
    • tel-national - 其余
  • 街道地址 - 完整地址,组成部分以逗号分隔,可拆分为

    • 地址第 1 行
    • address-line2 - 可能为空
  • locality - 市/镇

  • 地区 - 州代码、县或州

  • postal-code - 邮政编码

  • country

以上选项应与: - 结算 - 运费结合使用

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

同样,名称属性只是示例,您可以随意使用。显然,并非所有表单都应该要求提供送货地址。例如,不要问我想要将酒店客房送到何处,因为目前所在的位置通常是卖点。 好了,我们已经有了表单,知道如何请求 autocompletion。但是...

应在何时调用 requestAutocomplete ?

理想情况下,您希望显示 requestAutocomplete 对话框,而不是加载显示结账表单的页面。如果一切顺利,用户应该完全看不到表单。

付款流程

一种常见模式是,在购物车页面上有一个“结账”按钮,可将用户转到付款明细表单。在这种情况下,您需要在购物车页面上加载结算表单,但对用户隐藏该表单,并在用户点击“结账”按钮时对该表单调用 requestAutocomplete。请注意,您需要通过 SSL 提供购物车页,以免出现“骨架式”警告。 首先,我们应隐藏结账按钮,使用户在准备就绪之前无法点击该按钮,但我们只想为使用 JavaScript 的用户执行此操作。因此,在网页的标头部分:

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

在您的 CSS 中:

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

我们需要在购物车页面上提供结算表单。它可以位于任何位置,上面的 CSS 可确保用户看不到它。

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

现在,我们的 JavaScript 可以开始进行一切设置:

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
}

您需要在购物车页面上调用 enhanceForm(在结账表单和按钮之后的某个时间)。 支持 requestAutocomplete 的浏览器会获得精美绝伦的全新快速体验,其他浏览器则会回退到您的常规付款方式。 另外,您可能需要通过 XHR 作为 enhanceForm 的一部分加载表单 HTML。也就是说,您只能在支持 requestAutocomplete 的浏览器中加载表单,而且您不必记得将表单添加到可能会从中调用 enhanceForm 的每个页面。演示网站的运作方式如下。

您调用了 requestAutocomplete,接下来该做什么?

自动补全流程是异步进行的,requestAutocomplete 会立即返回结果。为了了解其运行过程,我们会监听两个新事件:

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

如果一切正常,那么您可以对数据执行所需的任何操作,最简单的方法是提交表单。然后,服务器会验证数据,并向用户提供包含运费信息的确认页面。 如果数据无效,您可以显示表单并突出显示用户需要修改的字段。或者,您也可以只提交表单,让常规的服务器端验证来接管。 如果用户取消了该流程,则您无需执行任何操作。如果该功能被停用,则将用户引导至常规表单。 因此在大多数情况下,您的监听器看起来非常像...

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

浏览器将我的数据存储在何处?

该规范并未规定数据的存储位置,因此浏览器具有以下创新功能。 在登录 Chrome 后,您可以选择将详细信息存储在 Google 钱包中,以便在您登录的其他设备上访问这些信息。如果您将详细信息存储在 Google 钱包中,requestAutocomplete 不会处理您的真实卡号,从而提高安全性。 如果您没有登录 Chrome 或选择不使用 Google 钱包,系统会视需要将您的详细信息存储在本地浏览器中,以供重复使用。 这是目前的情况,但将来 Chrome 和其他浏览器可能会采用其他付款服务机构。

轻松付款

每当用户想要购物时,都必须反复输入付款信息,真是太可笑了。网站存储您的收款信息后,情况会更轻松,但我对有多少网站会存储我的银行卡详细信息有些担心。这是 Web 标准需要解决的一个完美问题。requestAutocomplete 可以在整个网络上提供一键式付款服务,而不会受制于特定服务或平台,而且时间也很长!

额外奖励:处理多页表单

最好是调用一次 requestAutocomplete 并收集您需要的所有数据。如果您无法修改服务器以一次性接收所有这些数据,也没有关系,请从填写好的表单中获取数据,然后提交最适合您的方式。 您可以使用以下实用的小函数将当前支持的所有数据捕获为简单对象,而无需自行创建表单。获得数据后,您可以将其转换为服务器所需的任何格式,并通过多个步骤进行发布。

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