Service Worker での支払い情報(省略可)の処理

ウェブベースの支払いアプリをウェブ支払いに対応させて、ユーザー エクスペリエンスを向上させる方法。

ウェブベースの支払いアプリが支払いリクエストを受信して支払い取引を開始すると、サービス ワーカーが販売者と支払いアプリ間の通信のハブとして機能します。この記事では、支払いアプリがサービス ワーカーを使用して支払い方法、配送先住所、連絡先情報に関する情報を販売者に渡す方法について説明します。

Service Worker でオプションのお支払い情報を処理する
サービス ワーカーでオプションのお支払い情報を処理する

お支払い方法の変更を販売者に通知する

支払いアプリは、異なるお支払い方法の複数のお支払い手段をサポートできます。

顧客 お支払い方法 お支払い方法
A Credit Card Issuer 1 ****1234
Credit Card Issuer 1 ****4242
銀行 X ******123
B クレジット カード発行会社 2 ****5678
銀行 X ******456

たとえば、上記の表では、お客様 A のウェブベースのウォレットに 2 枚のクレジット カードと 1 つの銀行口座が登録されています。この場合、アプリは 3 つの支払い方法(****1234****4242******123)と 2 つの支払い方法(クレジットカード発行会社 1 と銀行 X)を処理しています。支払い取引で、支払いアプリを使用して、顧客がいずれかのお支払い方法を選択し、その方法で販売者に支払うことができます。

お支払い方法選択 UI
お支払い方法選択ツールの UI

支払いアプリは、完全な支払いレスポンスの送信前に、お客様が選択したお支払い方法について販売者に通知できます。これは、特定のお支払い方法のブランドの割引キャンペーンを実施する場合などに便利です。

Payment Handler API を使用すると、支払いアプリはサービス ワーカーを介して販売者に「お支払い方法の変更」イベントを送信し、新しいお支払い方法の ID を通知できます。サービス ワーカーは、新しいお支払い方法の情報を使用して PaymentRequestEvent.changePaymentMethod() を呼び出す必要があります。

お支払い方法の変更を販売者に伝える
お支払い方法の変更を販売者に通知

支払いアプリは、PaymentRequestEvent.changePaymentMethod() のオプションの 2 番目の引数として methodDetails オブジェクトを渡すことができます。このオブジェクトには、販売者が変更イベントを処理するために必要な任意のお支払い方法の詳細を含めることができます。

[支払いハンドラ] service-worker.js


