가이드

이 가이드의 단계에 따라 웹 애플리케이션을 Google Pay API와 통합하고 결제 카드를 사용할 수 있도록 구성합니다.

1단계: Google Pay API 버전 정의

사이트에서 사용하는 Google Pay API 버전을 선언합니다. 주 버전과 부 버전은 전달된 각 객체의 입력란에 필요하며 응답에 포함됩니다.

다음 코드 샘플은 선언된 API 버전을 보여줍니다.

    const baseRequest = {
      apiVersion: 2,
      apiVersionMinor: 0
    };

2단계: 결제 시스템 공급자의 결제 토큰 요청

Google은 결제 시스템 공급자의 보안 처리를 위해 결제자가 선택한 카드 정보를 암호화합니다.

    const tokenizationSpecification = {
      type: 'PAYMENT_GATEWAY',
      parameters: {
        'gateway': 'example',
        'gatewayMerchantId': 'exampleGatewayMerchantId'
      }
    };

exampleexampleGatewayMerchantId를 결제 시스템 공급자에 해당하는 값으로 바꿉니다. 다음 표를 사용하여 결제 시스템 공급자의 gatewaygatewayMerchantId 값을 찾습니다.

게이트웨이 매개변수 및 문서
ACI
"gateway": "aciworldwide"
"gatewayMerchantId": "YOUR_ENTITY_ID"

개발자 문서

Adyen
"gateway": "adyen"
"gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"

개발자 문서

Alfa-Bank
"gateway": "alfabank"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

APPEX
"gateway": "epos"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Assist
"gateway": "assist"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Billing Systems
"gateway": "billingsystems"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Blue Media
"gateway": "bluemedia"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

BlueSnap
"gateway": "bluesnap"
"gatewayMerchantId": "YOUR_shopToken"

개발자 문서

Braintree
"gateway": "braintree"
"braintree:apiVersion": "v1"
"braintree:sdkVersion": "braintree.client.VERSION"
"braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID"
"braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY"

개발자 문서

Braspag
"gateway": "cielo"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

CardConnect
"gateway": "cardconnect"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Cathay United Bank
"gateway": "cathaybk"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Chase Merchant Services
"gateway": "chase"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Checkout.com
"gateway": "checkoutltd"
"gatewayMerchantId": "YOUR_PUBLIC_KEY"

개발자 문서

CloudPayments
"gateway": "cloudpayments"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Computop
"gateway": "computop"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Cybersource
"gateway": "cybersource"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Datatrans
"gateway": "datatrans"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

dLocal
"gateway": "dlocal"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Dotpay
"gateway": "dotpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

e-SiTef - Software Express
"gateway": "softwareexpress"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

EasyPay
"gateway": "easypay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

EBANX
"gateway": "ebanx"
"gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY"

개발자 문서

eCard
"gateway": "ecard"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

ECPay
"gateway": "ecpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

eGHL
"gateway": "eghl"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

eSafe
"gateway": "esafe"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Evo Payment Gateway
"gateway": "evopaymentgateway"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Fat Zebra
"gateway": "fatzebra"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

First Data (Payeezy)
"gateway": "firstdata"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

FreedomPay
"gateway": "freedompay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Developer docs

Gestpay
"gateway": "gestpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Global One Pay
"gateway": "globalonepay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Global Payments
"gateway": "globalpayments"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

GMO Payment Gateway
"gateway": "gmopg"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

GoPay
"gateway": "gopay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

GP Webpay
"gateway": "gpwebpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

HiTrust
"gateway": "hitrustpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

iPay88
"gateway": "ipay88"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

iQmetrix
"gateway": "iqmetrixpaymentservicesgateway"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

IXOPAY
"gateway": "ixopay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Developer docs

JudoPay
"gateway": "judopay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Kassa
"gateway": "kassacom"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Developer docs

Kineox
"gateway": "kineox"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

LogPay
"gateway": "logpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Lyra
"gateway": "lyra"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Mastercard Payment Gateway Services
"gateway": "mpgs"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

MOBI.Money
"gateway": "mobimoney"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Molpay
"gateway": "molpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Moneris
"gateway": "moneris"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Moneta
"gateway": "moneta"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Monext
"gateway": "monext"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Money.Mail.Ru
"gateway": "moneymailru"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Multicarta
"gateway": "mulitcarta"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Mundipagg
"gateway": "mundipagg"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

MyCheck
"gateway": "mycheck"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

MyPay
"gateway": "mypay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서가 없음

Newebpay
"gateway": "newebpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Nexi
"gateway": "nexi"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

NMI
"gateway": "creditcall"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Nuvei
"gateway": "nuvei"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

paygent
"gateway": "paygent"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

PayLane
"gateway": "paylane"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Payler
"gateway": "payler"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Paymark
"gateway": "paymark"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Paymentwall
"gateway": "paymentwall"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Paymo
"gateway": "paymo"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Developer docs

PayOnline
"gateway": "payonline"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Paysafe
"gateway": "paysafe"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Payture
"gateway": "payture"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

PayU
"gateway": "payu"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Portmone
"gateway": "portmonecom"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Przelewy24
"gateway": "przelewy24"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

RBK.money
"gateway": "rbkmoney"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Redsys
"gateway": "redsys"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Sberbank
"gateway": "sberbank"
"gatewayMerchantId": "YOUR_ORGANIZATION_NAME"

개발자 문서

Sipay
"gateway": "sipay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Softbank Payment Service
"gateway": "sbps"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Solid
"gateway": "solid"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Sony Payment Services
"gateway": "sonypaymentservices"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Spreedly
"gateway": "spreedly"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Square
"gateway": "square"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Stripe
"gateway": "stripe"
"stripe:version": "2018-10-31"
"stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY"

개발자 문서

TapPay (Cherri Tech)
"gateway": "tappay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Tatra banka (CardPay)
"gateway": "tatrabanka"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

No developer docs available

