時間ではなくお金を払う
はじめに
私はウェブが好きです。総じて、これは良いアイデアだと思います。そのため、ウェブとネイティブの議論によく関わっています。すぐに、ネイティブ システムによる支払いの利便性について話が及ぶでしょう。私の場合、通常は煙幕を投げ、狂ったように笑いながら部屋から逃げ出します。これは私が勝てる議論ではないからです。 モバイル ウェブでのショッピング カートの放棄率は97%に達することがあります。現実世界でこれを想像してみてください。スーパーマーケットにいる人々の 97% を想像してみてください。ほしいもので満たされたカートを引きずり満足そうな人々です。 中には、商品の値上げのみを目的とし、購入するつもりがないユーザーもいますが、ウェブでの購入の恐ろしいユーザー エクスペリエンスが大きな要因となっています。ユーザーの精神に負担をかける税金です。 ウェブ(特にモバイル)で行った、快適な支払い体験を思い出してください。アプリストアですね。または、少なくとも、お支払い情報がすでに登録されている類似のクローズド システム。これは問題です。サイトは、ユーザーがすでにアカウントを作成してログインしている特定のお支払いプロバイダにコミットするか、ユーザーが特定のお支払いプロバイダにログインすることを必須とするプラットフォーム(そのプラットフォーム専用にコードを記述する必要があるアプリストアなど)にコミットする必要があります。これらのいずれかを行わないと、ユーザーは指の皮膚がすべて剥がれるか、あきらめるまで画面やキーボードをタップし続けなければなりません。修正いたします。
requestAutocomplete
WebGL、WebRTC、その他の「Web」で始まる高度なウェブ API の世界では、requestAutocomplete
は華やかさに欠けます。ただし、ベージュ色の衣装を着たスーパーヒーローです。ウェブ決済の時間を吸い取る吸血鬼の心臓に杭を打ち込むことができる、小さくて退屈な API。
特定の支払プロバイダに頼るサイトよりも、ブラウザから支払いの詳細を要求します。ブラウザはユーザーに代わって支払いの詳細を保存します。Chrome バージョンの requestAutocomplete() は、米国のユーザーのみ(現在)Google ウォレットと統合されています。テストサイトでお試しください。
form.requestAutocomplete
フォーム要素には、フォームへの入力をブラウザにリクエストする新しいメソッドが 1 つ追加されました。このメソッドは 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 - カードの有効期限の月(2 桁)
- cc-exp-year - カードの有効期限の年(4 桁)
- 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 - 氏名。氏名を 1 つのフィールドとして扱うほうが、複数のフィールドとして扱うよりもはるかに優れています。姓や名など複数のフィールドは西洋的な偏見を示しており、他の文化では意味が通じない可能性があります。また、1 つのフィールドに入力するほうが簡単です。
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
を呼び出します。Skeletor の警告を回避するには、カートページを 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 & 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
をサポートしているブラウザでは、新しい高速なエクスペリエンスが提供されます。他のブラウザでは、通常のお支払いフォームが使用されます。ボーナスポイントとして、enhanceForm
の一部として XHR 経由でフォーム 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 ウォレットに詳細を保存して、ログインしている他のデバイスからアクセスできるようになります。ウォレットにカード情報を保存すると、requestAutocomplete
から実際のカード番号が渡されなくなるため、セキュリティが強化されます。
Chrome にログインしていない場合や、Google ウォレットを使用しない場合は、必要に応じて、詳細がブラウザにローカルに保存され、再利用されます。現時点ではこのような状況ですが、今後、Chrome や他のブラウザで追加の決済プロバイダが採用される可能性があります。
お支払いを簡単にする
購入するたびにお支払い情報を何度も入力しなければならないのは、ちょっとばかばかしいものです。サイトにお支払い情報を保存しておくと便利ですが、保存しているサイトが多すぎて少し不安です。これは、ウェブ標準で解決するのに最適な問題です。requestAutocomplete
を使用すると、サービスやプラットフォームに縛られることなく、ウェブ全体でワンクリック決済を実現できます。
ボーナス ラウンド: 複数ページのフォームを処理する
requestAutocomplete
を 1 回呼び出して、必要なデータをすべて収集することをおすすめします。これらのデータをすべて一度に受信するようにサーバーを変更できない場合は、フォームに入力したデータを取得して、ご都合のよい方法で送信してください。この便利な関数を使用すると、フォームを自分で作成しなくても、現在サポートされているすべてのデータをシンプルなオブジェクトとして取得できます。データを取得したら、サーバーが必要な形式に変換し、複数のステップで投稿できます。
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
});
});
});