├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── android ├── app │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ └── gms │ │ │ └── samples │ │ │ └── wallet │ │ │ └── activity │ │ │ └── CheckoutActivity.kt │ │ └── res │ │ ├── drawable-v21 │ │ └── add_to_google_wallet_button_background_shape.xml │ │ ├── drawable-xxhdpi │ │ └── ts_10_11019a.jpg │ │ ├── drawable │ │ ├── add_to_google_wallet_button_background_shape.xml │ │ └── add_to_google_wallet_button_foreground.xml │ │ ├── layout │ │ └── activity_checkout.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── dimens.xml │ │ ├── googlepay_strings.xml │ │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── android_complete ├── app │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ └── gms │ │ │ └── samples │ │ │ └── wallet │ │ │ └── activity │ │ │ └── CheckoutActivity.kt │ │ └── res │ │ ├── drawable-v21 │ │ └── add_to_google_wallet_button_background_shape.xml │ │ ├── drawable-xxhdpi │ │ └── ts_10_11019a.jpg │ │ ├── drawable │ │ ├── add_to_google_wallet_button_background_shape.xml │ │ └── add_to_google_wallet_button_foreground.xml │ │ ├── layout │ │ ├── activity_checkout.xml │ │ └── add_to_google_wallet_button.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── dimens.xml │ │ ├── googlepay_strings.xml │ │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── backend ├── generic_class.js ├── generic_pass.js ├── package-lock.json └── package.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .gradle 4 | .vscode 5 | .idea 6 | 7 | local.properties 8 | build/ 9 | *.aar 10 | *.iml 11 | *.jks 12 | *.apk 13 | *.pem 14 | 15 | node_modules/ 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows 28 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2017 Google Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Google Wallet Android Codelab 2 | 3 | ## Overview 4 | 5 | This repository contains the resources used in the 6 | [Create passes on Android using the Google Wallet API](https://codelabs.developers.google.com/add-to-wallet-android) 7 | codelab. This codelab demonstrates how to perform the following tasks: 8 | 9 | 1. Create a new issuer account in development mode 10 | 1. Create a service account for issuing passes 11 | 1. Create a new Generic pass class 12 | 1. Create a new pass object 13 | 1. Create an "Add to Google Wallet" button to save a pass 14 | 1. Display the button in your Android app 15 | 1. Handle the pass save result 16 | 17 | ## Prerequisites 18 | 19 | * [Android Studio](https://developer.android.com/studio) 20 | * [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 21 | * The ability to create and run Android Studio projects 22 | 23 | ## Code Files 24 | 25 | | Directory | Description | 26 | |------------------------------------------|----------------------------------------------| 27 | | [android/](./android/) | The sample app that you will customize | 28 | | [android_complete/](./android_complete/) | The same sample app with all steps completed | 29 | | [backend/classes/](./backend) | Sample code files for creating passes | 30 | 31 | ## Support 32 | 33 | For any questions or issues, please submit an issue on this repository. 34 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | compileSdkVersion 33 6 | 7 | defaultConfig { 8 | applicationId "com.google.android.gms.samples.wallet" 9 | minSdkVersion 19 10 | targetSdkVersion 33 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | shrinkResources true 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 20 | } 21 | } 22 | 23 | buildFeatures { 24 | viewBinding true 25 | } 26 | } 27 | 28 | dependencies { 29 | implementation 'androidx.appcompat:appcompat:1.5.1' 30 | 31 | // TODO: Add the "com.google.android.gms:play-services-pay" dependency to 32 | // use the Google Wallet API 33 | 34 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" 35 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" 36 | implementation "androidx.activity:activity-ktx:1.6.0" 37 | } 38 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/google/android/gms/samples/wallet/activity/CheckoutActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.android.gms.samples.wallet.activity 18 | 19 | import android.content.Intent 20 | import android.os.Bundle 21 | import android.util.Log 22 | import android.view.View 23 | import androidx.appcompat.app.AppCompatActivity 24 | 25 | import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding 26 | import com.google.android.gms.pay.Pay 27 | import com.google.android.gms.pay.PayApiAvailabilityStatus 28 | import com.google.android.gms.pay.PayClient 29 | 30 | 31 | /** 32 | * Checkout implementation for the app 33 | */ 34 | class CheckoutActivity : AppCompatActivity() { 35 | 36 | private lateinit var layout: ActivityCheckoutBinding 37 | private lateinit var addToGoogleWalletButton: View 38 | 39 | // TODO: Add a request code for the save operation 40 | 41 | // TODO: Create a client to interact with the Google Wallet API 42 | 43 | override fun onCreate(savedInstanceState: Bundle?) { 44 | super.onCreate(savedInstanceState) 45 | 46 | // TODO: Instantiate the Pay client 47 | 48 | // Use view binding to access the UI elements 49 | layout = ActivityCheckoutBinding.inflate(layoutInflater) 50 | setContentView(layout.root) 51 | 52 | // TODO: Check if the Google Wallet API is available 53 | 54 | // TODO: Set an on-click listener on the "Add to Google Wallet" button 55 | } 56 | 57 | // TODO: Create a method to check for the Google Wallet SDK and API 58 | 59 | // TODO: Handle the result 60 | 61 | // TODO: Create the pass object definition 62 | } 63 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/add_to_google_wallet_button_background_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/ts_10_11019a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/drawable-xxhdpi/ts_10_11019a.jpg -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/add_to_google_wallet_button_background_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/add_to_google_wallet_button_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 18 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/activity_checkout.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 31 | 32 | 39 | 40 | 49 | 50 | 57 | 58 | 65 | 66 | 74 | 75 | 82 | 83 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 5dp 21 | 10dp 22 | 30dp 23 | 24 | 300dp 25 | 48dp 26 | 48dp 27 | 200dp 28 | 29 | 30 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/googlepay_strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Google Pay 4 | Buy with Google Pay 5 | Add to Google Wallet 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | Auto T-Shirt App 20 | Auto T-Shirt Shop 21 | Unfortunately, Google Pay is not available on this phone. 22 | Unfortunately, Google Wallet is not available on this phone. 23 | Checking if Google Pay is available... 24 | Successfully received payment data for %s! 25 | The pass was added successfully! 26 | 27 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.7.10' 5 | 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:7.3.0' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | 15 | // NOTE: Do not place your application dependencies here; they belong 16 | // in the individual module build.gradle files 17 | } 18 | } 19 | 20 | allprojects { 21 | repositories { 22 | google() 23 | mavenCentral() 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | android.useAndroidX=true 20 | android.enableJetifier=true -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jul 09 19:05:54 CEST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /android_complete/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | compileSdkVersion 33 6 | 7 | defaultConfig { 8 | applicationId "com.google.android.gms.samples.wallet" 9 | minSdkVersion 19 10 | targetSdkVersion 33 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | shrinkResources true 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 20 | } 21 | } 22 | 23 | buildFeatures { 24 | viewBinding true 25 | } 26 | } 27 | 28 | dependencies { 29 | implementation 'androidx.appcompat:appcompat:1.5.1' 30 | 31 | // TODO: Add the "com.google.android.gms:play-services-pay" dependency to 32 | // use the Google Wallet API 33 | implementation "com.google.android.gms:play-services-pay:16.0.3" 34 | 35 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" 36 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" 37 | implementation "androidx.activity:activity-ktx:1.6.0" 38 | } 39 | -------------------------------------------------------------------------------- /android_complete/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /android_complete/app/src/main/java/com/google/android/gms/samples/wallet/activity/CheckoutActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.android.gms.samples.wallet.activity 18 | 19 | import android.content.Intent 20 | import android.os.Bundle 21 | import android.util.Log 22 | import android.view.View 23 | import androidx.appcompat.app.AppCompatActivity 24 | 25 | import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding 26 | import com.google.android.gms.pay.Pay 27 | import com.google.android.gms.pay.PayApiAvailabilityStatus 28 | import com.google.android.gms.pay.PayClient 29 | 30 | 31 | /** 32 | * Checkout implementation for the app 33 | */ 34 | class CheckoutActivity : AppCompatActivity() { 35 | 36 | private lateinit var layout: ActivityCheckoutBinding 37 | private lateinit var addToGoogleWalletButton: View 38 | 39 | // TODO: Add a request code for the save operation 40 | private val addToGoogleWalletRequestCode = 1000 41 | 42 | // TODO: Create a client to interact with the Google Wallet API 43 | private lateinit var walletClient: PayClient 44 | 45 | override fun onCreate(savedInstanceState: Bundle?) { 46 | super.onCreate(savedInstanceState) 47 | 48 | // TODO: Instantiate the Pay client 49 | walletClient = Pay.getClient(this) 50 | 51 | // Use view binding to access the UI elements 52 | layout = ActivityCheckoutBinding.inflate(layoutInflater) 53 | setContentView(layout.root) 54 | 55 | // TODO: Check if the Google Wallet API is available 56 | fetchCanUseGoogleWalletApi() 57 | 58 | // TODO: Set an on-click listener on the "Add to Google Wallet" button 59 | addToGoogleWalletButton = layout.addToGoogleWalletButton.root 60 | addToGoogleWalletButton.setOnClickListener { 61 | walletClient.savePasses( 62 | TODO("Token goes here"), 63 | this, 64 | addToGoogleWalletRequestCode 65 | ) 66 | } 67 | } 68 | 69 | // TODO: Create a method to check for the Google Wallet SDK and API 70 | private fun fetchCanUseGoogleWalletApi() { 71 | walletClient 72 | .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES) 73 | .addOnSuccessListener { status -> 74 | if (status == PayApiAvailabilityStatus.AVAILABLE) 75 | layout.passContainer.visibility = View.VISIBLE 76 | } 77 | .addOnFailureListener { 78 | // Hide the button and optionally show an error message 79 | } 80 | } 81 | 82 | // TODO: Handle the result 83 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 84 | super.onActivityResult(requestCode, resultCode, data) 85 | 86 | if (requestCode == addToGoogleWalletRequestCode) { 87 | when (resultCode) { 88 | RESULT_OK -> { 89 | // Pass saved successfully. Consider informing the user. 90 | } 91 | RESULT_CANCELED -> { 92 | // Save canceled 93 | } 94 | 95 | PayClient.SavePassesResult.SAVE_ERROR -> data?.let { intentData -> 96 | val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE) 97 | // Handle error. Consider informing the user. 98 | } 99 | 100 | else -> { 101 | // Handle unexpected (non-API) exception 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/drawable-v21/add_to_google_wallet_button_background_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/drawable-xxhdpi/ts_10_11019a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/drawable-xxhdpi/ts_10_11019a.jpg -------------------------------------------------------------------------------- /android_complete/app/src/main/res/drawable/add_to_google_wallet_button_background_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/drawable/add_to_google_wallet_button_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 12 | 15 | 18 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/layout/activity_checkout.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 31 | 32 | 39 | 40 | 49 | 50 | 57 | 58 | 65 | 66 | 74 | 75 | 82 | 83 | 91 | 92 | 93 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/layout/add_to_google_wallet_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 15 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android_complete/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 5dp 21 | 10dp 22 | 30dp 23 | 24 | 300dp 25 | 48dp 26 | 48dp 27 | 200dp 28 | 29 | 30 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/values/googlepay_strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Google Pay 4 | Buy with Google Pay 5 | Add to Google Wallet 6 | 7 | -------------------------------------------------------------------------------- /android_complete/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | Auto T-Shirt App 20 | Auto T-Shirt Shop 21 | Unfortunately, Google Pay is not available on this phone. 22 | Unfortunately, Google Wallet is not available on this phone. 23 | Checking if Google Pay is available... 24 | Successfully received payment data for %s! 25 | The pass was added successfully! 26 | 27 | -------------------------------------------------------------------------------- /android_complete/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.7.10' 5 | 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:7.3.0' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | 15 | // NOTE: Do not place your application dependencies here; they belong 16 | // in the individual module build.gradle files 17 | } 18 | } 19 | 20 | allprojects { 21 | repositories { 22 | google() 23 | mavenCentral() 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android_complete/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | android.useAndroidX=true 20 | android.enableJetifier=true -------------------------------------------------------------------------------- /android_complete/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-wallet/android-codelab/e5855d9d6c38e60c29790656efe88d68e85351fd/android_complete/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android_complete/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jul 09 19:05:54 CEST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 7 | -------------------------------------------------------------------------------- /android_complete/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /android_complete/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android_complete/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /backend/generic_class.js: -------------------------------------------------------------------------------- 1 | const { GoogleAuth } = require('google-auth-library'); 2 | 3 | // TODO: Define issuer ID 4 | let issuerId = 'ISSUER_ID'; 5 | let classSuffix = 'codelab_class'; 6 | const classId = `${issuerId}.${classSuffix}`; 7 | const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; 8 | 9 | const baseUrl = 'https://walletobjects.googleapis.com/walletobjects/v1'; 10 | 11 | const credentials = require(keyFilePath); 12 | 13 | const httpClient = new GoogleAuth({ 14 | credentials: credentials, 15 | scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' 16 | }); 17 | 18 | // Create a Generic pass class 19 | let genericClass = { 20 | 'id': `${classId}`, 21 | 'classTemplateInfo': { 22 | 'cardTemplateOverride': { 23 | 'cardRowTemplateInfos': [ 24 | { 25 | 'twoItems': { 26 | 'startItem': { 27 | 'firstValue': { 28 | 'fields': [ 29 | { 30 | 'fieldPath': 'object.textModulesData["points"]', 31 | }, 32 | ], 33 | }, 34 | }, 35 | 'endItem': { 36 | 'firstValue': { 37 | 'fields': [ 38 | { 39 | 'fieldPath': 'object.textModulesData["contacts"]', 40 | }, 41 | ], 42 | }, 43 | }, 44 | }, 45 | }, 46 | ], 47 | }, 48 | 'detailsTemplateOverride': { 49 | 'detailsItemInfos': [ 50 | { 51 | 'item': { 52 | 'firstValue': { 53 | 'fields': [ 54 | { 55 | 'fieldPath': 'class.imageModulesData["event_banner"]', 56 | }, 57 | ], 58 | }, 59 | }, 60 | }, 61 | { 62 | 'item': { 63 | 'firstValue': { 64 | 'fields': [ 65 | { 66 | 'fieldPath': 'class.textModulesData["game_overview"]', 67 | }, 68 | ], 69 | }, 70 | }, 71 | }, 72 | { 73 | 'item': { 74 | 'firstValue': { 75 | 'fields': [ 76 | { 77 | 'fieldPath': 'class.linksModuleData.uris["official_site"]', 78 | }, 79 | ], 80 | }, 81 | }, 82 | }, 83 | ], 84 | }, 85 | }, 86 | 'imageModulesData': [ 87 | { 88 | 'mainImage': { 89 | 'sourceUri': { 90 | 'uri': 'https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/google-io-2021-card.png', 91 | }, 92 | 'contentDescription': { 93 | 'defaultValue': { 94 | 'language': 'en-US', 95 | 'value': 'Google I/O 2022 Banner', 96 | }, 97 | }, 98 | }, 99 | 'id': 'event_banner', 100 | }, 101 | ], 102 | 'textModulesData': [ 103 | { 104 | 'header': 'Gather points meeting new people at Google I/O', 105 | 'body': 'Join the game and accumulate points in this badge by meeting other attendees in the event.', 106 | 'id': 'game_overview', 107 | }, 108 | ], 109 | 'linksModuleData': { 110 | 'uris': [ 111 | { 112 | 'uri': 'https://io.google/2022/', 113 | 'description': 'Official I/O \'22 Site', 114 | 'id': 'official_site', 115 | }, 116 | ], 117 | }, 118 | }; 119 | 120 | // Check if the class exists already 121 | httpClient.request({ 122 | url: `${baseUrl}/genericClass/${classId}`, 123 | method: 'GET', 124 | }).then(response => { 125 | console.log('Class already exists'); 126 | console.log(response); 127 | 128 | console.log('Class ID'); 129 | console.log(response.data.id); 130 | }).catch(err => { 131 | if (err.response && err.response.status === 404) { 132 | // Class does not exist 133 | // Create it now 134 | httpClient.request({ 135 | url: `${baseUrl}/genericClass`, 136 | method: 'POST', 137 | data: genericClass, 138 | }).then(response => { 139 | console.log('Class insert response'); 140 | console.log(response); 141 | 142 | console.log('Class ID'); 143 | console.log(response.data.id); 144 | }); 145 | } else { 146 | // Something else went wrong 147 | console.log(err); 148 | } 149 | }); 150 | -------------------------------------------------------------------------------- /backend/generic_pass.js: -------------------------------------------------------------------------------- 1 | const { GoogleAuth } = require('google-auth-library'); 2 | const jwt = require('jsonwebtoken'); 3 | 4 | // TODO: Define issuer ID 5 | let issuerId = 'ISSUER_ID'; 6 | let classSuffix = 'codelab_class'; 7 | let objectSuffix = 'codelab_object'; 8 | const objectId = `${issuerId}.${objectSuffix}`; 9 | const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; 10 | 11 | const baseUrl = 'https://walletobjects.googleapis.com/walletobjects/v1'; 12 | 13 | const credentials = require(keyFilePath); 14 | 15 | const httpClient = new GoogleAuth({ 16 | credentials: credentials, 17 | scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' 18 | }); 19 | 20 | // Create a Generic pass object 21 | let genericObject = { 22 | 'id': `${objectId}`, 23 | 'classId': `${issuerId}.${classSuffix}`, 24 | 'genericType': 'GENERIC_TYPE_UNSPECIFIED', 25 | 'hexBackgroundColor': '#4285f4', 26 | 'logo': { 27 | 'sourceUri': { 28 | 'uri': 'https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg' 29 | } 30 | }, 31 | 'cardTitle': { 32 | 'defaultValue': { 33 | 'language': 'en-US', 34 | 'value': 'Google I/O \'22' 35 | } 36 | }, 37 | 'subheader': { 38 | 'defaultValue': { 39 | 'language': 'en-US', 40 | 'value': 'Attendee' 41 | } 42 | }, 43 | 'header': { 44 | 'defaultValue': { 45 | 'language': 'en-US', 46 | 'value': 'Alex McJacobs' 47 | } 48 | }, 49 | 'barcode': { 50 | 'type': 'QR_CODE', 51 | 'value': `${objectId}` 52 | }, 53 | 'heroImage': { 54 | 'sourceUri': { 55 | 'uri': 'https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/google-io-hero-demo-only.jpg' 56 | } 57 | }, 58 | 'textModulesData': [ 59 | { 60 | 'header': 'POINTS', 61 | 'body': '1234', 62 | 'id': 'points' 63 | }, 64 | { 65 | 'header': 'CONTACTS', 66 | 'body': '20', 67 | 'id': 'contacts' 68 | } 69 | ] 70 | } 71 | 72 | const claims = { 73 | iss: credentials.client_email, // `client_email` in service account file. 74 | aud: 'google', 75 | origins: ['http://localhost:3000'], 76 | typ: 'savetowallet', 77 | payload: { 78 | genericObjects: [genericObject], 79 | }, 80 | }; 81 | 82 | const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); 83 | console.log(token) -------------------------------------------------------------------------------- /backend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "google-auth-library": ">=5.9.2", 9 | "jsonwebtoken": ">=8.5.1" 10 | } 11 | }, 12 | "node_modules/agent-base": { 13 | "version": "6.0.2", 14 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 15 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 16 | "dependencies": { 17 | "debug": "4" 18 | }, 19 | "engines": { 20 | "node": ">= 6.0.0" 21 | } 22 | }, 23 | "node_modules/arrify": { 24 | "version": "2.0.1", 25 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 26 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", 27 | "engines": { 28 | "node": ">=8" 29 | } 30 | }, 31 | "node_modules/base64-js": { 32 | "version": "1.5.1", 33 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 34 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 35 | "funding": [ 36 | { 37 | "type": "github", 38 | "url": "https://github.com/sponsors/feross" 39 | }, 40 | { 41 | "type": "patreon", 42 | "url": "https://www.patreon.com/feross" 43 | }, 44 | { 45 | "type": "consulting", 46 | "url": "https://feross.org/support" 47 | } 48 | ] 49 | }, 50 | "node_modules/bignumber.js": { 51 | "version": "9.1.0", 52 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", 53 | "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==", 54 | "engines": { 55 | "node": "*" 56 | } 57 | }, 58 | "node_modules/buffer-equal-constant-time": { 59 | "version": "1.0.1", 60 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 61 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" 62 | }, 63 | "node_modules/debug": { 64 | "version": "4.3.4", 65 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 66 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 67 | "dependencies": { 68 | "ms": "2.1.2" 69 | }, 70 | "engines": { 71 | "node": ">=6.0" 72 | }, 73 | "peerDependenciesMeta": { 74 | "supports-color": { 75 | "optional": true 76 | } 77 | } 78 | }, 79 | "node_modules/ecdsa-sig-formatter": { 80 | "version": "1.0.11", 81 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 82 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 83 | "dependencies": { 84 | "safe-buffer": "^5.0.1" 85 | } 86 | }, 87 | "node_modules/extend": { 88 | "version": "3.0.2", 89 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 90 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 91 | }, 92 | "node_modules/fast-text-encoding": { 93 | "version": "1.0.6", 94 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", 95 | "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" 96 | }, 97 | "node_modules/gaxios": { 98 | "version": "5.0.2", 99 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.0.2.tgz", 100 | "integrity": "sha512-TjtV2AJOZoMQqRYoy5eM8cCQogYwazWNYLQ72QB0kwa6vHHruYkGmhhyrlzbmgNHK1dNnuP2WSH81urfzyN2Og==", 101 | "dependencies": { 102 | "extend": "^3.0.2", 103 | "https-proxy-agent": "^5.0.0", 104 | "is-stream": "^2.0.0", 105 | "node-fetch": "^2.6.7" 106 | }, 107 | "engines": { 108 | "node": ">=12" 109 | } 110 | }, 111 | "node_modules/gcp-metadata": { 112 | "version": "5.0.1", 113 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.0.1.tgz", 114 | "integrity": "sha512-jiRJ+Fk7e8FH68Z6TLaqwea307OktJpDjmYnU7/li6ziwvVvU2RlrCyQo5vkdeP94chm0kcSCOOszvmuaioq3g==", 115 | "dependencies": { 116 | "gaxios": "^5.0.0", 117 | "json-bigint": "^1.0.0" 118 | }, 119 | "engines": { 120 | "node": ">=12" 121 | } 122 | }, 123 | "node_modules/google-auth-library": { 124 | "version": "8.5.2", 125 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.5.2.tgz", 126 | "integrity": "sha512-FPfOSaI8n2TVXFHTP8/vAVFCXhyALj7w9/Rgefux3oeKZ/nQDNmfNTJ+lIKcoYT1cKkvMllp1Eood7Y5L+TP+A==", 127 | "dependencies": { 128 | "arrify": "^2.0.0", 129 | "base64-js": "^1.3.0", 130 | "ecdsa-sig-formatter": "^1.0.11", 131 | "fast-text-encoding": "^1.0.0", 132 | "gaxios": "^5.0.0", 133 | "gcp-metadata": "^5.0.0", 134 | "gtoken": "^6.1.0", 135 | "jws": "^4.0.0", 136 | "lru-cache": "^6.0.0" 137 | }, 138 | "engines": { 139 | "node": ">=12" 140 | } 141 | }, 142 | "node_modules/google-p12-pem": { 143 | "version": "4.0.1", 144 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", 145 | "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", 146 | "dependencies": { 147 | "node-forge": "^1.3.1" 148 | }, 149 | "bin": { 150 | "gp12-pem": "build/src/bin/gp12-pem.js" 151 | }, 152 | "engines": { 153 | "node": ">=12.0.0" 154 | } 155 | }, 156 | "node_modules/gtoken": { 157 | "version": "6.1.2", 158 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", 159 | "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", 160 | "dependencies": { 161 | "gaxios": "^5.0.1", 162 | "google-p12-pem": "^4.0.0", 163 | "jws": "^4.0.0" 164 | }, 165 | "engines": { 166 | "node": ">=12.0.0" 167 | } 168 | }, 169 | "node_modules/https-proxy-agent": { 170 | "version": "5.0.1", 171 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 172 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 173 | "dependencies": { 174 | "agent-base": "6", 175 | "debug": "4" 176 | }, 177 | "engines": { 178 | "node": ">= 6" 179 | } 180 | }, 181 | "node_modules/is-stream": { 182 | "version": "2.0.1", 183 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 184 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 185 | "engines": { 186 | "node": ">=8" 187 | }, 188 | "funding": { 189 | "url": "https://github.com/sponsors/sindresorhus" 190 | } 191 | }, 192 | "node_modules/json-bigint": { 193 | "version": "1.0.0", 194 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", 195 | "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", 196 | "dependencies": { 197 | "bignumber.js": "^9.0.0" 198 | } 199 | }, 200 | "node_modules/jsonwebtoken": { 201 | "version": "9.0.0", 202 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", 203 | "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", 204 | "dependencies": { 205 | "jws": "^3.2.2", 206 | "lodash": "^4.17.21", 207 | "ms": "^2.1.1", 208 | "semver": "^7.3.8" 209 | }, 210 | "engines": { 211 | "node": ">=12", 212 | "npm": ">=6" 213 | } 214 | }, 215 | "node_modules/jsonwebtoken/node_modules/jwa": { 216 | "version": "1.4.1", 217 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 218 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 219 | "dependencies": { 220 | "buffer-equal-constant-time": "1.0.1", 221 | "ecdsa-sig-formatter": "1.0.11", 222 | "safe-buffer": "^5.0.1" 223 | } 224 | }, 225 | "node_modules/jsonwebtoken/node_modules/jws": { 226 | "version": "3.2.2", 227 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 228 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 229 | "dependencies": { 230 | "jwa": "^1.4.1", 231 | "safe-buffer": "^5.0.1" 232 | } 233 | }, 234 | "node_modules/jwa": { 235 | "version": "2.0.0", 236 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 237 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 238 | "dependencies": { 239 | "buffer-equal-constant-time": "1.0.1", 240 | "ecdsa-sig-formatter": "1.0.11", 241 | "safe-buffer": "^5.0.1" 242 | } 243 | }, 244 | "node_modules/jws": { 245 | "version": "4.0.0", 246 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 247 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 248 | "dependencies": { 249 | "jwa": "^2.0.0", 250 | "safe-buffer": "^5.0.1" 251 | } 252 | }, 253 | "node_modules/lodash": { 254 | "version": "4.17.21", 255 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 256 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 257 | }, 258 | "node_modules/lru-cache": { 259 | "version": "6.0.0", 260 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 261 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 262 | "dependencies": { 263 | "yallist": "^4.0.0" 264 | }, 265 | "engines": { 266 | "node": ">=10" 267 | } 268 | }, 269 | "node_modules/ms": { 270 | "version": "2.1.2", 271 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 272 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 273 | }, 274 | "node_modules/node-fetch": { 275 | "version": "2.6.7", 276 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 277 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 278 | "dependencies": { 279 | "whatwg-url": "^5.0.0" 280 | }, 281 | "engines": { 282 | "node": "4.x || >=6.0.0" 283 | }, 284 | "peerDependencies": { 285 | "encoding": "^0.1.0" 286 | }, 287 | "peerDependenciesMeta": { 288 | "encoding": { 289 | "optional": true 290 | } 291 | } 292 | }, 293 | "node_modules/node-forge": { 294 | "version": "1.3.1", 295 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", 296 | "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", 297 | "engines": { 298 | "node": ">= 6.13.0" 299 | } 300 | }, 301 | "node_modules/safe-buffer": { 302 | "version": "5.2.1", 303 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 304 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 305 | "funding": [ 306 | { 307 | "type": "github", 308 | "url": "https://github.com/sponsors/feross" 309 | }, 310 | { 311 | "type": "patreon", 312 | "url": "https://www.patreon.com/feross" 313 | }, 314 | { 315 | "type": "consulting", 316 | "url": "https://feross.org/support" 317 | } 318 | ] 319 | }, 320 | "node_modules/semver": { 321 | "version": "7.3.8", 322 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", 323 | "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", 324 | "dependencies": { 325 | "lru-cache": "^6.0.0" 326 | }, 327 | "bin": { 328 | "semver": "bin/semver.js" 329 | }, 330 | "engines": { 331 | "node": ">=10" 332 | } 333 | }, 334 | "node_modules/tr46": { 335 | "version": "0.0.3", 336 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 337 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 338 | }, 339 | "node_modules/webidl-conversions": { 340 | "version": "3.0.1", 341 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 342 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 343 | }, 344 | "node_modules/whatwg-url": { 345 | "version": "5.0.0", 346 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 347 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 348 | "dependencies": { 349 | "tr46": "~0.0.3", 350 | "webidl-conversions": "^3.0.0" 351 | } 352 | }, 353 | "node_modules/yallist": { 354 | "version": "4.0.0", 355 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 356 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 357 | } 358 | }, 359 | "dependencies": { 360 | "agent-base": { 361 | "version": "6.0.2", 362 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 363 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 364 | "requires": { 365 | "debug": "4" 366 | } 367 | }, 368 | "arrify": { 369 | "version": "2.0.1", 370 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 371 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" 372 | }, 373 | "base64-js": { 374 | "version": "1.5.1", 375 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 376 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 377 | }, 378 | "bignumber.js": { 379 | "version": "9.1.0", 380 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", 381 | "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==" 382 | }, 383 | "buffer-equal-constant-time": { 384 | "version": "1.0.1", 385 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 386 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" 387 | }, 388 | "debug": { 389 | "version": "4.3.4", 390 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 391 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 392 | "requires": { 393 | "ms": "2.1.2" 394 | } 395 | }, 396 | "ecdsa-sig-formatter": { 397 | "version": "1.0.11", 398 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 399 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 400 | "requires": { 401 | "safe-buffer": "^5.0.1" 402 | } 403 | }, 404 | "extend": { 405 | "version": "3.0.2", 406 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 407 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 408 | }, 409 | "fast-text-encoding": { 410 | "version": "1.0.6", 411 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", 412 | "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" 413 | }, 414 | "gaxios": { 415 | "version": "5.0.2", 416 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.0.2.tgz", 417 | "integrity": "sha512-TjtV2AJOZoMQqRYoy5eM8cCQogYwazWNYLQ72QB0kwa6vHHruYkGmhhyrlzbmgNHK1dNnuP2WSH81urfzyN2Og==", 418 | "requires": { 419 | "extend": "^3.0.2", 420 | "https-proxy-agent": "^5.0.0", 421 | "is-stream": "^2.0.0", 422 | "node-fetch": "^2.6.7" 423 | } 424 | }, 425 | "gcp-metadata": { 426 | "version": "5.0.1", 427 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.0.1.tgz", 428 | "integrity": "sha512-jiRJ+Fk7e8FH68Z6TLaqwea307OktJpDjmYnU7/li6ziwvVvU2RlrCyQo5vkdeP94chm0kcSCOOszvmuaioq3g==", 429 | "requires": { 430 | "gaxios": "^5.0.0", 431 | "json-bigint": "^1.0.0" 432 | } 433 | }, 434 | "google-auth-library": { 435 | "version": "8.5.2", 436 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.5.2.tgz", 437 | "integrity": "sha512-FPfOSaI8n2TVXFHTP8/vAVFCXhyALj7w9/Rgefux3oeKZ/nQDNmfNTJ+lIKcoYT1cKkvMllp1Eood7Y5L+TP+A==", 438 | "requires": { 439 | "arrify": "^2.0.0", 440 | "base64-js": "^1.3.0", 441 | "ecdsa-sig-formatter": "^1.0.11", 442 | "fast-text-encoding": "^1.0.0", 443 | "gaxios": "^5.0.0", 444 | "gcp-metadata": "^5.0.0", 445 | "gtoken": "^6.1.0", 446 | "jws": "^4.0.0", 447 | "lru-cache": "^6.0.0" 448 | } 449 | }, 450 | "google-p12-pem": { 451 | "version": "4.0.1", 452 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", 453 | "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", 454 | "requires": { 455 | "node-forge": "^1.3.1" 456 | } 457 | }, 458 | "gtoken": { 459 | "version": "6.1.2", 460 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", 461 | "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", 462 | "requires": { 463 | "gaxios": "^5.0.1", 464 | "google-p12-pem": "^4.0.0", 465 | "jws": "^4.0.0" 466 | } 467 | }, 468 | "https-proxy-agent": { 469 | "version": "5.0.1", 470 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 471 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 472 | "requires": { 473 | "agent-base": "6", 474 | "debug": "4" 475 | } 476 | }, 477 | "is-stream": { 478 | "version": "2.0.1", 479 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 480 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" 481 | }, 482 | "json-bigint": { 483 | "version": "1.0.0", 484 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", 485 | "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", 486 | "requires": { 487 | "bignumber.js": "^9.0.0" 488 | } 489 | }, 490 | "jsonwebtoken": { 491 | "version": "9.0.0", 492 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", 493 | "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", 494 | "requires": { 495 | "jws": "^3.2.2", 496 | "lodash": "^4.17.21", 497 | "ms": "^2.1.1", 498 | "semver": "^7.3.8" 499 | }, 500 | "dependencies": { 501 | "jwa": { 502 | "version": "1.4.1", 503 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 504 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 505 | "requires": { 506 | "buffer-equal-constant-time": "1.0.1", 507 | "ecdsa-sig-formatter": "1.0.11", 508 | "safe-buffer": "^5.0.1" 509 | } 510 | }, 511 | "jws": { 512 | "version": "3.2.2", 513 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 514 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 515 | "requires": { 516 | "jwa": "^1.4.1", 517 | "safe-buffer": "^5.0.1" 518 | } 519 | } 520 | } 521 | }, 522 | "jwa": { 523 | "version": "2.0.0", 524 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 525 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 526 | "requires": { 527 | "buffer-equal-constant-time": "1.0.1", 528 | "ecdsa-sig-formatter": "1.0.11", 529 | "safe-buffer": "^5.0.1" 530 | } 531 | }, 532 | "jws": { 533 | "version": "4.0.0", 534 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 535 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 536 | "requires": { 537 | "jwa": "^2.0.0", 538 | "safe-buffer": "^5.0.1" 539 | } 540 | }, 541 | "lodash": { 542 | "version": "4.17.21", 543 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 544 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 545 | }, 546 | "lru-cache": { 547 | "version": "6.0.0", 548 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 549 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 550 | "requires": { 551 | "yallist": "^4.0.0" 552 | } 553 | }, 554 | "ms": { 555 | "version": "2.1.2", 556 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 557 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 558 | }, 559 | "node-fetch": { 560 | "version": "2.6.7", 561 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 562 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 563 | "requires": { 564 | "whatwg-url": "^5.0.0" 565 | } 566 | }, 567 | "node-forge": { 568 | "version": "1.3.1", 569 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", 570 | "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" 571 | }, 572 | "safe-buffer": { 573 | "version": "5.2.1", 574 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 575 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 576 | }, 577 | "semver": { 578 | "version": "7.3.8", 579 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", 580 | "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", 581 | "requires": { 582 | "lru-cache": "^6.0.0" 583 | } 584 | }, 585 | "tr46": { 586 | "version": "0.0.3", 587 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 588 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 589 | }, 590 | "webidl-conversions": { 591 | "version": "3.0.1", 592 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 593 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 594 | }, 595 | "whatwg-url": { 596 | "version": "5.0.0", 597 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 598 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 599 | "requires": { 600 | "tr46": "~0.0.3", 601 | "webidl-conversions": "^3.0.0" 602 | } 603 | }, 604 | "yallist": { 605 | "version": "4.0.0", 606 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 607 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 608 | } 609 | } 610 | } 611 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "google-auth-library": ">=5.9.2", 4 | "jsonwebtoken": ">=8.5.1" 5 | } 6 | } 7 | --------------------------------------------------------------------------------