Tinkoff
"gateway": "tinkoff"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

theMAP
"gateway": "themap"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

TPay.com
"gateway": "tpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Tranzzo
"gateway": "tranzzo"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Uniteller
"gateway": "uniteller"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Vantiv
"gateway": "vantiv"
"vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID"
"vantiv:merchantOrderId": "YOUR_ORDER_ID"
"vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID"
"vantiv:merchantReportGroup": "*web"

개발자 문서

Veritrans
"gateway": "veritrans"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Vindicia
"gateway": "vindicia"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

WayForPay
"gateway": "wayforpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Windcave
"gateway": "windcave"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Wirecard
"gateway": "wirecard"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Worldnet
"gateway": "worldnet"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

개발자 문서

Worldpay
"gateway": "worldpay"
"gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"

개발자 문서

Yandex.Checkout
"gateway": "yandexcheckout"
"gatewayMerchantId": "YOUR_SHOP_ID"

개발자 문서

PAYMENT_GATEWAY 토큰화 유형은 Google Pay API로 카드 결제 수단의 판매자를 구현하는 가장 일반적인 방식입니다. 결제 시스템 공급자가 지원되지 않는 경우에는 직접 통합을 통해 Google Pay를 허용하면 됩니다. 자세한 내용은 직접 토큰화 문서를 참조하세요.

3단계: 지원되는 결제 카드 네트워크 정의

사이트에서 사용할 수 있는 카드 네트워크를 정의합니다. 다음 코드 샘플을 참조하세요.

    const allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"];
    

Google Pay API는 Google에 등록된 카드(PAN_ONLY) 또는 3D Secure 암호로 인증된 Android 기기의 기기 토큰(CRYPTOGRAM_3DS)을 반환할 수 있습니다. 다음 코드 샘플을 참조하세요.

    const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];
    

자세한 내용은 객체 참조 문서의 CardParameters를 참조하세요. 또한 지원되는 카드 네트워크 및 Android 기기 토큰 지원은 게이트웨이 또는 대행업체에 확인하시기 바랍니다.

4단계: 사용할 수 있는 결제 수단 설명

사용할 수 있는 결제 수단을 설명하려면 다음 단계를 완료하세요.

  1. 지원되는 인증 수단과 지원되는 카드 네트워크를 결합하여 사이트에서 지원하는 CARD 결제 수단을 설명합니다. 다음 코드 샘플을 참조하세요.
        const baseCardPaymentMethod = {
          type: 'CARD',
          parameters: {
            allowedAuthMethods: allowedCardAuthMethods,
            allowedCardNetworks: allowedCardNetworks
          }
        };
        
  2. 기본 카드 결제 수단 객체를 확장하여 애플리케이션에 반환될 정보를 설명합니다. 토큰화된 결제 데이터에 대한 설명을 포함합니다. 다음 코드 샘플을 참조하세요.
        const cardPaymentMethod = Object.assign(
          {tokenizationSpecification: tokenizationSpecification},
          baseCardPaymentMethod
        );
        
  3. 지원되는 parameters에 대한 자세한 내용은 CardParameters를 참조하세요.

    Google Pay는 또한 CARD 유형과 PAYPAL 유형의 결제 수단을 지원합니다. Google Pay의 결제 수단으로 PAYPAL 유형을 추가하는 방법에 대한 자세한 내용은 PayPal 개발자 문서를 참조하세요.

5단계: Google Pay API 자바스크립트 라이브러리 로드

Google Pay API 자바스크립트 라이브러리를 로드하려면 다음 단계를 완료하세요.

  1. 페이지에 Google의 호스팅된 자바스크립트를 포함합니다. 다음 코드 샘플을 참조하세요.
        <script
          async
          src="https://pay.google.com/gp/p/js/pay.js"
          onload="console.log('TODO: add onload function')">
        </script>
  2. Google Pay API 자바스크립트 라이브러리가 로드된 후 PaymentsClient 객체를 초기화합니다. 초기 개발에서는 결제 응답의 구조를 참조하는 데 적합한 더미 결제 수단을 반환하는 TEST 환경을 사용합니다. 이 환경에서는 선택한 결제 수단을 사용한 거래는 지원하지 않습니다. 다음 코드 샘플을 참조하세요.
    const paymentsClient =
            new google.payments.api.PaymentsClient({environment: 'TEST'});

    청구 가능한 결제 수단을 반환하는 PRODUCTION 환경의 요구 사항에 대한 자세한 내용은 통합 체크리스트를 참조하세요.

6단계: Google Pay API로 결제할 준비가 되었는지 확인

Google Pay API로 결제할 준비가 되었는지 확인하려면 다음 단계를 완료하세요.

  1. 사용할 수 있는 결제 수단을 기본 요청 객체에 추가합니다. 다음 코드 샘플을 참조하세요.
        const isReadyToPayRequest = Object.assign({}, baseRequest);
        isReadyToPayRequest.allowedPaymentMethods = [baseCardPaymentMethod];
  2. isReadyToPay()를 호출하여 현재 기기 및 브라우저에서 지정된 결제 수단에 Google Pay API를 지원하는지 확인합니다. 다음 코드 샘플을 참조하세요.
        paymentsClient.isReadyToPay(isReadyToPayRequest)
            .then(function(response) {
              if (response.result) {
                // add a Google Pay payment button
              }
            })
            .catch(function(err) {
              // show error in developer console for debugging
              console.error(err);
            });

7단계: Google Pay 결제 버튼 추가

페이지에 Google Pay 결제 버튼을 추가하여 쇼핑객이 Google Pay API 및 대행업체 사이트에서 지원하는 결제 수단을 사용하여 결제하도록 유도하세요. 사용 가능한 버튼 유형, 색상, 디스플레이 요구사항에 대한 자세한 내용은 브랜드 가이드라인을 참조하세요.

