與服務工作人員處理選擇性付款資訊

如何將網頁式付款應用程式調整為網路付款模式,並為消費者提供更優質的使用者體驗。

網頁式付款應用程式收到付款要求,並啟動付款交易後,服務工作站會擔任商家和付款應用程式之間的通訊中樞。這篇文章說明如何透過服務工作站將付款方式、運送地址或聯絡資訊傳送給商家。

透過服務工作人員處理選用付款資訊
使用 Service Worker 處理選用付款資訊

通知商家付款方式變更

付款應用程式可支援使用不同付款方式的多種付款方式。

客戶 付款方式 付款方式
A 信用卡發卡機構 1 ****1234
信用卡發卡機構 1 ****4242
X 銀行 ******123
B 信用卡發卡機構 2 ****5678
X 銀行 ******456

舉例來說,在上表中,客戶 A 的網路式錢包有兩個信用卡和一個銀行帳戶註冊。在此情況下,應用程式會處理三種付款方式 (****1234****4242******123) 和兩種付款方式 (信用卡發卡機構 1 和銀行 X)。在付款交易中,付款應用程式可讓客戶挑選任一付款方式,並使用該付款方式支付商家費用。

付款方式挑選器使用者介面
付款方式挑選器 UI

付款應用程式可在傳送完整付款回應前,讓商家瞭解客戶選擇的付款方式。舉例來說,如果商家想針對特定付款方式品牌放送折扣廣告活動,這項功能就能派上用場。

在 Payment Handler API 中,付款應用程式可透過服務工作站將「付款方式變更」事件傳送給商家,藉此通知新的付款方式 ID。Service Worker 應使用新的付款方式資訊叫用 PaymentRequestEvent.changePaymentMethod()

通知商家付款方式變更
通知商家付款方式變更

付款應用程式可以將 methodDetails 物件做為 PaymentRequestEvent.changePaymentMethod() 的選用第二個引數傳遞。這個物件可包含商家處理變更事件所需的各種付款方式詳細資料。

[付款處理常式] 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() 承諾會以 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;
…

使用物件更新前端的使用者介面。請參閱「反映更新後的付款詳情」。

通知商家運送地址已變更

付款應用程式可在付款交易中,將客戶的運送地址提供給商家。

這項功能對商家相當實用,因為商家可以將地址收集作業委派給付款應用程式。此外,由於地址資料會以標準資料格式提供,因此商家預期會收到結構一致的運送地址。

此外,客戶可以在偏好的付款應用程式註冊地址資訊,並重複用於不同的商家。

運送地址挑選器使用者介面
運送地址挑選器使用者介面

付款應用程式可提供使用者介面,以便編輯運送地址,或選取付款交易中客戶預先註冊的地址資訊。當系統暫時判定運送地址時,付款應用程式會通知商家已遮蓋的地址資訊。因此,商家可以享有多項好處:

  • 商家可以判斷客戶是否符合運送商品的區域限制 (例如僅限國內)。
  • 商家可根據運送地址的區域 (例如國際一般或快遞) 變更運送選項清單。
  • 商家可根據地址套用新的運費,並更新總價。

付款應用程式可以利用 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 做出回應。

[商家]

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);
});

商家回應後,傳回的承諾 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;
…

使用物件更新前端的使用者介面。請參閱「反映更新後的付款詳情」。

通知商家運送選項異動

運送選項是商家將所購商品出貨給消費者的運送方式。一般運送選項包括:

  • 免運費
  • 快速配送
  • 跨國運送
  • 優質國際運送

每種類型都有各自的成本。一般而言,更快的方法/選項會比較昂貴。

使用 Payment Request API 的商家可以將這個選擇委派給付款應用程式。付款應用程式可以使用這項資訊建構 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);
      …

商家會收到來自 PaymentRequest 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() 承諾會以 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;
…

使用物件更新前端的使用者介面。請參閱「反映更新後的付款詳情」。

顯示更新後的付款詳情

商家完成付款資料更新後,從 .changePaymentMethod().changeShippingAddress().changeShippingOption() 傳回的承諾就會使用常見的 PaymentRequestDetailsUpdate 物件解決。付款處理常式可以使用結果,將更新後的總價和運送選項反映在 UI 上。

商家傳回錯誤的可能原因如下:

  • 系統不接受這個付款方式。
  • 運送地址不在其支援地區內。
  • 運送地址含有無效的資訊。
  • 提供的運送地址或其他原因無法選取運送選項。

請使用下列屬性反映錯誤狀態:

  • error:使用者可理解的錯誤字串。這是向客戶顯示的最佳字串。
  • shippingAddressErrorsAddressErrors 物件,其中包含每個地址屬性的詳細錯誤字串。如果您要開啟表單,讓客戶編輯地址,而您必須直接指向無效欄位,這項功能就能派上用場。
  • paymentMethodErrors:付款方式專屬錯誤物件。您可以要求商家提供結構化錯誤,但 Web Payments 規格作者建議保留簡單字串。

程式碼範例

在本文件中,您看到的大部分程式碼範例均摘錄自下列有用的範例應用程式:

https://paymenthandler-demo.glitch.me

[付款處理常式] Service Worker

[付款處理常式] 前端

試用方法如下:

  1. 前往 https://paymentrequest-demo.glitch.me/
  2. 瀏覽至網頁底部。
  3. 按下「新增付款方式」按鈕
  4. 在「付款方式 ID」欄位中輸入 https://paymenthandler-demo.glitch.me
  5. 按一下欄位旁邊的「付款」按鈕