Google Pay™ Express Checkout lets customers complete a purchase directly from the product, cart, or any pre-checkout page using payment, shipping and contact details already saved in their Google Account — no manual form filling required.
By exposing the Google Pay™ button earlier in the buying journey, merchants can shorten the funnel, reduce abandonment and offer a one-tap experience on the web.
Overview
This page describes only the `Express Checkout` possibility and advices how to handle some specific scenarios.
Express Checkout builds on top of the standard Google Pay integration. All gateway configuration (gateway: 'payonegmbh', gatewayMerchantId.) remains identical. The extensions described on this page are additive — you layer them onto your existing PaymentDataRequest and existing logic.
Google Pay can collect shipping address, shipping options, billing address, email and apply offers/promo codes directly inside the Google Pay™ payment sheet.
As you don`t need to have any changes towards Payone API for Google Pay Express - you can use Google Pay documentation directly to implement the Express option. Please be aware that Google Pay Express is not an official name and is not mentioned on Google Pay documentation.
---end
Prerequisites
Implementation of the Google pAY
---end
Please follow our Google Pay integration Guide and complete a standard integration before implementing Express Checkout option.
---end
---end
Express checkout flow
The folowing simplifed steps are done by user/merchant during Google Pay Express.
---end
Customer taps the Google Pay button on a product page, mini-cart, or cart page. The button is rendered with Express Checkout parameters (shipping, offers, email).
Google Pay opens the payment sheet pre-filled with the user's saved cards, addresses, and email. If shippingAddressRequired is true, the sheet shows an address selector.
User selects or changes a shipping address → onPaymentDataChanged fires with callbackTrigger: SHIPPING_ADDRESS.
Your Integration calculates updated shipping costs and returns a PaymentDataRequestUpdate with new transactionInfo and shippingOptionParameters.
User selects a shipping option → onPaymentDataChanged fires with callbackTrigger: SHIPPING_OPTION. Your code recalculates the total and returns an updated transactionInfo.
(Optional) User enters a promo code → onPaymentDataChanged fires with callbackTrigger: OFFER. Your code validates the code, applies the discount and returns the updated totals plus an offerData result.
User confirms payment → onPaymentAuthorized fires. You receive the full paymentData including tokenized card data, billing/shipping addresses, email, and selected shipping option.
Your server sends the payment token to the PAYONE Commerce Platform API exactly as in a standard Google Pay integration. No API-level difference exists for Express Checkout.
---end
---end
---end
eNABLING THE EXPRESS CHECKOUT
In order to retrieve address information needed for the express checkout please follow the configuration steps below.
Configure the callback Intents in the payment data object
---end
Google Pay supports the following callback intents for Express Checkout. Add them to the callbackIntents array in your PaymentDataRequest:
Intent
Triggers callback
Purpose
Requirement
PAYMENT_AUTHORIZATION
onPaymentAuthorized
Invoked after the user authorizes the payment. You must return a PaymentAuthorizationResult to confirm or reject the transaction.
Mandatory
SHIPPING_ADDRESS
onPaymentDataChanged
Fires when the user selects or changes a shipping address. Use it to validate the address and update shipping options / prices.
Recommended - (Needed for Express checkout)
SHIPPING_OPTION
onPaymentDataChanged
Fires when the user picks a different shipping option. Recalculate totals accordingly.
Recommended
OFFER
onPaymentDataChanged
Fires when the user enters or removes a promo/offer code. Validate the code and apply the discount.
Optional
The callback method associated with SHIPPING_ADDRESS and SHIPPING_OPTION, onPaymentDataChanged can be used to dynamically update shipping cost.
Set shippingOptionRequired to true to set shippingOptionParameters. It is used to set different shipping options.
shippingOptionParameters is used to define shippinh options Fields- defaultSelectedOptionId and shippingOptions. shippingOptions has the details of different shipping methods - id, label and description
This allows you also to pass a default delivery option
---end
shippingOptionParameters sample
shippingOptionRequired: true,
shippingOptionParameters: {
defaultSelectedOptionId: 'shipping-001',
shippingOptions: [
{
id: 'shipping-001',
label: '$0.00: Free shipping',
description: 'Free Shipping delivered in 5 business days.'
},
{
id: 'shipping-002',
label: '$1.99: Standard shipping',
description: 'Standard shipping delivered in 3 business days.'
},
{
id: 'shipping-003',
label: '$1000: Express shipping',
description: 'Express shipping delivered in 1 business day.'
},
],
}
---end
Provide the Transaction info
Transaction information has to be configured for the Express checkout flow. Display Items are mandatory for a use case when you plan to update the Payment after the initiation. We recommend to consult Google Pay documentation for more specifics.
When Express Checkout includes shipping, set totalPriceStatus: 'ESTIMATED' in your initial transactionInfo. Inside the onPaymentDataChanged callback, once you have computed the definitive total (including shipping and tax), switch to totalPriceStatus: 'FINAL' in the returned PaymentDataRequestUpdate.
Dynamic price updates are the core mechanism of Express Checkout. Every time the user changes their shipping address, selects a different shipping option, or enters a promo code, the onPaymentDataChanged callback fires and you must return updated pricing.
Handle the callbacks and update the payment information
In order to dynamically update the Final amount and/or implement other business logic it is natural to handle specific Google Pay callbacks below. Most important is is described below. However for complete documentation please consult Response objects Google Pay Documentation.
As part of the basic implementation you should already handle onPaymentAuthorized - however this handling now has to be extended to fetch additional information.
---end
Handle onPaymentDataChanged and update the payment information
onPaymentDataChanged callback provides payment data changes in the payment sheet such as shipping address, shipping option, and offer code changes. It is invoked whenever any of the SHIPPING_ADDRESS, SHIPPING_OPTION, or OFFER callback intents are triggered.
You should use the information provided in this callback to modify the Payment request information .
During the onPaymentDataChanged callback, the shippingAddress is redacted for privacy — you only receive administrativeArea, locality, countryCode, and postalCode. The full address (street, name, etc.) is only available in onPaymentAuthorized.
---end
---end
Sample of an intermediate payload returned from Google Pay API
Dynamic price updates are the core mechanism of Express Checkout. Every time the user changes their shipping address, selects a different shipping option, or enters a promo code, the onPaymentDataChanged callback fires and you must return updated pricing.
---end
Always return newTransactionInfo — even if the price hasn't changed. This ensures the payment sheet stays in sync.
Use ESTIMATED on initial load and switch to FINAL once shipping and tax are resolved.
Include displayItems to provide transparency. If you show a shipping line item, update its price to match the selected shipping option.
The totalPrice must equal the sum of subtotal + shipping + tax − discount. Google does not auto-compute it.
Negative prices in displayItems are only allowed for items with type: 'DISCOUNT'.
---end
Sample Implementation for dynamic pricing updates logic
function getShippingCosts() {
return {
"shipping-001": "0.00",
"shipping-002": "1.99",
"shipping-003": "10.00",
"shipping-munich-001": "4.99",
"shipping-munich-002": "14.99",
};
}
function getShippingOptionsForMunich() {
return {
defaultSelectedOptionId: "shipping-munich-001",
shippingOptions: [
{
id: "shipping-munich-001",
label: "$4.99: Standard shipping",
description: "Standard shipping delivered in 3 business days.",
},
{
id: "shipping-munich-002",
label: "$14.99: Express shipping",
description: "Express shipping delivered in 1 business day.",
},
],
};
}
function calculateNewTransactionInfo(shippingOptionId) {
let newTransactionInfo = transactionInfo;
// removing the existing shipping info
newTransactionInfo.displayItems = newTransactionInfo.displayItems.filter(
(item) => item.type !== "SHIPPING_OPTION",
);
let shippingCost = getShippingCosts()[shippingOptionId];
newTransactionInfo.displayItems.push({
type: "SHIPPING_OPTION",
label: "Shipping cost",
price: shippingCost,
});
let totalPrice = 0.0;
newTransactionInfo.displayItems.forEach(
(displayItem) => (totalPrice += parseFloat(displayItem.price)),
);
newTransactionInfo.totalPrice = totalPrice.toString();
return newTransactionInfo;
}
function onPaymentDataChanged(intermediatePaymentData) {
let paymentDataRequestUpdate = {};
let shippingAddress = intermediatePaymentData.shippingAddress;
let shippingOptionData = intermediatePaymentData.shippingOptionData;
switch (intermediatePaymentData.callbackTrigger) {
case "INITIALIZE":
case "SHIPPING_ADDRESS":
// Read intermediatePaymentData.transactionInfo
// Read intermediatePaymentData.shippingAddress
// Update paymentDataRequestUpdate.newTransactionInfo
// For example, read the shipping address and update the shipping options
// if the postal code belongs to Munich
const postalCode = Number(shippingAddress?.postalCode);
if (postalCode >= 80331 && postalCode <= 81929) {
const newShippingOptionParameters = getShippingOptionsForMunich();
const newTransactionInfo = calculateNewTransactionInfo(newShippingOptionParameters.defaultSelectedOptionId); );
paymentDataRequestUpdate.newShippingOptionParameters = newShippingOptionParameters;
paymentDataRequestUpdate.newTransactionInfo = newTransactionInfo;
} else if (postalCode === 18581) {
// throw error is postal code is 18581
paymentDataRequestUpdate.error = {
reason: "SHIPPING_ADDRESS_UNSERVICEABLE",
message: "Cannot ship to the selected address",
intent: "SHIPPING_ADDRESS",
};
}
break;
case "SHIPPING_OPTION":
// Read intermediatePaymentData.transactionInfo
// Read intermediatePaymentData.shippingOptionData
// Update paymentDataRequestUpdate.newTransactionInfo
// Update paymentDataRequestUpdate.newShippingOptionParameters
const newTransactionInfo = calculateNewTransactionInfo(shippingOptionData.id);
paymentDataRequestUpdate.newTransactionInfo = newTransactionInfo;
break;
default:
}
return paymentDataRequestUpdate;
}
Handle onPaymentAuthorized callback and retrieve Address information
onPaymentAuthorized is Invoked when a payment is authorized in the payment sheet. This should be already handled by your standard implementation.
For Express checkout flow it is important to extend your handling to fetch additional information based on the configuration provided in the Payment Request/while invoking Google Pay
This is a final callback and the response information (Shipping, Billing, email) should be used to make requests against Payone API.
Billing address details can be requested from the user by configuring the parameters field under allowedPaymentMethods. These details are collected when the user adds a card to their Google Pay profile.
Parameters can be passed with billingAddressRequired, billingAddressParameters fields to request billing address from the user:
The information provided in the response can now be used to send an API Request to Payone for payment processing. There is no different compared to a `standard` Google Pay implementation.
Example React Implementation for google pay express checkout button without dynamic updates