1. Introduction
This codelab is a continuation of Google Pay API for Web 101: Basics and relies on code written in that codelab. In order to complete this codelab, be sure to complete that one first.
What you'll learn
- How to customize the Google Pay button
- How to start the payment process
- How to acknowledge payment authorization status
- How to handle shipping address changes
- How to handle redemption codes
What you'll need
- A text editor of your choice to edit HTML and JavaScript files.
- The Google Chrome web browser, or another way to test a local website.
- For production, you will need a Google Pay
merchantId
. It only takes a minute to register at Google Pay & Wallet Console so might as well take care of it now.
Follow along using Project IDX
2. Button customization
This is a brief overview of the ButtonOptions
. Consult the documentation for more detailed explanation
Option | Necessity | Values |
onClick | Required | Name of JavaScript event handler |
allowedPaymentMethods | Optional | |
buttonColor | Optional | default, black, white |
buttonLocale | Optional | Two letter ISO 639-1 code. |
buttonRadius | Optional | 0 to 100 |
buttonRootNode | Optional | HTMLDocument or ShadowRoot |
buttonSizeMode | Optional | static, fill |
buttonType | Optional | book, buy, checkout, donate, order, pay, plain, subscribe |
Look for the renderGooglePayButton()
method in your main.js
file and replace it with the code listed here.
function renderGooglePayButton() {
const button = getGooglePaymentsClient().createButton({
buttonColor: 'default',
buttonType: 'buy',
buttonRadius: 4,
buttonLocale: 'en',
onClick: onGooglePaymentButtonClicked,
allowedPaymentMethods: baseGooglePayRequest.allowedPaymentMethods,
});
document.getElementById(GPAY_BUTTON_CONTAINER_ID).appendChild(button);
}
Code explanation
- The
createButton()
library method takes aButtonOptions
configuration argument that lets you define how you want the button to look and behave.
3. Payment data callbacks
The payments client provides a mechanism for you to register functions to handle when certain events happen. The first is payment authorization and the second is payment data change.
- Find the
// todo: paymentDataCallbacks
comment inmain.js
and replace it with this code.paymentDataCallbacks: { onPaymentAuthorized: onPaymentAuthorized, onPaymentDataChanged: onPaymentDataChanged },
- Then, find the
Event Handlers
section ofmain.js
and append the following code to the end of the section.function onPaymentAuthorized(paymentData) { // We'll fill this in later } function onPaymentDataChanged(intermediatePaymentData) { // We'll fill this in later }
- Finally, find
// todo: callbackIntents
comment withinmain.js
and replace the comment with this code. In this codelab, we are going to implement all 4 of the intents.callbackIntents: [ 'PAYMENT_AUTHORIZATION', 'SHIPPING_ADDRESS', 'SHIPPING_OPTION', 'OFFER', ], shippingAddressRequired: true, 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.' }, ], },
Code explanation
- The
PaymentDataCallbacks
property has two sub-properties one for a payment authorization callback and the second for a payment data change callback. - If implementing callbacks,
onPaymentAuthorized
is required. This callback is invoked when thecallbackIntents
list containsPAYMENT_AUTHORIZATION
in thePaymentDataRequest
. onPaymentDataChanged
is optional. This callback is invoked when thecallbackIntents
list containsOFFER
,SHIPPING_ADDRESS
, orSHIPPING_OPTION
in thePaymentDataRequest
.- Set the
callbackIntents
in thePaymentDataRequest
to trigger both callbacks for this codelab.
4. Payment authorization
Authorize Payments is used to start the payment process and acknowledge payment authorization status.
Find the onPaymentAuthorized()
function in main.js
that you've added in the last step and replace it with the following code.
function onPaymentAuthorized(paymentData) {
return new Promise(function(resolve, reject) {
// Write the data to console for debugging
console.log("onPaymentAuthorized", paymentData);
// Do something here to pass token to your gateway
// To simulate the payment processing, there is a 70% chance of success
const paymentAuthorizationResult = (Math.random() > 0.3)
? {transactionState: 'SUCCESS'}
: {
transactionState: 'ERROR',
error: {
intent: 'PAYMENT_AUTHORIZATION',
message: 'Insufficient funds',
reason: 'PAYMENT_DATA_INVALID'
}
};
resolve(paymentAuthorizationResult);
});
}
Code explanation
- The
onPaymentAuthorized()
callback function is invoked with aPaymentData
argument and must return a promise. In this example, the function is randomly choosing whether to return success or an error. In your project, you'll use this opportunity to process the transaction with your gateway using the token found inpaymentData
atpaymentData.paymentMethodData.tokenizationData.token
.
5. Payment data change
Dynamic Price Updates allows a merchant to dynamically update shipping options and transaction information based on a chosen shipping address. Additionally, you can dynamically update transaction information based on a chosen shipping option.
Find the onPaymentDataChanged()
function in main.js
that you've added in the last step and replace it with the following code.
function onPaymentDataChanged(intermediatePaymentData) {
return new Promise(function(resolve, reject) {
let paymentDataRequestUpdate = {};
// Write the data to console for debugging
console.log("onPaymentDataChanged", intermediatePaymentData);
switch(intermediatePaymentData.callbackTrigger)
{
case "INITIALIZE":
// Handle initialize
break;
case "SHIPPING_ADDRESS":
// Read intermediatePaymentData.transactionInfo
// Read intermediatePaymentData.shippingAddress
// Update paymentDataRequestUpdate.newTransactionInfo
break;
case "SHIPPING_OPTION":
// Read intermediatePaymentData.transactionInfo
// Read intermediatePaymentData.shippingOptionData
// Update paymentDataRequestUpdate.newTransactionInfo
// Update paymentDataRequestUpdate.newShippingOptionParameters
break;
case "OFFER":
// Read intermediatePaymentData.offerData
// Read intermediatePaymentData.transactionInfo
// Update paymentDataRequestUpdate.newTransactionInfo
// Update paymentDataRequestUpdate.newOfferInfo
break;
default:
// Update paymentDataRequestUpdate.error
}
resolve(paymentDataRequestUpdate);
});
}
Code explanation
- The
onPaymentDataChanged()
function takesIntermediatePaymentData
as an argument. This function is invoked when the shipping address or shipping options is changed in the payment sheet. - The
onPaymentDataChanged()
function must return a promise that resolves aPaymentDataRequestUpdate
object which specifies new transaction info, shipping options and error to update the payment sheet. redemptionCodes
are a set of promotional codes entered into the payment sheet. Includes codes that have already been approved.
6. Conclusion
Congratulations on completing this Codelab! You have learned how to ...
Run the project
Test with Google Chrome
Using the Google Chrome web browser, open index.html
using File > Open File... from Chrome's main menu. Chrome will execute main.js
when the project is opened this way. Other web browsers might not allow JavaScript execution.
– or –
Test with a local web server
If you have Python installed, run python3 -m http.server
from a terminal prompt in the root pay-web-101
folder.
$ cd /your/path/to/pay-web-101
$ python3 -m http.server
Serving HTTP on :: port 8000 (http://[::]:8000/) ...
Then, visit your site at http://localhost:8000
.
Where to go from here
Additional resources
- Join the conversation in the #payments channel on Discord
- Follow @GooglePayDevs on X
- Watch Google Pay related videos on YouTube