서비스 워커로 선택적 결제 정보 처리

웹 기반 결제 앱을 웹 결제에 맞게 조정하고 고객에게 더 나은 사용자 환경을 제공하는 방법

웹 기반 결제 앱이 결제 요청을 수신하고 결제 거래를 시작하면 서비스 워커가 판매자와 결제 앱 간의 통신 허브 역할을 합니다. 이 게시물에서는 결제 앱이 서비스 워커를 사용하여 결제 수단, 배송지 주소 또는 연락처 정보에 관한 정보를 판매자에게 전달하는 방법을 설명합니다.

서비스 워커로 선택적 결제 정보 처리
서비스 워커로 선택적 결제 정보 처리

판매자에게 결제 수단 변경 알림

결제 앱은 다양한 결제 수단으로 여러 결제 수단을 지원할 수 있습니다.

고객 결제 수단 결제 수단
A 신용카드 발급기관 1 ****1234
신용카드 발급기관 1 ****4242
은행 X ******123
B 신용카드 발급기관 2 ****5678
은행 X ******456

예를 들어 위의 표에서 고객 A의 웹 기반 지갑에는 신용카드 2개와 은행 계좌 1개가 등록되어 있습니다. 이 경우 앱은 3가지 결제 수단 (****1234, ****4242, ******123)과 2가지 결제 방법 (신용카드 발급기관 1 및 은행 X)을 처리합니다. 결제 거래에서 결제 앱은 고객이 결제 수단 중 하나를 선택하고 이를 사용하여 판매자에게 결제하도록 허용할 수 있습니다.

결제 수단 선택 도구 UI
결제 수단 선택기 UI

결제 앱은 전체 결제 응답을 보내기 전에 판매자에게 고객이 선택한 결제 수단을 알릴 수 있습니다. 이는 판매자가 특정 결제 수단 브랜드에 대한 할인 캠페인을 운영하려는 경우에 유용합니다.

Payment Handler API를 사용하면 결제 앱이 서비스 워커를 통해 판매자에게 '결제 수단 변경' 이벤트를 전송하여 새 결제 수단 식별자를 알릴 수 있습니다. 서비스 워커는 새 결제 수단 정보로 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 객체로 응답할 수 있습니다.

[merchant]

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;

이 객체를 사용하여 프런트엔드에서 UI를 업데이트합니다. 업데이트된 결제 세부정보 반영을 참고하세요.

배송지 주소 변경을 판매자에게 알림

결제 앱은 결제 거래의 일환으로 판매자에게 고객의 배송지 주소를 제공할 수 있습니다.

이는 판매자가 주소 수집을 결제 앱에 위임할 수 있으므로 판매자에게 유용합니다. 또한 주소 데이터는 표준 데이터 형식으로 제공되므로 판매자는 일관된 구조로 배송지 주소를 받을 수 있습니다.

또한 고객은 선호하는 결제 앱에 주소 정보를 등록하고 여러 판매자에게 재사용할 수 있습니다.

배송지 주소 선택기 UI
배송지 주소 선택 도구 UI

결제 앱은 배송지 주소를 수정하거나 결제 거래에서 고객의 사전 등록된 주소 정보를 선택하는 UI를 제공할 수 있습니다. 배송지 주소가 일시적으로 결정되면 결제 앱에서 판매자에게 수정된 주소 정보를 알릴 수 있습니다. 이를 통해 판매자는 다음과 같은 여러 이점을 얻을 수 있습니다.

  • 판매자는 고객이 상품을 배송하기 위한 지역 제한 (예: 국내 배송만 가능)을 충족하는지 확인할 수 있습니다.
  • 판매자는 배송지 주소의 지역 (예: 국제 일반 또는 특급)에 따라 배송 옵션 목록을 변경할 수 있습니다.
  • 판매자는 주소를 기반으로 새 배송비를 적용하고 총 가격을 업데이트할 수 있습니다.

Payment Handler API를 사용하면 결제 앱이 서비스 워커에서 판매자에게 '배송지 주소 변경' 이벤트를 전송하여 새 배송지 주소를 알릴 수 있습니다. 서비스 워커는 새 주소 객체를 사용하여 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);
      

판매자는 업데이트된 PaymentDetailsUpdate로 응답할 수 있도록 Payment Request API에서 shippingaddresschange 이벤트를 수신합니다.

[merchant]

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;

이 객체를 사용하여 프런트엔드에서 UI를 업데이트합니다. 업데이트된 결제 세부정보 반영을 참고하세요.

판매자에게 배송 옵션 변경 알림

배송 옵션은 판매자가 구매한 상품을 고객에게 배송하는 데 사용하는 배송 방법입니다. 일반적인 배송 옵션은 다음과 같습니다.

  • 무료 배송
  • 빠른 배송
  • 해외 배송
  • 프리미엄 해외 배송

각 방법에는 고유한 비용이 있습니다. 일반적으로 더 빠른 방법/옵션은 더 비쌉니다.

Payment Request API를 사용하는 판매자는 이 선택을 결제 앱에 위임할 수 있습니다. 결제 앱은 이 정보를 사용하여 UI를 구성하고 고객이 배송 옵션을 선택하도록 할 수 있습니다.

배송 옵션 선택 도구 UI
배송 옵션 선택기 UI

판매자의 Payment Request API에 지정된 배송 옵션 목록은 PaymentRequestEvent의 속성으로 결제 앱의 서비스 워커에 전파됩니다.

[merchant]

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를 사용하면 결제 앱이 서비스 워커에서 판매자에게 '배송 옵션 변경' 이벤트를 보낼 수 있습니다. 서비스 워커는 새 배송 옵션 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);
      

판매자는 Payment Request API에서 shippingoptionchange 이벤트를 수신합니다. 판매자는 이 정보를 사용하여 총 가격을 업데이트한 다음 업데이트된 PaymentDetailsUpdate로 응답해야 합니다.

[merchant]

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;

이 객체를 사용하여 프런트엔드에서 UI를 업데이트합니다. 업데이트된 결제 세부정보 반영을 참고하세요.

업데이트된 결제 세부정보 반영

판매자가 결제 세부정보 업데이트를 완료하면 .changePaymentMethod(), .changeShippingAddress(), .changeShippingOption()에서 반환된 약속이 공통 PaymentRequestDetailsUpdate 객체로 확인됩니다. 결제 핸들러는 이 결과를 사용하여 업데이트된 총 가격과 배송 옵션을 UI에 반영할 수 있습니다.

판매자가 다음과 같은 이유로 오류를 반환할 수 있습니다.

  • 허용되지 않는 결제 수단입니다.
  • 배송지 주소가 지원되는 지역 밖에 있습니다.
  • 배송지 주소에 잘못된 정보가 있습니다.
  • 제공된 배송지 주소 또는 기타 이유로 배송 옵션을 선택할 수 없습니다.

오류 상태를 반영하려면 다음 속성을 사용하세요.

  • error: 사람이 읽을 수 있는 오류 문자열입니다. 고객에게 표시할 가장 좋은 문자열입니다.
  • shippingAddressErrors: 주소 속성별로 자세한 오류 문자열을 포함하는 AddressErrors 객체입니다. 이는 고객이 주소를 수정할 수 있는 양식을 열고 잘못된 입력란을 직접 안내해야 하는 경우에 유용합니다.
  • paymentMethodErrors: 결제 수단별 오류 객체입니다. 판매자에게 구조화된 오류를 제공하도록 요청할 수 있지만 웹 결제 사양 작성자는 간단한 문자열로 유지하는 것이 좋습니다.

샘플 코드

이 문서에 표시된 샘플 코드의 대부분은 다음과 같은 작동하는 샘플 앱에서 발췌한 내용입니다.

https://paymenthandler-demo.glitch.me

[payment handler] 서비스 워커

[payment handler] 프런트엔드

사용해 보려면 다음 단계를 따르세요.

  1. https://paymentrequest-demo.glitch.me/로 이동합니다.
  2. 페이지 하단으로 이동합니다.
  3. 결제 수단 추가 버튼을 누릅니다.
  4. 결제 수단 식별자 필드에 https://paymenthandler-demo.glitch.me를 입력합니다.
  5. 입력란 옆에 있는 결제 버튼을 누릅니다.