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

ウェブベースの決済アプリをウェブ決済に適応させ、より優れたユーザー エクスペリエンスを提供する方法。

ウェブベースの支払いアプリが支払いリクエストを受け取って支払いトランザクションを開始すると、Service Worker は販売者と支払いアプリ間の通信ハブとして機能します。この投稿では、支払いアプリが Service Worker を使用して、支払い方法、配送先住所、連絡先情報に関する情報を販売者に渡す方法について説明します。

Service Worker で支払い情報(省略可)を処理する
Service Worker で省略可能な支払い情報を処理する

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

決済アプリは、さまざまなお支払い方法で複数のお支払い方法をサポートできます。

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

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

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

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

Payment Handler API を使用すると、決済アプリは Service Worker を介して「お支払い方法の変更」イベントを販売者に送信し、新しいお支払い方法 ID に通知できます。Service Worker は、新しいお支払い方法の情報を指定して 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 オブジェクトで応答できます。

[販売者]

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 から販売者に「配送先住所の変更」イベントを送信し、新しい配送先住所に通知できます。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 で応答できます。

[販売者]

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 のプロパティとして決済アプリの Service Worker に伝播されます。

[販売者]

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 から販売者に「配送オプションの変更」イベントを送信できます。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: お支払い方法固有のエラー オブジェクト。販売者に構造化されたエラーを提供するよう依頼することもできますが、ウェブ決済の仕様作成者は、単純な文字列にすることをおすすめします。

サンプルコード

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

https://paymenthandler-demo.glitch.me

[支払いハンドラ] Service Worker

[支払いハンドラ] frontend

試してみるには:

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