웹 기반 결제 앱을 웹 결제에 맞게 조정하고 고객에게 더 나은 사용자 환경을 제공하는 방법
결제 앱이 등록되면 판매자의 결제 요청을 수락할 수 있습니다. 이 게시물에서는 런타임 중에 서비스 워커에서 결제 트랜잭션을 오케스트레이션하는 방법을 설명합니다 (즉, 창이 표시되고 사용자가 창과 상호작용할 때).

'런타임 결제 매개변수 변경'은 사용자가 결제 핸들러와 상호작용하는 동안 판매자와 결제 핸들러가 메시지를 교환할 수 있도록 하는 일련의 이벤트를 말합니다. 서비스 워커로 선택적 결제 정보 처리하기에서 자세히 알아보세요.
판매자로부터 결제 요청 이벤트 수신
고객이 웹 기반 결제 앱으로 결제하기로 선택하고 판매자가 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 |
호출자의 출처를 나타내는 문자열입니다. 판매자가 결제 요청 API를 직접 호출하는 경우 topOrigin 과 동일할 수 있지만, 결제 게이트웨이와 같은 서드 파티가 iframe 내에서 API를 호출하는 경우에는 다를 수 있습니다.
|
paymentRequestId |
Payment Request API에 제공된 PaymentDetailsInit 의 id 속성입니다. 판매자가 생략하면 브라우저에서 자동 생성된 ID를 제공합니다.
|
methodData |
판매자가 PaymentMethodData 의 일부로 제공하는 결제 수단별 데이터입니다.
이를 사용하여 결제 거래 세부정보를 확인합니다.
|
total |
판매자가 PaymentDetailsInit 의 일부로 제공한 총 금액입니다.
이를 사용하여 고객에게 지불해야 할 총금액을 알리는 UI를 구성합니다.
|
instrumentKey |
사용자가 선택한 악기 키입니다. 이는 사전에 제공한 instrumentKey 을 반영합니다. 빈 문자열은 사용자가 악기를 지정하지 않았음을 나타냅니다.
|
결제 핸들러 창을 열어 웹 기반 결제 앱 프런트엔드 표시
paymentrequest
이벤트를 수신하면 결제 앱은 PaymentRequestEvent.openWindow()
을 호출하여 결제 핸들러 창을 열 수 있습니다. 결제 처리기 창에는 고객이 인증하고, 배송지 주소와 옵션을 선택하고, 결제를 승인할 수 있는 결제 앱의 인터페이스가 표시됩니다. 결제 프런트엔드에서 결제 처리 (출시 예정)에서 프런트엔드 코드를 작성하는 방법을 설명합니다.
나중에 결제 결과로 해결할 수 있도록 보존된 약속을 PaymentRequestEvent.respondWith()
에 전달합니다.
[결제 핸들러] 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
폴리필을 사용하여 임의의 타이밍에 프로미스를 해결할 수 있습니다.
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 });
}
프런트엔드에서 준비 신호 수신
결제 핸들러 창이 열리면 서비스 워커는 결제 앱 프런트엔드에서 전송되는 준비 상태 신호를 기다려야 합니다. 서비스 워커는 준비가 되면 중요한 정보를 프런트엔드에 전달할 수 있습니다.
[결제 핸들러] 프런트엔드:
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;
…
[결제 핸들러] 프런트엔드:
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 |
결제에 사용된 결제 수단 식별자입니다. |
details |
판매자가 결제를 처리하는 데 필요한 정보를 제공하는 결제 수단별 데이터입니다. |
[결제 핸들러] 프런트엔드:
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;
…
결제 거래 취소
고객이 거래를 취소할 수 있도록 프런트엔드는 서비스 워커에 POST 메시지를 전송하여 거래를 취소할 수 있습니다. 그러면 서비스 워커가 PaymentRequestEvent.respondWith()
에 전달된 프로미스를 null
로 확인하여 판매자에게 거래가 취소되었음을 알릴 수 있습니다.
[결제 핸들러] 프런트엔드:
postMessage('CANCEL_PAYMENT');
[결제 핸들러] 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;
…
샘플 코드
이 문서에 나온 모든 샘플 코드는 다음에서 발췌한 것입니다. 결제 핸들러 데모
다음 단계
이 도움말에서는 서비스 워커에서 결제 거래를 오케스트레이션하는 방법을 알아봤습니다. 다음 단계는 서비스 워커에 고급 기능을 추가하는 방법을 알아보는 것입니다.