requestAutocomplete

收錢就好,別浪費我時間

Jake Archibald
Jake Archibald

簡介

我喜歡網頁。總而言之,我認為這是個不錯的想法。因此,我經常參與許多網頁與原生廣告的辯論。對方很快就開始談論透過原生系統付款的便利性。我通常會回應,丟出煙霧彈,然後瘋狂大笑著跑出房間,因為這是我無法勝出的論點。行動版網站的購物車放棄率可能高達 97%。想像一下,在現實世界中,假設 97% 的超市顧客手推車裡裝滿了想要的商品,然後翻過推車離開。其中有些人只是想抬高價格,從未打算購買,但網路購物帶來的糟糕使用者體驗,是造成這種情況的重要原因。我們正在向使用者收取「理智稅」。想想你在網路上 (尤其是在行動裝置上) 曾有過的愉快付款體驗。這是應用程式商店,對吧?或至少是已擁有您付款資訊的類似封閉式系統。這會造成問題。這類網站必須採用特定付款服務供應商,使用者必須已擁有該服務供應商的帳戶並登入,或是採用平台,要求使用者登入特定付款服務供應商 (例如要求您專為該平台編寫程式的應用程式商店)。如果您沒有採取上述做法,使用者就只能不斷輕觸螢幕或鍵盤,直到手指皮膚磨損為止,或者乾脆放棄。我們需要修正這個問題。

requestAutocomplete

在 WebGL、WebRTC 和其他以「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 會辨識以下項目:

付款

  • 電子郵件
  • 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 - 其餘
  • street-address - 完整地址,包含以半形逗號分隔的元件,可細分為

    • address-line1
    • address-line2 - 可空白
  • 地區 - 城市/鄉鎮

  • 區域 - 州代碼、縣或州

  • 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 提供購物車頁面,才能避免 Skeletor 警告。首先,我們應該隱藏結帳按鈕,讓使用者在我們準備就緒前無法點選,但我們只想針對使用 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 載入表單 HTML,做為 enhanceForm 的一部分。也就是說,您只能在支援 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 和其他瀏覽器日後可能會採用其他付款服務供應商。

提供簡便的付款方式

使用者每次購物時都必須重複輸入付款資訊,這實在有點荒謬。網站儲存你的付款詳情會讓你更輕鬆,但我有點擔心有那麼多網站會儲存我的卡片資料。這是網路標準最適合解決的問題。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
    });
  });
});