Если ваше приложение Android распространяется через Google Play, вы можете интегрировать его с Google Pay API и настроить в нем поддержку платежных карт. О том, как это сделать, рассказывается ниже.
- Шаг 1. Укажите версию Google Pay API
- Шаг 2. Запросите токен для поставщика платежных услуг
- Шаг 3. Задайте поддерживаемые платежные системы
- Шаг 4. Укажите поддерживаемые способы оплаты
- Шаг 5. Создайте экземпляр объекта PaymentsClient
- Шаг 6. Определите готовность к оплате с помощью Google Pay API
- Шаг 7. Создайте объект PaymentDataRequest
- Шаг 8. Настройте обработчик жестов пользователей
- Шаг 9. Обработайте объект ответа
- Выводы
Шаг 1. Укажите версию Google Pay API
Укажите версию Google Pay API, которая используется в вашем приложении. Основной и дополнительный номера версии указываются в ответе и влияют на то, какой набор полей будет проверяться во всех объектах.
Создайте базовый объект запроса со свойствами, имеющимися во всех прочих объектах запроса.
Kotlin
private val baseRequest = JSONObject().apply { put("apiVersion", 2) put("apiVersionMinor", 0) }
Java
private static JSONObject getBaseRequest() throws JSONException { return new JSONObject().put("apiVersion", 2).put("apiVersionMinor", 0); }
Шаг 2. Запросите токен для поставщика платежных услуг
Компания Google шифрует информацию о выбранной карте покупателя, чтобы обеспечить безопасную обработку данных поставщиком платежных услуг.
Kotlin
private fun gatewayTokenizationSpecification(): JSONObject { return JSONObject().apply { put("type", "PAYMENT_GATEWAY") put("parameters", JSONObject(mapOf( "gateway" to "example", "gatewayMerchantId" to "exampleGatewayMerchantId"))) } }
Java
private static JSONObject getGatewayTokenizationSpecification() throws JSONException { return new JSONObject() {{ put("type", "PAYMENT_GATEWAY"); put("parameters", new JSONObject() {{ put("gateway", "example"); put("gatewayMerchantId", "exampleGatewayMerchantId"); }}); }}; }
Замените значения example и exampleGatewayMerchantId значениями, подходящими для вашего поставщика платежных услуг. В таблице ниже приведены значения gateway
и gatewayMerchantId
для конкретных поставщиков.
Шлюз | Значения параметров и ссылки на документацию |
---|---|
accept.blue |
"gateway": "acceptblue" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ACI |
"gateway": "aciworldwide" "gatewayMerchantId": "YOUR_ENTITY_ID" |
ACpay |
"gateway": "acpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Acquired.com |
"gateway": "acquired" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Adyen |
"gateway": "adyen" "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME" |
Airba Pay |
"gateway": "airbapay" "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME" |
Airwallex |
"gateway": "airwallex" "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME" |
Альфа-Банк |
"gateway": "alfabank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
AllPayments |
"gateway": "allpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
alticepay |
"gateway": "alticepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Anedot |
"gateway": "anedot" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ApcoPay |
"gateway": "apcopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
АППЕКС |
"gateway": "epos" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
AsiaBill |
"gateway": "asiabill" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
Assist |
"gateway": "assist" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Assist Belarus |
"gateway": "belassist" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Assist Kazakhstan |
"gateway": "assistkz" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Aurus |
"gateway": "auruspay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Axerve |
"gateway": "gestpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Bank 131 |
"gateway": "bank131" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Bank Vostok |
"gateway": "bankvostok" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Barclaycard |
"gateway": "barclayssmartpayadvance" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Barion |
"gateway": "barion" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
BCC.KZ |
"gateway": "bccpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
bePaid |
"gateway": "ecomcharge" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Платежные системы |
"gateway": "billingsystems" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Bizzon |
"gateway": "bizzon" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Blocks |
"gateway": "blocks" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Bluefin |
"gateway": "bluefin" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Blue Media |
"gateway": "bluemedia" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
BlueSnap |
"gateway": "bluesnap" "gatewayMerchantId": "YOUR_shopToken" |
BPC |
"gateway": "bpcpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
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" |
Buya |
"gateway": "buya" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CardCom |
"gateway": "cardcom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CardConnect |
"gateway": "cardconnect" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Cardknox |
"gateway": "cardknox" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Cardstream |
"gateway": "crst" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Cashflows |
"gateway": "cashflowsgateway" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Cathay United Bank |
"gateway": "cathaybk" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Cecabank |
"gateway": "cecabank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Celerispay |
"gateway": "celerispay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CentralPay |
"gateway": "centralpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Chargehive |
"gateway": "chargehive" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CharityEngine |
"gateway": "charityengine" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Merchant Services (Chase) |
"gateway": "chase" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Checkout.com |
"gateway": "checkoutltd" "gatewayMerchantId": "YOUR_PUBLIC_KEY" |
CityPay |
"gateway": "citypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Cloud9 Payment Gateway (C9PG) |
"gateway": "c9pg" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CloudPayments |
"gateway": "cloudpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Computop |
"gateway": "computop" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ConcordPay |
"gateway": "concordpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Connectum |
"gateway": "connectum" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ConnexPay |
"gateway": "connexpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Corefy |
"gateway": "paycoreio" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Credorax |
"gateway": "credorax" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CrossPay |
"gateway": "crosspay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CSG Forte |
"gateway": "csgforte" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CTBC Bank |
"gateway": "ctbcbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CURO Payments |
"gateway": "curopayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
CyberSource |
"gateway": "cybersource" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
danube.pay |
"gateway": "danubepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Datacap Systems, Inc. |
"gateway": "datacap systems inc." "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Datatrans |
"gateway": "datatrans" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Deutsche Bank AG |
"gateway": "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" окументация для разработчиков отсутствует |
Deutsche Bank – Merchant Solutions |
"gateway": "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
DG Financial Technology, Inc. |
"gateway": "veritrans" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Digital Finance |
"gateway": "digitalfinance" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
dLocal |
"gateway": "dlocal" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
DNA Payments |
"gateway": "dnapayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Dojo |
"gateway": "dojo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Dotpay |
"gateway": "dotpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
e-SiTef – Software Express |
"gateway": "softwareexpress" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
easycard |
"gateway": "easycard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
EasyPay |
"gateway": "easypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
EBANX |
"gateway": "ebanx" "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY" |
EBANX Pay |
"gateway": "ebanxpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
eCard |
"gateway": "ecard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ECOMMPAY |
"gateway": "ecommpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Ecopaynet |
"gateway": "ecopaynet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ECPay |
"gateway": "ecpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
eGHL |
"gateway": "eghl" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Elavon (Converge) |
"gateway": "convergepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Emerchantpay |
"gateway": "emerchantpay" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
emspay |
"gateway": "emsonline" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
Encoded |
"gateway": "encoded" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
EpicPay |
"gateway": "epicpay" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
Espago |
"gateway": "espago" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
EveryPay |
"gateway": "everypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
EVONET |
"gateway": "cardinfolink" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
EvoPay |
"gateway": "evopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Evo Payment Gateway |
"gateway": "evopaymentgateway" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
exactly.com |
"gateway": "exactly" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Exact Payments |
"gateway": "exactpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Fat Zebra |
"gateway": "fatzebra" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Fenige |
"gateway": "fenige" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Fibonatix |
"gateway": "fibonatixparagon" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Finix |
"gateway": "finix" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
First American by Deluxe |
"gateway": "firstpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
First Data (Payeezy) |
"gateway": "firstdata" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
FIS Biller Solutions |
"gateway": "fisglobalbsp" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Fluid Pay |
"gateway": "fluidpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ForteBank |
"gateway": "fortebank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Банк "Фридом Финанс" |
"gateway": "axayscom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
FreedomPay |
"gateway": "freedompay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
FreedomPay.Money |
"gateway": "payboxmoney" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Freepay |
"gateway": "freepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Frontstream |
"gateway": "frontstreampayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
GBPayments |
"gateway": "gbpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
GETTRX |
"gateway": "globalelectronictechnology" "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" |
Good Idea Technologies |
"gateway": "git" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
GoPay |
"gateway": "gopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
GP Webpay |
"gateway": "gpwebpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
Gr4vy |
"gateway": "gr4vy" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Gravity Payments |
"gateway": "gravitypayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Halyk Bank |
"gateway": "halykbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Helcim |
"gateway": "helcim" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
HIPS |
"gateway": "hips" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
HiTrust |
"gateway": "hitrustpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Hyp |
"gateway": "hyp" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
icard |
"gateway": "icardwallet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
imoje |
"gateway": "imoje" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Impaya |
"gateway": "impayarus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ИнПлат |
"gateway": "inplat" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
InstaMed |
"gateway": "instamed" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
IntellectMoney |
"gateway": "intellectmoney" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Interactive Transaction Solutions |
"gateway": "interactivets" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Interswitch Payment Gateway |
"gateway": "interswitch" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Intervale |
"gateway": "intervale" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ioka fintech |
"gateway": "ioka" "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" |
JetPay |
"gateway": "jetpay" "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" |
Life Pay |
"gateway": "lifepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Limepay |
"gateway": "limepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
LiqPay |
"gateway": "liqpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Littlepay |
"gateway": "littlepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
LogPay |
"gateway": "logpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Loyale |
"gateway": "loyale" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Lyra |
"gateway": "lyra" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
maib |
"gateway": "maibecomm" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Mandarin |
"gateway": "mandarin" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Mastercard Payment Gateway Services |
"gateway": "mpgs" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MerchantE |
"gateway": "merchante" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Merchant Warrior |
"gateway": "merchantwarrior" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Minsait Payments Systems |
"gateway": "minsaitpaymentsgateway" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MITEC |
"gateway": "mitecmx" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MIXPLAT |
"gateway": "mixplat" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
МОБИ.Деньги |
"gateway": "mobimoney" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
МодульБанк |
"gateway": "modulbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Molpay |
"gateway": "molpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
Mondido |
"gateway": "mondido" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Monei |
"gateway": "monei" "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" |
MultiSafepay |
"gateway": "multisafepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Mundipagg |
"gateway": "mundipagg" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MyCheck |
"gateway": "mycheck" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MyChoice2Pay |
"gateway": "mychoice2pay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MyFatoorah |
"gateway": "myfatoorah" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
MyPay |
"gateway": "mypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
myPOS |
"gateway": "mypos" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
N&TS Group |
"gateway": "netsgroup" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
NCCC |
"gateway": "nccc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Neon Pay |
"gateway": "neonpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Netopia |
"gateway": "netopia" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
NewebPay (ранее STPath, Pay2Go) |
"gateway": "newebpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Newtech |
"gateway": "newtechmobile" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Nexi |
"gateway": "nexi" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
NMI |
"gateway": "gatewayservices" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Novalnet |
"gateway": "novalnet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
NTT DATA |
"gateway": "nttdatahk" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Nuvei |
"gateway": "nuvei" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Oceanpayment |
"gateway": "oceanpayment" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Omise |
"gateway": "omise" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
One Inc |
"gateway": "oneinc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Онэлия |
"gateway": "onelya" "gatewayMerchantId": "YOUR_GATWAY_MERCHANT_ID" |
Onerway |
"gateway": "ronghan" "gatewayMerchantId": "YOUR_GATWAY_MERCHANT_ID" |
OnPay |
"gateway": "onpayio" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Oschadbank |
"gateway": "oschadbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
pagarme |
"gateway": "pagarme" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payarc |
"gateway": "payarc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pay.com |
"gateway": "paycom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PAYCOMET |
"gateway": "paycomet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paydock |
"gateway": "paydock" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayEase |
"gateway": "payeasenet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayFabric |
"gateway": "payfabric" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayFacto |
"gateway": "payfacto" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
paygent |
"gateway": "paygent" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payhub |
"gateway": "payhub" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayLane |
"gateway": "paylane" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payler |
"gateway": "payler" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayLink® |
"gateway": "paylink" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payload |
"gateway": "payload" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paymark |
"gateway": "paymark" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayMaster |
"gateway": "paymaster" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payment Fusion |
"gateway": "paymentfusion" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paymentwall |
"gateway": "paymentwall" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paymo |
"gateway": "paymo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paymtech |
"gateway": "paymtech" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayNearMe |
"gateway": "paynearme" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payneteasy |
"gateway": "payneteasy" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pay.nl |
"gateway": "paynl" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paynopain |
"gateway": "paynopain" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayOnline |
"gateway": "payonline" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayPlus |
"gateway": "payplus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payrails |
"gateway": "payrails" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payrexx |
"gateway": "payrexx" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayRiff |
"gateway": "payriff" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payrix |
"gateway": "payrix" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paysafe |
"gateway": "paysafe" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payscout |
"gateway": "payscout" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paysend Business |
"gateway": "paysend" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paysoft |
"gateway": "paysoft" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pay360 |
"gateway": "pay360" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayTech Ukraine |
"gateway": "paytech" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paythru |
"gateway": "paythru" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Payture |
"gateway": "payture" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayU |
"gateway": "payu" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayU LATAM |
"gateway": "payulatam" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PAYUNi |
"gateway": "payuni" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayU Romania |
"gateway": "payuro" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayU Russia |
"gateway": "payuru" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PayWay |
"gateway": "payway" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Paywiser |
"gateway": "paywiser" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pelecard |
"gateway": "pelecard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pikassa |
"gateway": "pikassa" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PingPong |
"gateway": "pingpongx" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pin Payments |
"gateway": "pinpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Planet |
"gateway": "cccpayment" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Plategka.com |
"gateway": "plategkacom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Платон |
"gateway": "platon" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Pomelo |
"gateway": "pomelopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Portmone |
"gateway": "portmonecom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Primer |
"gateway": "primer" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ProcessOut |
"gateway": "processout" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Przelewy24 |
"gateway": "przelewy24" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Промсвязьбанк |
"gateway": "psbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
ПСКБ |
"gateway": "pscbru" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PXP Financial |
"gateway": "pxpfinancial" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Qenta Payment CEE |
"gateway": "qenta" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
QIWI |
"gateway": "qiwi" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Qualpay |
"gateway": "qualpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
QuickPay |
"gateway": "quickpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Qvalent |
"gateway": "qvalent" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Radial |
"gateway": "radial" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Rapyd |
"gateway": "rapyd" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
RBK.money |
"gateway": "rbkmoney" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Rebail Capital |
"gateway": "rebailcapital" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Rebilly |
"gateway": "Rebilly" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Recurly |
"gateway": "recurly" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Reddot |
"gateway": "reddotpayment" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Rede |
"gateway": "rede" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Redsys |
"gateway": "redsys" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Reepay |
"gateway": "reepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
RocketGate |
"gateway": "rocketgate" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Банк Русский Стандарт |
"gateway": "rsb" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Ryft |
"gateway": "ryft" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Saferpay |
"gateway": "worldlinesaferpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Сбербанк |
"gateway": "sberbank" "gatewayMerchantId": "YOUR_ORGANIZATION_NAME" |
Sense Bank |
"gateway": "sensebank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
SensePass |
"gateway": "sensepass" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
SH Start High |
"gateway": "shstartpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
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" |
Splitit |
"gateway": "splitit" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Spreedly |
"gateway": "spreedly" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Square |
"gateway": "square" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Stancer |
"gateway": "stancer" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Stripe |
"gateway": "stripe" "stripe:version": "2018-10-31" "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY" |
Suntech |
"gateway": "esafe" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Svea Bank |
"gateway": "svea" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Swedbank Pay |
"gateway": "payexswedbankpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TabaPay |
"gateway": "tabapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TapPay (Cherri Tech) |
"gateway": "tappay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TapPayments |
"gateway": "tappayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
tarlanpayments |
"gateway": "tarlanpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TAS Link |
"gateway": "taslink" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Tatra banka (CardPay) |
"gateway": "tatrabanka" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
TEKO |
"gateway": "teko" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
theMAP |
"gateway": "themap" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Тинькофф |
"gateway": "tinkoff" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TPay |
"gateway": "tpaycom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TPay.com |
"gateway": "tpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Transact Campus |
"gateway": "transactcampus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Transaction Services Network |
"gateway": "tns" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Transpayrent |
"gateway": "transpayrent" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Tranzila |
"gateway": "tranzila" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Tranzzo |
"gateway": "tranzzo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Truevo |
"gateway": "truevo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
TrustPay |
"gateway": "trustpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Trust Payments |
"gateway": "trustpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Tuna |
"gateway": "tuna" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
2can&ibox |
"gateway": "twocan" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
UAPAY |
"gateway": "uapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
УБРиР |
"gateway": "ubrrpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
UkrGasBank Pay |
"gateway": "ukrgasbankpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
unitedfinancialcorporation |
"gateway": "unitedfinancialcorporation" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Uniteller |
"gateway": "uniteller" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Unitpay |
"gateway": "unitpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Unlimint |
"gateway": "unlimint" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Unzer Austria |
"gateway": "unzeraustria" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
UPC |
"gateway": "upc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
USAePay |
"gateway": "usaepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
UseePay |
"gateway": "useepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Valitor |
"gateway": "valitor" "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" |
Verestro |
"gateway": "verestro" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Very Good Security |
"gateway": "verygoodsecurity" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Vindicia |
"gateway": "vindicia" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Viva Wallet |
"gateway": "vivawallet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
VTEX |
"gateway": "vtex" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Walletto |
"gateway": "walletto" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
WayForPay |
"gateway": "wayforpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
WEAT |
"gateway": "weatpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
WhenThen |
"gateway": "whenthen" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Windcave |
"gateway": "windcave" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Wirebank |
"gateway": "wirebank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Wirecard |
"gateway": "wirecard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
WOOPPAY |
"gateway": "wooppay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Worldline (GlobalCollect) |
"gateway": "globalcollect" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Worldline – Ingenico (онлайн-оплата Worldline) |
"gateway": "worldlineingenicoogone" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Worldline Sips |
"gateway": "wlsips" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Worldnet |
"gateway": "worldnet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Worldpay |
"gateway": "worldpay" "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID" |
Wpay |
"gateway": "wpayaus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
WSPay |
"gateway": "wspay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
YIĞIM Payment System |
"gateway": "yigim" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" Документация для разработчиков отсутствует |
ЮKassa |
"gateway": "yoomoney" "gatewayMerchantId": "YOUR_SHOP_ID" |
your payment |
"gateway": "yourpayment" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Z-credit |
"gateway": "zcredit" "gatewayMerchantId": "YOUR_SHOP_ID" |
ZEN.com |
"gateway": "zen" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
Zest |
"gateway": "zestpayment" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
example
– допустимое название шлюза в тестовой среде. Если вы хотите протестировать API, можно вставить представленный выше код без изменений. При использовании шлюза example
ваш сайт не будет получать данные карты для осуществления транзакции, однако путь пользователя будет выглядеть как обычно.Тип токенизации PAYMENT_GATEWAY
– наиболее распространенный способ внедрения Google Pay API для оплаты картой. Если ваш поставщик платежных услуг не поддерживается, попробуйте выполнить интеграцию типа DIRECT
. Более подробную информацию можно найти в документации.
Шаг 3. Задайте поддерживаемые платежные системы
Выберите платежные системы, карты которых принимаются в вашем приложении.
Kotlin
private val allowedCardNetworks = JSONArray(listOf( "AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"))
Java
private static JSONArray getAllowedCardNetworks() { return new JSONArray() .put("AMEX") .put("DISCOVER") .put("INTERAC") .put("JCB") .put("MASTERCARD") .put("VISA"); }
Google Pay API может показать результаты поиска карт в архивах Google.com (PAN_ONLY
) или токен устройства на устройстве Android, аутентифицированном с помощью криптограммы 3-D Secure (CRYPTOGRAM_3DS
).
Kotlin
private val allowedCardAuthMethods = JSONArray(listOf( "PAN_ONLY", "CRYPTOGRAM_3DS"))
Java
private static JSONArray getAllowedCardAuthMethods() { return new JSONArray() .put("PAN_ONLY") .put("CRYPTOGRAM_3DS"); }
Дополнительную информацию можно найти в разделе CardParameters
в сведениях об объектах JSON. Список поддерживаемых токенов для устройств Android можно получить через шлюз, а информацию о поддерживаемых платежных системах – у обработчика платежей.
- Все транзакции Google Pay должны проходить те же процедуры проверки и оценки рисков, что и другие ваши платежные операции. Проверки, выполняемые в Google Pay, не заменяют ваши процедуры управления рисками.
- Если вы используете
PAN_ONLY
, требуйте аутентификацию через 3-D Secure при выполнении транзакций Google Pay PANPAN_ONLY
так же, как и для обычных транзакций по картам.
Шаг 4. Укажите поддерживаемые способы оплаты
Указать, что ваше приложение поддерживает способ оплаты CARD
, можно через сочетание методов аутентификации и платежных систем.
Kotlin
private fun baseCardPaymentMethod(): JSONObject { return JSONObject().apply { val parameters = JSONObject().apply { put("allowedAuthMethods", allowedCardAuthMethods) put("allowedCardNetworks", allowedCardNetworks) put("billingAddressRequired", true) put("billingAddressParameters", JSONObject().apply { put("format", "FULL") }) } put("type", "CARD") put("parameters", parameters) } }
Java
private static JSONObject getBaseCardPaymentMethod() throws JSONException { JSONObject cardPaymentMethod = new JSONObject(); cardPaymentMethod.put("type", "CARD"); JSONObject parameters = new JSONObject(); parameters.put("allowedAuthMethods", getAllowedCardAuthMethods()); parameters.put("allowedCardNetworks", getAllowedCardNetworks()); // Optionally, you can add billing address/phone number associated with a CARD payment method. parameters.put("billingAddressRequired", true); JSONObject billingAddressParameters = new JSONObject(); billingAddressParameters.put("format", "FULL"); parameters.put("billingAddressParameters", billingAddressParameters); cardPaymentMethod.put("parameters", parameters); return cardPaymentMethod; }
Расширьте объект базового способа оплаты картой, чтобы указать, какая информация (включая токенизированные платежные данные) должна возвращаться в приложение.
Kotlin
private fun cardPaymentMethod(): JSONObject { val cardPaymentMethod = baseCardPaymentMethod() cardPaymentMethod.put("tokenizationSpecification", gatewayTokenizationSpecification()) return cardPaymentMethod }
Java
private static JSONObject getCardPaymentMethod() throws JSONException { JSONObject cardPaymentMethod = getBaseCardPaymentMethod(); cardPaymentMethod.put("tokenizationSpecification", getGatewayTokenizationSpecification()); return cardPaymentMethod; }
Дополнительную информацию о поддерживаемых параметрах parameters
можно найти в разделе CardParameters
в сведениях об объектах JSON.
Помимо карт (CARD
), в Google Pay поддерживается способ оплаты PAYPAL
. Подробнее о том, как добавить счет PayPal в Google Pay, написано здесь.
Шаг 5. Создайте экземпляр объекта PaymentsClient
Создайте экземпляр PaymentsClient
в методе onCreate
объекта Activity
. Экземпляр PaymentsClient
используется для взаимодействия с Google Pay API.
Kotlin
fun createPaymentsClient(activity: Activity): PaymentsClient { val walletOptions = Wallet.WalletOptions.Builder() .setEnvironment(Constants.PAYMENTS_ENVIRONMENT) .build() return Wallet.getPaymentsClient(activity, walletOptions) }
Java
public static PaymentsClient createPaymentsClient(Activity activity) { Wallet.WalletOptions walletOptions = new Wallet.WalletOptions.Builder().setEnvironment(Constants.PAYMENTS_ENVIRONMENT).build(); return Wallet.getPaymentsClient(activity, walletOptions); }
Шаг 6. Определите готовность к оплате с помощью Google Pay API
Добавьте разрешенные способы оплаты в базовый объект запроса с помощью следующего фрагмента кода:
Kotlin
fun isReadyToPayRequest(): JSONObject? { return try { baseRequest.apply { put("allowedPaymentMethods", JSONArray().put(baseCardPaymentMethod())) } } catch (e: JSONException) { null } }
Java
public static Optional<JSONObject> getIsReadyToPayRequest() { try { JSONObject isReadyToPayRequest = getBaseRequest(); isReadyToPayRequest.put( "allowedPaymentMethods", new JSONArray().put(getBaseCardPaymentMethod())); return Optional.of(isReadyToPayRequest); } catch (JSONException e) { return Optional.empty(); } }
Прежде чем отображать кнопку Google Pay, вызовите isReadyToPay API, чтобы определить, может ли пользователь расплатиться через Google Pay API. Полный список свойств конфигурации можно найти в документации JSON по объекту IsReadyToPayRequest
.
Kotlin
private fun possiblyShowGooglePayButton() { val isReadyToPayJson = PaymentsUtil.isReadyToPayRequest() ?: return val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString()) ?: return // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an // OnCompleteListener to be triggered when the result of the call is known. val task = paymentsClient.isReadyToPay(request) task.addOnCompleteListener { completedTask -> try { completedTask.getResult(ApiException::class.java)?.let(::setGooglePayAvailable) } catch (exception: ApiException) { // Process error Log.w("isReadyToPay failed", exception) } } }
Java
private void possiblyShowGooglePayButton() { final Optional<JSONObject> isReadyToPayJson = PaymentsUtil.getIsReadyToPayRequest(); if (!isReadyToPayJson.isPresent()) { return; } // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an // OnCompleteListener to be triggered when the result of the call is known. IsReadyToPayRequest request = IsReadyToPayRequest.fromJson(isReadyToPayJson.get().toString()); Task<Boolean> task = paymentsClient.isReadyToPay(request); task.addOnCompleteListener(this, new OnCompleteListener<Boolean>() { @Override public void onComplete(@NonNull Task<Boolean> task) { if (task.isSuccessful()) { setGooglePayAvailable(task.getResult()); } else { Log.w("isReadyToPay failed", task.getException()); } } }); }
Как показывает пример, лучше всего указать Google Pay в качестве способа оплаты только после получения положительного результата от функции isReadyToPay
. Как правило, кнопка Google Pay отображается в макете include
, когда вы применяете способ оплаты. Более подробную информацию о доступных кнопках оплаты, логотипах и метках Google Pay можно найти в правилах фирменного оформления Google.
Шаг 7. Создайте объект PaymentDataRequest
Объект JSON PaymentDataRequest
описывает информацию, которую нужно запросить у покупателя на странице оплаты Google Pay.
Укажите данные о цене сделки и о ее статусе. Более подробная информация приведена в документации JSON по объекту TransactionInfo
.
В следующем примере показано, как запросить цену, ее статус и сведения о валюте транзакции.
< aside class="warning">Важно! Продавцам, которые обрабатывают транзакции в Европейской экономической зоне (ЕЭЗ) или других странах, где требуется строгая аутентификация клиента (SCA), необходимо добавлять параметрыcountryCode
, totalPrice
и merchantName
в соответствии с требованиями SCA.
Kotlin
private fun getTransactionInfo(price: String): JSONObject { return JSONObject().apply { put("totalPrice", price) put("totalPriceStatus", "FINAL") put("countryCode", Constants.COUNTRY_CODE) put("currencyCode", Constants.CURRENCY_CODE) } }
Java
private static JSONObject getTransactionInfo(String price) throws JSONException { JSONObject transactionInfo = new JSONObject(); transactionInfo.put("totalPrice", price); transactionInfo.put("totalPriceStatus", "FINAL"); transactionInfo.put("countryCode", Constants.COUNTRY_CODE); transactionInfo.put("currencyCode", Constants.CURRENCY_CODE); transactionInfo.put("checkoutOption", "COMPLETE_IMMEDIATE_PURCHASE"); return transactionInfo; }
Укажите название продавца для пользователей. Более подробная информация приведена в документации JSON по объекту MerchantInfo
.
В примере ниже показано, как получить название продавца.
Kotlin
private val merchantInfo: JSONObject = JSONObject().put("merchantName", "Example Merchant")
Java
private static JSONObject getMerchantInfo() throws JSONException { return new JSONObject().put("merchantName", "Example Merchant"); }
Выберите базовый объект запроса в качестве нового объекта JSON PaymentDataRequest
.
Добавьте способы оплаты, поддерживаемые вашим приложением, с указанием конфигураций дополнительных данных, ожидаемых в ответе. Укажите данные о транзакции и о продавце, отправившем запрос.
В примере ниже показано, как запросить платежные данные:
Kotlin
fun getPaymentDataRequest(price: String): JSONObject? { try { return baseRequest.apply { put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod())) put("transactionInfo", getTransactionInfo(price)) put("merchantInfo", merchantInfo) // An optional shipping address requirement is a top-level property of the // PaymentDataRequest JSON object. val shippingAddressParameters = JSONObject().apply { put("phoneNumberRequired", false) put("allowedCountryCodes", JSONArray(listOf("US", "GB"))) } put("shippingAddressParameters", shippingAddressParameters) put("shippingAddressRequired", true) } } catch (e: JSONException) { return null } }
Java
public static Optional<JSONObject> getPaymentDataRequest(long priceCents) { final String price = PaymentsUtil.centsToString(priceCents); try { JSONObject paymentDataRequest = PaymentsUtil.getBaseRequest(); paymentDataRequest.put( "allowedPaymentMethods", new JSONArray().put(PaymentsUtil.getCardPaymentMethod())); paymentDataRequest.put("transactionInfo", PaymentsUtil.getTransactionInfo(price)); paymentDataRequest.put("merchantInfo", PaymentsUtil.getMerchantInfo()); /* An optional shipping address requirement is a top-level property of the PaymentDataRequest JSON object. */ paymentDataRequest.put("shippingAddressRequired", true); JSONObject shippingAddressParameters = new JSONObject(); shippingAddressParameters.put("phoneNumberRequired", false); JSONArray allowedCountryCodes = new JSONArray(Constants.SHIPPING_SUPPORTED_COUNTRIES); shippingAddressParameters.put("allowedCountryCodes", allowedCountryCodes); paymentDataRequest.put("shippingAddressParameters", shippingAddressParameters); return Optional.of(paymentDataRequest); } catch (JSONException e) { return Optional.empty(); } }
Более подробная информация приведена в документации JSON по объекту PaymentDataRequest
.
Шаг 8. Настройте обработчик жестов пользователей
Чтобы запросить вывод страницы оплаты Google Pay при нажатии пользователем кнопки оплаты Google Pay, задайте параметр OnClickListener
.
Kotlin
googlePayButton.setOnClickListener { requestPayment() }
Java
googlePayButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { requestPayment(view); } });
Объект PaymentDataRequest
– это Parcelable
, который представляет собой запрос платежных данных. Сведения объекта PaymentDataRequest
необходимы для оплаты. Используйте класс AutoResolveHelper
, чтобы автоматически выполнить поставленную задачу Task
. Затем обработайте результат с помощью метода onActivityResult
класса Activity
.
Шаг 9. Обработайте объект ответа
После того как покупатель укажет всю запрашиваемую информацию на странице оплаты Google Pay, объект PaymentData
возвращается в onActivityResult
.
Чтобы передать платежные данные обработчику и выдать подтверждение покупки пользователю, преобразуйте ответ в JSON. Если параметр transactionInfo.totalPriceStatus
, переданный в PaymentDataRequest
, имеет статус ESTIMATED
, необходимо показать итоговую цену до списания средств в рамках возвращенного способа оплаты.
Извлеките токен из ответа paymentData
. Если вы выполняете интеграцию шлюза, передайте этот токен шлюзу, не совершая никаких изменений.
Kotlin
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { // Value passed in AutoResolveHelper LOAD_PAYMENT_DATA_REQUEST_CODE -> { when (resultCode) { RESULT_OK -> data?.let { intent -> PaymentData.getFromIntent(intent)?.let(::handlePaymentSuccess) } RESULT_CANCELED -> { // The user cancelled the payment attempt } AutoResolveHelper.RESULT_ERROR -> { AutoResolveHelper.getStatusFromIntent(data)?.let { handleError(it.statusCode) } } } // Re-enables the Google Pay payment button. googlePayButton.isClickable = true } } }
Java
public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // value passed in AutoResolveHelper case LOAD_PAYMENT_DATA_REQUEST_CODE: switch (resultCode) { case Activity.RESULT_OK: PaymentData paymentData = PaymentData.getFromIntent(data); handlePaymentSuccess(paymentData); break; case Activity.RESULT_CANCELED: // The user cancelled the payment attempt break; case AutoResolveHelper.RESULT_ERROR: Status status = AutoResolveHelper.getStatusFromIntent(data); handleError(status.getStatusCode()); break; } // Re-enables the Google Pay payment button. googlePayButton.setClickable(true); } }
Дополнительную информацию о содержании и структуре ответа можно найти в документации JSON по объекту PaymentData
.
Выводы
Далее представлен полный пример правильно настроенного проекта. Инструкции см. в разделе Настройте ваш проект.
CheckoutActivity.kt (Kotlin)
В рамках данного примера Activity
предполагается, что кнопка оплаты Google Pay с атрибутом id
в googlepay_button
имеется в макете.
/* * Copyright 2018 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.gms.samples.wallet.activity import android.app.Activity import android.content.Intent import android.os.Bundle import android.text.Html import android.util.Log import android.view.View import android.widget.Toast import com.google.android.gms.common.api.ApiException import com.google.android.gms.samples.wallet.util.PaymentsUtil import com.google.android.gms.samples.wallet.R import com.google.android.gms.samples.wallet.util.Json import com.google.android.gms.wallet.* import kotlinx.android.synthetic.main.activity_checkout.* import org.json.JSONArray import org.json.JSONException import org.json.JSONObject /** * Checkout implementation for the app */ class CheckoutActivity : Activity() { private val SHIPPING_COST_CENTS = 9 * PaymentsUtil.CENTS.toLong() /** * A client for interacting with the Google Pay API. * * @see [PaymentsClient](https://developers.google.com/android/reference/com/google/android/gms/wallet/PaymentsClient) */ private lateinit var paymentsClient: PaymentsClient private lateinit var garmentList: JSONArray private lateinit var selectedGarment: JSONObject /** * Arbitrarily-picked constant integer you define to track a request for payment data activity. * * @value #LOAD_PAYMENT_DATA_REQUEST_CODE */ private val LOAD_PAYMENT_DATA_REQUEST_CODE = 991 /** * Initialize the Google Pay API on creation of the activity * * @see Activity.onCreate */ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_checkout) // Set up the mock information for our item in the UI. selectedGarment = fetchRandomGarment() displayGarment(selectedGarment) // Initialize a Google Pay API client for an environment suitable for testing. // It's recommended to create the PaymentsClient object inside of the onCreate method. paymentsClient = PaymentsUtil.createPaymentsClient(this) possiblyShowGooglePayButton() googlePayButton.setOnClickListener { requestPayment() } } /** * Determine the viewer's ability to pay with a payment method supported by your app and display a * Google Pay payment button. * * @see [](https://developers.google.com/android/reference/com/google/android/gms/wallet/PaymentsClient.html.isReadyToPay ) */ private fun possiblyShowGooglePayButton() { val isReadyToPayJson = PaymentsUtil.isReadyToPayRequest() ?: return val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString()) ?: return // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an // OnCompleteListener to be triggered when the result of the call is known. val task = paymentsClient.isReadyToPay(request) task.addOnCompleteListener { completedTask -> try { completedTask.getResult(ApiException::class.java)?.let(::setGooglePayAvailable) } catch (exception: ApiException) { // Process error Log.w("isReadyToPay failed", exception) } } } /** * If isReadyToPay returned `true`, show the button and hide the "checking" text. Otherwise, * notify the user that Google Pay is not available. Please adjust to fit in with your current * user flow. You are not required to explicitly let the user know if isReadyToPay returns `false`. * * @param available isReadyToPay API response. */ private fun setGooglePayAvailable(available: Boolean) { if (available) { googlePayButton.visibility = View.VISIBLE } else { Toast.makeText( this, "Unfortunately, Google Pay is not available on this device", Toast.LENGTH_LONG).show(); } } private fun requestPayment() { // Disables the button to prevent multiple clicks. googlePayButton.isClickable = false // The price provided to the API should include taxes and shipping. // This price is not displayed to the user. val garmentPrice = selectedGarment.getDouble("price") val priceCents = Math.round(garmentPrice * PaymentsUtil.CENTS.toLong()) + SHIPPING_COST_CENTS val paymentDataRequestJson = PaymentsUtil.getPaymentDataRequest(priceCents) if (paymentDataRequestJson == null) { Log.e("RequestPayment", "Can't fetch payment data request") return } val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString()) // Since loadPaymentData may show the UI asking the user to select a payment method, we use // AutoResolveHelper to wait for the user interacting with it. Once completed, // onActivityResult will be called with the result. if (request != null) { AutoResolveHelper.resolveTask( paymentsClient.loadPaymentData(request), this, LOAD_PAYMENT_DATA_REQUEST_CODE) } } /** * Handle a resolved activity from the Google Pay payment sheet. * * @param requestCode Request code originally supplied to AutoResolveHelper in requestPayment(). * @param resultCode Result code returned by the Google Pay API. * @param data Intent from the Google Pay API containing payment or error data. * @see [Getting a result * from an Activity](https://developer.android.com/training/basics/intents/result) */ public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { // Value passed in AutoResolveHelper LOAD_PAYMENT_DATA_REQUEST_CODE -> { when (resultCode) { RESULT_OK -> data?.let { intent -> PaymentData.getFromIntent(intent)?.let(::handlePaymentSuccess) } RESULT_CANCELED -> { // The user cancelled the payment attempt } AutoResolveHelper.RESULT_ERROR -> { AutoResolveHelper.getStatusFromIntent(data)?.let { handleError(it.statusCode) } } } // Re-enables the Google Pay payment button. googlePayButton.isClickable = true } } } /** * PaymentData response object contains the payment information, as well as any additional * requested information, such as billing and shipping address. * * @param paymentData A response object returned by Google after a payer approves payment. * @see [Payment * Data](https://developers.google.com/pay/api/android/reference/object.PaymentData) */ private fun handlePaymentSuccess(paymentData: PaymentData) { val paymentInformation = paymentData.toJson() ?: return try { // Token will be null if PaymentDataRequest was not constructed using fromJson(String). val paymentMethodData = JSONObject(paymentInformation).getJSONObject("paymentMethodData") val billingName = paymentMethodData.getJSONObject("info") .getJSONObject("billingAddress").getString("name") Log.d("BillingName", billingName) Toast.makeText(this, getString(R.string.payments_show_name, billingName), Toast.LENGTH_LONG).show() // Logging token string. Log.d("GooglePaymentToken", paymentMethodData .getJSONObject("tokenizationData") .getString("token")) } catch (e: JSONException) { Log.e("handlePaymentSuccess", "Error: " + e.toString()) } } /** * At this stage, the user has already seen a popup informing them an error occurred. Normally, * only logging is required. * * @param statusCode will hold the value of any constant from CommonStatusCode or one of the * WalletConstants.ERROR_CODE_* constants. * @see [ * Wallet Constants Library](https://developers.google.com/android/reference/com/google/android/gms/wallet/WalletConstants.constant-summary) */ private fun handleError(statusCode: Int) { Log.w("loadPaymentData failed", String.format("Error code: %d", statusCode)) } private fun fetchRandomGarment() : JSONObject { if (!::garmentList.isInitialized) { garmentList = Json.readFromResources(this, R.raw.tshirts) } val randomIndex:Int = Math.round(Math.random() * (garmentList.length() - 1)).toInt() return garmentList.getJSONObject(randomIndex) } private fun displayGarment(garment:JSONObject) { detailTitle.setText(garment.getString("title")) detailPrice.setText("\$${garment.getString("price")}") val escapedHtmlText:String = Html.fromHtml(garment.getString("description")).toString() detailDescription.setText(Html.fromHtml(escapedHtmlText)) val imageUri = "@drawable/${garment.getString("image")}" val imageResource = resources.getIdentifier(imageUri, null, packageName) detailImage.setImageResource(imageResource) } }
PaymentsUtil.kt (Kotlin)
Ниже приведен пример файла для создания объектов JSON, используемых для построения запросов IsReadyToPayRequest
или PaymentDataRequest
.
/* * Copyright 2017 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.gms.samples.wallet.util import android.app.Activity import com.google.android.gms.samples.wallet.Constants import com.google.android.gms.wallet.PaymentsClient import com.google.android.gms.wallet.Wallet import org.json.JSONArray import org.json.JSONException import org.json.JSONObject import java.math.BigDecimal import java.math.RoundingMode /** * Contains helper static methods for dealing with the Payments API. * * Many of the parameters used in the code are optional and are set here merely to call out their * existence. Please consult the documentation to learn more and feel free to remove ones not * relevant to your implementation. */ object PaymentsUtil { val CENTS = BigDecimal(100) /** * Create a Google Pay API base request object with properties used in all requests. * * @return Google Pay API base request object. * @throws JSONException */ private val baseRequest = JSONObject().apply { put("apiVersion", 2) put("apiVersionMinor", 0) } /** * Gateway Integration: Identify your gateway and your app'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 and modify them in Constants.java. * * @return Payment data tokenization for the CARD payment method. * @throws JSONException * @see [PaymentMethodTokenizationSpecification](https://developers.google.com/pay/api/android/reference/object.PaymentMethodTokenizationSpecification) */ private fun gatewayTokenizationSpecification(): JSONObject { return JSONObject().apply { put("type", "PAYMENT_GATEWAY") put("parameters", JSONObject(Constants.PAYMENT_GATEWAY_TOKENIZATION_PARAMETERS)) } } /** * `DIRECT` Integration: Decrypt a response directly on your servers. This configuration has * additional data security requirements from Google and additional PCI DSS compliance complexity. * * * Please refer to the documentation for more information about `DIRECT` integration. The * type of integration you use depends on your payment processor. * * @return Payment data tokenization for the CARD payment method. * @throws JSONException * @see [PaymentMethodTokenizationSpecification](https://developers.google.com/pay/api/android/reference/object.PaymentMethodTokenizationSpecification) */ private fun directTokenizationSpecification(): JSONObject { if (Constants.DIRECT_TOKENIZATION_PUBLIC_KEY == "REPLACE_ME" || (Constants.DIRECT_TOKENIZATION_PARAMETERS.isEmpty() || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY.isEmpty())) { throw RuntimeException( "Please edit the Constants.java file to add protocol version & public key.") } return JSONObject().apply { put("type", "DIRECT") put("parameters", JSONObject(Constants.DIRECT_TOKENIZATION_PARAMETERS)) } } /** * Card networks supported by your app and your gateway. * * * TODO: Confirm card networks supported by your app and gateway & update in Constants.java. * * @return Allowed card networks * @see [CardParameters](https://developers.google.com/pay/api/android/reference/object.CardParameters) */ private val allowedCardNetworks = JSONArray(Constants.SUPPORTED_NETWORKS) /** * Card authentication methods supported by your app and your gateway. * * * TODO: Confirm your processor supports Android device tokens on your supported card networks * and make updates in Constants.java. * * @return Allowed card authentication methods. * @see [CardParameters](https://developers.google.com/pay/api/android/reference/object.CardParameters) */ private val allowedCardAuthMethods = JSONArray(Constants.SUPPORTED_METHODS) /** * Describe your app's support for the CARD payment method. * * * The provided properties are applicable to both an IsReadyToPayRequest and a * PaymentDataRequest. * * @return A CARD PaymentMethod object describing accepted cards. * @throws JSONException * @see [PaymentMethod](https://developers.google.com/pay/api/android/reference/object.PaymentMethod) */ // Optionally, you can add billing address/phone number associated with a CARD payment method. private fun baseCardPaymentMethod(): JSONObject { return JSONObject().apply { val parameters = JSONObject().apply { put("allowedAuthMethods", allowedCardAuthMethods) put("allowedCardNetworks", allowedCardNetworks) put("billingAddressRequired", true) put("billingAddressParameters", JSONObject().apply { put("format", "FULL") }) } put("type", "CARD") put("parameters", parameters) } } /** * Describe the expected returned payment data for the CARD payment method * * @return A CARD PaymentMethod describing accepted cards and optional fields. * @throws JSONException * @see [PaymentMethod](https://developers.google.com/pay/api/android/reference/object.PaymentMethod) */ private fun cardPaymentMethod(): JSONObject { val cardPaymentMethod = baseCardPaymentMethod() cardPaymentMethod.put("tokenizationSpecification", gatewayTokenizationSpecification()) return cardPaymentMethod } /** * An object describing accepted forms of payment by your app, used to determine a viewer's * readiness to pay. * * @return API version and payment methods supported by the app. * @see [IsReadyToPayRequest](https://developers.google.com/pay/api/android/reference/object.IsReadyToPayRequest) */ fun isReadyToPayRequest(): JSONObject? { return try { baseRequest.apply { put("allowedPaymentMethods", JSONArray().put(baseCardPaymentMethod())) } } catch (e: JSONException) { null } } /** * Information about the merchant requesting payment information * * @return Information about the merchant. * @throws JSONException * @see [MerchantInfo](https://developers.google.com/pay/api/android/reference/object.MerchantInfo) */ private val merchantInfo: JSONObject = JSONObject().put("merchantName", "Example Merchant") /** * Creates an instance of [PaymentsClient] for use in an [Activity] using the * environment and theme set in [Constants]. * * @param activity is the caller's activity. */ fun createPaymentsClient(activity: Activity): PaymentsClient { val walletOptions = Wallet.WalletOptions.Builder() .setEnvironment(Constants.PAYMENTS_ENVIRONMENT) .build() return Wallet.getPaymentsClient(activity, walletOptions) } /** * Provide Google Pay API with a payment amount, currency, and amount status. * * @return information about the requested payment. * @throws JSONException * @see [TransactionInfo](https://developers.google.com/pay/api/android/reference/object.TransactionInfo) */ @Throws(JSONException::class) private fun getTransactionInfo(price: String): JSONObject { return JSONObject().apply { put("totalPrice", price) put("totalPriceStatus", "FINAL") put("countryCode", Constants.COUNTRY_CODE) put("currencyCode", Constants.CURRENCY_CODE) } } /** * An object describing information requested in a Google Pay payment sheet * * @return Payment data expected by your app. * @see [PaymentDataRequest](https://developers.google.com/pay/api/android/reference/object.PaymentDataRequest) */ fun getPaymentDataRequest(priceCemts: Long): JSONObject? { return try { baseRequest.apply { put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod())) put("transactionInfo", getTransactionInfo(priceCemts.centsToString())) put("merchantInfo", merchantInfo) // An optional shipping address requirement is a top-level property of the // PaymentDataRequest JSON object. val shippingAddressParameters = JSONObject().apply { put("phoneNumberRequired", false) put("allowedCountryCodes", JSONArray(listOf("US", "GB"))) } put("shippingAddressParameters", shippingAddressParameters) put("shippingAddressRequired", true) } } catch (e: JSONException) { null } } } /** * Converts cents to a string format accepted by [PaymentsUtil.getPaymentDataRequest]. * * @param cents value of the price. */ fun Long.centsToString() = BigDecimal(this) .divide(PaymentsUtil.CENTS) .setScale(2, RoundingMode.HALF_EVEN) .toString()
CheckoutActivity.java (Java)
В рамках данного примера Activity
предполагается, что кнопка оплаты Google Pay с атрибутом id
в googlepay_button
имеется в макете.
/* * Copyright 2020 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.gms.samples.wallet.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.Html; import android.util.Log; import android.view.View; import android.widget.Toast; import com.google.android.gms.common.api.Status; import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding; import com.google.android.gms.samples.wallet.util.PaymentsUtil; import com.google.android.gms.samples.wallet.R; import com.google.android.gms.samples.wallet.util.Json; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.android.gms.wallet.AutoResolveHelper; import com.google.android.gms.wallet.IsReadyToPayRequest; import com.google.android.gms.wallet.PaymentData; import com.google.android.gms.wallet.PaymentDataRequest; import com.google.android.gms.wallet.PaymentsClient; import java.util.Locale; import java.util.Optional; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; /** * Checkout implementation for the app */ public class CheckoutActivity extends AppCompatActivity { // Arbitrarily-picked constant integer you define to track a request for payment data activity. private static final int LOAD_PAYMENT_DATA_REQUEST_CODE = 991; private static final long SHIPPING_COST_CENTS = 90 * PaymentsUtil.CENTS_IN_A_UNIT.longValue(); // A client for interacting with the Google Pay API. private PaymentsClient paymentsClient; private ActivityCheckoutBinding layoutBinding; private View googlePayButton; private JSONArray garmentList; private JSONObject selectedGarment; /** * Initialize the Google Pay API on creation of the activity * * @see Activity#onCreate(android.os.Bundle) */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initializeUi(); // Set up the mock information for our item in the UI. try { selectedGarment = fetchRandomGarment(); displayGarment(selectedGarment); } catch (JSONException e) { throw new RuntimeException("The list of garments cannot be loaded"); } // Initialize a Google Pay API client for an environment suitable for testing. // It's recommended to create the PaymentsClient object inside of the onCreate method. paymentsClient = PaymentsUtil.createPaymentsClient(this); possiblyShowGooglePayButton(); } /** * Handle a resolved activity from the Google Pay payment sheet. * * @param requestCode Request code originally supplied to AutoResolveHelper in requestPayment(). * @param resultCode Result code returned by the Google Pay API. * @param data Intent from the Google Pay API containing payment or error data. * @see <a href="https://developer.android.com/training/basics/intents/result">Getting a result * from an Activity</a> */ @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // value passed in AutoResolveHelper case LOAD_PAYMENT_DATA_REQUEST_CODE: switch (resultCode) { case Activity.RESULT_OK: PaymentData paymentData = PaymentData.getFromIntent(data); handlePaymentSuccess(paymentData); break; case Activity.RESULT_CANCELED: // The user cancelled the payment attempt break; case AutoResolveHelper.RESULT_ERROR: Status status = AutoResolveHelper.getStatusFromIntent(data); handleError(status.getStatusCode()); break; } // Re-enables the Google Pay payment button. googlePayButton.setClickable(true); } } private void initializeUi() { // Use view binding to access the UI elements layoutBinding = ActivityCheckoutBinding.inflate(getLayoutInflater()); setContentView(layoutBinding.getRoot()); // The Google Pay button is a layout file – take the root view googlePayButton = layoutBinding.googlePayButton.getRoot(); googlePayButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { requestPayment(view); } }); } private void displayGarment(JSONObject garment) throws JSONException { layoutBinding.detailTitle.setText(garment.getString("title")); layoutBinding.detailPrice.setText( String.format(Locale.getDefault(), "$%.2f", garment.getDouble("price"))); final String escapedHtmlText = Html.fromHtml( garment.getString("description"), Html.FROM_HTML_MODE_COMPACT).toString(); layoutBinding.detailDescription.setText(Html.fromHtml( escapedHtmlText, Html.FROM_HTML_MODE_COMPACT)); final String imageUri = String.format("@drawable/%s", garment.getString("image")); final int imageResource = getResources().getIdentifier(imageUri, null, getPackageName()); layoutBinding.detailImage.setImageResource(imageResource); } /** * Determine the viewer's ability to pay with a payment method supported by your app and display a * Google Pay payment button. * * @see <a href="https://developers.google.com/android/reference/com/google/android/gms/wallet/ * PaymentsClient.html#isReadyToPay(com.google.android.gms.wallet. * IsReadyToPayRequest)">PaymentsClient#IsReadyToPay</a> */ private void possiblyShowGooglePayButton() { final Optional<JSONObject> isReadyToPayJson = PaymentsUtil.getIsReadyToPayRequest(); if (!isReadyToPayJson.isPresent()) { return; } // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an // OnCompleteListener to be triggered when the result of the call is known. IsReadyToPayRequest request = IsReadyToPayRequest.fromJson(isReadyToPayJson.get().toString()); Task<Boolean> task = paymentsClient.isReadyToPay(request); task.addOnCompleteListener(this, new OnCompleteListener<Boolean>() { @Override public void onComplete(@NonNull Task<Boolean> task) { if (task.isSuccessful()) { setGooglePayAvailable(task.getResult()); } else { Log.w("isReadyToPay failed", task.getException()); } } }); } /** * If isReadyToPay returned {@code true}, show the button and hide the "checking" text. Otherwise, * notify the user that Google Pay is not available. Please adjust to fit in with your current * user flow. You are not required to explicitly let the user know if isReadyToPay returns {@code * false}. * * @param available isReadyToPay API response. */ private void setGooglePayAvailable(boolean available) { if (available) { googlePayButton.setVisibility(View.VISIBLE); } else { Toast.makeText(this, R.string.googlepay_status_unavailable, Toast.LENGTH_LONG).show(); } } /** * PaymentData response object contains the payment information, as well as any additional * requested information, such as billing and shipping address. * * @param paymentData A response object returned by Google after a payer approves payment. * @see <a href="https://developers.google.com/pay/api/android/reference/ * object#PaymentData">PaymentData</a> */ private void handlePaymentSuccess(PaymentData paymentData) { // Token will be null if PaymentDataRequest was not constructed using fromJson(String). final String paymentInfo = paymentData.toJson(); if (paymentInfo == null) { return; } try { JSONObject paymentMethodData = new JSONObject(paymentInfo).getJSONObject("paymentMethodData"); // If the gateway is set to "example", no payment information is returned - instead, the // token will only consist of "examplePaymentMethodToken". final JSONObject tokenizationData = paymentMethodData.getJSONObject("tokenizationData"); final String token = tokenizationData.getString("token"); final JSONObject info = paymentMethodData.getJSONObject("info"); final String billingName = info.getJSONObject("billingAddress").getString("name"); Toast.makeText( this, getString(R.string.payments_show_name, billingName), Toast.LENGTH_LONG).show(); // Logging token string. Log.d("Google Pay token: ", token); } catch (JSONException e) { throw new RuntimeException("The selected garment cannot be parsed from the list of elements"); } } /** * At this stage, the user has already seen a popup informing them an error occurred. Normally, * only logging is required. * * @param statusCode will hold the value of any constant from CommonStatusCode or one of the * WalletConstants.ERROR_CODE_* constants. * @see <a href="https://developers.google.com/android/reference/com/google/android/gms/wallet/ * WalletConstants#constant-summary">Wallet Constants Library</a> */ private void handleError(int statusCode) { Log.e("loadPaymentData failed", String.format("Error code: %d", statusCode)); } public void requestPayment(View view) { // Disables the button to prevent multiple clicks. googlePayButton.setClickable(false); // The price provided to the API should include taxes and shipping. // This price is not displayed to the user. try { double garmentPrice = selectedGarment.getDouble("price"); long garmentPriceCents = Math.round(garmentPrice * PaymentsUtil.CENTS_IN_A_UNIT.longValue()); long priceCents = garmentPriceCents + SHIPPING_COST_CENTS; Optional<JSONObject> paymentDataRequestJson = PaymentsUtil.getPaymentDataRequest(priceCents); if (!paymentDataRequestJson.isPresent()) { return; } PaymentDataRequest request = PaymentDataRequest.fromJson(paymentDataRequestJson.get().toString()); // Since loadPaymentData may show the UI asking the user to select a payment method, we use // AutoResolveHelper to wait for the user interacting with it. Once completed, // onActivityResult will be called with the result. if (request != null) { AutoResolveHelper.resolveTask( paymentsClient.loadPaymentData(request), this, LOAD_PAYMENT_DATA_REQUEST_CODE); } } catch (JSONException e) { throw new RuntimeException("The price cannot be deserialized from the JSON object."); } } private JSONObject fetchRandomGarment() { // Only load the list of items if it has not been loaded before if (garmentList == null) { garmentList = Json.readFromResources(this, R.raw.tshirts); } // Take a random element from the list int randomIndex = Math.toIntExact(Math.round(Math.random() * (garmentList.length() - 1))); try { return garmentList.getJSONObject(randomIndex); } catch (JSONException e) { throw new RuntimeException("The index specified is out of bounds."); } } }
PaymentsUtil.java (Java)
Ниже приведен пример файла для создания объектов JSON, используемых для построения запросов IsReadyToPayRequest
или PaymentDataRequest
.
/* * Copyright 2020 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.gms.samples.wallet.util; import android.app.Activity; import com.google.android.gms.samples.wallet.Constants; import com.google.android.gms.wallet.PaymentsClient; import com.google.android.gms.wallet.Wallet; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Optional; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * Contains helper static methods for dealing with the Payments API. * * <p>Many of the parameters used in the code are optional and are set here merely to call out their * existence. Please consult the documentation to learn more and feel free to remove ones not * relevant to your implementation. */ public class PaymentsUtil { public static final BigDecimal CENTS_IN_A_UNIT = new BigDecimal(100d); /** * Create a Google Pay API base request object with properties used in all requests. * * @return Google Pay API base request object. * @throws JSONException */ private static JSONObject getBaseRequest() throws JSONException { return new JSONObject().put("apiVersion", 2).put("apiVersionMinor", 0); } /** * Creates an instance of {@link PaymentsClient} for use in an {@link Activity} using the * environment and theme set in {@link Constants}. * * @param activity is the caller's activity. */ public static PaymentsClient createPaymentsClient(Activity activity) { Wallet.WalletOptions walletOptions = new Wallet.WalletOptions.Builder().setEnvironment(Constants.PAYMENTS_ENVIRONMENT).build(); return Wallet.getPaymentsClient(activity, walletOptions); } /** * Gateway Integration: Identify your gateway and your app's gateway merchant identifier. * * <p>The Google Pay API response will return an encrypted payment method capable of being charged * by a supported gateway after payer authorization. * * <p>TODO: Check with your gateway on the parameters to pass and modify them in Constants.java. * * @return Payment data tokenization for the CARD payment method. * @throws JSONException * @see <a href= * "https://developers.google.com/pay/api/android/reference/object#PaymentMethodTokenizationSpecification">PaymentMethodTokenizationSpecification</a> */ private static JSONObject getGatewayTokenizationSpecification() throws JSONException { return new JSONObject() {{ put("type", "PAYMENT_GATEWAY"); put("parameters", new JSONObject() {{ put("gateway", "example"); put("gatewayMerchantId", "exampleGatewayMerchantId"); }}); }}; } /** * {@code DIRECT} Integration: Decrypt a response directly on your servers. This configuration has * additional data security requirements from Google and additional PCI DSS compliance complexity. * * <p>Please refer to the documentation for more information about {@code DIRECT} integration. The * type of integration you use depends on your payment processor. * * @return Payment data tokenization for the CARD payment method. * @throws JSONException * @see <a * href="https://developers.google.com/pay/api/android/reference/object#PaymentMethodTokenizationSpecification">PaymentMethodTokenizationSpecification</a> */ private static JSONObject getDirectTokenizationSpecification() throws JSONException, RuntimeException { if (Constants.DIRECT_TOKENIZATION_PARAMETERS.isEmpty() || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY.isEmpty() || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY == null || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY == "REPLACE_ME") { throw new RuntimeException( "Please edit the Constants.java file to add protocol version & public key."); } JSONObject tokenizationSpecification = new JSONObject(); tokenizationSpecification.put("type", "DIRECT"); JSONObject parameters = new JSONObject(Constants.DIRECT_TOKENIZATION_PARAMETERS); tokenizationSpecification.put("parameters", parameters); return tokenizationSpecification; } /** * Card networks supported by your app and your gateway. * * <p>TODO: Confirm card networks supported by your app and gateway & update in Constants.java. * * @return Allowed card networks * @see <a * href="https://developers.google.com/pay/api/android/reference/object#CardParameters">CardParameters</a> */ private static JSONArray getAllowedCardNetworks() { return new JSONArray(Constants.SUPPORTED_NETWORKS); } /** * Card authentication methods supported by your app and your gateway. * * <p>TODO: Confirm your processor supports Android device tokens on your supported card networks * and make updates in Constants.java. * * @return Allowed card authentication methods. * @see <a * href="https://developers.google.com/pay/api/android/reference/object#CardParameters">CardParameters</a> */ private static JSONArray getAllowedCardAuthMethods() { return new JSONArray(Constants.SUPPORTED_METHODS); } /** * Describe your app's support for the CARD payment method. * * <p>The provided properties are applicable to both an IsReadyToPayRequest and a * PaymentDataRequest. * * @return A CARD PaymentMethod object describing accepted cards. * @throws JSONException * @see <a * href="https://developers.google.com/pay/api/android/reference/object#PaymentMethod">PaymentMethod</a> */ private static JSONObject getBaseCardPaymentMethod() throws JSONException { JSONObject cardPaymentMethod = new JSONObject(); cardPaymentMethod.put("type", "CARD"); JSONObject parameters = new JSONObject(); parameters.put("allowedAuthMethods", getAllowedCardAuthMethods()); parameters.put("allowedCardNetworks", getAllowedCardNetworks()); // Optionally, you can add billing address/phone number associated with a CARD payment method. parameters.put("billingAddressRequired", true); JSONObject billingAddressParameters = new JSONObject(); billingAddressParameters.put("format", "FULL"); parameters.put("billingAddressParameters", billingAddressParameters); cardPaymentMethod.put("parameters", parameters); return cardPaymentMethod; } /** * Describe the expected returned payment data for the CARD payment method * * @return A CARD PaymentMethod describing accepted cards and optional fields. * @throws JSONException * @see <a * href="https://developers.google.com/pay/api/android/reference/object#PaymentMethod">PaymentMethod</a> */ private static JSONObject getCardPaymentMethod() throws JSONException { JSONObject cardPaymentMethod = getBaseCardPaymentMethod(); cardPaymentMethod.put("tokenizationSpecification", getGatewayTokenizationSpecification()); return cardPaymentMethod; } /** * An object describing accepted forms of payment by your app, used to determine a viewer's * readiness to pay. * * @return API version and payment methods supported by the app. * @see <a * href="https://developers.google.com/pay/api/android/reference/object#IsReadyToPayRequest">IsReadyToPayRequest</a> */ public static Optional<JSONObject> getIsReadyToPayRequest() { try { JSONObject isReadyToPayRequest = getBaseRequest(); isReadyToPayRequest.put( "allowedPaymentMethods", new JSONArray().put(getBaseCardPaymentMethod())); return Optional.of(isReadyToPayRequest); } catch (JSONException e) { return Optional.empty(); } } /** * Provide Google Pay API with a payment amount, currency, and amount status. * * @return information about the requested payment. * @throws JSONException * @see <a * href="https://developers.google.com/pay/api/android/reference/object#TransactionInfo">TransactionInfo</a> */ private static JSONObject getTransactionInfo(String price) throws JSONException { JSONObject transactionInfo = new JSONObject(); transactionInfo.put("totalPrice", price); transactionInfo.put("totalPriceStatus", "FINAL"); transactionInfo.put("countryCode", Constants.COUNTRY_CODE); transactionInfo.put("currencyCode", Constants.CURRENCY_CODE); transactionInfo.put("checkoutOption", "COMPLETE_IMMEDIATE_PURCHASE"); return transactionInfo; } /** * Information about the merchant requesting payment information * * @return Information about the merchant. * @throws JSONException * @see <a * href="https://developers.google.com/pay/api/android/reference/object#MerchantInfo">MerchantInfo</a> */ private static JSONObject getMerchantInfo() throws JSONException { return new JSONObject().put("merchantName", "Example Merchant"); } /** * An object describing information requested in a Google Pay payment sheet * * @return Payment data expected by your app. * @see <a * href="https://developers.google.com/pay/api/android/reference/object#PaymentDataRequest">PaymentDataRequest</a> */ public static Optional<JSONObject> getPaymentDataRequest(long priceCents) { final String price = PaymentsUtil.centsToString(priceCents); try { JSONObject paymentDataRequest = PaymentsUtil.getBaseRequest(); paymentDataRequest.put( "allowedPaymentMethods", new JSONArray().put(PaymentsUtil.getCardPaymentMethod())); paymentDataRequest.put("transactionInfo", PaymentsUtil.getTransactionInfo(price)); paymentDataRequest.put("merchantInfo", PaymentsUtil.getMerchantInfo()); /* An optional shipping address requirement is a top-level property of the PaymentDataRequest JSON object. */ paymentDataRequest.put("shippingAddressRequired", true); JSONObject shippingAddressParameters = new JSONObject(); shippingAddressParameters.put("phoneNumberRequired", false); JSONArray allowedCountryCodes = new JSONArray(Constants.SHIPPING_SUPPORTED_COUNTRIES); shippingAddressParameters.put("allowedCountryCodes", allowedCountryCodes); paymentDataRequest.put("shippingAddressParameters", shippingAddressParameters); return Optional.of(paymentDataRequest); } catch (JSONException e) { return Optional.empty(); } } /** * Converts cents to a string format accepted by {@link PaymentsUtil#getPaymentDataRequest}. * * @param cents value of the price in cents. */ public static String centsToString(long cents) { return new BigDecimal(cents) .divide(CENTS_IN_A_UNIT, RoundingMode.HALF_EVEN) .setScale(2, RoundingMode.HALF_EVEN) .toString(); } }