如何調整網路付款應用程式,以支援 Web Payments,為消費者提供更優質的使用者體驗。
網路付款應用程式收到付款要求並啟動付款交易後,服務工作人員會做為商家與付款應用程式之間的通訊中樞。本文說明付款應用程式如何使用服務工作人員,將付款方式、運送地址或聯絡資訊傳遞給商家。

通知商家
請務必告知商家下列異動。
變更付款方式
付款應用程式可以支援多種付款工具,並提供不同付款方式。
客戶 | 付款方式 | 付款方式 |
---|---|---|
A | 信用卡發卡機構 1 | ****1234 |
信用卡發卡機構 1 | ****4242 |
|
銀行 X | ******123 |
|
B | 信用卡發卡機構 2 | ****5678 |
銀行 X | ******456 |
舉例來說,在上表中,客戶 A 的網路錢包已註冊兩張信用卡和一個銀行帳戶。在本例中,應用程式會處理三種付款方式 (****1234
、****4242
、******123
) 和兩種付款方法 (信用卡發卡機構 1 和銀行 X)。在付款交易中,付款應用程式可讓消費者選擇其中一種付款工具,並用來支付商家款項。

付款應用程式可以先告知商家顧客選擇的付款方式,再傳送完整付款回應。舉例來說,商家想為特定付款方式品牌放送折扣廣告活動時,這項功能就相當實用。
透過 Payment Handler API,付款應用程式可以透過 Service Worker 將「付款方式變更」事件傳送給商家,通知新的付款方式 ID。服務工作人員應使用新的付款方式資訊叫用 PaymentRequestEvent.changePaymentMethod()
。

付款應用程式可以將 methodDetails
物件當做 PaymentRequestEvent.changePaymentMethod()
的選用第二個引數傳遞。這個物件可以包含商家處理變更事件所需的任意付款方式詳細資料。
[payment handler] 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);
…
商家收到 PaymentRequest 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);
});
商家回覆後,系統會使用 PaymentRequestDetailsUpdate
物件解析 PaymentRequestEvent.changePaymentMethod()
傳回的 Promise。
[payment handler] 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;
…
使用該物件更新前端的使用者介面。請參閱反映更新後的付款詳細資料。
變更運送地址
付款應用程式可以在付款交易中,將顧客的運送地址提供給商家。
商家可將地址收集作業委派給付款應用程式,此外,由於地址資料會以標準資料格式提供,商家可望收到結構一致的運送地址。
此外,顧客可以向偏好的付款應用程式註冊地址資訊,並重複用於不同商家。

付款應用程式可提供使用者介面,讓顧客在付款交易中編輯運送地址,或選取預先註冊的地址資訊。暫時決定運送地址後,付款應用程式可以將經過編輯的地址資訊告知商家。這項功能可為商家帶來多項好處:
- 商家可以判斷顧客是否符合運送商品的區域限制 (例如僅限國內)。
- 商家可以根據運送地址的區域變更運送選項清單 (例如國際普通或快遞)。
- 商家可以根據地址套用新的運費,並更新總價。
付款應用程式可透過 Payment Handler API,從 Service Worker 將「shipping address change」事件傳送給商家,通知新的運送地址。服務工作人員應使用 new address 物件叫用 PaymentRequestEvent.changeShippingAddress()
。

[payment handler] 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);
…
關鍵字:已遮蓋地址。在這種情況下,向商家提供完整運送地址並無必要,且可能侵犯顧客隱私。商家只會收到決定運費所需的地址資訊,具體來說,瀏覽器會在商家 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
物件解析。
[payment handler] 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;
…
使用該物件更新前端的使用者介面。請參閱反映更新後的付款詳細資料。
通知商家運送選項變更
運送選項是商家用來將所購商品運送給消費者的配送方式。常見的運送選項包括:
- 免運費
- 快速到貨
- 跨國運送
- 國際優先配送
每項功能都有各自的費用。通常較快速的方法和選項費用較高。
使用 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()
。

[payment handler] 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 });
});
商家回覆後,系統會使用 PaymentRequestDetailsUpdate
物件解析 PaymentRequestEvent.changeShippingOption()
傳回的 Promise。
[payment handler] 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;
…
使用該物件更新前端的使用者介面。請參閱反映更新後的付款詳細資料。
反映更新後的付款詳細資料
商家更新付款詳細資料後,從 .changePaymentMethod()
、.changeShippingAddress()
和 .changeShippingOption()
傳回的 Promise 會解析為常見的 PaymentRequestDetailsUpdate
物件。付款處理常式可以使用結果,在 UI 中反映更新後的總價和運送選項。
商家可能會因下列原因傳回錯誤:
- 系統不接受該付款方式。
- 運送地址不在支援的區域內。
- 運送地址含有無效資訊。
- 由於提供的運送地址或其他原因,無法選取運送選項。
請使用下列屬性反映錯誤狀態:
error
:使用者可閱讀的錯誤字串。這是向消費者顯示的最佳字串。shippingAddressErrors
:AddressErrors
物件,內含每個地址屬性的詳細錯誤字串。如果您想開啟表單,讓顧客編輯地址,並直接指出無效的欄位,這項功能就非常實用。paymentMethodErrors
:付款方式專屬的錯誤物件。您可以要求商家提供結構化錯誤,但 Web Payments 規格作者建議保留簡單字串。
程式碼範例
您在本文件中看到的大部分程式碼範例,都是從範例應用程式擷取而來。
如要試用這項功能,請按照下列步驟操作:
- 前往 https://paymentrequest-demo.glitch.me/。
- 前往頁面底部。
- 按下「新增付款按鈕」。
- 在「付款方式 ID」欄位中輸入
https://paymenthandler-demo.glitch.me
。 - 按下欄位旁的「付款」按鈕。