// Received a message from the frontend
self.addEventListener('message', async e => {
  let details;
  try {
    switch (e.data.type) {
      
      case 'PAYMENT_METHOD_CHANGED':
        const newMethod = e.data.paymentMethod;
        const newDetails = e.data.methodDetails;
        // Redact or check that no sensitive information is passed in
        // `newDetails`.
        // Notify the merchant of the payment method change
        details =
          await payment_request_event.changePaymentMethod(newMethod, newDetails);
      

販売者は、Payment Request API から paymentmethodchange イベントを受信すると、支払いの詳細を更新し、PaymentDetailsUpdate オブジェクトで応答できます。

[merchant]

request.addEventListener('paymentmethodchange', e => {
  if (e.methodName === 'another-pay') {
    // Apply $10 discount for example.
    const discount = {
      label: 'special discount',
      amount: {
        currency: 'USD',
        // The value being string complies the spec
        value: '-10.00'
      }
    };
    let total = 0;
    details.displayItems.push(discount);
    for (let item of details.displayItems) {
     total += parseFloat(item.amount.value);
    }
    // Convert the number back to string
    details.total.amount.value = total.toString();
  }
  // Pass a promise to `updateWith()` and send updated payment details
  e.updateWith(details);
});

販売者が返信すると、PaymentRequestEvent.changePaymentMethod() が返した Promise は PaymentRequestDetailsUpdate オブジェクトで解決されます。

[支払いハンドラ] service-worker.js


        // Notify the merchant of the payment method change
        details = await payment_request_event.changePaymentMethod(newMethod, newDetails);
        // Provided the new payment details,
        // send a message back to the frontend to update the UI
        postMessage('UPDATE_REQUEST', details);
        break;

このオブジェクトを使用して、フロントエンドの UI を更新します。更新されたお支払い情報を反映するをご覧ください。

配送先住所の変更を販売者に伝える

支払いアプリは、支払い取引の一環として、お客様の配送先住所を販売者に提供できます。

販売者は住所の収集を決済アプリに委任できるため、これは販売者にとって便利です。また、住所データは標準データ形式で提供されるため、販売者は一貫した構造の配送先住所を受け取ることができます。

また、顧客は住所情報を任意の決済アプリに登録し、別の販売者で再利用できます。

配送先住所選択 UI
配送先住所選択ツールの UI

お支払いアプリでは、配送先住所を編集したり、お支払い取引でお客様の登録済み住所情報を選択したりするための UI を提供できます。配送先住所が一時的に決定されると、決済アプリは削除された住所情報を販売者に通知できます。これにより、販売者は次のようなメリットを得ることができます。

  • 販売者は、商品を発送するための地域制限(国内のみなど)をお客様が満たしているかどうかを判断できます。
  • 販売者は、配送先住所の地域に基づいて配送オプションのリストを変更できます(例: 国際標準便や速達便)。
  • 販売者は、住所に基づいて新しい配送料金を適用し、合計金額を更新できます。

Payment Handler API を使用すると、支払いアプリはサービス ワーカーから販売者に「配送先住所の変更」イベントを送信して、新しい配送先住所を通知できます。Service Worker は、新しいアドレス オブジェクトを使用して PaymentRequestEvent.changeShippingAddress() を呼び出す必要があります。

配送先住所の変更を販売者に伝える
販売者に配送先住所の変更を通知する

[支払いハンドラ] service-worker.js

...
// Received a message from the frontend
self.addEventListener('message', async e => {
  let details;
  try {
    switch (e.data.type) {
      
      case 'SHIPPING_ADDRESS_CHANGED':
        const newAddress = e.data.shippingAddress;
        details =
          await payment_request_event.changeShippingAddress(newAddress);
      

販売者は Payment Request API から shippingaddresschange イベントを受信し、更新された PaymentDetailsUpdate で応答できます。

[merchant]

request.addEventListener('shippingaddresschange', e => {
  // Read the updated shipping address and update the request.
  const addr = request.shippingAddress;
  const details = getPaymentDetailsFromShippingAddress(addr);
  // `updateWith()` sends back updated payment details
  e.updateWith(details);
});

販売者が返信すると、返された Promise PaymentRequestEvent.changeShippingAddress()PaymentRequestDetailsUpdate オブジェクトで解決されます。

[支払いハンドラ] service-worker.js


        // Notify the merchant of the shipping address change
        details = await payment_request_event.changeShippingAddress(newAddress);
        // Provided the new payment details,
        // send a message back to the frontend to update the UI
        postMessage('UPDATE_REQUEST', details);
        break;

このオブジェクトを使用して、フロントエンドの UI を更新します。更新されたお支払い情報を反映するをご覧ください。

配送オプションの変更を販売者に伝える

配送オプションは、購入された商品をお客様に配送するために販売者が使用する配送方法です。一般的な配送オプションは次のとおりです。

  • 送料無料
  • エクスプレス配送
  • 国外配送について
  • プレミアム国際配送

それぞれに独自の費用が発生します。通常、高速な方法やオプションは費用が高くなります。

Payment Request API を使用する販売者は、この選択を決済アプリに委任できます。決済アプリは、この情報を使用して UI を作成し、ユーザーが配送オプションを選択できるようにします。

配送オプション選択ツールの UI
配送オプション選択ツールの UI

販売者の Payment Request API で指定された配送オプションのリストは、PaymentRequestEvent のプロパティとして支払いアプリのサービス ワーカーに伝播されます。

[販売者]

const request = new PaymentRequest([{
  supportedMethods: 'https://bobbucks.dev/pay',
  data: { transactionId: '****' }
}], {
  displayItems: [{
    label: 'Anvil L/S Crew Neck - Grey M x1',
    amount: { currency: 'USD', value: '22.15' }
  }],
  shippingOptions: [{
    id: 'standard',
    label: 'Standard',
    amount: { value: '0.00', currency: 'USD' },
    selected: true
  }, {
    id: 'express',
    label: 'Express',
    amount: { value: '5.00', currency: 'USD' }
  }],
  total: {
    label: 'Total due',
    amount: { currency: 'USD', value : '22.15' }
  }
}, {  requestShipping: true });

支払いアプリでは、お客様が選択した配送オプションを販売者に知らせることができます。配送オプションを変更すると合計金額も変更されるため、これは販売者と顧客の両方にとって重要です。販売者は後で支払い確認の最新の価格を通知する必要があります。また、顧客もこの変更を認識する必要があります。

Payment Handler API を使用すると、決済アプリはサービス ワーカーから販売者に「配送オプションの変更」イベントを送信できます。Service Worker は、新しい配送オプション ID を使用して PaymentRequestEvent.changeShippingOption() を呼び出す必要があります。

配送オプションの変更を販売者に伝える
販売者に配送オプションの変更を通知する

[支払いハンドラ] service-worker.js


// Received a message from the frontend
self.addEventListener('message', async e => {
  let details;
  try {
    switch (e.data.type) {
      
      case 'SHIPPING_OPTION_CHANGED':
        const newOption = e.data.shippingOptionId;
        details =
          await payment_request_event.changeShippingOption(newOption);
      

販売者は Payment Request API から shippingoptionchange イベントを受信します。販売者は、この情報を使用して合計金額を更新し、更新された PaymentDetailsUpdate で返信する必要があります。

[販売者]

request.addEventListener('shippingoptionchange', e => {
  // selected shipping option
  const shippingOption = request.shippingOption;
  const newTotal = {
    currency: 'USD',
    label: 'Total due',
    value: calculateNewTotal(shippingOption),
  };
  // `updateWith()` sends back updated payment details
  e.updateWith({ total: newTotal });
});

販売者が返信すると、PaymentRequestEvent.changeShippingOption() が返した Promise は PaymentRequestDetailsUpdate オブジェクトで解決されます。

[支払いハンドラ] service-worker.js


        // Notify the merchant of the shipping option change
        details = await payment_request_event.changeShippingOption(newOption);
        // Provided the new payment details,
        // send a message back to the frontend to update the UI
        postMessage('UPDATE_REQUEST', details);
        break;

このオブジェクトを使用して、フロントエンドの UI を更新します。更新されたお支払い情報を反映するをご覧ください。

更新されたお支払い情報を反映する

販売者がお支払い情報の更新を完了すると、.changePaymentMethod().changeShippingAddress().changeShippingOption() から返された Promise は、共通の PaymentRequestDetailsUpdate オブジェクトで解決されます。支払いハンドラは、この結果を使用して、更新された合計金額と配送オプションを UI に反映できます。

販売者がエラーを返す理由はいくつかあります。

  • このお支払い方法は利用できません。
  • 配送先住所がサポート対象地域外である。
  • 配送先住所に無効な情報が含まれています。
  • 指定された配送先住所またはその他の理由で、配送オプションを選択できません。

エラーのステータスを反映するには、次のプロパティを使用します。

  • error: 人が読めるエラー文字列。これは、ユーザーに表示するのに最適な文字列です。
  • shippingAddressErrors: アドレス プロパティごとに詳細なエラー文字列を含む AddressErrors オブジェクト。これは、お客様が住所を編集できるフォームを開き、無効なフィールドを直接指摘する必要がある場合に便利です。
  • paymentMethodErrors: 支払い方法固有のエラー オブジェクト。販売者に構造化エラーを提供するよう依頼することもできますが、Web Payments 仕様の作成者は、単純な文字列のままにすることを推奨しています。

サンプルコード

このドキュメントで紹介したサンプルコードのほとんどは、次の動作中のサンプルアプリからの抜粋です。

https://paymenthandler-demo.glitch.me

[支払いハンドラ] Service Worker

[payment handler] フロントエンド

試すには:

  1. https://paymentrequest-demo.glitch.me/ にアクセスします。
  2. ページの一番下に移動します。
  3. [お支払い方法を追加] ボタンを押します。
  4. [お支払い方法 ID] フィールドに「https://paymenthandler-demo.glitch.me」と入力します。
  5. フィールドの横にある [支払い] ボタンを押します。