다음 결제 버튼 코드 샘플을 참조하세요.

    const button =
        paymentsClient.createButton({onClick: () => console.log('TODO: click handler')});
    document.getElementById('container').appendChild(button);

8단계: PaymentDataRequest 객체 만들기

PaymentDataRequest 객체를 만들려면 다음 단계를 완료하세요.

  1. Google Pay API에 대한 사이트의 지원을 설명하는 자바스크립트 객체를 빌드합니다. 지원되는 속성의 전체 목록은 PaymentDataRequest를 참조하세요. 다음 코드 샘플을 참조하세요.
    const paymentDataRequest = Object.assign({}, baseRequest);
  2. 응답에서 예상되는 추가 데이터 구성과 같이 앱이 지원하는 결제 수단을 추가합니다. 다음 코드 샘플을 참조하세요.
        paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
        
  3. 쇼핑객이 승인할 총 가격과 통화를 정의합니다. 다음 코드 샘플을 참조하세요.
    paymentDataRequest.transactionInfo = {
          totalPriceStatus: 'FINAL',
          totalPrice: '123.45',
          currencyCode: 'USD',
          countryCode: 'US'
        };
  4. 사용자에게 표시되는 판매자 이름을 제공하고, TEST에서 TEST merchantId 값을 사용합니다. TEST merchantId 값을 대체해야 하는 경우에 대한 자세한 내용 및 정보는 MerchantInfo를 참조하세요. 사용자에게 표시되는 판매자 이름에 대한 다음 코드 샘플을 참조하세요.
        paymentDataRequest.merchantInfo = {
          merchantName: 'Example Merchant'
          merchantId: '01234567890123456789'
        };
        

9단계: 사용자 동작용 이벤트 핸들러 등록

사용자 동작에 대한 이벤트 핸들러를 등록하려면 다음 단계를 완료하세요.

  1. 구매 버튼에 대한 클릭 이벤트 핸들러를 등록합니다. 이벤트 핸들러는 Google Pay 결제 버튼과 상호작용한 직후에 loadPaymentData()를 호출합니다.
  2. Google 사용자가 선택한 결제 방법 및 연락처 데이터(선택사항)에 대한 정보를 수신할 수 있는 권한을 사이트에 부여한 후 Google Pay API의 응답을 처리합니다.
  3. paymentData 응답에서 결제 토큰을 추출합니다. 게이트웨이 통합을 구현하는 경우 이 토큰을 수정하지 않고 게이트웨이에 전달합니다.
        paymentsClient.loadPaymentData(paymentDataRequest).then(function(paymentData){
          // if using gateway tokenization, pass this token without modification
          paymentToken = paymentData.paymentMethodData.tokenizationData.token;
        }).catch(function(err){
          // show error in developer console for debugging
          console.error(err);
        });

10단계(선택사항): 사용자와 상호작용하기 전에 결제 데이터 프리페치

실행 시간을 단축하려면 loadPaymentData()를 호출하기 전에 Google Pay API에서 웹사이트의 결제 구성을 프리페치합니다. 아래 예시를 참조하세요.

    paymentsClient.prefetchPaymentData(paymentDataRequest);
    

11단계(선택사항): 결제 승인 설정

결제 승인은 결제 프로세스를 시작하고 결제 승인 상태를 확인하는 데 사용됩니다. 결제 승인을 설정하려면 다음 단계를 수행하세요.

  1. PaymentOptionsonPaymentAuthorized() 콜백을 등록합니다.
  2. PAYMENT_AUTHORIZATION 콜백 인텐트를 사용하여 loadPaymentData() 함수를 호출합니다.
  3. onPaymentAuthorized()를 구현합니다.

onPaymentAuthorized 콜백 등록

다음 코드 샘플은 onPaymentAuthorized 콜백을 등록하는 방법을 보여줍니다.

    {
      environment: "TEST",
      merchantInfo: {
        merchantName: "Example Merchant",
        merchantId: "01234567890123456789"
      },
      paymentDataCallbacks: {
        onPaymentAuthorized: onPaymentAuthorized
      }
    }
    

콜백 인텐트로 결제 데이터 로드

다음 코드 샘플은 결제 승인을 사용하여 결제 명세서를 초기화하는 방법을 보여줍니다.

    const paymentDataRequest = Object.assign({}, baseRequest);
    paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
    paymentDataRequest.transactionInfo = getGoogleTransactionInfo();
    paymentDataRequest.merchantInfo = {
      merchantName: 'Example Merchant'
      merchantId: '01234567890123456789',
    };

    paymentDataRequest.callbackIntents = ["PAYMENT_AUTHORIZATION"];
    

onPaymentAuthorized 콜백 처리

지급인이 결제를 클릭하는 등의 사용자 동작을 통해 결제를 승인하면 Google에서 PaymentData 객체를 사용하여 onPaymentAuthorized() 콜백을 호출합니다.

콜백은 Promise<PaymentAuthorizationResult> 값을 반환합니다. PaymentAuthorizationResult 객체의 거래 상태 값은 SUCCESS 또는 ERROR입니다. 성공하면 결제 명세서가 닫힙니다. 오류가 발생하면 결제를 처리한 후 반환된 오류 정보가 결제 명세서에 렌더링됩니다. 사용자는 결제 명세서의 결제 데이터를 변경하고 결제를 다시 승인할 수 있습니다. 다음 코드 샘플을 참조하세요.

    function onPaymentAuthorized(paymentData) {
      return new Promise(function(resolve, reject){
        // handle the response
        processPayment(paymentData)
        .then(function() {
          resolve({transactionState: 'SUCCESS'});
        })
        .catch(function() {
          resolve({
            transactionState: 'ERROR',
            error: {
              intent: 'PAYMENT_AUTHORIZATION',
              message: 'Insufficient funds',
              reason: 'PAYMENT_DATA_INVALID'
            }
          });
        });
      });
    }
    

12단계(배송 사용 설정에 대한 선택사항): 유동 가격 업데이트 설정

