Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 명세서는 웹 애플리케이션이 결제 요청을 처리할 수 있도록 하는 기능을 정의합니다.
이 섹션은 이 문서가 게시될 당시의 상태를 설명합니다. 현재 W3C 출판물 목록과 이 기술 보고서의 최신 개정본은 W3C 표준 및 초안 색인에서 찾을 수 있습니다.
웹 결제 작업 그룹은 그룹이 아직 처리하지 않은 모든 버그 보고서 목록을 유지합니다. 이 초안은 작업 그룹에서 여전히 논의되어야 하는 일부 보류 중인 문제를 강조합니다. 이러한 문제들의 결과(유효성 여부 포함)에 대해 어떠한 결정도 내려지지 않았습니다. 미해결 문제에 대해 제안된 명세 텍스트가 포함된 풀 리퀘스트 제출을 적극 권장합니다.
이 문서는 Web Payments Working Group에 의해 권고 경로(Recommendation track)를 사용하여 작업 초안으로 게시되었습니다.
작업 초안으로서의 게시가 W3C와 그 구성원의 승인(endorsement)을 의미하지는 않습니다.
이 문서는 초안이며 언제든지 업데이트, 교체 또는 다른 문서에 의해 대체될 수 있습니다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 적절하지 않습니다.
이 문서는 다음의 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C 특허 정책에 따라 제작되었습니다.
W3C는 그룹의 산출물과 관련하여 이루어진 특허 공개의 공개 목록을 유지합니다. 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 개인이 본인이 핵심 청구항(Essential Claim(s))을 포함한다고 믿는 특허에 대해 실제로 알고 있는 경우, 해당 정보는 W3C 특허 정책의 섹션 6에 따라 공개해야 합니다.
이 문서는 2025년 8월 18일 W3C 프로세스 문서에 의해 규율됩니다.
이 섹션은 비규범적입니다.
이 명세서는 웹 애플리케이션이 사용자를 대신하여 결제 요청을 처리할 수 있도록 허용하는 여러 새로운 기능을 정의합니다:
PaymentRequestEvent). 결제 핸들러는 PaymentRequestEvent에 대한 이벤트 핸들러입니다.
PaymentManager)으로 결제 핸들러의 속성을 관리합니다.
PaymentRequestEvent에
응답하는 메커니즘.
이 명세서는 운영체제 특정 메커니즘(예: "네이티브 앱")으로 구축된 소프트웨어가 결제 요청을 어떻게 처리하는지는 다루지 않습니다.
이 문서에서는 다음과 같은 흐름을 상정합니다:
PaymentRequestEvent를 (사용자 상호작용 작업 소스에 따라) 해당
결제 핸들러의 서비스
워커에 발생시킵니다. PaymentRequestEvent에는
PaymentRequest([payment-request])의 일부 정보와 추가 정보(예: 수취인의 출처)가 포함됩니다.
하나의 출처는 둘 이상의 서비스 워커로 결제 앱을 구현할 수 있으므로, 출처당 여러 결제 핸들러가 등록될 수 있습니다. 호출되는 핸들러는 사용자가 선택한 항목에 따라 결정됩니다.
이 섹션은 비규범적입니다.
결제 핸들러는 사용자를 대신하여 결제 요청을 처리할 수 있는 웹 애플리케이션입니다.
결제 핸들러의 동작은 지원하는 결제 수단에 의해 좌우됩니다. 일부 결제 수단은 결제 핸들러가 거의 처리할 필요 없이 응답에 결제 카드 정보를 반환하도록 기대합니다. 그런 경우 수취인 웹사이트가 반환된 데이터를 입력으로 사용하여 결제를 처리하는 역할을 합니다.
반면 암호화폐 결제나 은행 이체와 같은 일부 결제 수단은 결제 핸들러가 결제 처리를 시작하도록 요구합니다. 이러한 경우 결제 핸들러는 결제 참조, 엔드포인트 URL 또는 수취인 웹사이트가 결제 결과를 판단하는 데 사용할 수 있는 기타 데이터를 반환합니다(결제를 직접 처리하는 대신).
결제 요청 처리에는 새 창을 통한 사용자와의 상호작용이나 Web Cryptography API와 같은 다른 API, 또는 웹 요청이나 기타 수단을 통한 다른 서비스 및 출처와의 상호작용 등 수많은 상호작용이 포함될 수 있습니다.
이 명세서는 PaymentRequestEvent를 결제
핸들러가 수락한 이후부터 결제 핸들러가 응답을 반환할 때까지 발생하는 활동들을 다루지 않습니다. 결제 핸들러를 구성하고 결제 요청을 처리하는 데 필요할 수 있는 모든 이러한 활동은 결제
핸들러 구현에 맡깁니다. 예를 들어:
따라서 출처는 라이프사이클 관리, 보안, 사용자 인증, 사용자 상호작용 등 다른 여러 웹 기술에 의존하게 됩니다.
이 섹션은 비규범적입니다.
이 명세서는 서드파티 모바일 결제 앱이 사용자 에이전트와 독점적 메커니즘을 통해 어떻게 상호작용하는지, 또는 사용자 에이전트 자체가 간단한 결제 앱 기능을 어떻게 제공하는지는 다루지 않습니다.
결제 핸들러는 즉시 설치(Just-in-time, JIT) 등록 메커니즘을 통해 사용자 에이전트에 등록됩니다.
결제 핸들러가 상인이 show()
메서드를 호출할 때 등록되어 있지 않다면, 사용자 에이전트는 거래 중에 사용자가 이 결제 핸들러를 등록하도록 허용할 수 있습니다("즉시").
이 섹션의 나머지 내용은 비규범적입니다.
사용자 에이전트는 상인이 요청한 URL 기반 결제 수단 식별자(URL-based payment method identifier)를 통해 찾은 payment method manifest로부터 결제 핸들러 정보를 유도하여 즉시 설치를 수행할 수 있습니다.
이 섹션은 결제 핸들러가 자체 속성을 관리하는 데 사용할 수 있는 기능을 설명합니다.
WebIDLpartial interface ServiceWorkerRegistration {
[SameObject] readonly attribute PaymentManager paymentManager;
};
paymentManager 속성은 결제 핸들러 관리 기능을 노출합니다.
WebIDL[SecureContext, Exposed=(Window)]
interface PaymentManager {
attribute DOMString userHint;
Promise<undefined> enableDelegations(sequence<PaymentDelegation> delegations);
};
PaymentManager는 결제 핸들러가 지원하는
delegation을 관리하는 데 사용됩니다.
결제 핸들러 이름과 아이콘을 표시할 때, 사용자 에이전트는 이 문자열을 사용하여 사용자 경험을 개선할 수 있습니다. 예를 들어 "**** 1234" 같은 user hint는 특정 카드가 이 결제 핸들러를 통해 제공된다는 것을 사용자에게 상기시켜 줄 수 있습니다.
이 메서드는 결제 핸들러가 비동기적으로 지원하는 PaymentDelegation 목록을 선언할 수 있게 합니다.
WebIDLenum PaymentDelegation {
"shippingAddress",
"payerName",
"payerPhone",
"payerEmail"
};
shippingAddress"
payerName"
payerPhone"
payerEmail"
결제 핸들러가 CanMakePaymentEvent를 지원하는
경우,
사용자
에이전트는 사용 가능한
결제 핸들러를 필터링하는 데 이를 사용할 수 있습니다.
구현에서는 개발자가
CanMakePaymentEvent에 응답할 수 있도록
타임아웃을 부과할 수 있습니다. 타임아웃이 만료되면,
구현은 respondWith()가
false로 호출된 것처럼 동작합니다.
WebIDLpartial interface ServiceWorkerGlobalScope {
attribute EventHandler oncanmakepayment;
};
oncanmakepayment
속성은
해당하는 이벤트 핸들러
이벤트 타입이
"canmakepayment"인 이벤트 핸들러입니다.
CanMakePaymentEvent는
결제 핸들러가 결제 요청에 응답할 수 있는지 여부를 나타내는 신호로 사용됩니다.
WebIDL[Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
constructor(DOMString type);
undefined respondWith(Promise<boolean> canMakePaymentResponse);
};
이 메서드는 결제 핸들러가 결제 요청에 응답할 수 있는지 여부를 알리는 신호로 사용됩니다.
PaymentRequest를 수신하면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:
CanMakePaymentEvent 사용을 금지하는 경우(예: 사생활
보호 모드),
이 단계를 종료합니다.
ServiceWorkerRegistration으로
둡니다.
기능 이벤트 발생
"canmakepayment"를
CanMakePaymentEvent를 사용해
registration에서 수행합니다.
CanMakePaymentEvent 처리 예시
이 섹션은 비규범적입니다.
이 예시는
CanMakePaymentEvent를 수신하는
서비스 워커를 작성하는 방법을 보여줍니다. CanMakePaymentEvent가
수신되면, 서비스 워커는 항상 true를 반환합니다.
self.addEventListener("canmakepayment", function(e) {
e.respondWith(new Promise(function(resolve, reject) {
resolve(true);
}));
});
PaymentMethodData와
결제 수단 식별자와 일치하는
결제 핸들러가 주어졌을 때, 이 알고리즘은 해당 결제 핸들러를 결제에 사용할 수 있으면
true를 반환합니다:
ServiceWorkerRegistration
scope URL의 origin으로 둡니다.
"*" 문자열이 있다면, true를 반환합니다.
CanMakePaymentEvent를 발생시키고 그 결과를 반환합니다.
CanMakePaymentEvent를 발생시키고 결과를 반환합니다.
false를 반환합니다.
사용자가 결제 핸들러를 선택하면, 사용자 에이전트는
PaymentRequestEvent를 발생시키고,
이어지는 PaymentHandlerResponse를 사용하여
[payment-request]의
PaymentResponse를 생성합니다.
Payment Request API는 결제 앱에 대한 중단(abort) 관리 책임의 위임을 지원합니다. Payment Handler 인터페이스에 paymentRequestAborted 이벤트를 추가하는 제안이 있습니다. 이 이벤트에는 paymentRequest가 성공적으로 중단되었는지를 나타내는 불리언 매개변수를 받는 respondWith 메서드가 포함될 것입니다.
ServiceWorkerGlobalScope
의 확장
이 명세는
ServiceWorkerGlobalScope
인터페이스를 확장합니다.
WebIDLpartial interface ServiceWorkerGlobalScope {
attribute EventHandler onpaymentrequest;
};
onpaymentrequest
속성은 이벤트 핸들러이며,
해당 이벤트 핸들러
이벤트 타입은
PaymentRequestEvent입니다.
PaymentRequestDetailsUpdate는 갱신된 총액(선택적으로 modifier와 배송 옵션 포함)과
결제 핸들러 내에서 사용자가 결제 수단, 배송 주소 또는 배송 옵션을 선택한 결과로 발생할 수 있는
에러를 포함합니다.
WebIDLdictionary PaymentRequestDetailsUpdate {
DOMString error;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
sequence<PaymentShippingOption> shippingOptions;
object paymentMethodErrors;
AddressErrors shippingAddressErrors;
};
사용자가 선택한 결제 수단, 배송 주소 또는 배송 옵션을 사용할 수 없는 이유를 설명하는 사람이 읽을 수 있는 문자열입니다.
변경된 결제 수단, 배송 주소 또는 배송 옵션을 기반으로 갱신된 총액입니다. 예를 들어 사용자가 선택한 결제 수단의 청구지 주소 때문에 부가가치세(VAT)가 바뀌거나, 사용자가 선택/제공한 배송 옵션/주소 때문에 배송비가 바뀔 수 있습니다.
변경된 결제 수단, 배송 주소 또는 배송 옵션을 기반으로 갱신된 modifiers입니다. 예를 들어 청구지 또는 배송 주소를 기반으로 전체 합계가 €1.00 증가했다면, 각 modifier에 지정된 합계도 €1.00 증가해야 합니다.
변경된 배송 주소를 기반으로 갱신된 shippingOptions입니다. 예를 들어, 사용자 제공 국가에서는 빠른 배송이 더 비싸거나 사용 불가능할 수 있습니다.
해당하는 경우, 결제 수단에 대한 검증 오류입니다.
해당하는 경우, 배송 주소에 대한 검증 오류입니다.
PaymentRequestEvent는 사용자가 선택한 이후 결제 핸들러에서 사용할 수 있는 데이터와 메서드를 나타냅니다. 사용자 에이전트는 PaymentRequest에서 사용 가능한 데이터의 하위 집합을 결제 핸들러에 전달합니다.
WebIDL[Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
constructor(DOMString type, optional PaymentRequestEventInit eventInitDict = {});
readonly attribute USVString topOrigin;
readonly attribute USVString paymentRequestOrigin;
readonly attribute DOMString paymentRequestId;
readonly attribute FrozenArray<PaymentMethodData> methodData;
readonly attribute object total;
readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
readonly attribute object? paymentOptions;
readonly attribute FrozenArray<PaymentShippingOption>? shippingOptions;
Promise<WindowClient?> openWindow(USVString url);
Promise<PaymentRequestDetailsUpdate?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
Promise<PaymentRequestDetailsUpdate?> changeShippingAddress(optional AddressInit shippingAddress = {});
Promise<PaymentRequestDetailsUpdate?> changeShippingOption(DOMString shippingOption);
undefined respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};
최상위 origin을 나타내는 문자열을 반환합니다. 이는 최상위 수취인 웹 페이지의 origin입니다. 이 속성은 PaymentRequestEvent 처리에 의해 초기화됩니다.
PaymentRequest가
초기화된 origin을 나타내는 문자열을
반환합니다.
PaymentRequest가
topOrigin에서 초기화된 경우,
두 속성의 값은 같고, 그렇지 않으면 서로 다릅니다.
예를 들어 PaymentRequest가
topOrigin이 아닌 origin의 iframe
내에서
초기화된 경우, 이 속성 값은 해당 iframe의 origin입니다. 이 속성은
PaymentRequestEvent 처리에 의해 초기화됩니다.
가져올 때, paymentRequestId
속성은 이 PaymentRequestEvent에 대응하는
PaymentRequest의
[[details]].id를 반환합니다.
이 속성에는 웹 사이트가 수락하는 결제 수단 식별자를 포함하는 PaymentMethodData 딕셔너리들과, 관련된 결제 수단별 데이터가 포함됩니다. 이는 아래에 정의된 MethodData 채우기 알고리즘을 사용하여 PaymentRequest로부터 채워집니다.
이 속성은 결제를 위해 요청되는 총액을 나타냅니다. 이는
[payment-request]에 정의된
PaymentCurrencyAmount
딕셔너리 타입이며, 해당
PaymentRequest 객체가
생성될 때 제공된
total 필드의 복사본으로 초기화됩니다.
이 PaymentDetailsModifier 딕셔너리의 시퀀스는 특정 결제 수단 식별자에 대한 modifier들을 포함합니다(예: 결제 수단에 따라 결제 금액이나 통화가 달라지는 경우). 이는 아래에 정의된 Modifiers 채우기 알고리즘을 사용하여 PaymentRequest로부터 채워집니다.
PaymentOptions의 값입니다. 배송 주소 및/또는 지불자의 연락처 정보의 일부가 요청된 경우에만 사용할 수 있습니다. 이 값은 PaymentRequest에서 가져옵니다.
해당 PaymentRequest의 PaymentDetailsInit 딕셔너리에 있는 ShippingOptions의 값입니다. (PaymentDetailsInit은 PaymentDetailsBase로부터 ShippingOptions를 상속합니다). 배송 주소가 요청된 경우에만 사용할 수 있습니다.
이 메서드는 결제 핸들러가 사용자에게 창을 표시하는 데 사용됩니다. 호출되면 창 열기 알고리즘을 실행합니다.
이 메서드는 결제 핸들러가 청구지 주소와 같은 결제 수단 세부 정보가 주어졌을 때 갱신된 총액을 얻는 데 사용됩니다. 호출되면 결제 수단 변경 알고리즘을 실행합니다.
이 메서드는 결제 핸들러가 shippingAddress가 주어졌을 때 갱신된 결제 상세 정보를 얻는 데 사용됩니다. 호출되면 결제 상세 변경 알고리즘을 실행합니다.
이 메서드는 결제 핸들러가 shippingOption 식별자가 주어졌을 때 갱신된 결제 상세 정보를 얻는 데 사용됩니다. 호출되면 결제 상세 변경 알고리즘을 실행합니다.
이 메서드는 결제가 성공적으로 완료되었을 때
PaymentHandlerResponse를 제공하는 데 사용됩니다.
호출되면, event와 handlerResponsePromise를 인수로 하여
PaymentRequest에 응답하는 알고리즘을 실행합니다.
사용자 에이전트에 저장된 사용자 데이터를, 사용자의 명시적 동의를 받아 결제 앱이 수신해야 할까요? 결제 앱은 설치 시점 또는 최초 호출 시점에 권한을 요청할 수 있습니다.
WebIDLdictionary PaymentRequestEventInit : ExtendableEventInit {
USVString topOrigin;
USVString paymentRequestOrigin;
DOMString paymentRequestId;
sequence<PaymentMethodData> methodData;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
PaymentOptions paymentOptions;
sequence<PaymentShippingOption> shippingOptions;
};
topOrigin,
paymentRequestOrigin,
paymentRequestId,
methodData,
total,
modifiers,
paymentOptions,
그리고 shippingOptions
멤버들은
PaymentRequestEvent에 대해 정의된 것들과
동일한 정의를 공유합니다.
methodData의 값을 초기화하기 위해,
사용자 에이전트는 다음 단계(또는 그에 상응하는 단계)를 MUST 수행합니다:
methodData를
dataList로 설정합니다.
modifiers의 값을 초기화하기 위해,
사용자 에이전트는 다음 단계(또는 그에 상응하는 단계)를 MUST 수행합니다:
modifiers의
각 항목에 대해 다음 단계를 수행합니다:
total을
inModifier.total의 복사본으로 설정합니다.
modifiers를
modifierList로 설정합니다.
PaymentRequestEvent의
인스턴스는
다음 표의 내부 슬롯들과 함께 생성됩니다:
| 내부 슬롯 | 기본값 | 설명 (비규범적) |
|---|---|---|
| [[windowClient]] | null | 현재 활성 WindowClient입니다. 결제 핸들러가 현재 사용자에게 창을 표시 중이라면 설정됩니다. 그렇지 않으면 null입니다. |
| [[respondWithCalled]] | false | YAHO |
PaymentRequest가 PaymentRequest.show()에 의해 전달되고, 이후 사용자가 결제 핸들러를 선택하면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:
ServiceWorkerRegistration으로
둡니다.
Promise를
"InvalidStateError"
DOMException과 함께 거부하고,
이 단계를 종료합니다. 이 Promise는
PaymentRequest.show()에 의해 생성된 것입니다.
다음 속성들과 함께 registration에서
기능 이벤트 발생
"paymentrequest"를
PaymentRequestEvent를 사용해 수행합니다:
topOrigin
paymentRequestOrigin
methodData
modifiers
total
paymentRequestId
paymentOptions
shippingOptions
그런 다음, dispatchedEvent에 대해 다음 단계를 병렬로 실행합니다:
PaymentHandlerResponse를 제공하지
않았다면,
PaymentRequest.show()에 의해
생성된
Promise를
"OperationError"
DOMException과
함께 거부합니다.
호출된 결제 핸들러는 자체 정보 표시나 사용자 입력 요청이 필요할 수도, 필요하지 않을 수도 있습니다. 가능한 결제 핸들러 표시의 예시는 다음과 같습니다:
시각적 표시 및 사용자 상호작용이 필요한 결제 핸들러는 사용자를 위한 페이지를 표시하기 위해 openWindow()를 호출할 수 있습니다.
사용자 에이전트는 이 메서드가
PaymentRequestEvent와
연결되어 있음을 알고 있으므로,
흐름과 일관되고 사용자에게 혼란을 주지 않는 방식으로 창을 SHOULD 렌더링해야 합니다. 생성된
윈도우 클라이언트는 PaymentRequest를 시작한 탭/창에
바인딩됩니다. 단일 결제 핸들러는 이 메서드를 사용하여 둘 이상의 클라이언트 창을 열어서는
SHOULD NOT 합니다.
단계를 복사하는 대신 Service Workers 명세를 참조해야 할까요?
PaymentRequestEvent로 둔다.
isTrusted 속성이
false이면,
"InvalidStateError"
DOMException으로 거부된
Promise를 반환한다.
PaymentRequestEvent를 트리거한
PaymentRequest로 둔다.
Promise를 반환한다.
about:blank이면,
TypeError로 거부된
Promise를 반환한다.
Promise를 null로 이행하여 반환한다.
Promise로 둔다.
[[windowClient]]가 null이
아니면:
[[windowClient]].visibilityState
가 "unloaded"가 아니면, promise를
"InvalidStateError"
DOMException으로
거부하고 이 단계를 중단한다.
[[windowClient]]를
client로 설정한다.
PaymentRequestEvent
처리 예시
이 섹션은 비규범적입니다.
이 예시는
PaymentRequestEvent를
수신하는 서비스 워커를 작성하는 방법을 보여줍니다.
PaymentRequestEvent가
수신되면,
서비스 워커는 사용자와 상호작용하기 위해 창을 엽니다.
async function getPaymentResponseFromWindow() {
return new Promise((resolve, reject) => {
self.addEventListener("message", listener = e => {
self.removeEventListener("message", listener);
if (!e.data || !e.data.methodName) {
reject();
return;
}
resolve(e.data);
});
});
}
self.addEventListener("paymentrequest", e => {
e.respondWith((async() => {
// Open a new window for providing payment UI to user.
const windowClient = await e.openWindow("payment_ui.html");
// Send data to the opened window.
windowClient.postMessage({
total: e.total,
modifiers: e.modifiers
});
// Wait for a payment response from the opened window.
return await getPaymentResponseFromWindow();
})());
});
위에서 설명한 간단한 방식으로, 결제 핸들러 창에 로드되는 아주 간단한 HTML 페이지는 다음과 같을 수 있습니다:
<form id="form">
<table>
<tr><th>Cardholder Name:</th><td><input name="cardholderName"></td></tr>
<tr><th>Card Number:</th><td><input name="cardNumber"></td></tr>
<tr><th>Expiration Month:</th><td><input name="expiryMonth"></td></tr>
<tr><th>Expiration Year:</th><td><input name="expiryYear"></td></tr>
<tr><th>Security Code:</th><td><input name="cardSecurityCode"></td></tr>
<tr><th></th><td><input type="submit" value="Pay"></td></tr>
</table>
</form>
<script>
navigator.serviceWorker.addEventListener("message", e => {
/* Note: message sent from payment app is available in e.data */
});
document.getElementById("form").addEventListener("submit", e => {
const details = {};
["cardholderName", "cardNumber", "expiryMonth", "expiryYear", "cardSecurityCode"]
.forEach(field => {
details[field] = form.elements[field].value;
});
const paymentAppResponse = {
methodName: "https://example.com/pay",
details
};
navigator.serviceWorker.controller.postMessage(paymentAppResponse);
window.close();
});
</script>
WebIDLdictionary PaymentHandlerResponse {
DOMString methodName;
object details;
DOMString? payerName;
DOMString? payerEmail;
DOMString? payerPhone;
AddressInit shippingAddress;
DOMString? shippingOption;
};
상인이 거래를 처리하고 자금 이체의 성공 여부를 결정하는 데 사용하는, 결제 수단별 메시지를 제공하는 JSON으로 직렬화 가능한 객체입니다.
사용자 에이전트는 해당
PaymentRequestEvent
인터페이스의 respondWith 함수에 제공된
Promise의 이행을 통해 결제 핸들러로부터 성공적인 응답을 받습니다. 애플리케이션은 결제 응답을 포함하는
PaymentHandlerResponse 인스턴스로
해당 Promise를 이행해야 합니다. 사용자가 취소하거나 오류가 발생한 경우, 애플리케이션은 Promise를 거부하여 실패를 알릴 수 있습니다.
Promise가 거부되면, 사용자 에이전트는 MUST 결제 앱 실패 알고리즘을 실행해야 합니다. 이 알고리즘의 정확한 세부사항은 구현자에게 맡깁니다. 허용 가능한 동작에는 다음이 포함되나 이에 국한되지는 않습니다:
사용자가 제공한 지불자 이름입니다.
사용자가 제공한 지불자 이메일입니다.
사용자가 제공한 지불자 전화번호입니다.
사용자가 제공한 배송 주소입니다.
사용자가 선택한 배송 옵션의 식별자입니다.
이 알고리즘이 methodName 및 methodDetails 매개변수와 함께 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:
null을 반환한다.
InvalidStateError"
DOMException을 던진다.
PaymentRequestDetailsUpdate를
구성하여 반환한다.
이 알고리즘이 shippingAddress 또는 shippingOption과 함께 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:
null을 반환한다.
InvalidStateError"
DOMException을 던진다.
PaymentRequestDetailsUpdate를
구성하여 반환한다.
이 알고리즘이 event 및 handlerResponsePromise 매개변수와 함께 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:
isTrusted가 false이면,
"InvalidStateError"
DOMException을 던지고
이 단계를 중단한다.
InvalidStateError"
DOMException을 던지고
이 단계를 중단한다.
[[respondWithCalled]]가 true이면,
"InvalidStateError"
DOMException을 던지고
이 단계를 중단한다.
[[respondWithCalled]]를 true로 설정한다.
PaymentHandlerResponse로 둔다.
변환이 예외를 던지면, 결제 앱 실패 알고리즘을
실행하고 이 단계를 종료한다.
methodName이
없거나 event의
methodData의
값들 중 하나로 설정되어 있지 않으면,
결제 앱 실패 알고리즘을 실행하고 이 단계를 종료한다.
details가
없거나
JSON으로 직렬화
가능하지 않으면,
결제 앱
실패 알고리즘을 실행하고 이 단계를 종료한다.
shippingAddress가
없으면,
결제 앱 실패
알고리즘을 실행하고
이 단계를 종료한다.
shippingOption이
없거나
event의
shippingOptions의
배송 옵션 식별자들 중 하나로 설정되어 있지 않으면,
결제
앱 실패 알고리즘을 실행하고 이 단계를 종료한다.
payerName이
없으면,
결제
앱 실패 알고리즘을 실행하고 이 단계를 종료한다.
payerEmail이
없으면,
결제
앱 실패 알고리즘을 실행하고 이 단계를 종료한다.
payerPhone이
없으면,
결제
앱 실패 알고리즘을 실행하고 이 단계를 종료한다.
다음 예시는 결제 요청에 응답하는 방법을 보여줍니다:
paymentRequestEvent.respondWith(new Promise(function(accept,reject) {
/* ... processing may occur here ... */
accept({
methodName: "https://example.com/pay",
details: {
cardHolderName: "John Smith",
cardNumber: "1232343451234",
expiryMonth: "12",
expiryYear : "2020",
cardSecurityCode: "123"
},
shippingAddress: {
addressLine: [
"1875 Explorer St #1000",
],
city: "Reston",
country: "US",
dependentLocality: "",
organization: "",
phone: "+15555555555",
postalCode: "20190",
recipient: "John Smith",
region: "VA",
sortingCode: ""
},
shippingOption: "express",
payerEmail: "john.smith@gmail.com",
});
}));
[payment-request]는 생태계의 당사자(결제 앱 제공자 및 수취인 포함)가 네트워크 또는 기타 오류 이후에 정합을 위해 사용할 수 있는 ID를 정의합니다.
Web Payments 워킹 그룹은 개인정보 보호 이슈로 인해 Payment Request API의 원래 버전에서 배송지와 청구지 주소 지원을 제거했습니다. 자세한 내용은 issue 842를 참조하십시오. 여전히 이 기능을 지원하는 구현을 위한 문서를 제공하기 위해, 워킹 그룹은 개인정보 이슈에 대응할 것을 전제로 이 기능을 복구하고 있습니다. 이 과정에서 워킹 그룹은 다른 API(예: Content Picker API)의 발전을 바탕으로 Payment Request API에 변경을 가할 수도 있습니다.
CanMakePaymentEvent가 발생합니다.
이 이벤트는 사용자가 해당 결제 핸들러를 선택하기 전에 발생하지만, 트리거한 출처(즉, 상점 웹사이트)에 대한 정보를
포함하지 않으므로 사용자를 직접 추적하는 데 사용할 수 없습니다.
CanMakePaymentEvent를 통한 타이밍 공격의
위험을 인지합니다:
CanMakePaymentEvent를 트리거합니다.
CanMakePaymentEvent 지원을 비활성화할 수 있도록
허용해야 합니다.
CanMakePaymentEvent가 발생합니다.
CanMakePaymentEvent 이벤트는 사생활 보호
모드에서 발생해서는 안 합니다. 사용자 에이전트는
respondWith()가
false로 호출된 것처럼 동작해야 합니다. 한 가지 수반되는 위험을 인지합니다: 동일한 엔티티가 Payment
Request API 호출의 출처와 결제 핸들러의 출처를 모두 제어하는 경우, 사용자가 사생활 보호 모드에 있을 가능성을
추론할 수 있습니다.
이 섹션은 비규범적입니다.
결제 핸들러의 순서를 정할 때, 사용자 에이전트는 다른 어떤 선호도보다 사용자 선호도를 우선시하는 것이 바람직합니다. 사용자 에이전트는 특정 출처 또는 모든 출처에 대해 선호하는 결제 핸들러 표시 순서를 설정하는 등의 수동 구성 옵션을 허용하는 것이 기대됩니다.
사용자 경험에 관한 세부사항은 구현자에게 맡깁니다.
이 명세는 여러 다른 기반 명세에 의존합니다.
JSON.stringify
는
[ECMASCRIPT]에 의해 정의됩니다.
ServiceWorkerRegistration,
ServiceWorkerGlobalScope,
fire
functional event, extend
lifetime
promises,pending
promises
count, containing
service worker registration,
Try
Clear Registration, Try
Activate,
ExtendableEvent,
ExtendableEventInit,
그리고 scope URL
은 [SERVICE-WORKERS]에 정의되어 있습니다.
비규범적으로 표시된 섹션들뿐 아니라, 이 명세의 모든 저작 가이드라인, 다이어그램, 예시, 그리고 주석은 비규범적입니다. 그 외의 모든 내용은 규범적입니다.
본 문서에서 MAY, MUST, SHOULD, SHOULD NOT과 같은 핵심 용어는 BCP 14 [RFC2119] [RFC8174] 에서 설명된 대로, 그리고 여기에서처럼 전부 대문자로 나타날 때에만 해당 의미로 해석되어야 합니다.
이 명세에 대한 적합성을 주장할 수 있는 제품 클래스는 단 하나입니다: 사용자 에이전트.
사용자 에이전트는 이 명세에 제시된 알고리즘과 구별할 수 없는 동일한 결과를 산출하는 한, 어떤 방식으로든 이 명세의 알고리즘을 구현할 MAY 있습니다.
사용자 에이전트는 서비스 거부 공격을 방지하거나, 메모리 부족을 방지하거나, 플랫폼 고유의 한계를 우회하기 위해, 원래는
제한되지 않은 입력에 대해 구현별 한계를 부과할 MAY 있습니다. 입력이 구현별 한계를 초과하는
경우, 사용자 에이전트는 MUST 예외를 던지거나, 프로미스의 문맥에서는
TypeError로 거부하면서,
특정 입력이 구현별 한계를 어떻게 초과했는지 개발자에게 선택적으로 알릴 수 있습니다.
WebIDLpartial interface ServiceWorkerRegistration {
[SameObject] readonly attribute PaymentManager paymentManager;
};
[SecureContext, Exposed=(Window)]
interface PaymentManager {
attribute DOMString userHint;
Promise<undefined> enableDelegations(sequence<PaymentDelegation> delegations);
};
enum PaymentDelegation {
"shippingAddress",
"payerName",
"payerPhone",
"payerEmail"
};
partial interface ServiceWorkerGlobalScope {
attribute EventHandler oncanmakepayment;
};
[Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
constructor(DOMString type);
undefined respondWith(Promise<boolean> canMakePaymentResponse);
};
partial interface ServiceWorkerGlobalScope {
attribute EventHandler onpaymentrequest;
};
dictionary PaymentRequestDetailsUpdate {
DOMString error;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
sequence<PaymentShippingOption> shippingOptions;
object paymentMethodErrors;
AddressErrors shippingAddressErrors;
};
[Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
constructor(DOMString type, optional PaymentRequestEventInit eventInitDict = {});
readonly attribute USVString topOrigin;
readonly attribute USVString paymentRequestOrigin;
readonly attribute DOMString paymentRequestId;
readonly attribute FrozenArray<PaymentMethodData> methodData;
readonly attribute object total;
readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
readonly attribute object? paymentOptions;
readonly attribute FrozenArray<PaymentShippingOption>? shippingOptions;
Promise<WindowClient?> openWindow(USVString url);
Promise<PaymentRequestDetailsUpdate?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
Promise<PaymentRequestDetailsUpdate?> changeShippingAddress(optional AddressInit shippingAddress = {});
Promise<PaymentRequestDetailsUpdate?> changeShippingOption(DOMString shippingOption);
undefined respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};
dictionary PaymentRequestEventInit : ExtendableEventInit {
USVString topOrigin;
USVString paymentRequestOrigin;
DOMString paymentRequestId;
sequence<PaymentMethodData> methodData;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
PaymentOptions paymentOptions;
sequence<PaymentShippingOption> shippingOptions;
};
dictionary PaymentHandlerResponse {
DOMString methodName;
object details;
DOMString? payerName;
DOMString? payerEmail;
DOMString? payerPhone;
AddressInit shippingAddress;
DOMString? shippingOption;
};
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: