> For the complete documentation index, see [llms.txt](https://plexo.gitbook.io/rest-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://plexo.gitbook.io/rest-api/wallets/google-pay/google-pay-api.md).

# Google Pay API Integration

Use this flow when you want to render the Google Pay™ button in your own UI and send the resulting token to Plexo through the Payments API.

In this model:

* Your frontend renders the Google Pay button
* Your backend or BFF fetches runtime Google Pay configuration from Plexo
* Your frontend collects the Google Pay token
* Your frontend sends the encrypted payment data to your backend or BFF
* Your backend either sends the Base64-encoded Google Pay payload directly to `POST /v1/payments`, or tokenizes it first and sends the returned Plexo payment instrument token

## Official Google Resources

Follow these Google requirements when you render the Google Pay™ button in your own UI:

* [Google Pay Web Brand Guidelines](https://developers.google.com/pay/api/web/guides/brand-guidelines)
* [Google Pay Android Brand Guidelines](https://developers.google.com/pay/api/android/guides/brand-guidelines)
* [Google Pay Web Integration Checklist](https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist)
* [Google Pay Android Integration Checklist](https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist)

## Prerequisites

1. Ask `soporte@plexo.com.uy` to enable Google Pay for the merchant with mode `api` or `both`
2. If you use `profileMode = plexo`, configure:
   * `googleMerchantName`
   * `googleMerchantOrigin` as a hostname without protocol
   * optional `allowedAuthMethods`
   * `allowedOrigins` as full origins with scheme
3. Call Plexo from your backend or BFF, not directly from browser code with Plexo API credentials

For `profileMode = plexo`, Plexo manages the runtime `merchantInfo.merchantId` automatically. TEST responses use Google Pay's `googletest` merchant ID. PRODUCTION responses use Plexo's managed production merchant ID.

## Authorization Methods and PAN\_ONLY 3DS

Plexo supports the two Google Pay card authorization methods returned by Google:

| Auth Method      | What It Means                                  | Plexo Handling                                                                                                  |
| ---------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `CRYPTOGRAM_3DS` | Network token with device cryptogram           | Plexo routes the payment as a network-token payment. A new 3DS challenge is usually not required.               |
| `PAN_ONLY`       | PAN-based credential without device cryptogram | Plexo routes the payment as a card payment. 3DS depends on the merchant's standard 3DS configuration and rules. |

To expose both methods in the Google Pay sheet, include both values in `googlePayProfile.allowedAuthMethods` when you enable Google Pay:

```json
{
  "mode": "api",
  "tosAccepted": true,
  "googlePayProfile": {
    "profileMode": "plexo",
    "googleMerchantName": "Example Store",
    "googleMerchantOrigin": "pay.example.com",
    "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
    "allowedOrigins": ["https://pay.example.com"]
  }
}
```

If you omit `allowedAuthMethods`, TEST defaults to `["PAN_ONLY", "CRYPTOGRAM_3DS"]` and PRODUCTION defaults to `["CRYPTOGRAM_3DS"]`.

To have Plexo trigger 3DS for `PAN_ONLY` payments:

1. Include `PAN_ONLY` in `googlePayProfile.allowedAuthMethods`.
2. Keep the merchant's standard 3DS configuration enabled in Plexo.
3. Make sure the payment matches the merchant's configured 3DS rules.

If those conditions are not met, Plexo returns `google-pay-pan-only-cvc-required`. Collect the payer's CVC and retry the payment with `paymentMethod.googlePayToken.cvc`, or `paymentMethod.paymentInstrument.cvc` if you already tokenized the wallet response.

See the [Wallet Integrations API Reference](/rest-api/api-reference/wallet-integrations.md) for the full enablement request and field list.

## Step 0: Check Wallet Availability

Before loading the Google Pay SDK on your page, verify that Google Pay is enabled for the merchant. This avoids initializing the SDK unnecessarily when the wallet is not configured.

**Endpoint:** `GET /v1/merchants/{merchantId}/wallet-integrations`

```bash
curl -X GET "https://api.plexo.com.uy/v1/merchants/12345/wallet-integrations" \
  -u "username:password"
```

### Example Response

```json
{
  "googlePay": {
    "enabled": true,
    "mode": "api"
  },
  "applePay": null
}
```

If `googlePay` is `null` or `enabled` is `false`, skip Google Pay SDK initialization entirely. Only proceed to Step 1 when `googlePay.enabled` is `true` and `mode` is `api` or `both`.

{% hint style="info" %}
Cache the wallet availability response on your backend for a reasonable period to avoid repeated calls on every page load.
{% endhint %}

## Step 1: Fetch Runtime Configuration

Fetch Google Pay runtime configuration from your backend or BFF using the merchant's Plexo credentials.

**Endpoint:** `GET /v1/merchants/{merchantId}/google-pay/configuration`

If you expect `merchantInfo.authJwt`, forward the browser `Origin` header.

For JWT integrations, Google Pay also requires `existingPaymentMethodRequired: true` in the browser request flow that uses `merchantInfo` and `authJwt`.

```bash
curl -X GET "https://api.plexo.com.uy/v1/merchants/12345/google-pay/configuration" \
  -u "username:password" \
  -H "Origin: https://pay.example.com"
```

### Example Response

```json
{
  "apiVersion": 2,
  "apiVersionMinor": 0,
  "environment": "PRODUCTION",
  "merchantInfo": {
    "merchantId": "BCR2DN4T2M6S7P6X",
    "merchantName": "Example Store",
    "merchantOrigin": "pay.example.com",
    "authJwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "allowedPaymentMethods": [
    {
      "type": "CARD",
      "parameters": {
        "allowedCardNetworks": ["VISA", "MASTERCARD"],
        "allowedAuthMethods": ["CRYPTOGRAM_3DS"]
      },
      "tokenizationSpecification": {
        "type": "PAYMENT_GATEWAY",
        "parameters": {
          "gateway": "plexouy",
          "gatewayMerchantId": "12345"
        }
      }
    }
  ]
}
```

### Gateway Configuration

Use `allowedPaymentMethods[].tokenizationSpecification` exactly as returned by Plexo.

| Field                          | Value                                          |
| ------------------------------ | ---------------------------------------------- |
| `type`                         | `PAYMENT_GATEWAY`                              |
| `parameters.gateway`           | `plexouy`                                      |
| `parameters.gatewayMerchantId` | Your Plexo `merchantId` serialized as a string |

For example, merchant `12345` must use `"gatewayMerchantId": "12345"`. Plexo validates the decrypted wallet payload against this merchant ID, so do not replace it with a Google merchant ID or an internal store identifier.

### When `merchantInfo.authJwt` Is Returned

`merchantInfo.authJwt` is included only when all of these conditions are true:

1. `profileMode` is `plexo`
2. The wallet integration mode includes API support: `api` or `both`
3. The request `Origin` matches one of the configured `allowedOrigins`
4. The runtime environment is `PRODUCTION`
5. Plexo has a managed Google Pay signing key configured

When `profileMode` is `merchant`, Plexo does not issue `merchantInfo.authJwt`.

`allowedPaymentMethods[].parameters.allowedAuthMethods` is driven by the merchant's dashboard configuration. If it has not been configured yet, TEST falls back to `["PAN_ONLY", "CRYPTOGRAM_3DS"]` and PRODUCTION falls back to `["CRYPTOGRAM_3DS"]`.

## Step 2: Initialize the Google Pay Button

Use the configuration returned by Plexo to initialize the Google Pay client and render the button. The example below follows the same browser flow as Plexo's Google Pay JWT demo.

```html
<script async src="https://pay.google.com/gp/p/js/pay.js"></script>
<div id="google-pay-button"></div>

<script>
  let googlePayConfig;
  let paymentsClient;

  async function initGooglePay() {
    googlePayConfig = await fetch('/api/google-pay/configuration?merchantId=12345')
      .then((response) => response.json());

    paymentsClient = new google.payments.api.PaymentsClient({
      environment: googlePayConfig.environment,
    });

    const authJwt = googlePayConfig.merchantInfo.authJwt;
    const requiresJwtIntegration =
      googlePayConfig.environment === 'PRODUCTION' && Boolean(authJwt);
    const merchantInfo = {
      merchantId: googlePayConfig.merchantInfo.merchantId,
      merchantName: googlePayConfig.merchantInfo.merchantName,
      merchantOrigin: googlePayConfig.merchantInfo.merchantOrigin,
    };

    const readinessRequest = {
      apiVersion: googlePayConfig.apiVersion,
      apiVersionMinor: googlePayConfig.apiVersionMinor,
      allowedPaymentMethods: googlePayConfig.allowedPaymentMethods,
      merchantInfo: requiresJwtIntegration ? merchantInfo : undefined,
      authJwt: authJwt || undefined,
      existingPaymentMethodRequired: requiresJwtIntegration,
    };

    const readiness = await paymentsClient.isReadyToPay(readinessRequest);
    if (!readiness.result) {
      return;
    }

    const button = paymentsClient.createButton({
      onClick: () => void onGooglePayButtonClicked(),
    });

    document.getElementById('google-pay-button').replaceChildren(button);
  }

  initGooglePay();
</script>
```

## Step 3: Load Payment Data and Send It to Your Server

The browser should send the raw `paymentMethodData.tokenizationData.token` value to your own backend or BFF. Do not call Plexo directly from the browser with API credentials.

```javascript
async function onGooglePayButtonClicked() {
  const authJwt = googlePayConfig.merchantInfo.authJwt;
  const requiresJwtIntegration =
    googlePayConfig.environment === 'PRODUCTION' && Boolean(authJwt);
  const merchantInfo = {
    merchantId: googlePayConfig.merchantInfo.merchantId,
    merchantName: googlePayConfig.merchantInfo.merchantName,
    merchantOrigin: googlePayConfig.merchantInfo.merchantOrigin,
  };

  const paymentDataRequest = {
    apiVersion: googlePayConfig.apiVersion,
    apiVersionMinor: googlePayConfig.apiVersionMinor,
    merchantInfo,
    allowedPaymentMethods: googlePayConfig.allowedPaymentMethods.map((method) => ({
      ...method,
      parameters: {
        ...method.parameters,
        billingAddressRequired: true,
        billingAddressParameters: {
          format: 'FULL',
          phoneNumberRequired: true,
        },
      },
    })),
    transactionInfo: {
      totalPriceStatus: 'FINAL',
      totalPrice: '100.00',
      currencyCode: 'UYU',
      countryCode: 'UY',
    },
    emailRequired: true,
    authJwt: authJwt || undefined,
    existingPaymentMethodRequired: requiresJwtIntegration,
  };

  const paymentData = await paymentsClient.loadPaymentData(paymentDataRequest);
  const rawTokenValue = paymentData.paymentMethodData.tokenizationData.token;
  const rawToken =
    typeof rawTokenValue === 'string' ? rawTokenValue : JSON.stringify(rawTokenValue);

  await fetch('/api/google-pay/payments', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      referenceId: 'order-123',
      amount: {
        total: 100.0,
        currency: 'UYU',
      },
      transaction: {
        countryCode: 'UY',
      },
      googlePay: {
        rawToken,
        cardholder: {
          firstName: 'John',
          lastName: 'Doe',
          email: paymentData.email,
        },
      },
    }),
  });
}
```

## Step 4 (Optional): Tokenize for Installment Decisions

If your checkout flow needs to display installment options before charging, tokenize the Google Pay token first using `POST /v1/tokenizations`. The response includes `cardType` (credit, debit), `cardOrigin` (uruguay, international), and `issuer.countryCode` — use these to determine which installment plans to offer.

If your browser sent the raw Google Pay token to your server in Step 3, Base64-encode that raw JSON string on the server before calling `POST /v1/tokenizations`.

**Endpoint:** `POST /v1/tokenizations`

```json
{
  "merchantId": 12345,
  "type": "temporal",
  "paymentMethod": {
    "source": "google-pay-token",
    "googlePayToken": {
      "token": "eyJzaWduYXR1cmUiOiJNRVVDSVFELi4uIiwidHJ...",
      "cardholder": {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com"
      }
    }
  }
}
```

### Example Response

```json
{
  "token": "9b7f1c2e-4a3d-4e8b-9c1f-2d3e4f5a6b7c",
  "paymentMethodId": "VISA",
  "paymentMethodType": "card",
  "tokenizationType": "temporal",
  "status": "active",
  "source": "network-token",
  "bin": "41111111",
  "last4": "1111",
  "expMonth": 12,
  "expYear": 2030,
  "cardType": "credit",
  "cardOrigin": "uruguay",
  "issuer": {
    "id": 101,
    "name": "Banco República Oriental del Uruguay",
    "shortName": "BROU",
    "country": "Uruguay",
    "countryCode": "UY"
  },
  "expiresAt": "2025-01-16T10:30:00Z"
}
```

After tokenization, use `cardType` and `cardOrigin` (or `issuer.countryCode`) combined with your merchant configuration to present the appropriate installment options. Then proceed to Step 5 using the returned `token` as `paymentMethod.paymentInstrument.token` with `paymentMethod.source = token`. Do not re-send the raw Google Pay token in the payment request when you use this branch.

{% hint style="info" %}
Skip this step if your flow does not offer installments. You can send the Google Pay token directly in Step 5 without tokenizing first.
{% endhint %}

## Step 5: Send the Payment to Plexo

Submit the payment through the Payments API using one of the two request shapes below.

**Endpoint:** `POST /v1/payments`

### Option A: Pay Directly With the Google Pay Token

**Intent:** Use this option when you do not need to tokenize before charging. This is the shortest payment path: your backend Base64-encodes the raw Google Pay token from Step 3 and sends it directly in the payment request.

Use `paymentMethod.source = google-pay-token` and send the Base64-encoded token in `paymentMethod.googlePayToken.token`.

```json
{
  "merchantId": 12345,
  "referenceId": "order-123",
  "amount": {
    "total": 100.00,
    "currency": "UYU"
  },
  "capture": {
    "method": "automatic"
  },
  "paymentMethod": {
    "source": "google-pay-token",
    "googlePayToken": {
      "token": "eyJzaWduYXR1cmUiOiJNRVVDSVFELi4uIiwidHJ...",
      "cardholder": {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com"
      }
    }
  }
}
```

### Option B: Pay With the Token Returned by Step 4

**Intent:** Use this option when you tokenized the Google Pay payload first, usually to inspect card metadata and decide which installment plans to offer before creating the payment.

Use `paymentMethod.source = token` and send the token returned by `POST /v1/tokenizations` in `paymentMethod.paymentInstrument.token`. Send the selected installment count in `installments`.

```json
{
  "merchantId": 12345,
  "referenceId": "order-123",
  "amount": {
    "total": 100.00,
    "currency": "UYU"
  },
  "capture": {
    "method": "automatic"
  },
  "installments": 3,
  "paymentMethod": {
    "source": "token",
    "paymentInstrument": {
      "token": "9b7f1c2e-4a3d-4e8b-9c1f-2d3e4f5a6b7c"
    }
  }
}
```

For `PAN_ONLY` Google Pay cards, Plexo may require a CVV instead of starting a 3DS flow. When that happens, retry the payment with either:

* `paymentMethod.googlePayToken.cvc` when you are sending the raw Google Pay token directly
* `paymentMethod.paymentInstrument.cvc` when you are using Option B

### Request Fields

| Field                                     | Type    | Required                                 | Description                                                                                                                          |
| ----------------------------------------- | ------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `merchantId`                              | integer | Yes                                      | Plexo merchant ID                                                                                                                    |
| `referenceId`                             | string  | Yes                                      | Your transaction reference                                                                                                           |
| `amount.total`                            | decimal | Yes                                      | Payment amount                                                                                                                       |
| `amount.currency`                         | string  | Yes                                      | ISO currency code                                                                                                                    |
| `installments`                            | integer | No                                       | Selected installment count. Include this after Step 4 when your checkout presented installment options.                              |
| `paymentMethod.source`                    | string  | Yes                                      | Use `google-pay-token` when sending the raw wallet payload directly, or `token` when paying with the Plexo token returned by Step 4. |
| `paymentMethod.googlePayToken.token`      | string  | Required for `source = google-pay-token` | Base64-encoded complete Google Pay token JSON.                                                                                       |
| `paymentMethod.googlePayToken.cvc`        | string  | No                                       | CVV/CVC retry field for `PAN_ONLY` payments when Plexo returns `google-pay-pan-only-cvc-required`.                                   |
| `paymentMethod.googlePayToken.cardholder` | object  | Required for `source = google-pay-token` | Cardholder details.                                                                                                                  |
| `paymentMethod.paymentInstrument.token`   | string  | Required for `source = token`            | Plexo payment instrument token returned by Step 4.                                                                                   |
| `paymentMethod.paymentInstrument.cvc`     | string  | No                                       | CVV/CVC retry field when a previously tokenized `PAN_ONLY` Google Pay payment requires CVV.                                          |

## Error Behavior

The exact error depends on the failure point. Common client-visible codes for this flow include:

| Error Code                         | When It Happens                                                                        |
| ---------------------------------- | -------------------------------------------------------------------------------------- |
| `google-pay-not-enabled`           | Google Pay is not enabled for the merchant                                             |
| `google-pay-not-configured`        | The runtime configuration endpoint is called before the merchant profile is configured |
| `invalid-cardholder`               | The cardholder object is missing or invalid                                            |
| `request-validation-errors`        | The token is missing, not Base64, invalid JSON, or another request field is invalid    |
| `invalid-card-payment-method`      | The Google Pay token cannot be used after validation or decryption checks              |
| `google-pay-pan-only-cvc-required` | A `PAN_ONLY` Google Pay payment must be retried with CVV because 3DS will not run      |
| `internal-error`                   | An unexpected backend failure occurs                                                   |

{% hint style="info" %}
Do not rely on invented uppercase codes such as `INVALID_GOOGLE_PAY_TOKEN`. Public API responses use the published error-code contract.
{% endhint %}

## Testing

Use Google Pay's [test card suite](https://developers.google.com/pay/api/android/guides/resources/test-card-suite) with your test merchant configuration.

## Next Steps

* [Google Pay Integration Guide](/rest-api/wallets/google-pay.md)
* [Digital Wallets Overview](/rest-api/wallets/digital-wallets.md)
* [Wallet Integrations API Reference](/rest-api/api-reference/wallet-integrations.md)
* [Payment Processing Guide](/rest-api/payments/payment-processing.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://plexo.gitbook.io/rest-api/wallets/google-pay/google-pay-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