유동 가격 업데이트를 사용하면 판매자는 선택한 배송지 주소를 기반으로 배송 옵션 및 거래 정보를 동적으로 업데이트할 수 있습니다. 또한 선택한 배송 옵션에 따라 거래 정보를 동적으로 업데이트할 수 있습니다.

유동 가격 업데이트를 설정하려면 다음 단계를 수행하세요.

  1. onPaymentAuthorizedonPaymentDataChanged 콜백을 모두 PaymentOptions에 등록합니다.
  2. 콜백 인텐트를 사용하여 loadPaymentData() 함수를 호출합니다. 자세한 내용은 해당 예시를 참조하세요.
  3. onPaymentAuthorizedonPaymentDataChanged를 구현합니다.

PaymentData 콜백 등록

다음 코드 샘플은 유동 가격 업데이트를 사용하려면 PaymentsClient paymentOptions 객체에 콜백 함수를 등록해야 함을 보여줍니다.

    {
      environment: "TEST",
      merchantInfo: {
        merchantName: "Example Merchant",
        merchantId: "01234567890123456789"
      },
      paymentDataCallbacks: {
        onPaymentAuthorized: onPaymentAuthorized,
        onPaymentDataChanged: onPaymentDataChanged
      }
    }
    

콜백 인텐트로 결제 데이터 로드

다음 코드 샘플은 필수 배송지 주소와 배송 옵션 구성으로 결제 명세서를 초기화하는 방법을 보여줍니다.

    const paymentDataRequest = Object.assign({}, baseRequest);
    paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
    paymentDataRequest.transactionInfo = getGoogleTransactionInfo();
    paymentDataRequest.merchantInfo = {
      merchantId: '01234567890123456789',
      merchantName: 'Example Merchant'
    };

    paymentDataRequest.callbackIntents = ["SHIPPING_ADDRESS",  "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"];

    paymentDataRequest.shippingAddressRequired = true;
    paymentDataRequest.shippingAddressParameters = getGoogleShippingAddressParameters();
    paymentDataRequest.shippingOptionRequired = true;
    

onPaymentDataChanged 콜백 처리

onPaymentDataChanged 콜백은 IntermediatePaymentData 객체를 사용하여 호출됩니다. 이 객체는 결제 명세서에서 선택한 배송지 주소 및 배송 옵션을 포함합니다.

콜백은 Promise<PaymentDataRequestUpdate>를 반환합니다. PaymentDataRequestUpdate 객체에는 새 거래 정보, 배송 옵션, 결제 데이터 오류가 있습니다. 이 데이터로 결제 명세서가 업데이트됩니다.

사용할 수 없는 배송지 주소나 잘못된 배송 옵션과 같은 예외 사항은 결제 명세서에서 직접 처리합니다. 사용자에게 오류 메시지와 오류 이유가 강조표시되도록 PaymentDataError 객체를 설정합니다. 이때 메시지에는 관련된 인텐트가 포함되어야 합니다. 객체와 메시지를 설정하는 방법에 대한 자세한 내용은 다음 코드 샘플을 참조하세요.

    function onPaymentDataChanged(intermediatePaymentData) {
      return new Promise(function(resolve, reject) {

        let shippingAddress = intermediatePaymentData.shippingAddress;
        let shippingOptionData = intermediatePaymentData.shippingOptionData;
        let paymentDataRequestUpdate = {};

        if (intermediatePaymentData.callbackTrigger == "INITIALIZE" || intermediatePaymentData.callbackTrigger == "SHIPPING_ADDRESS") {
          if(shippingAddress.administrativeArea == "NJ")  {
            paymentDataRequestUpdate.error = getGoogleUnserviceableAddressError();
          }
          else {
            paymentDataRequestUpdate.newShippingOptionParameters = getGoogleDefaultShippingOptions();
            let selectedShippingOptionId = paymentDataRequestUpdate.newShippingOptionParameters.defaultSelectedOptionId;
            paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(selectedShippingOptionId);
          }
        }
        else if (intermediatePaymentData.callbackTrigger == "SHIPPING_OPTION") {
          paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(shippingOptionData.id);
        }

        resolve(paymentDataRequestUpdate);
      });
    }
    

총정리

이 섹션의 예시 코드 블록은 Google Pay API 자바스크립트 라이브러리 가이드, 결제 승인, 유동 가격 업데이트의 완전한 엔드 투 엔드 예시를 보여줍니다.

