ウェブベースの支払いアプリを Web Payments に適応させ、ユーザー エクスペリエンスを向上させる方法。
ウェブベースの支払いアプリが支払いリクエストを受け取り、支払いトランザクションを開始すると、サービス ワーカーは販売者と支払いアプリ間の通信のハブとして機能します。この投稿では、支払いアプリがサービス ワーカーを使用して支払い方法、配送先住所、連絡先情報に関する情報を販売者に渡す方法について説明します。

販売者に通知する
販売者に以下の変更点を伝えることが重要です。
お支払い方法の変更
支払いアプリは、異なる支払い方法で複数のお支払い手段をサポートできます。
お客様 | お支払い方法 | お支払い方法 |
---|---|---|
A | クレジット カード発行会社 1 | ****1234 |
クレジット カード発行会社 1 | ****4242 |
|
銀行 X | ******123 |
|
B | クレジット カード発行会社 2 | ****5678 |
銀行 X | ******456 |
たとえば、上の表では、顧客 A のウェブベースのウォレットに 2 枚のクレジット カードと 1 つの銀行口座が登録されています。この場合、アプリは 3 つの支払い手段(****1234
、****4242
、******123
)と 2 つの支払い方法(クレジット カード発行会社 1 と銀行 X)を処理しています。支払いトランザクションでは、支払いアプリで顧客が支払い手段を選択し、それを使用して販売者に支払うことができます。

支払いアプリは、全額の支払いレスポンスを送信する前に、お客様が選択した支払い方法を販売者に通知できます。これは、販売者が特定の支払い方法ブランドの割引キャンペーンを実施する場合などに便利です。
Payment Handler API を使用すると、支払いアプリはサービス ワーカーを介して販売者に「支払い方法の変更」イベントを送信し、新しい支払い方法の識別子を通知できます。サービス ワーカーは、新しいお支払い方法の情報を使用して 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 を提供できます。配送先住所が一時的に決定されると、支払いアプリは編集された住所情報を販売者に通知できます。これにより、販売者には次のようなメリットがあります。
- 販売者は、商品の配送に関する地域制限(国内のみなど)をお客様が満たしているかどうかを判断できます。
- 販売者は、配送先住所の地域に基づいて配送オプションのリストを変更できます(国際普通郵便や国際速達など)。
- 販売者は、住所に基づいて新しい送料を適用し、合計金額を更新できます。
Payment Handler API を使用すると、支払いアプリはサービス ワーカーから販売者に「配送先住所の変更」イベントを送信して、新しい配送先住所を通知できます。サービス ワーカーは、新しいアドレス オブジェクトを使用して 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);
…
キーワード: Redacted address(編集された住所)。この場合、販売者に完全な配送先住所を伝える必要はなく、お客様のプライバシーが侵害されるおそれがあります。販売者は、送料の決定に必要な住所の一部のみを受け取ります。具体的には、ブラウザは、販売者の DOM で shippingaddresschange
イベントを発生させる前に、支払いアプリから提供されたアドレスから organization
、phone
、recipient
、addressLine
の各フィールドをクリアします。
販売者は 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 を構築し、お客様が配送オプションを選択できるようにします。

販売者の Payment Request API で指定された配送オプションのリストは、PaymentRequestEvent
のプロパティとして支払いアプリのサービス ワーカーに伝播されます。
[merchant]
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 を使用すると、決済アプリはサービス ワーカーから販売者に「配送オプションの変更」イベントを送信できます。サービス ワーカーは、新しい配送オプション 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
で応答する必要があります。
[merchant]
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://paymentrequest-demo.glitch.me/ にアクセスします。
- ページの一番下まで移動します。
- [お支払いボタンを追加] を押します。
- [Payment Method Identifier] フィールドに「
https://paymenthandler-demo.glitch.me
」と入力します。 - フィールドの横にある [Pay] ボタンを押します。