如果您是透過 Google Play 商店發布 Android 應用程式,就可以將該應用程式與 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 值:
| 閘道 | 參數和文件 |
|---|---|
| 9Pay |
"gateway": "ninepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| ABA PayWay |
"gateway": "ababank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| 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" |
| Airvend |
"gateway": "airvend" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Airwallex |
"gateway": "airwallex" "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME" |
| Akurateco |
"gateway": "akuratecolab" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Alfa-Bank |
"gateway": "alfabank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Algoritma |
"gateway": "algoritma" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Allinpay |
"gateway": "allinpayintl" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| AllPayments |
"gateway": "allpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| alticepay |
"gateway": "alticepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| AMO FINTECH LLC |
"gateway": "amofintech" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Anedot |
"gateway": "anedot" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| ApcoPay |
"gateway": "apcopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| APPEX |
"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" |
| azericardgpay |
"gateway": "azericardgpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Bank 131 |
"gateway": "bank131" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BANK RBK |
"gateway": "bankrbkkzpay" "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" |
| Basis Theory |
"gateway": "basistheory" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BCC.KZ |
"gateway": "bccpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| bePaid |
"gateway": "ecomcharge" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Bereke Bank |
"gateway": "berekepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Billing Systems |
"gateway": "billingsystems" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| bisys.kz |
"gateway": "bisysgpay" "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" |
| Bluefin Europe |
"gateway": "bluefineurope" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Blue Media |
"gateway": "bluemedia" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BlueSnap |
"gateway": "bluesnap" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BORICA |
"gateway": "borica" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BPC |
"gateway": "bpcpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BR-DGE |
"gateway": "comcarde" "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" |
| BridgerPay |
"gateway": "bridgerpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| BT Pay |
"gateway": "btpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Buya |
"gateway": "buya" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CardConnect |
"gateway": "cardconnect" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Cardknox |
"gateway": "cardknox" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| cardlink |
"gateway": "cardlink" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Cardstream |
"gateway": "crst" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Cashflows |
"gateway": "cashflowsgateway" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| 國泰世華商業銀行 |
"gateway": "cathaybk" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CCAvenue UAE |
"gateway": "ccavenueuae" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CCV |
"gateway": "ccv" "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" |
| Chase Merchant Services |
"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" |
CloudWalk |
"gateway": "cloudwalk" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Coinflow |
"gateway": "coinflow" "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" |
| CoralPay |
"gateway": "coralpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Corefy |
"gateway": "paycoreio" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Corvus Pay |
"gateway": "corvuspay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Credorax |
"gateway": "credorax" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CrossPay |
"gateway": "crosspay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Cross Switch |
"gateway": "crossswitch" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CTBC Bank |
"gateway": "ctbcbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CURO Payments |
"gateway": "curopayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| CYBERBIZ |
"gateway": "cyberbizpay" "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" |
| DECTA |
"gateway": "decta" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" 沒有可用的開發人員說明文件 |
| Dejavoo |
"gateway": "denovosystempay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| DEUNA |
"gateway": "deuna" "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" |
| Dintero |
"gateway": "dintero" "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" |
| EasyPay |
"gateway": "easypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Easypay EU |
"gateway": "easypaypt" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| EBANX |
"gateway": "ebanx" "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY" |
| 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" 沒有可用的開發人員說明文件 |
| eftcorporation |
"gateway": "eftcorporation" "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" |
| epay |
"gateway": "epay" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
| EPAYJSC |
"gateway": "epayjsc" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
| EpicPay |
"gateway": "epicpay" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
| Espago |
"gateway": "espago" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" |
| Etisalat |
"gateway": "etisalatpaymentgateway" "gatewayMerchantID": "YOUR_GATEWAY_MERCHANT_ID" 沒有可用的開發人員說明文件 |
| EveryPay S.A. |
"gateway": "EveryPay S.A." "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Evervault |
"gateway": "evervault" "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" |
| Fexco payUnite |
"gateway": "fexco" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Fibonatix |
"gateway": "fibonatixparagon" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Financial Line |
"gateway": "finline" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Finanso UA |
"gateway": "finansoua" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| fincode byGMO |
"gateway": "fincode" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| FINEXUS |
"gateway": "finexus" "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" |
| Flitt |
"gateway": "flitt" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Fluid Pay |
"gateway": "fluidpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| FM Finance LTD |
"gateway": "fmfinanceltd" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| ForteBank |
"gateway": "fortebank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Fractal |
"gateway": "fractal" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Freedom Finance Bank |
"gateway": "axayscom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| FreedomPay |
"gateway": "freedompay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Freepay |
"gateway": "freepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Frontstream |
"gateway": "frontstreampayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Fung Payments |
"gateway": "fungpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| GBPayments |
"gateway": "gbpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| geidea |
"gateway": "geidea" "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" |
| globalpaymentsinc |
"gateway": "globalpaymentsinc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| GMO Payment Gateway |
"gateway": "gmopg" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| GoDaddy Payments |
"gateway": "godaddypayments" "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" |
| hutko |
"gateway": "hutko" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Hyp |
"gateway": "hyp" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| icard |
"gateway": "icardwallet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| iCount |
"gateway": "iCount" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| IDid Tecnologia Ltda |
"gateway": "idid" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| iKhokha |
"gateway": "ikhokha" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| IMOJE |
"gateway": "imoje" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Impaya |
"gateway": "impayarus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Inovio Payments |
"gateway": "inoviopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| InPlat |
"gateway": "inplat" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| InstaMed |
"gateway": "instamed" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| IntaSend Solutions Limited |
"gateway": "intasend" "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 (TOO Payment Processing) |
"gateway": "ioka" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| iPay88 |
"gateway": "ipay88" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| IPSI |
"gateway": "ipsi" "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" 沒有可用的開發人員說明文件 |
| KapitalBank |
"gateway": "eCommerceKapitalBank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Kassa |
"gateway": "kassacom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| kassa24pay |
"gateway": "kassa24pay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Kineox |
"gateway": "kineox" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Klix by Citadele |
"gateway": "klix" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Koin |
"gateway": "koin" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Lapsa Payments |
"gateway": "lapsapayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| LHV Pank |
"gateway": "lhvpank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Liberty |
"gateway": "liberty" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Life Pay |
"gateway": "lifepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Limepay |
"gateway": "limepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Linkly |
"gateway": "linkly" "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" |
| lynck |
"gateway": "lynck" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Lyra |
"gateway": "lyra" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Magnetiq Bank |
"gateway": "magnetiq" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| MakeCommerce (Maksekeskus) |
"gateway": "maksekeskus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Maksu GMBH |
"gateway": "maksupayeu" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Mastercard Payment Gateway Services |
"gateway": "mpgs" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Mandarin |
"gateway": "mandarin" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Market Pay |
"gateway": "marketpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| MerchantE |
"gateway": "merchante" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Merchant Warrior |
"gateway": "merchantwarrior" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Midtrans |
"gateway": "midtrans" "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" |
| MOBI.Money |
"gateway": "mobimoney" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Modulbank |
"gateway": "modulbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Mollie |
"gateway": "mollie" "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" |
| monek |
"gateway": "monek" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Moneris |
"gateway": "moneris" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Moneta |
"gateway": "moneta" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" 沒有可用的開發人員說明文件 |
| Monext |
"gateway": "monext" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Money.Mail.Ru |
"gateway": "moneymailru" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| monripayments |
"gateway": "monripayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Moov |
"gateway": "moov" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| MPay |
"gateway": "managepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| mstartipg |
"gateway": "mstartipg" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Multicarta |
"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" |
| Neolink |
"gateway": "neolinkprocessing" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Neon Pay |
"gateway": "neonpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Netopia |
"gateway": "netopia" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Netvalve |
"gateway": "netvalve" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Network International |
"gateway": "networkintl" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| 藍新金流 (原為「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" |
| Nexi Easy |
"gateway": "easy" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| NMI |
"gateway": "gatewayservices" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| noon payments |
"gateway": "noonpayments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Noqoody Pay |
"gateway": "noqoodypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Novalnet |
"gateway": "novalnet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Nexi Relay |
"gateway": "nexirelay" "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" |
| Omno |
"gateway": "omno" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| One Inc |
"gateway": "oneinc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Onelya |
"gateway": "onelya" "gatewayMerchantId": "YOUR_GATWAY_MERCHANT_ID" |
| Onerway |
"gateway": "ronghan" "gatewayMerchantId": "YOUR_GATWAY_MERCHANT_ID" |
| OneVision Limited |
"gateway": "onevision" "gatewayMerchantId": "YOUR_GATWAY_MERCHANT_ID" |
| OnPay |
"gateway": "onpayio" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Opayo by Elavon |
"gateway": "opayoelavon" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| OrkestaPay |
"gateway": "orkestapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Oschadbank |
"gateway": "oschadbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| pagarme |
"gateway": "pagarme" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PagBank |
"gateway": "pagbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PagBrasil |
"gateway": "pagbrasil" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PagSeguro |
"gateway": "pagsegurointernational" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PAY2M |
"gateway": "pay2m" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Payarc |
"gateway": "payarc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PAYCOMET |
"gateway": "paycomet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Paydock |
"gateway": "paydock" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| 首信易支付 |
"gateway": "payeasenet" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayEngine |
"gateway": "payengine" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayFabric |
"gateway": "payfabric" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayFacto |
"gateway": "payfacto" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayFast |
"gateway": "gopayfastuat" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| paygent |
"gateway": "paygent" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Payhub |
"gateway": "payhub" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayKKa |
"gateway": "paykkaeu" "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" |
| Paymentvision |
"gateway": "paymentvision" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Paymentwall |
"gateway": "paymentwall" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Paymo |
"gateway": "paymo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Paymob |
"gateway": "gpaymob" "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" |
| PayOne |
"gateway": "payone" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayOnline |
"gateway": "payonline" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Payoo |
"gateway": "payoo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Pay Theory |
"gateway": "paytheory" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayPlus |
"gateway": "payplus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayPro Pvt Ltd |
"gateway": "paypro" "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 |
"gateway": "paytechsolutions" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PayTech Ukraine |
"gateway": "paytech" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Payten Payment Gateway |
"gateway": "paytentr" "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" |
| Payzone Ireland |
"gateway": "payzoneireland" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PBT Gateway Services Ltd |
"gateway": "pbtgateway" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Pelecard |
"gateway": "pelecard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Pensopay |
"gateway": "pensopay" "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" |
| PlanetPay |
"gateway": "itcardpaymentservice" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Plategka.com |
"gateway": "plategkacom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Platon |
"gateway": "platon" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Pomelo |
"gateway": "pomelopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Portmone |
"gateway": "portmonecom" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Preczn |
"gateway": "preczn" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PrimePay |
"gateway": "primepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Primer |
"gateway": "primer" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Procard |
"gateway": "procard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| ProcessOut |
"gateway": "processout" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Przelewy24 |
"gateway": "przelewy24" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PSB Bank |
"gateway": "psbank" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PSCB |
"gateway": "pscbru" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PSiGate Inc. |
"gateway": "psigate" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| PXP Financial |
"gateway": "pxpfinancial" "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" |
| Raiffeisen Processing Centre |
"gateway": "raiffeisenprocessingcentre" "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" |
| Redsys |
"gateway": "redsys" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Reepay |
"gateway": "reepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| RocketGate |
"gateway": "rocketgate" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Russian Standard Bank |
"gateway": "rsb" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Ryft |
"gateway": "ryft" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Saferpay |
"gateway": "worldlinesaferpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Safexpay |
"gateway": "safexpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Sberbank |
"gateway": "sberbank" "gatewayMerchantId": "YOUR_ORGANIZATION_NAME" |
| SEB Baltic |
"gateway": "sebbaltic" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| SEBES Technology |
"gateway": "sebes" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| SecurePay |
"gateway": "securepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Sense Bank |
"gateway": "sensebank" "gatewayMerchantId": "YOUR_ORGANIZATION_NAME" |
| SensePass |
"gateway": "sensepass" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Servicios Digitales Popular S.A. |
"gateway": "pagosazul" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Shift4 |
"gateway": "shift4payments" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Shiji Group |
"gateway": "shijipaymentsolutions" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| SH Start High |
"gateway": "shstartpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| shvarenapay |
"gateway": "shvarenapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| simbasoft |
"gateway": "simbasoft" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Sipay |
"gateway": "sipay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| SmartPay |
"gateway": "smartpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Softbank Payment Service |
"gateway": "sbps" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Softtouch POS and Payments |
"gateway": "softtouch" "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" |
| SredaPay |
"gateway": "sredapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| SSLCOMMERZ |
"gateway": "sslcommerz" "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" |
| 紅陽科技 |
"gateway": "esafe" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| SUMIT |
"gateway": "sumit" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Surfboard Payments |
"gateway": "surfboard" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Swedbank Baltic |
"gateway": "swedbankbaltic" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| TabaPay |
"gateway": "tabapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| TapPay (喬睿科技) |
"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" |
| Time Project LLC |
"gateway": "timeproject" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Tinkoff |
"gateway": "tinkoff" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Tinkoff |
"gateway": "tinkoff" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| TIPTOP PAY |
"gateway": "tiptoppay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" 沒有可用的開發人員說明文件 |
| theMAP |
"gateway": "themap" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| tillpayments |
"gateway": "themap" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| TPay.com |
"gateway": "tpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Transact Campus |
"gateway": "transactcampus" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Transact Pro |
"gateway": "transactpro" "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" |
| Tribe Payments |
"gateway": "tribepayments" "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" |
| UBRR |
"gateway": "ubrrpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Ukrcard |
"gateway": "ukrcardpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| UkrGasBank Pay |
"gateway": "ukrgasbankpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Unibank OJSC |
"gateway": "unibankcheckout" "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 |
"gateway": "unzer" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Unzer Austria |
"gateway": "unzeraustria" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| UPC |
"gateway": "upc" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Upgate |
"gateway": "upgate" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| USAePay |
"gateway": "usaepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| UseePay |
"gateway": "useepay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| USIO, Inc. |
"gateway": "usio" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Valitor |
"gateway": "valitor" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| value.io |
"gateway": "inspirecommerce" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Vanco |
"gateway": "vanco" "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" |
| Vayapay |
"gateway": "vayapay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" 沒有可用的開發人員說明文件 |
| Verestro |
"gateway": "verestro" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Very Good Security |
"gateway": "verygoodsecurity" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Victoriabank | "
"gateway": "victoriabank" "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" |
| Waffo |
"gateway": "waffo" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Wallee |
"gateway": "wallee" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Walletdoc |
"gateway": "walletdoc" "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" |
| WooshPay |
"gateway": "swooshtransfer" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Worldline (GlobalCollect) |
"gateway": "globalcollect" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Worldline - Ingenico (WL Online Checkout) |
"gateway": "worldlineingenicoogone" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Worldline Nordics (Worldline Online Checkout) |
"gateway": "worldlineonlinecheckout" "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" |
| xMoney |
"gateway": "xmoneypay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| XPATE |
"gateway": "xpate" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| xpay |
"gateway": "xpaycomua" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| XPay by PostEx |
"gateway": "xpaybypostex" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| YabandPay B.V. |
"gateway": "yabandpay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| YIĞIM Payment System |
"gateway": "yigim" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" 沒有可用的開發人員說明文件 |
| ЮKassa (YooKassa) |
"gateway": "yoomoney" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Yuno |
"gateway": "yuno" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Z-credit |
"gateway": "zcredit" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Zalopay |
"gateway": "zalopay" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| ZEN.com |
"gateway": "zen" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Zest |
"gateway": "zestpayment" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
| Zuora |
"gateway": "zuora" "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" |
PAYMENT_GATEWAY 代碼化類型是商家最常在 Google Pay API 中實作的卡片付款方式。如果系統不支援您的付款服務供應商,您或許可以透過 DIRECT 整合的方式接受透過 Google Pay 付款。詳情請參閱直接權杖化說明文件。
步驟 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 安全密文驗證的裝置權杖 (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"); }
詳情請參閱 JSON 物件參考資料中的 CardParameters。如要取得 Android 裝置權杖的相關支援,請洽詢閘道或處理方以確認支援的發卡機構。
步驟 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,請參閱 JSON 物件參考資料中的 CardParameters。
除了 CARD 之外,Google Pay 也支援 PAYPAL 付款方式。如要進一步瞭解如何將 PayPal 新增為 Google Pay 付款方式,請參閱 PayPal 的開發人員說明文件。
步驟 5:建立 PaymentsClient 執行個體
在 Activity 的 onCreate 方法中建立 PaymentsClient 執行個體。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 付款。如需完整的設定屬性清單,請參閱 IsReadyToPayRequest JSON 物件說明文件。
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()); } } }); }
如範例所示,最好在收到來自 isReadyToPay 函式的成功結果後,才將 Google Pay 顯示為付款選項。實作付款選項時,在版面配置中透過 include 顯示 Google Pay 付款按鈕是最常見的做法。如要進一步瞭解應用程式可用的 Google Pay 付款按鈕、標誌和標記,請參閱品牌宣傳指南。
步驟 7:建立 PaymentDataRequest 物件
PaymentDataRequest JSON 物件會說明在 Google Pay 付款畫面中,要求付款人提供的資訊。
請提供交易價格和所提供價格的狀態相關資訊。詳情請參閱 TransactionInfo JSON 物件說明文件。
以下例子說明如何取得價格、價格狀態和幣別交易資訊。
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; }
提供可讓使用者查看的商家名稱。詳情請參閱 MerchantInfo JSON 物件說明文件。
以下範例顯示如何取得商家名稱:
Kotlin
private val merchantInfo: JSONObject = JSONObject().put("merchantName", "Example Merchant")
Java
private static JSONObject getMerchantInfo() throws JSONException { return new JSONObject().put("merchantName", "Example Merchant"); }
將基本要求物件指派給新的 PaymentDataRequest JSON 物件。接下來,請新增應用程式支援的付款方式,包括設定回應中應包含的任何其他資料。最後,請新增交易和提出要求商家的相關資訊。
以下範例說明如何要求付款資料:
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(); } }
步驟 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,然後再處理 Activity 類別中 onActivityResult 方法 的結果。
步驟 9:處理回應物件
當付款人成功在 Google Pay 付款畫面中提供要求的資訊後,系統就會將 PaymentData 物件傳回給 onActivityResult。
如要將付款資訊傳送至處理方,並向使用者顯示確認購買的訊息,請將成功的回應轉換為 JSON。如果傳送至 PaymentDataRequest 的 transactionInfo.totalPriceStatus 是 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); } }
如要進一步瞭解回應的內容和結構,請參閱 PaymentData JSON 物件參考資料。
完整的實作範例
下列程式碼片段顯示了正確設定的完整專案範例。如需專案層級的設定步驟,請參閱設定專案一節。
CheckoutActivity.kt (Kotlin)
範例 Activity 假設你的版面配置中含有 id 屬性為 googlepay_button 的 Google Pay 付款按鈕。
/* * 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)
這個範例檔案會建構適合建立 IsReadyToPayRequest 或 PaymentDataRequest 的 JSON 物件。
/* * 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 假設你的版面配置中含有 id 屬性為 googlepay_button 的 Google Pay 付款按鈕。
/* * 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)
這個範例檔案會建構適合建立 IsReadyToPayRequest 或 PaymentDataRequest 的 JSON 物件。
/* * 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(); } }