가이드

    <div id="container"></div>
    
    <script>
    /**
     * Define the version of the Google Pay API referenced when creating your
     * configuration
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|apiVersion in PaymentDataRequest}
     */
    const baseRequest = {
      apiVersion: 2,
      apiVersionMinor: 0
    };

    /**
     * Card networks supported by your site and your gateway
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     * @todo confirm card networks supported by your site and gateway
     */
    const allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"];

    /**
     * Card authentication methods supported by your site and your gateway
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     * @todo confirm your processor supports Android device tokens for your
     * supported card networks
     */
    const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];

    /**
     * Identify your gateway and your site's gateway merchant identifier
     *
     * The Google Pay API response will return an encrypted payment method capable
     * of being charged by a supported gateway after payer authorization
     *
     * @todo check with your gateway on the parameters to pass
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#gateway|PaymentMethodTokenizationSpecification}
     */
    const tokenizationSpecification = {
      type: 'PAYMENT_GATEWAY',
      parameters: {
        'gateway': 'example',
        'gatewayMerchantId': 'exampleGatewayMerchantId'
      }
    };

    /**
     * Describe your site's support for the CARD payment method and its required
     * fields
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     */
    const baseCardPaymentMethod = {
      type: 'CARD',
      parameters: {
        allowedAuthMethods: allowedCardAuthMethods,
        allowedCardNetworks: allowedCardNetworks
      }
    };

    /**
     * Describe your site's support for the CARD payment method including optional
     * fields
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     */
    const cardPaymentMethod = Object.assign(
      {},
      baseCardPaymentMethod,
      {
        tokenizationSpecification: tokenizationSpecification
      }
    );

    /**
     * An initialized google.payments.api.PaymentsClient object or null if not yet set
     *
     * @see {@link getGooglePaymentsClient}
     */
    let paymentsClient = null;

    /**
     * Configure your site's support for payment methods supported by the Google Pay
     * API.
     *
     * Each member of allowedPaymentMethods should contain only the required fields,
     * allowing reuse of this base request when determining a viewer's ability
     * to pay and later requesting a supported payment method
     *
     * @returns {object} Google Pay API version, payment methods supported by the site
     */
    function getGoogleIsReadyToPayRequest() {
      return Object.assign(
          {},
          baseRequest,
          {
            allowedPaymentMethods: [baseCardPaymentMethod]
          }
      );
    }

    /**
     * Configure support for the Google Pay API
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|PaymentDataRequest}
     * @returns {object} PaymentDataRequest fields
     */
    function getGooglePaymentDataRequest() {
      const paymentDataRequest = Object.assign({}, baseRequest);
      paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
      paymentDataRequest.transactionInfo = getGoogleTransactionInfo();
      paymentDataRequest.merchantInfo = {
        // @todo a merchant ID is available for a production environment after approval by Google
        // See {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist|Integration checklist}
        // merchantId: '01234567890123456789',
        merchantName: 'Example Merchant'
      };
      return paymentDataRequest;
    }

    /**
     * Return an active PaymentsClient or initialize
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient|PaymentsClient constructor}
     * @returns {google.payments.api.PaymentsClient} Google Pay API client
     */
    function getGooglePaymentsClient() {
      if ( paymentsClient === null ) {
        paymentsClient = new google.payments.api.PaymentsClient({environment: 'TEST'});
      }
      return paymentsClient;
    }

    /**
     * Initialize Google PaymentsClient after Google-hosted JavaScript has loaded
     *
     * Display a Google Pay payment button after confirmation of the viewer's
     * ability to pay.
     */
    function onGooglePayLoaded() {
      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.isReadyToPay(getGoogleIsReadyToPayRequest())
          .then(function(response) {
            if (response.result) {
              addGooglePayButton();
              // @todo prefetch payment data to improve performance after confirming site functionality
              // prefetchGooglePaymentData();
            }
          })
          .catch(function(err) {
            // show error in developer console for debugging
            console.error(err);
          });
    }

    /**
     * Add a Google Pay purchase button alongside an existing checkout button
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ButtonOptions|Button options}
     * @see {@link https://developers.google.com/pay/api/web/guides/brand-guidelines|Google Pay brand guidelines}
     */
    function addGooglePayButton() {
      const paymentsClient = getGooglePaymentsClient();
      const button =
          paymentsClient.createButton({onClick: onGooglePaymentButtonClicked});
      document.getElementById('container').appendChild(button);
    }

    /**
     * Provide Google Pay API with a payment amount, currency, and amount status
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo}
     * @returns {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest
     */
    function getGoogleTransactionInfo() {
      return {
        countryCode: 'US',
        currencyCode: 'USD',
        totalPriceStatus: 'FINAL',
        // set to cart total
        totalPrice: '1.00'
      };
    }

    /**
     * Prefetch payment data to improve performance
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/client#prefetchPaymentData|prefetchPaymentData()}
     */
    function prefetchGooglePaymentData() {
      const paymentDataRequest = getGooglePaymentDataRequest();
      // transactionInfo must be set but does not affect cache
      paymentDataRequest.transactionInfo = {
        totalPriceStatus: 'NOT_CURRENTLY_KNOWN',
        currencyCode: 'USD'
      };
      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.prefetchPaymentData(paymentDataRequest);
    }

    /**
     * Show Google Pay payment sheet when Google Pay payment button is clicked
     */
    function onGooglePaymentButtonClicked() {
      const paymentDataRequest = getGooglePaymentDataRequest();
      paymentDataRequest.transactionInfo = getGoogleTransactionInfo();

      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.loadPaymentData(paymentDataRequest)
          .then(function(paymentData) {
            // handle the response
            processPayment(paymentData);
          })
          .catch(function(err) {
            // show error in developer console for debugging
            console.error(err);
          });
    }
    /**
     * Process payment data returned by the Google Pay API
     *
     * @param {object} paymentData response from Google Pay API after user approves payment
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData|PaymentData object reference}
     */
    function processPayment(paymentData) {
      // show returned data in developer console for debugging
        console.log(paymentData);
      // @todo pass payment token to your gateway to process payment
      paymentToken = paymentData.paymentMethodData.tokenizationData.token;
    }</script>
    <script async
      src="https://pay.google.com/gp/p/js/pay.js"
      onload="onGooglePayLoaded()"></script>
    

