原文:Bring your payment method to the web with the Payment Handler API(需越牆)
做者:Eiji Kitamura
譯者:西樓聽雨
原文是谷歌開發者網站發佈的關於基於 Web 的標準化支付 API 系列文章之一。(轉載請註明出處)javascript
支付請求 API 爲瀏覽器帶來了一個開放的、標準化的用於處理支付請求的方式。經過一個簡單、快捷的用戶界面,便可採集到付款人的寄送信息、聯繫方式和支付憑據。html
而支付處理器 API 則爲支付方式提供商(譯註:即支付類的應用)打開了一個全新的生態。它可讓那些基於 Web 的支付類應用(採用 service worker 支撐)經過支付請求 API 將本身做爲一種支付方式整合到商家的網站中。java
從用戶角度看,它帶來的用戶體驗是這樣子的:git
視頻演示:v.youku.com/v_show/id_X…github
(譯註:下面是操做流程)web
你能夠用 Chrome 68 beta 版本在這裏嘗試下。api
注意,整個流程涉及到的三方有:終端用戶,商家網站,支付方式提供商。promise
對於商家的網站來講,要將一個支付應用整合進來,只需在支付請求 API 的第一個參數中的 supportedMethods
中將其添加進去(支付方法 ID)便可,同時能夠有選擇性地攜帶一個 data
數據。例如,要添加一個名叫 BobPay,支付方式 ID 爲https://bobpay.xyz/pay
的支付應用,其實現以下:瀏覽器
const request = new PaymentRequest([{
supportedMethods: 'https://bobpay.xyz/pay'
}], {
total: {
label: ‘總額’,
amount: { value: '10', currency: 'USD' }
}
});
複製代碼
若是能夠處理 BobPay 支付方式的 service worker 已經安裝,那麼這個支付應用就會出如今支付請求的界面中供用戶選擇。在某些狀況下,Chrome 還會跳過跳轉到支付處理商一塊的操做步驟,以此帶來一種輕快的支付體驗。app
Chrome 支持一個非標準的特性,咱們稱之爲 just-in-time (JIT) 安裝(譯註:即時安裝)。在咱們的這個例子中,這個特性可讓 BobPay 信任的支付處理器進行即時安裝,不須要用戶在事先有對 BobPay 網站進行過訪問。不過只有用戶在支付請求界面中明確選擇了 BobPay 做爲支付方式時纔會開始安裝;並且一種支付方式只能夠指定最多一個信任的支付處理方。
要開發一個支付請求處理器,咱們須要在除了實現支付處理器 API 以外再作一點額外的工做。
支付處理器 API 的關鍵點就是 Service Worker。你須要在你的支付應用網站上註冊一個 Service Worker 並在 ServiceWorkerRegistration
對象下的 paymentManger
中將支付指令添加進去。
if ('serviceWorker' in navigator) {
// 註冊一個 service worker
const registratoin = await navigator.serviceWorker.register(
// service worker 是一個單獨的 js 文件
'service-worker.js'
);
// 檢查支付處理器 API 是否可用
if (!registration.paymentManager) return;
registration.paymentManager.instruments.set(
// 支付指令的 key 但是任意字符串
"https://bobpay.xyz",
// 支付指令的詳情
{
name: '支付處理器示例',
method: 'https://bobpay.xyz/pay'
}
)
}
複製代碼
要處理支付請求,須要對在 service worker 中對 paymentrequest
進行監聽;而後當咱們收到這樣一個事件時,打開一個窗口並等待其在用戶受權進行支付以後返回一個支付憑據。
const origin = 'https://bobpay.xyz';
const methodName = `${origin}/pay`;
const checkoutURL = `${origin}/checkout`;
let resolver;
let payment_request_event;
self.addEventListener('paymentrequest', e => {
// 保存這個事件,以便以後使用
payment_request_event = e;
// 另外你還須要提供一個 `PromiseResolver` 墊片,
// 由於目前 Chrome 還未實現
resolver = new PromiseResolver();
e.respondWith(resolver.promise);
e.openWindow(checkoutURL).then(client => {
if (client === null) {
resolver.reject('Failed to open window');
}
}).catch(err => {
resolver.reject(err);
});
});
self.addEventListener('message', e => {
console.log('A message received:', e);
if (e.data === "payment_app_window_ready") {
sendPaymentRequest();
return;
}
if (e.data.methodName === methodName) {
resolver.resolve(e.data);
} else {
resolver.reject(e.data);
}
});
const sendPaymentRequest = () => {
if (!payment_request_event) return;
clients.matchAll({
includeUncontrolled: false,
type: 'window'
}).then(clientList => {
for (let client of clientList) {
client.postMessage(payment_request_event.total);
}
});
}
複製代碼
由於支付處理器 API 的設計理念就是保持最大的靈活性,以支持任意類型的支付方式,因此它所支持的包含了:
(譯註:如下連接均需越牆)