Руководство

Из этого руководства вы узнаете, как интегрировать веб-приложение с 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'
  }
};

Замените значения example и exampleGatewayMerchantId значениями, подходящими для вашего поставщика платежных услуг. В таблице ниже приведены значения gateway и gatewayMerchantId для конкретных поставщиков.

Шлюз Значения параметров и ссылки на документацию
ACI

  "gateway": "aciworldwide"
  "gatewayMerchantId": "YOUR_ENTITY_ID"

Документация для разработчиков

Adyen

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

Документация для разработчиков

Альфа-Банк

  "gateway": "alfabank"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Документация для разработчиков

АППЕКС

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

Документация для разработчиков

Assist

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

Документация для разработчиков

Биллинговые системы

  "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"

Документация для разработчиков

Merchant Services (Chase)

  "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"

Документация для разработчиков

ConcordPay

  "gateway": "concordpay"
  "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"

Документация для разработчиков

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"

Документация для разработчиков

JudoPay

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

Документация для разработчиков отсутствует

Kassa

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

Документация для разработчиков

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"

Документация для разработчиков

МОБИ.Деньги

  "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"

Документация для разработчиков

Деньги@Mail.Ru

  "gateway": "moneymailru"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Документация для разработчиков

МультиКарта

  "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 (ранее STPath, Pay2Go)

  "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"

Документация для разработчиков

PayFacto

  "gateway": "payfacto"
  "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"

Документация для разработчиков

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"

Документация для разработчиков

PayWay

  "gateway": "payway"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Документация для разработчиков

Platon

  "gateway": "platon"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Документация для разработчиков

Portmone

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

Документация для разработчиков

Przelewy24

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

Документация для разработчиков

Radial

  "gateway": "radial"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Документация для разработчиков

RBK.money

  "gateway": "rbkmoney"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Документация для разработчиков

Redsys

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

Документация для разработчиков

Сбербанк

  "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"

Документация для разработчиков отсутствует

Тинькофф

  "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"

Документация для разработчиков

Яндекс.Касса

  "gateway": "yandexcheckout"
  "gatewayMerchantId": "YOUR_SHOP_ID"

Документация для разработчиков

Тип токенизации PAYMENT_GATEWAY – наиболее распространенный способ внедрения Google Pay API для оплаты картой. Если ваш поставщик платежных услуг не поддерживается, попробуйте выполнить прямую интеграцию. Более подробную информацию можно найти в документации по прямой токенизации.

Шаг 3. Задайте поддерживаемые платежные системы

Выберите поддерживаемые вашим сайтом платежные системы. Пример кода:

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

Google Pay API может показать результаты поиска карт в аккаунте Google (PAN_ONLY) и/или токенов на устройстве Android, которое прошло аутентификацию с помощью криптограммы 3-D Secure (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. Подробнее о том, как добавить тип PAYPAL в качестве способа оплаты в Google Pay, написано в документации для разработчиков PayPal.

Шаг 5. Загрузите библиотеку JavaScript для Google Pay API

Выполните следующие действия:

  1. Добавьте на свой сайт код JavaScript, размещенный на серверах Google. Пример кода:
    <script
      async
      src="https://pay.google.com/gp/p/js/pay.js"
      onload="console.log('TODO: add onload function')">
    </script>
  2. После загрузки библиотеки JavaScript для Google Pay API инициализируйте объект PaymentsClient. На начальных этапах разработки будет использоваться среда TEST, имитирующая структуру реакции на платеж и использующая пробные способы оплаты, с помощью которых будет невозможно совершить реальную транзакцию. Пример кода:
    const paymentsClient =
        new google.payments.api.PaymentsClient({environment: 'TEST'});

    Подробная информация о требованиях для среды PRODUCTION, использующей действительные способы оплаты, есть в разделе Контрольный список интеграции.

Шаг 6. Определите готовность к оплате с помощью 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 и вашим сайтом. Более подробную информацию о доступных типах кнопок, цветах и требованиях к отображению на экранах можно найти в разделе Правила фирменного оформления Google.

Пример кода для кнопки оплаты:

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

Шаг 8. Создайте объект PaymentDataRequest

Чтобы создать объект PaymentDataRequest, выполните следующие действия:

  1. Создайте объект JavaScript с информацией о поддержке вашим сайтом 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 merchantId в среде TEST. Подробные сведения и инструкции по замене значения TEST merchantId приведены в разделе MerchantInfo. Пример кода с названием продавца для пользователей:
    paymentDataRequest.merchantInfo = {
      merchantName: 'Example Merchant'
      merchantId: '12345678901234567890'
    };
    

Шаг 9. Настройте обработчик жестов пользователей

Выполните следующие действия:

  1. Настройте обработчик жестов для кнопки оплаты. Обработчик жестов мгновенно вызывает loadPaymentData() после нажатия кнопки оплаты через Google Pay.
  2. Проверьте ответ 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. Предварительно загрузите платежные данные до взаимодействия пользователя с приложением (необязательно)

Чтобы сократить время оформления платежа, загрузите на сайт платежные данные из Google Pay API, прежде чем будет вызван метод loadPaymentData(). Вот пример:

paymentsClient.prefetchPaymentData(paymentDataRequest);

Шаг 11. Настройте авторизацию платежей (необязательно)

Авторизация платежа нужна для запуска процесса оплаты и подтверждения ее статуса. Вот как происходит настройка авторизации платежей:

  1. В объекте PaymentOptions зарегистрируйте обратный вызов onPaymentAuthorized().
  2. Вызовите функцию loadPaymentData() с намерением обратного вызова PAYMENT_AUTHORIZATION.
  3. Реализуйте обработчик onPaymentAuthorized().

Регистрация обратного вызова onPaymentAuthorized

Ниже приведен пример того, как регистрируется обратный вызов onPaymentAuthorized.

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

Загрузка платежных данных с намерениями обратного вызова

В приведенном ниже фрагменте кода показано, как инициализировать страницу оплаты с авторизацией платежа:

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

paymentDataRequest.callbackIntents = ["PAYMENT_AUTHORIZATION"];

Обработка обратного вызова onPaymentAuthorized

Функция onPaymentAuthorized() вызывается объектом PaymentData после того, как пользователь одобрит оплату жестом, например нажмет кнопку Оплатить.

Обратный вызов возвращает значение 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. В объекте PaymentOptions зарегистрируйте обработчики обратного вызова onPaymentAuthorized и onPaymentDataChanged.
  2. Вызовите функцию loadPaymentData() с намерениями обратного вызова. Подробные сведения можно посмотреть в этом примере.
  3. Реализуйте обработчики onPaymentAuthorized и onPaymentDataChanged.

Регистрация обратного вызова PaymentData

Для динамического обновления цен требуется зарегистрировать функцию обратного вызова в объекте PaymentsClientpaymentOptions.

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

Загрузка платежных данных с намерениями обратного вызова

В приведенном ниже фрагменте кода показано, как инициализировать страницу оплаты с обязательным адресом доставки и способами доставки:

const paymentDataRequest = Object.assign({}, baseRequest);
paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
paymentDataRequest.transactionInfo = getGoogleTransactionInfo();
paymentDataRequest.merchantInfo = {
  merchantId: '12345678901234567890',
  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);
  });
}

Объедините части кода

Примеры кода, представленные в этом разделе, охватывают все процессы интеграции с использованием библиотеки JavaScript для 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: '12345678901234567890',
    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: '12345678901234567890',
    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: '12345678901234567890',
    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>