결제 승인

    <div id="container"></div>
    
    <script>
    /**
     * Define the version of the Google Pay API referenced when creating your
     * configuration
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|apiVersion in PaymentDataRequest}
     */
    const baseRequest = {
      apiVersion: 2,
      apiVersionMinor: 0
    };

    /**
     * Card networks supported by your site and your gateway
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     * @todo confirm card networks supported by your site and gateway
     */
    const allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"];

    /**
     * Card authentication methods supported by your site and your gateway
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     * @todo confirm your processor supports Android device tokens for your
     * supported card networks
     */
    const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];

    /**
     * Identify your gateway and your site's gateway merchant identifier
     *
     * The Google Pay API response will return an encrypted payment method capable
     * of being charged by a supported gateway after payer authorization
     *
     * @todo check with your gateway on the parameters to pass
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#gateway|PaymentMethodTokenizationSpecification}
     */
    const tokenizationSpecification = {
      type: 'PAYMENT_GATEWAY',
      parameters: {
        'gateway': 'example',
        'gatewayMerchantId': 'exampleGatewayMerchantId'
      }
    };

    /**
     * Describe your site's support for the CARD payment method and its required
     * fields
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     */
    const baseCardPaymentMethod = {
      type: 'CARD',
      parameters: {
        allowedAuthMethods: allowedCardAuthMethods,
        allowedCardNetworks: allowedCardNetworks
      }
    };

    /**
     * Describe your site's support for the CARD payment method including optional
     * fields
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     */
    const cardPaymentMethod = Object.assign(
      {},
      baseCardPaymentMethod,
      {
        tokenizationSpecification: tokenizationSpecification
      }
    );

    /**
     * An initialized google.payments.api.PaymentsClient object or null if not yet set
     *
     * @see {@link getGooglePaymentsClient}
     */
    let paymentsClient = null;

    /**
     * Configure your site's support for payment methods supported by the Google Pay
     * API.
     *
     * Each member of allowedPaymentMethods should contain only the required fields,
     * allowing reuse of this base request when determining a viewer's ability
     * to pay and later requesting a supported payment method
     *
     * @returns {object} Google Pay API version, payment methods supported by the site
     */
    function getGoogleIsReadyToPayRequest() {
      return Object.assign(
          {},
          baseRequest,
          {
            allowedPaymentMethods: [baseCardPaymentMethod]
          }
      );
    }

    /**
     * Configure support for the Google Pay API
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|PaymentDataRequest}
     * @returns {object} PaymentDataRequest fields
     */
    function getGooglePaymentDataRequest() {
      const paymentDataRequest = Object.assign({}, baseRequest);
      paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
      paymentDataRequest.transactionInfo = getGoogleTransactionInfo();
      paymentDataRequest.merchantInfo = {
        // @todo a merchant ID is available for a production environment after approval by Google
        // See {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist|Integration checklist}
        // merchantId: '01234567890123456789',
        merchantName: 'Example Merchant'
      };

      paymentDataRequest.callbackIntents = ["PAYMENT_AUTHORIZATION"];

      return paymentDataRequest;
    }

    /**
     * Return an active PaymentsClient or initialize
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient|PaymentsClient constructor}
     * @returns {google.payments.api.PaymentsClient} Google Pay API client
     */
    function getGooglePaymentsClient() {
      if ( paymentsClient === null ) {
        paymentsClient = new google.payments.api.PaymentsClient({
        	environment: 'TEST',
          paymentDataCallbacks: {
          	onPaymentAuthorized: onPaymentAuthorized
          }
        });
      }
      return paymentsClient;
    }

    /**
     * Handles authorize payments callback intents.
     *
     * @param {object} paymentData response from Google Pay API after a payer approves payment through user gesture.
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData object reference}
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentAuthorizationResult}
     * @returns Promise<{object}> Promise of PaymentAuthorizationResult object to acknowledge the payment authorization status.
     */
    function onPaymentAuthorized(paymentData) {
    	return new Promise(function(resolve, reject){
        // handle the response
        processPayment(paymentData)
        .then(function() {
          resolve({transactionState: 'SUCCESS'});
        })
        .catch(function() {
          resolve({
            transactionState: 'ERROR',
            error: {
              intent: 'PAYMENT_AUTHORIZATION',
              message: 'Insufficient funds',
              reason: 'PAYMENT_DATA_INVALID'
            }
          });
      	});
      });
    }

    /**
     * Initialize Google PaymentsClient after Google-hosted JavaScript has loaded
     *
     * Display a Google Pay payment button after confirmation of the viewer's
     * ability to pay.
     */
    function onGooglePayLoaded() {
      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.isReadyToPay(getGoogleIsReadyToPayRequest())
          .then(function(response) {
            if (response.result) {
              addGooglePayButton();
            }
          })
          .catch(function(err) {
            // show error in developer console for debugging
            console.error(err);
          });
    }

    /**
     * Add a Google Pay purchase button alongside an existing checkout button
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ButtonOptions|Button options}
     * @see {@link https://developers.google.com/pay/api/web/guides/brand-guidelines|Google Pay brand guidelines}
     */
    function addGooglePayButton() {
      const paymentsClient = getGooglePaymentsClient();
      const button =
          paymentsClient.createButton({onClick: onGooglePaymentButtonClicked});
      document.getElementById('container').appendChild(button);
    }

    /**
     * Provide Google Pay API with a payment amount, currency, and amount status
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo}
     * @returns {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest
     */
    function getGoogleTransactionInfo() {
      return {
            displayItems: [
            {
              label: "Subtotal",
              type: "SUBTOTAL",
              price: "11.00",
            },
          {
              label: "Tax",
              type: "TAX",
              price: "1.00",
            }
        ],
        countryCode: 'US',
        currencyCode: "USD",
        totalPriceStatus: "FINAL",
        totalPrice: "12.00",
        totalPriceLabel: "Total"
      };
    }

    /**
     * Show Google Pay payment sheet when Google Pay payment button is clicked
     */
    function onGooglePaymentButtonClicked() {
      const paymentDataRequest = getGooglePaymentDataRequest();
      paymentDataRequest.transactionInfo = getGoogleTransactionInfo();

      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.loadPaymentData(paymentDataRequest);
    }

    /**
     * Process payment data returned by the Google Pay API
     *
     * @param {object} paymentData response from Google Pay API after user approves payment
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData|PaymentData object reference}
     */
    function processPayment(paymentData) {
    	return new Promise(function(resolve, reject) {
      	setTimeout(function() {
      		// @todo pass payment token to your gateway to process payment
      		paymentToken = paymentData.paymentMethodData.tokenizationData.token;

        	resolve({});
        }, 3000);
      });
    }</script>
    <script async
      src="https://pay.google.com/gp/p/js/pay.js"
      onload="onGooglePayLoaded()"></script>
    

