# Google Pay

_Integrate Google Pay with Evervault to capture encrypted payment credentials across web and Android._

![An illustration of a Google Pay payment]()

Google Pay allows customers to securely complete payments using credit or debit cards linked to their Google account. Evervault has built-in support for Google Pay. Our Google Pay component will intercept the Google Pay token and provide you with direct access to the encrypted payment method, which can then be sent to any payment processor using [Relay](/relay).

## Getting started

All users of Google Pay must agree to the [Google Pay Terms and Conditions](https://payments.developers.google.com/terms/sellertos).

### Create a merchant

Before you can use Google Pay, you need to create a merchant record to use for the transaction. You can create a merchant from inside the payments section in the [Evervault Dashboard](https://app.evervault.com) or via the [Merchants API](/api#createMerchant).

### Install the SDK

#### Browser

Our [JavaScript SDK](/sdks/javascript) is distributed from our CDN, and can be installed by placing this script tag in the head of your HTML file. The SDK must be loaded directly from our CDN and cannot be bundled with your application or self hosted.

```html
<script src="https://js.evervault.com/v2"></script>
```

Once the SDK is installed, initialize it using your Team ID and App ID. You can find these in the [Evervault Dashboard](https://app.evervault.com).

```javascript
const evervault = new Evervault("<TEAM_ID>", "<APP_ID>");
```

You can also install Evervault via the `@evervault/js` package on npm. This package is a light wrapper which handles loading the SDK from our CDN and also provides TypeScript definitions.

```javascript
import { loadEvervault } from "@evervault/js";

const evervault = loadEvervault("<TEAM_ID>", "<APP_ID>");
```

#### Frequently Asked Questions

##### Why does the SDK need to be loaded from the CDN?

The SDK must be loaded directly from our CDN in order to be PCI Compliant.

##### How do I get my Team ID and App ID?

You can find your Team ID and App ID in the [Evervault Dashboard](https://app.evervault.com).

##### Can I load the SDK asynchronously?

You can load the SDK asynchronously using the `async` attribute on the script tag to prevent blocking the loading of your page. However, it is important to note that you will need to wait for the SDK to load before making any API calls.

    ```html
    <!DOCTYPE html>
    <html>
      <head>
        <script src="https://js.evervault.com/v2" onload="onEvervaultReady()" async></script>
        <script>
          function onEvervaultReady() {
            const evervault = new Evervault('<TEAM_ID>', '<APP_ID>');
          }
        </script>
      </head>
    </html>
    ```

#### Android

Our Android SDK distributed via [maven](https://central.sonatype.com/search?q=com.evervault.sdk), and can be installed using your preferred build tool.

If you are installing `evervault-inputs` from version `2.0.0` and onwards you will also need to add the JitPack repository to your build file:

```kotlin
dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
    mavenCentral()
    maven { url = uri("https://jitpack.io") }
  }
}
```

#### Gradle DSL

```kotlin
implementation("com.evervault.sdk:evervault-core:1.2")
implementation("com.evervault.sdk:evervault-inputs:2.0.0")
implementation("com.evervault.sdk:evervault-enclaves:2.0.0")
```

#### Maven

```xml
<dependency>
  <groupId>com.evervault.sdk</groupId>
  <artifactId>evervault-core</artifactId>
  <version>1.2</version>
  </dependency>
<dependency>
  <groupId>com.evervault.sdk</groupId>
  <artifactId>evervault-inputs</artifactId>
  <version>2.0.0</version>
  </dependency>
<dependency>
  <groupId>com.evervault.sdk</groupId>
  <artifactId>evervault-enclaves</artifactId>
  <version>2.0.0</version>
  </dependency>
```

#### Initialize SDK

Before using the Evervault Android SDK, you need to configure it with your Evervault Team ID and App ID. This step is essential for establishing a connection with the Evervault encryption service.

```kotlin
Evervault.shared.configure("<TEAM_ID>", "<APP_ID>")
```

Make sure to replace `<TEAM_ID>` and `<APP_ID>` with your actual Evervault Team ID and App ID which can be found in the [Evervault Dashboard](https://app.evervault.com)

#### Android

### Prerequisites

To support Evervault Google Pay in Android, you need to add the following to your `build.gradle.kts`.

```kotlin
dependencies {
    implementation("com.evervault.inputs:2.0.0")
}
```

You will also need to add the JitPack repository to your build file:

```kotlin
dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
    mavenCentral()
    maven { url = uri("https://jitpack.io") }
  }
}
```

To use Google Pay, first you need to enable the Google Pay API by adding the following to the `<application>` tag of your `AndroidManifest.xml`:

```xml
<application>
  <meta-data
    android:name="com.google.android.gms.wallet.api.enabled"
    android:value="true" />
</application>
```

### Instantiate the EvervaultPaymentViewModel

The Evervault Android SDK provides a Google Pay button composable and view model to encapsulate all Google Pay setup, readiness checks, payment data handling, and interception of the Google Pay token to provide you with direct access to the encrypted payment method, which can then be sent to any payment processor using [Evervault Relay](/relay).

To initiate the view model you need to pass a `Config` with a minimum of `appId` and `merchantId`.

```kotlin
private val viewModel: EvervaultPayViewModel by viewModels {
  EvervaultPayViewModelFactory(
    application,
    Config(
      appId = "YOUR_EVERVAULT_APP_ID", // Your Evervault App ID
      merchantId = "YOUR_EVERVAULT_MERCHANT_ID", // Your Evervault Merchant ID
    )
  )
}
```

### React to PaymentState

`PaymentState` is your single source of truth for what should happen in the UI. Handle it reactively so that screens transition automatically as soon as the view model publishes a new state. An example of handling these can be found at the bottom of this section.

| State | Typical timing | What you should do |
| --- | --- | --- |
| `NotStarted` | Immediately after composition, before you call `start()` | Display a progress indicator or a placeholder so users know something is loading. |
| `Unavailable` | `start()` has been called but Google Pay isn't available on the device. | Display other payment options instead. |
| `Available` | `start()` has been called and Google Pay is available on the device. | Display the Google Pay button. |
| `Error` | Something went wrong - likely something with the payment sheet and it closed with an error. | Display an error message to the user via a toast or similar. |
| `PaymentComplete` | The user completed the Payment and Evervault has provided encrypted payment details back to you. | Display a success screen or receipt and trigger your server side flow for payment processing with one of your PSPs. |

### Check Google Pay is available on the device

Now that you have created the view model, you need to check that Google Pay is supported and that a payment can be made. If this method fails and Google Pay is not supported then `PaymentState.Unavailable` will be emitted.

```kotlin
viewModel.start()
```

This should be called once (e.g. in a `LaunchEffect(Unit) { ... }`)

This API checks the following minimum requirements to finish a transaction using the Google Pay API:

- Device is running on a supported Android system version and also has a supported version of Google Play services installed.
- Google Pay API has launched in the user's country.
- User either has or can add a card in flow according to the specifications given for the `Config` passed during initialisation of the `EvervaultPaymentViewModel`.

### Create a transaction

Next, you will need to create a transaction to describe the payment you want to process. You will need to provide the amount, currency, country, and merchant details for the transaction.

#### Browser

```javascript
const transaction = evervault.transactions.create({
  amount: 1000,
  currency: "USD",
  country: "US",
  merchantId: "merchant_8f3dc605aa5d",
  lineItems: [
    {
      label: "Example Item",
      amount: 1000,
    },
  ],
});
```

#### Android

```kotlin
val transaction = Transaction(
  country = "IE"
  currency = "EUR"
  total = Amount("54.99")
  lineItems = arrayOf(
    LineItem("Men's Shirt", Amount("50.00")),
    LineItem("Socks", Amount("04.99")),
  )
)
```

#### Browser

### Mount a Google Pay component

Now that you have created a transaction, you can create and mount the Google Pay component to display the Google Pay button to your users. The Google Pay component takes the transaction you created as a first argument and an options object with a `process` function that will be called with the encrypted payment method when the user completes the payment.

```javascript
const google = evervault.ui.googlePay(transaction, {
  process: async (paymentMethod) => {
    console.log(paymentMethod.card?.number);
    // ev:Tk9D:hY5KJanIPOHBoI8S:AsnnjRl0FDe2zEddBAQG/eI2vN+b...:$
  },
});

google.on("cancel", () => {
  console.log("Google Pay canceled");
});

google.on("success", () => {
  console.log("Google Pay success");
});

// Mount the Google Pay component to a container element
google.mount("#google-pay");
```

#### Android

### Render the Pay Button

Now that you have created a transaction and checked that Google Pay is supported, you can create and display the Google Pay button to your users by using the `EvervaultPaymentButton` composable.

```kotlin
EvervaultPaymentButton(
  modifier = Modifier
    .fillMaxWidth(),
  transaction,
  model,
)
```

### Process the payment

#### Browser

The `process` function is an asynchronous function that is called when the user authorizes the payment. Typically you will want to forward the encrypted payment method to your backend in order to process the payment. You can use [Relay](/relay) to forward the encrypted payment method to any third party payment processor.

```javascript
const google = evervault.ui.googlePay(transaction, {
  process: async (paymentMethod) => {
    await fetch("your-api.com/payments", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(paymentMethod),
    });
  },
});
```

Google Pay can return either a `networkToken` or a `card` object. Typically this depends on whether the transaction was initiated and authenticated via biometrics on a mobile device, or via a web browser on a desktop device.

Optional `card.paymentMethodType` is one of `credit`, `debit`, `prepaid`, or `store` when Google Pay supplies [`cardFundingSource`](https://developers.google.com/pay/api/web/reference/object#CardInfo) for the selected card. Values are normalized to lowercase. If the funding source is unknown or not returned, the field is omitted (there is no `"unknown"` sentinel). Like Apple Pay, this wallet-provided value can be more reliable than BIN-derived `funding` for dual-network cards.

Network tokens offer inherent security due to their device-bound nature. However, responses containing only card details carry a higher risk and require additional authentication steps. We recommend leveraging our [3D Secure](/cards/3d-secure) API to perform this necessary authentication for card-based responses.

#### Android

When the user completes the payment, cancels, or otherwise exits the Google Pay sheet, a callback is delivered to `onActivityResult()`. In the event of a successful payment, the Google Pay Payment token needs to be decrypted in order to be passed on to your PSP for processing. Call the `handlePaymentDataIntent()` method on the `viewModel` to handle this.

```kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  super.onActivityResult(requestCode, resultCode, data)
  viewModel.handlePaymentDataIntent(requestCode, resultCode, data)
}
```

Once `handlePaymentDataIntent()` has been called, the `EvervaultPaymentViewModel` will handle decryption of the Google Pay token and encrypt any sensitive PCI data for you and emit `PaymentState.PaymentComplete(response)` with the encrypted payload or `PaymentState.Error` if an error occurred.

If the payment is handled successfully, the Evervault encrypted payment method is available in `PaymentState.PaymentComplete(response)`. The `response` is a JSON object containing the payment method details encrypted with the Evervault public key. You can send this encrypted payment method to your server and use Evervault [Relay](/relay) to decrypt the payment details when you send them to your PSP.

Google Pay can return a `NetworkTokenResponse` or a `CardResponse` object, typically depending on whether the supported method was `PAN_ONLY` or `CRYPTOGRAM_3DS` and whether or not the network supports that method.

A `NetworkTokenResponse` object contains the following fields:

```json
{
  "token": {
    "number": "ev:Tk9D:hY5KJanIPOHBoI8S:AsnnjRl0FDe2zEddBAQG/eI2vN+b...:$",
    "expiry": {
      "month": "12",
      "year": "31"
    },
    "tokenServiceProvider": "Google"
  },
  "cryptogram": "ev:Tk9D:vUVeybXqrA9Ds4rZ...=:$",
  "eci": "5",
  "card": {
    "brand": "visa",
    "lastFour": "1234",
    "displayName": "visa 1234",
    "funding": "debit",
    "segment": "consumer",
    "country": "ie",
    "currency": "eur",
    "issuer": "Revolut Bank Uab"
  },
  "messageId": "AB2Ejtf45mS02sSec_rbBgPtTCBvH1p-4Y-Ga_8_Pi9ZDgCiReH...",
  "messageExpiration": "1766011111111"
}
```

A `CardResponse` object contains the following fields:

```json
{
  "card": {
    "number": "ev:Tk9D:hY5KJanIPOHBoI8S:AsnnjRl0FDe2zEddBAQG/eI2vN+b...:$",
    "expiry": {
      "month": "12",
      "year": "31"
    },
    "lastFour": "1234",
    "displayName": "visa 1234",
    "brand": "visa",
    "funding": "debit",
    "segment": "consumer",
    "country": "ie",
    "currency": "eur",
    "issuer": "Revolut Bank Uab"
  },
  "messageId": "AB2Ejtf45mS02sSec_rbBgPtTCBvH1p-4Y-Ga_8_Pi9ZDgCiReH...",
  "messageExpiration": "1766011111111"
}
```

If available, both objects will also contain a `billingAddress` which is a the root and contains the following:

```json
{
  "name": "John Smith",
  "postalCode": "94043",
  "countryCode": "US",
  "phoneNumber": "561-555-7689",
  "address1": "1600 Amphitheatre Parkway",
  "address2": "",
  "address3": "",
  "locality": "Mountain View",
  "administrativeArea": "CA",
  "sortingCode": ""
}
```

Google Pay responses containing a `networkToken` offer inherent security due to their device-bound nature. However, responses containing only `card` details carry a higher risk and require additional authentication steps. We recommend leveraging our [3DS API](/cards/3d-secure) to perform this necessary authentication for card-based responses.

### Complete example

Below is a full example of Evervault Google Pay in action:

```kotlin
class MainActivity : AppCompatActivity() {

  private val model: EvervaultPayViewModel by viewModels {
    EvervaultPayViewModelFactory(
      application,
      Config(
        appId = "YOUR_EVERVAUL_APP_ID",
        merchantId = "YOUR_EVERVAULT_MERCHANT_ID",
      )
    )
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val transaction = Transaction(
      country = "GB",
      currency = "GBP",
      total = Amount("54.99"), // The total of the below line items
      lineItems = arrayOf(
        LineItem("Men's Tech Shell Full Zip", Amount("50.00")),
        LineItem("Something small", Amount("04.99")),
      )
    )

    setContent {
      LaunchedEffect(Unit) {
        model.start()
      }

      // Initialise your payment UI state
      val payState: PaymentState by
        model.paymentState.collectAsState()

      // Handle state updates
      when (val state = payState) {
        is PaymentState.Unavailable -> {
          // Google Pay is unavailable
          Text("Google Pay is unavailable.")
        }
        is PaymentState.Available -> {
          // Google Pay is available so render the Button
          EvervaultPaymentButton(
            modifier = Modifier
              .fillMaxWidth(),
            transaction,
            model,
          )
        }
        is PaymentState.PaymentCompleted -> {
          // Type is either `NetworkTokenResponse` or `CardResponse`
          when (val token = state.response) {
            is NetworkTokenResponse -> {
              Text("Network Token Cryptogram: ${token.cryptogram}")
            }
            is CardResponse -> {
              Text("Encrypted Card Number: ${token.card.number}")
            }
          }
        }
        is PaymentState.Error -> {
          // An error occurred in the Google Pay payment sheeet
          Text("Error: ${state.message}")
        }
        is PaymentState.NotStarted -> {
          // `viewModel.start()` has not been called yet
          CircularProgressIndicator()
        }
      }
    }
  }

  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    // Allow Evervault to handle the result of the payment request
    model.handlePaymentDataIntent(requestCode, resultCode, data)
  }
}
```

#### Browser

## Error handling

### Errors while processing the payment

The process function also accepts a second argument which is an object of helper methods. This object includes a `fail` function that can be called with an error message to display an error to the user in the event of an error during payment processing.

```javascript
const google = evervault.ui.googlePay(transaction, {
  process: async (paymentMethod, { fail }) => {
    try {
      // ...
    } catch (error) {
      fail({
        message: "Cannot pay with payment credentials",
      });
    }
  },
});
```

### Errors while rendering the component

In the rare event that the Google Pay component fails to render, you can handle the error by listening to the `error` event.

```javascript
const google = evervault.ui.googlePay(transaction, { ... })

google.on("error", (error) => {
  console.error("Google Pay error", error);
});
```

## Use Google Pay with your PSP

You can use Evervault's Google Pay integration with any PSP. This means you:

- Don't use your PSP's Google Pay integration.
- Preferably use network tokens with your PSP's APIs.

When Google Pay returns a network token, use it for all payments, retries, etc. with your PSP. There's no additional configuration (e.g., certificates) with your PSP or Google needed. Most PSPs have network token APIs and parameters for passing network token data. Like other 3rd party API calls, use [Relay](/relay) to decrypt network token data and send it to your PSP.

## Customization

#### Browser

Google Pay allows you to customize the appearance of the payment button with various predefined styles. These can be passed as additional options when initializing the Google Pay component. You can see all of the available options in the [JS SDK documentation](/sdks/javascript#google-pay).

```javascript
const google = evervault.ui.googlePay(transaction, {
  color: "white",
  type: "checkout",
  locale: "fr",
  padding: "10px",
  borderRadius: 5,
  size: {
    width: "200px",
    height: "40px",
  },
  process: async (paymentMethod) => {
    // ...
  },
});
```

#### Android

Google Pay allows you to customize the appearance of the payment button with various predefined styles. These can be passed as additional options when initializing the `EvervaultPaymentButton`. Below is an example:

```kotlin
EvervaultPaymentButton(
  modifier = Modifier
    .fillMaxWidth(),
  transaction,
  model,
  type = ButtonType.Donate,
  theme = ButtonTheme.Light,
)
```

The default theme is `Dark` and the default type is `Pay`.

## Configuration

#### Browser

Google Pay allows you to specify the authorization methods and card networks that are supported by your merchant. This can be done by passing the `allowedAuthMethods` and `allowedCardNetworks` options when initializing the Google Pay component. You can see the available options in the [JS SDK](/sdks/javascript#google-pay).

```javascript
const google = evervault.ui.googlePay(transaction, {
  allowedAuthMethods: ["PAN_ONLY"],
  allowedCardNetworks: ["VISA", "MASTERCARD"],
  process: async (paymentMethod) => {
    // ...
  },
});
```

#### Android

The `Config` object initialises your `EvervaultPaymentViewModel` with everything it needs to handle the interactions with the Google Pay API. At a minimum you're required to provide your Evervault App ID and Evervault Merchant ID. There are other options to allow you to customise how the Google Pay payment sheet functions. Below is an example with all the possible options:

```kotlin
Config(
  appId = "app_1234567890",
  merchantId = "merchant_1234567890"
  environment = EvervaultConstants.ENVIRONMENT_TEST, // Default
  supportedNetworks = listOf(
    CardNetworks.VISA,
    CardNetworks.MASTERCARD,
    // AMEX, DISCOVER, JCB also supported
  ),
  supportedMethods: listOf(
    CardAuthMethod.PAN_ONLY,
    CardAuthMethod.CRYPTOGRAM_3DS
  )
)
```

When you're testing the Evervault Google Pay integration in an emulator or on a real device, the environment should be set to the test environment. When you're ready to go live, you should set the environment to `EvervaultConstants.ENVIRONMENT_PRODUCTION`.

For the `supportedNetworks` option, all of the networks listed above, including those in the comment are enabled. If you wish to only support a select few of the networks, please override the list as shown above.

For the `supportedMethods`, please refer to Google's documentation on `PAN_ONLY` vs `CRYPTOGRAM_3DS`. Depending on the values you use here, you may encounter errors when initialising the component, for example, `JCB` and `DISCOVER` don't support `CRYPTOGRAM_3DS` because they don't support DPANs.

## 3D Secure

Google Pay supports encrypted and non-encrypted payment methods. Encrypted payment methods are preferred as they provide enhanced security and reduced fraud. Non-encrypted payment methods are also supported, and when used can subsequently be submitted for authentication via our 3D Secure API. See our [3D Secure guide](/cards/3d-secure) for more information. You can directly pass the encrypted card number string from the returned payment method to our 3DS API to perform an authentication.

## Content Security Policy (CSP)

If you are using a Content Security Policy (CSP), you will need to add the following directives to allow the Evervault SDK to function correctly.

```text
script-src https://js.evervault.com;
connect-src https://keys.evervault.com https://api.evervault.com;
frame-src https://ui-components.evervault.com;
```

- [3D Secure](/cards/3d-secure): Learn how 3D Secure works and how it can be used to enhance your payment security.
- [Apple Pay](/cards/apple-pay): Learn how to integrate Apple Pay with Evervault.

