-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding Google Pay API for Web 101 and 201 codelab folders which are a…
…lso configured as Project IDX templates.
- Loading branch information
Showing
11 changed files
with
799 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Google Pay for Web | ||
|
||
<!--- Try in IDX button --> | ||
<a href="https://idx.google.com/new?template=https%3A%2F%2Fgithub.com%2Fgoogle-pay%2Fgoogle-pay-button%2Ftree%2Fweb-codelabs%2Fexamples%2Fhtml%2Fgpay-web-101"> | ||
<picture> | ||
<source | ||
media="(prefers-color-scheme: dark)" | ||
srcset="https://cdn.idx.dev/btn/try_dark_32.svg"> | ||
<source | ||
media="(prefers-color-scheme: light)" | ||
srcset="https://cdn.idx.dev/btn/try_light_32.svg"> | ||
<img | ||
height="32" | ||
alt="Try in IDX" | ||
src="https://cdn.idx.dev/btn/try_purple_32.svg"> | ||
</picture> | ||
</a> | ||
|
||
## About | ||
|
||
This project is a minimum viable integration of Google Pay for Web using HTML and JavaScript. For a more complete | ||
integration, refer to [`gpay-web-201/`][17] project template. | ||
|
||
## Learning | ||
|
||
To learn about the code in this project template, follow to the [Google Pay API for Web 101: Basic][10] codelab which is | ||
one of the [Google Pay API for Web learning pathway][11] activities. Learning paths help you get the most of your | ||
integration by taking you through a guided developer journey from start to finish. | ||
|
||
## Community | ||
|
||
- Join the conversation in the [#payments channel on Discord][12] | ||
- Follow [@GooglePayDevs on X][13] for announcements about more content like this | ||
- Subscribe to the [Google for Developers][14] YouTube channel | ||
|
||
## Support | ||
|
||
- Question about this template? Ask in the [discussions][16] section of the Google Pay button repo. | ||
- For assistance with your implementation, create a support ticket from the [Google Pay & Wallet Console][15]. | ||
|
||
[10]: https://codelabs.developers.google.com/codelabs/gpay-web-101 | ||
[11]: https://developers.google.com/learn/pathways/google-pay-for-web | ||
[12]: https://goo.gle/payments-dev-community | ||
[13]: https://x.com/GooglePayDevs | ||
[14]: https://goo.gle/developers | ||
[15]: https://goo.gle/3Cg8KxJ | ||
[16]: https://github.com/google-pay/google-pay-button/discussions | ||
[17]: https://github.com/google-pay/google-pay-button/tree/main/examples/html/gpay-web-201/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "Google Pay API for Web", | ||
"description": "Minimum viable web integration of the Google Pay API on Web.", | ||
"categories": ["Web app", "Misc"], | ||
"icon": "https://www.gstatic.com/images/branding/productlogos/google_pay_round/v6/192px.svg", | ||
"publisher": "Google Pay DevRel", | ||
"website": "https://codelabs.developers.google.com/codelabs/gpay-web-101" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ pkgs, ... }: { | ||
bootstrap = '' | ||
# Copy the folder containing the `idx-template` files to the final | ||
# project folder for the new workspace. ${./.} inserts the directory | ||
# of the checked-out Git folder containing this template. | ||
cp -rf ${./.} "$out" | ||
# Set some permissions | ||
chmod -R +w "$out" | ||
# Remove the template files themselves and any connection to the template's | ||
# Git repository | ||
rm -rf "$out/.git" "$out/idx-template".{nix,json} | ||
''; | ||
idx = { | ||
workspace = { | ||
onCreate = { | ||
default.openFiles = [ | ||
"src/main.js" | ||
"src/index.html" | ||
]; | ||
}; | ||
}; | ||
previews = { | ||
enable = true; | ||
previews = { | ||
web = { | ||
command = ["python3" "-m" "http.server" "$PORT" "--bind" "0.0.0.0"]; | ||
manager = "web"; | ||
}; | ||
}; | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<!DOCTYPE html> | ||
<!-- | ||
Copyright 2024 Google LLC | ||
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. | ||
--> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Google Pay API for Web</title> | ||
</head> | ||
|
||
<body> | ||
<div id="gpay-container"></div> | ||
<p>Transaction info and errors will be logged to the console.</p> | ||
<script type="text/javascript" src="main.js"></script> | ||
<script async src="https://pay.google.com/gp/p/js/pay.js" onload="onGooglePayLoaded()"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
/** | ||
* Copyright 2024 Google LLC | ||
* | ||
* 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. | ||
*/ | ||
|
||
//============================================================================= | ||
// Configuration | ||
//============================================================================= | ||
|
||
// The DOM element that the Google Pay button will be rendered into | ||
const GPAY_BUTTON_CONTAINER_ID = 'gpay-container'; | ||
|
||
// Update the `merchantId` and `merchantName` properties with your own values. | ||
// These fields are optional when the environment is `TEST`. | ||
const merchantInfo = { | ||
merchantId: '12345678901234567890', | ||
merchantName: 'Example Merchant', | ||
}; | ||
|
||
/** | ||
* This is the base configuration for all Google Pay requests. This | ||
* configuration will be cloned, modified, and used for all Google Pay requests. | ||
* | ||
* @see {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist} | ||
* @see {@link https://developers.google.com/pay/api/web/reference/request-objects} | ||
* @see {@link https://developers.google.com/pay/api/web/reference/request-objects#gateway} | ||
* @see {@link https://developers.google.com/pay/api/web/reference/request-objects#MerchantInfo} | ||
*/ | ||
const baseGooglePayRequest = { | ||
apiVersion: 2, | ||
apiVersionMinor: 0, | ||
allowedPaymentMethods: [ | ||
{ | ||
type: 'CARD', | ||
parameters: { | ||
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], | ||
allowedCardNetworks: ['AMEX', 'DISCOVER', 'INTERAC', 'JCB', 'MASTERCARD', 'VISA'], | ||
}, | ||
tokenizationSpecification: { | ||
type: 'PAYMENT_GATEWAY', | ||
parameters: { | ||
gateway: 'example', | ||
gatewayMerchantId: 'exampleGatewayMerchantId', | ||
}, | ||
}, | ||
}, | ||
], | ||
merchantInfo, | ||
}; | ||
|
||
// Prevent accidental edits to the base configuration. Mutations will be | ||
// handled by cloning the config using deepCopy() and modifying the copy. | ||
Object.freeze(baseGooglePayRequest); | ||
|
||
//============================================================================= | ||
// Google payments client singleton | ||
//============================================================================= | ||
|
||
/** | ||
* A variable to store the Google Payments Client instance. | ||
* Initialized to null to indicate it hasn't been created yet. | ||
*/ | ||
let paymentsClient = null; | ||
|
||
/** | ||
* Gets an instance of the Google Payments Client. | ||
* | ||
* This function ensures that only one instance of the Google Payments Client | ||
* is created and reused throughout the application. It lazily initializes | ||
* the client if it hasn't been created yet. | ||
* | ||
* @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient} | ||
* @return {google.payments.api.PaymentsClient} Google Payments Client instance. | ||
*/ | ||
function getGooglePaymentsClient() { | ||
// Check if the paymentsClient has already been initialized. | ||
if (paymentsClient === null) { | ||
// If not, create a new instance of the Google Payments Client. | ||
paymentsClient = new google.payments.api.PaymentsClient({ | ||
// Set the environment for the client ('TEST' or 'PRODUCTION'). | ||
// `TEST` is default. | ||
environment: 'TEST', | ||
// Add the merchant information (optional) | ||
merchantInfo, | ||
}); | ||
} | ||
|
||
return paymentsClient; | ||
} | ||
|
||
//============================================================================= | ||
// Helpers | ||
//============================================================================= | ||
|
||
/** | ||
* Creates a deep copy of an object. | ||
* | ||
* This function uses JSON serialization and deserialization to create a deep | ||
* copy of the provided object. It's a convenient way to clone objects without | ||
* worrying about shared references. | ||
* | ||
* @param {Object} obj - The object to be copied. | ||
* @returns {Object} A deep copy of the original object. | ||
*/ | ||
const deepCopy = obj => JSON.parse(JSON.stringify(obj)); | ||
|
||
/** | ||
* Renders the Google Pay button to the DOM. | ||
* | ||
* This function creates a Google Pay button using the Google Pay API and adds | ||
* it to the container element specified by `GPAY_BUTTON_CONTAINER_ID`. | ||
* When clicked, button triggers the `onGooglePaymentButtonClicked` handler. | ||
* | ||
* @see {@link https://developers.google.com/pay/api/web/reference/client#createButton} | ||
* @returns {void} | ||
*/ | ||
function renderGooglePayButton() { | ||
// Create a Google Pay button using the PaymentsClient. | ||
const button = getGooglePaymentsClient().createButton({ | ||
// Set the click handler for the button to the onGooglePaymentButtonClicked | ||
onClick: onGooglePaymentButtonClicked, | ||
}); | ||
// Add the Google Pay button to the container element on the page. | ||
document.getElementById(GPAY_BUTTON_CONTAINER_ID).appendChild(button); | ||
} | ||
|
||
//============================================================================= | ||
// Event Handlers | ||
//============================================================================= | ||
|
||
/** | ||
* Google Pay API loaded handler | ||
* | ||
* This function will be called by the script tag in index.html when the pay.js | ||
* script has finished loading. Once the script is loaded, it will first check | ||
* to see if the consumer is ready to pay with Google Pay. If they are ready, | ||
* the next thing it does is add the Google Pay button to the page. Otherwise, | ||
* it logs an error to the console. | ||
* | ||
* @see {@link https://developers.google.com/pay/api/web/reference/client#isReadyToPay} | ||
* @returns {void} | ||
*/ | ||
function onGooglePayLoaded() { | ||
// Create a deep copy of the base Google Pay request object. | ||
// This ensures that any modifications made to the request object | ||
// do not affect the original base request. | ||
const req = deepCopy(baseGooglePayRequest); | ||
|
||
// Get an instance of the Google Payments Client. | ||
getGooglePaymentsClient() | ||
// Check if the user is ready to pay with Google Pay. | ||
.isReadyToPay(req) | ||
// Handle the response from the isReadyToPay() method. | ||
.then(function (res) { | ||
// If the user is ready to pay with Google Pay... | ||
if (res.result) { | ||
// Render the Google Pay button to the page. | ||
renderGooglePayButton(); | ||
} else { | ||
// If the user is not ready to pay with Google Pay, log | ||
// an error to the console. | ||
console.log('Google Pay is not ready for this user.'); | ||
} | ||
}) | ||
// Handle any errors that occur during the process. | ||
.catch(console.error); | ||
} | ||
|
||
/** | ||
* Google Pay button click handler | ||
* | ||
* @see {@link https://developers.google.com/pay/api/web/reference/client#loadPaymentData} | ||
* @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentMethodTokenizationData} | ||
* @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo} | ||
* @returns {void} | ||
*/ | ||
function onGooglePaymentButtonClicked() { | ||
// Create a new request data object for this request | ||
const req = { | ||
...deepCopy(baseGooglePayRequest), | ||
transactionInfo: { | ||
countryCode: 'US', | ||
currencyCode: 'USD', | ||
totalPriceStatus: 'FINAL', | ||
totalPrice: (Math.random() * 999 + 1).toFixed(2), | ||
}, | ||
}; | ||
|
||
// Write the data to console for debugging | ||
console.log('onGooglePaymentButtonClicked', req); | ||
|
||
// Get an instance of the Google Payments Client. | ||
getGooglePaymentsClient() | ||
// Load the payment data in console for the transaction. | ||
.loadPaymentData(req) | ||
// If the payment is successful, process the payment | ||
.then(function (res) { | ||
// show returned data for debugging | ||
console.log(res); | ||
// @todo pass payment token to your gateway to process payment | ||
// @note DO NOT save the payment credentials for future transactions, | ||
// unless they're used for merchant-initiated transactions with user | ||
// consent in place. | ||
paymentToken = res.paymentMethodData.tokenizationData.token; | ||
}) | ||
// If there is an error, log it to the console. | ||
.catch(console.error); | ||
} |
Oops, something went wrong.