유동 가격 업데이트

    <div id="container"></div>
    
    <script>
    /**
     * Define the version of the Google Pay API referenced when creating your
     * configuration
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|apiVersion in PaymentDataRequest}
     */
    const baseRequest = {
      apiVersion: 2,
      apiVersionMinor: 0
    };

    /**
     * Card networks supported by your site and your gateway
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     * @todo confirm card networks supported by your site and gateway
     */
    const allowedCardNetworks = ["AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA"];

    /**
     * Card authentication methods supported by your site and your gateway
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     * @todo confirm your processor supports Android device tokens for your
     * supported card networks
     */
    const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];

    /**
     * Identify your gateway and your site's gateway merchant identifier
     *
     * The Google Pay API response will return an encrypted payment method capable
     * of being charged by a supported gateway after payer authorization
     *
     * @todo check with your gateway on the parameters to pass
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#gateway|PaymentMethodTokenizationSpecification}
     */
    const tokenizationSpecification = {
      type: 'PAYMENT_GATEWAY',
      parameters: {
        'gateway': 'example',
        'gatewayMerchantId': 'exampleGatewayMerchantId'
      }
    };

    /**
     * Describe your site's support for the CARD payment method and its required
     * fields
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     */
    const baseCardPaymentMethod = {
      type: 'CARD',
      parameters: {
        allowedAuthMethods: allowedCardAuthMethods,
        allowedCardNetworks: allowedCardNetworks
      }
    };

    /**
     * Describe your site's support for the CARD payment method including optional
     * fields
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
     */
    const cardPaymentMethod = Object.assign(
      {},
      baseCardPaymentMethod,
      {
        tokenizationSpecification: tokenizationSpecification
      }
    );

    /**
     * An initialized google.payments.api.PaymentsClient object or null if not yet set
     *
     * @see {@link getGooglePaymentsClient}
     */
    let paymentsClient = null;

    /**
     * Configure your site's support for payment methods supported by the Google Pay
     * API.
     *
     * Each member of allowedPaymentMethods should contain only the required fields,
     * allowing reuse of this base request when determining a viewer's ability
     * to pay and later requesting a supported payment method
     *
     * @returns {object} Google Pay API version, payment methods supported by the site
     */
    function getGoogleIsReadyToPayRequest() {
      return Object.assign(
          {},
          baseRequest,
          {
            allowedPaymentMethods: [baseCardPaymentMethod]
          }
      );
    }

    /**
     * Configure support for the Google Pay API
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|PaymentDataRequest}
     * @returns {object} PaymentDataRequest fields
     */
    function getGooglePaymentDataRequest() {
      const paymentDataRequest = Object.assign({}, baseRequest);
      paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
      paymentDataRequest.transactionInfo = getGoogleTransactionInfo();
      paymentDataRequest.merchantInfo = {
        // @todo a merchant ID is available for a production environment after approval by Google
        // See {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist|Integration checklist}
        // merchantId: '01234567890123456789',
        merchantName: 'Example Merchant'
      };

      paymentDataRequest.callbackIntents = ["SHIPPING_ADDRESS",  "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"];
      paymentDataRequest.shippingAddressRequired = true;
      paymentDataRequest.shippingAddressParameters = getGoogleShippingAddressParameters();
      paymentDataRequest.shippingOptionRequired = true;

      return paymentDataRequest;
    }

    /**
     * Return an active PaymentsClient or initialize
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient|PaymentsClient constructor}
     * @returns {google.payments.api.PaymentsClient} Google Pay API client
     */
    function getGooglePaymentsClient() {
      if ( paymentsClient === null ) {
        paymentsClient = new google.payments.api.PaymentsClient({
          environment: "TEST",
          merchantInfo: {
            merchantName: "Example Merchant",
            merchantId: "01234567890123456789"
          },
          paymentDataCallbacks: {
          	onPaymentAuthorized: onPaymentAuthorized,
            onPaymentDataChanged: onPaymentDataChanged
          }
        });
      }
      return paymentsClient;
    }

    function onPaymentAuthorized(paymentData) {
    	return new Promise(function(resolve, reject){

      // handle the response
      processPayment(paymentData)
        .then(function() {
          resolve({transactionState: 'SUCCESS'});
        })
        .catch(function() {
        	resolve({
            transactionState: 'ERROR',
            error: {
              intent: 'PAYMENT_AUTHORIZATION',
              message: 'Insufficient funds',
              reason: 'PAYMENT_DATA_INVALID'
            }
          });
        });

      });
    }

    /**
     * Handles dynamic buy flow shipping address and shipping options callback intents.
     *
     * @param {object} itermediatePaymentData response from Google Pay API a shipping address or shipping option is selected in the payment sheet.
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#IntermediatePaymentData|IntermediatePaymentData object reference}
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentDataRequestUpdate|PaymentDataRequestUpdate}
     * @returns Promise<{object}> Promise of PaymentDataRequestUpdate object to update the payment sheet.
     */
    function onPaymentDataChanged(intermediatePaymentData) {
      return new Promise(function(resolve, reject) {

       	let shippingAddress = intermediatePaymentData.shippingAddress;
        let shippingOptionData = intermediatePaymentData.shippingOptionData;
        let paymentDataRequestUpdate = {};

        if (intermediatePaymentData.callbackTrigger == "INITIALIZE" || intermediatePaymentData.callbackTrigger == "SHIPPING_ADDRESS") {
          if(shippingAddress.administrativeArea == "NJ")  {
            paymentDataRequestUpdate.error = getGoogleUnserviceableAddressError();
          }
          else {
            paymentDataRequestUpdate.newShippingOptionParameters = getGoogleDefaultShippingOptions();
            let selectedShippingOptionId = paymentDataRequestUpdate.newShippingOptionParameters.defaultSelectedOptionId;
            paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(selectedShippingOptionId);
          }
        }
        else if (intermediatePaymentData.callbackTrigger == "SHIPPING_OPTION") {
          paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(shippingOptionData.id);
        }

        resolve(paymentDataRequestUpdate);
      });
    }

    /**
     * Helper function to create a new TransactionInfo object.

     * @param string shippingOptionId respresenting the selected shipping option in the payment sheet.
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo}
     * @returns {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest
     */
    function calculateNewTransactionInfo(shippingOptionId) {
            let newTransactionInfo = getGoogleTransactionInfo();

      let shippingCost = getShippingCosts()[shippingOptionId];
      newTransactionInfo.displayItems.push({
        type: "LINE_ITEM",
        label: "Shipping cost",
        price: shippingCost,
        status: "FINAL"
      });

      let totalPrice = 0.00;
      newTransactionInfo.displayItems.forEach(displayItem => totalPrice += parseFloat(displayItem.price));
      newTransactionInfo.totalPrice = totalPrice.toString();

      return newTransactionInfo;
    }

    /**
     * Initialize Google PaymentsClient after Google-hosted JavaScript has loaded
     *
     * Display a Google Pay payment button after confirmation of the viewer's
     * ability to pay.
     */
    function onGooglePayLoaded() {
      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.isReadyToPay(getGoogleIsReadyToPayRequest())
          .then(function(response) {
            if (response.result) {
              addGooglePayButton();
              // @todo prefetch payment data to improve performance after confirming site functionality
              // prefetchGooglePaymentData();
            }
          })
          .catch(function(err) {
            // show error in developer console for debugging
            console.error(err);
          });
    }

    /**
     * Add a Google Pay purchase button alongside an existing checkout button
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ButtonOptions|Button options}
     * @see {@link https://developers.google.com/pay/api/web/guides/brand-guidelines|Google Pay brand guidelines}
     */
    function addGooglePayButton() {
      const paymentsClient = getGooglePaymentsClient();
      const button =
          paymentsClient.createButton({onClick: onGooglePaymentButtonClicked});
      document.getElementById('container').appendChild(button);
    }

    /**
     * Provide Google Pay API with a payment amount, currency, and amount status
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo}
     * @returns {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest
     */
    function getGoogleTransactionInfo() {
      return {
            displayItems: [
            {
              label: "Subtotal",
              type: "SUBTOTAL",
              price: "11.00",
            },
          {
              label: "Tax",
              type: "TAX",
              price: "1.00",
            }
        ],
        countryCode: 'US',
        currencyCode: "USD",
        totalPriceStatus: "FINAL",
        totalPrice: "12.00",
        totalPriceLabel: "Total"
      };
    }

    /**
     * Provide a key value store for shippping options.
     */
    function getShippingCosts() {
            return {
        "shipping-001": "0.00",
        "shipping-002": "1.99",
        "shipping-003": "10.00"
      }
    }

    /**
     * Provide Google Pay API with shipping address parameters when using dynamic buy flow.
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ShippingAddressParameters|ShippingAddressParameters}
     * @returns {object} shipping address details, suitable for use as shippingAddressParameters property of PaymentDataRequest
     */
    function getGoogleShippingAddressParameters() {
            return  {
            allowedCountryCodes: ['US'],
        phoneNumberRequired: true
      };
    }

    /**
     * Provide Google Pay API with shipping options and a default selected shipping option.
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ShippingOptionParameters|ShippingOptionParameters}
     * @returns {object} shipping option parameters, suitable for use as shippingOptionParameters property of PaymentDataRequest
     */
    function getGoogleDefaultShippingOptions() {
            return {
          defaultSelectedOptionId: "shipping-001",
          shippingOptions: [
            {
              "id": "shipping-001",
              "label": "Free: Standard shipping",
              "description": "Free Shipping delivered in 5 business days."
            },
            {
              "id": "shipping-002",
              "label": "$1.99: Standard shipping",
              "description": "Standard shipping delivered in 3 business days."
            },
            {
              "id": "shipping-003",
              "label": "$10: Express shipping",
              "description": "Express shipping delivered in 1 business day."
            },
          ]
      };
    }

    /**
     * Provide Google Pay API with a payment data error.
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentDataError|PaymentDataError}
     * @returns {object} payment data error, suitable for use as error property of PaymentDataRequestUpdate
     */
    function getGoogleUnserviceableAddressError() {
            return {
        reason: "SHIPPING_ADDRESS_UNSERVICEABLE",
        message: "Cannot ship to the selected address",
        intent: "SHIPPING_ADDRESS"
            };
    }

    /**
     * Prefetch payment data to improve performance
     *
     * @see {@link https://developers.google.com/pay/api/web/reference/client#prefetchPaymentData|prefetchPaymentData()}
     */
    function prefetchGooglePaymentData() {
      const paymentDataRequest = getGooglePaymentDataRequest();
      // transactionInfo must be set but does not affect cache
      paymentDataRequest.transactionInfo = {
        totalPriceStatus: 'NOT_CURRENTLY_KNOWN',
        currencyCode: 'USD'
      };
      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.prefetchPaymentData(paymentDataRequest);
    }

    /**
     * Show Google Pay payment sheet when Google Pay payment button is clicked
     */
    function onGooglePaymentButtonClicked() {
      const paymentDataRequest = getGooglePaymentDataRequest();
      paymentDataRequest.transactionInfo = getGoogleTransactionInfo();

      const paymentsClient = getGooglePaymentsClient();
      paymentsClient.loadPaymentData(paymentDataRequest);
    }

    /**
     * Process payment data returned by the Google Pay API
     *
     * @param {object} paymentData response from Google Pay API after user approves payment
     * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData|PaymentData object reference}
     */
    function processPayment(paymentData) {
    	return new Promise(function(resolve, reject) {
      	setTimeout(function() {
        	// show returned data in developer console for debugging
       	 console.log(paymentData);
      		// @todo pass payment token to your gateway to process payment
      		paymentToken = paymentData.paymentMethodData.tokenizationData.token;

        	resolve({});
        }, 3000);
      });
    }</script>
    <script async
      src="https://pay.google.com/gp/p/js/pay.js"
      onload="onGooglePayLoaded()"></script>