如何將網頁版付款應用程式改用 Web Payments,為客戶提供更優質的使用者體驗。
註冊付款應用程式後,即可接受商家的付款要求。本文章會說明如何 在執行階段 (即 當使用者與視窗互動時)。
「執行階段付款參數變更」都代表一組事件 商家和付款處理常式,以便在使用者進行互動時交換訊息 與付款處理常式連結。如要進一步瞭解如何處理選用付款資訊,請參閱「使用服務工作者處理選用付款資訊」一文。
接收來自商家的付款要求事件
當消費者選擇使用您的網路付款應用程式付款,且商家叫用 PaymentRequest.show()
時,服務工作者就會收到 paymentrequest
事件。將事件監聽器新增至服務工作站,以便擷取事件並準備下一個動作。
[付款處理常式] service-worker.js:
…
let payment_request_event;
let resolver;
let client;
// `self` is the global object in service worker
self.addEventListener('paymentrequest', async e => {
if (payment_request_event) {
// If there's an ongoing payment transaction, reject it.
resolver.reject();
}
// Preserve the event for future use
payment_request_event = e;
…
保留的 PaymentRequestEvent
包含此交易的重要資訊:
屬性名稱 | 說明 |
---|---|
topOrigin |
用來指出頂層網頁來源 (通常是收款人商家) 的字串。請使用這個屬性來識別商家來源。 |
paymentRequestOrigin |
指出叫用者來源的字串。當商家直接叫用 Payment Request API 時,此值可能與 topOrigin 相同,但如果 API 是由付款閘道等第三方從 iframe 中叫用,則此值可能會與 topOrigin 不同。
|
paymentRequestId |
提供給 Payment Request API 的 PaymentDetailsInit 的 id 屬性。如果商家省略,瀏覽器會提供自動產生的 ID。
|
methodData |
商家在 PaymentMethodData 中提供的付款方式專屬資料。
用於判斷付款交易詳細資料。
|
total |
商家提供的 PaymentDetailsInit 總金額。請使用此項目建構 UI,告知客戶需支付的總金額。
|
instrumentKey |
使用者選取的樂器鍵。這反映了您先前提供的instrumentKey ,空白字串表示使用者未指定任何儀器。 |
開啟付款處理常式視窗,顯示以網頁為基礎的付款應用程式前端
收到 paymentrequest
事件時,支付應用程式可以呼叫 PaymentRequestEvent.openWindow()
來開啟支付處理常式視窗。付款處理程式視窗會向客戶顯示付款應用程式的介面,方便他們驗證身分、選擇運送地址和選項,以及授權付款。在「處理
付款前端 (即將推出)。
將已保留的承諾傳遞至 PaymentRequestEvent.respondWith()
,以便日後透過付款結果解決。
[payment handler] service-worker.js:
…
self.addEventListener('paymentrequest', async e => {
…
// Retain a promise for future resolution
// Polyfill for PromiseResolver is provided below.
resolver = new PromiseResolver();
// Pass a promise that resolves when payment is done.
e.respondWith(resolver.promise);
// Open the checkout page.
try {
// Open the window and preserve the client
client = await e.openWindow(checkoutURL);
if (!client) {
// Reject if the window fails to open
throw 'Failed to open window';
}
} catch (err) {
// Reject the promise on failure
resolver.reject(err);
};
});
…
您可以使用方便的 PromiseResolver
polyfill,在任意時間解析承諾。
class PromiseResolver {
constructor() {
this.promise_ = new Promise((resolve, reject) => {
this.resolve_ = resolve;
this.reject_ = reject;
})
}
get promise() { return this.promise_ }
get resolve() { return this.resolve_ }
get reject() { return this.reject_ }
}
與前端交換資訊
付款應用程式的服務工作者可以透過 ServiceWorkerController.postMessage()
與付款應用程式的前端交換訊息。為了接收訊息
監聽 message
事件。
[付款處理常式] service-worker.js:
// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
if (client) client.postMessage({ type, ...contents });
}
從前端接收就緒信號
付款處理常式視窗開啟後,Service Worker 會等候 付款應用程式前端的就緒狀態信號。服務工作者可在準備就緒時,將重要資訊傳遞至前端。
[付款處理常式] 前端:
navigator.serviceWorker.controller.postMessage({
type: 'WINDOW_IS_READY'
});
[付款處理常式] service-worker.js:
…
// Received a message from the frontend
self.addEventListener('message', async e => {
let details;
try {
switch (e.data.type) {
// `WINDOW_IS_READY` is a frontend's ready state signal
case 'WINDOW_IS_READY':
const { total } = payment_request_event;
…
將交易明細傳遞至前端
請傳送付款詳細資料。在這種情況下,您只需傳送付款要求的總金額,但您也可以傳送更多詳細資料。
[付款處理常式] service-worker.js:
…
// Pass the payment details to the frontend
postMessage('PAYMENT_IS_READY', { total });
break;
…
[payment handler] frontend:
let total;
navigator.serviceWorker.addEventListener('message', async e => {
switch (e.data.type) {
case 'PAYMENT_IS_READY':
({ total } = e.data);
// Update the UI
renderHTML(total);
break;
…
傳回客戶的付款憑證
當客戶授權付款時,前端可以向服務工作者傳送訊息,以便繼續進行。您可以解析傳遞給
PaymentRequestEvent.respondWith()
,以便將結果傳回商家。
傳送
PaymentHandlerResponse
物件。
屬性名稱 | 說明 |
---|---|
methodName |
用於付款的付款方式 ID。 |
details |
付款方式專屬資料,可提供商家處理付款所需的資訊。 |
[payment handler] frontend:
const paymentMethod = …
postMessage('PAYMENT_AUTHORIZED', {
paymentMethod, // Payment method identifier
});
[付款處理常式] service-worker.js:
…
// Received a message from the frontend
self.addEventListener('message', async e => {
let details;
try {
switch (e.data.type) {
…
case 'PAYMENT_AUTHORIZED':
// Resolve the payment request event promise
// with a payment response object
const response = {
methodName: e.data.paymentMethod,
details: { id: 'put payment credential here' },
}
resolver.resolve(response);
// Don't forget to initialize.
payment_request_event = null;
break;
…
取消付款交易
為讓消費者能夠取消交易,前端可以傳送郵件訊息給服務工作者,以便執行這項操作。服務工作者接著可以使用 null
解析傳遞至 PaymentRequestEvent.respondWith()
的承諾,向商家表明交易已取消。
[payment handler] frontend:
postMessage('CANCEL_PAYMENT');
[payment handler] service-worker.js:
…
// Received a message from the frontend
self.addEventListener('message', async e => {
let details;
try {
switch (e.data.type) {
…
case 'CANCEL_PAYMENT':
// Resolve the payment request event promise
// with null
resolver.resolve(null);
// Don't forget to initialize.
payment_request_event = null;
break;
…
程式碼範例
您在本文件中看到的所有程式碼範例,都是從以下可運作的範例應用程式中擷錄:
https://paymenthandler-demo.glitch.me
[付款處理常式] 服務工作人員
[付款處理常式] 前端
如要試用這項功能,請按照下列步驟操作:
- 前往 https://paymentrequest-demo.glitch.me/。
- 前往頁面底部。
- 按下「新增付款按鈕」。
- 在「付款方式 ID」欄位中輸入
https://paymenthandler-demo.glitch.me
。 - 按下欄位旁的「付款」按鈕。
後續步驟
在本文中,我們瞭解如何透過服務工作者協調付款交易。下一步是瞭解如何新增更多進階功能 Service Worker。