-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add Google Pay yellow path #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add Google Pay yellow path #40
Conversation
- add resumeAddCardToGoogleWallet() method for resuming card provisioning using existing token reference ID - add listTokens() method to retrieve all tokens stored in Google Wallet - add AndroidResumeCardData and TokenInfo types for new functionality - update README.md with documentation for new methods These methods provide better token lifecycle management and support for existing card tokens in Google Wallet integration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
All contributors have signed the CLA ✍️ ✅ |
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, it looks good. I've left some comments. Additionally, could you please add a video to the PR description that demonstrates how your solution works in our example app?
example/src/walletUtils.ts
Outdated
|
||
if (!existingToken) { | ||
throw new Error( | ||
`No se encontró el token para la tarjeta terminada en ${CONST.AndroidDummyResumeCardData.lastDigits}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this error message to english
`No se encontró el token para la tarjeta terminada en ${CONST.AndroidDummyResumeCardData.lastDigits}`, | |
`Token not found for card ending with ${CONST.AndroidDummyResumeCardData.lastDigits}`, |
src/NativeWallet.ts
Outdated
@@ -29,6 +29,13 @@ type AndroidCardData = { | |||
userAddress: UserAddress; | |||
}; | |||
|
|||
type AndroidResumeCardData = { | |||
network: string; | |||
tokenReferenceId: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tokenReferenceId: string; | |
tokenReferenceID: string; |
src/index.tsx
Outdated
async function listTokens(): Promise<TokenInfo[]> { | ||
if (Platform.OS === 'ios') { | ||
throw new Error('listTokens is not available on iOS'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great to add the listTokens()
function also for iOS. Since it's Android-specific PR, how about adding an iOS stub here, and renaming TokenInfo
return type keys to be more cross-platform reusable. For example:
type TokenInfo = {
identifier: string;
lastDigits: string;
tokenState: number;
};
Thanks to that iOS implementation can be added in a follow-up PR
src/NativeWallet.ts
Outdated
type TokenInfo = { | ||
tokenReferenceId: string; | ||
fpanLastFour: string; | ||
tokenState: number; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As said before, how about renaming keys to something like this:
type TokenInfo = { | |
tokenReferenceId: string; | |
fpanLastFour: string; | |
tokenState: number; | |
}; | |
type TokenInfo = { | |
identifier: string; | |
lastDigits: string; | |
tokenState: number; | |
}; |
README.md
Outdated
| **UserAddress** | Structured address used for cardholder verification. | `name: string`,<br>`addressOne: string`,<br>`addressTwo: string`,<br>`city: string`,<br>`administrativeArea: string`,<br>`countryCode: string`,<br>`postalCode: string`,<br>`phoneNumber: string` | | ||
| **IOSCardData** | Data related to a card that is to be added on iOS platform. | `network: string`,<br>`activationData: string`,<br>`encryptedPassData: string`,<br>`ephemeralPublicKey: string`,<br>`cardHolderTitle: string`,<br>`cardHolderName: string`,<br>`lastDigits: string`,<br>`cardDescription: string`,<br>`cardDescriptionComment: string` | | ||
| **onCardActivatedPayload** | Data used by listener to notice when a card’s status changes. | `tokenId: string`,<br> `actionStatus: 'activated' \| 'canceled'`<br> | | ||
| **IOSIssuerCallback** | This callback is invoked with a nonce, its signature, and a certificate array obtained from Apple. It is expected that you will forward these details to your server or the card issuer's API to securely encrypt the payload required for adding cards to the Apple Wallet. | `(nonce: string, nonceSignature: string, certificate: string[]) => IOSEncryptPayload` | | ||
| **IOSEncryptPayload** | An object containing the necessary elements to complete the addition of a card to Apple Wallet. | `encryptedPassData: string`,<br>`activationData: string`,<br>`ephemeralPublicKey: string` | | ||
| **TokenInfo** | Information about a token stored in Google Wallet. | `tokenReferenceId: string`,<br>`fpanLastFour: string`,<br>`tokenState: number` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update type value names here too
@ReactMethod | ||
override fun resumeAddCardToGoogleWallet(data: ReadableMap, promise: Promise) { | ||
try { | ||
val tokenReferenceId = data.getString("tokenReferenceId") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
val tokenReferenceId = data.getString("tokenReferenceId") | |
val tokenReferenceID = data.getString("tokenReferenceID") |
Thanks for the review! Regarding the demo video, I need to clarify the testing constraints: To demonstrate the Google Pay tokenization flow, I would need:
The testing I performed was done using my work environment, but I cannot share that footage publicly as it contains |
Greetings @Skalakid, I'm looking forward to continuing the approval process. If there's any way I can proceed, please let me know. |
Hello, had to finish some other tasks. We need to check if it actually works before merging. Since you've tested it in your unreleased app and can't attach a video here, I think we can try testing it in the Expensify app. I will try to add this flow there and will come back to you with more information |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dbracamonte Finally got some time to test this PR. Everything works fine. Left some last comments, and I think we can merge it ;)
yellow-path.mp4
|
||
val cardNetwork = getCardNetwork(network) | ||
val tokenServiceProvider = getTokenServiceProvider(network) | ||
val displayName = getDisplayName(data, network) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we use just cardHolderName
as a display name, like in the addCardToGoogleWallet
function? Is the getDisplayName
function necessary?
} | ||
|
||
return "${network.uppercase(Locale.getDefault())} Card" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the above comment, why do we need this?
This PR introduces new features to integrate the Google Pay yellow path flow, allowing users to resume adding cards to Google Wallet and managing existing tokens. This is essential to comply with Google Pay requirements.
Summary
resumeAddCardToGoogleWallet()
method for resuming card provisioning using existing token reference IDlistTokens()
method to retrieve all tokens stored in Google WalletAndroidResumeCardData
andTokenInfo
Changes Made
Android Native (Kotlin)
resumeAddCardToGoogleWallet
andlistTokens
methods with proper error handlingTypeScript/React Native
Documentation
Features
resumeAddCardToGoogleWallet(cardData: AndroidResumeCardData)
tokenReferenceId
TokenizationStatus
to track the operation resultlistTokens()
TokenInfo
objects containing:tokenReferenceId
: Unique token identifierfpanLastFour
: Last four digits of the tokenized cardtokenState
: Current state of the token (numeric value)