Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified modules/expensify-react-native-wallet.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 18 additions & 2 deletions src/components/AddToWalletButton/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import {AddToWalletButton as RNAddToWalletButton} from '@expensify/react-native-wallet';
import type {TokenizationStatus} from '@expensify/react-native-wallet';
import React, {useCallback, useEffect, useState} from 'react';
import {ActivityIndicator, View} from 'react-native';
import {ActivityIndicator, Alert, View} from 'react-native';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {openWalletPage} from '@libs/actions/PaymentMethods';
import getPlatform from '@libs/getPlatform';
import Log from '@libs/Log';
import {checkIfWalletIsAvailable, handleAddCardToWallet, isCardInWallet} from '@libs/Wallet/index';
import CONST from '@src/CONST';
import type AddToWalletButtonProps from './types';
Expand Down Expand Up @@ -35,7 +38,20 @@ function AddToWalletButton({card, cardHolderName, cardDescription, buttonStyle}:

const handleOnPress = useCallback(() => {
setIsLoading(true);
handleAddCardToWallet(card, cardHolderName, cardDescription, () => setIsLoading(false));
handleAddCardToWallet(card, cardHolderName, cardDescription, () => setIsLoading(false))
.then((status: TokenizationStatus) => {
if (status === 'success') {
Log.info('Card added to wallet');
openWalletPage();
} else {
setIsLoading(false);
}
})
.catch((error) => {
setIsLoading(false);
Log.warn(`Error while adding card to wallet: ${error}`);
Alert.alert('Failed to add card to wallet', 'Please try again later.');
});
}, [card, cardDescription, cardHolderName]);

useEffect(() => {
Expand Down
29 changes: 4 additions & 25 deletions src/libs/Wallet/index.android.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {addCardToGoogleWallet, checkWalletAvailability, getCardStatusBySuffix, getSecureWalletInfo} from '@expensify/react-native-wallet';
import type {AndroidCardData, AndroidWalletData, CardStatus, TokenizationStatus} from '@expensify/react-native-wallet';
import {Alert} from 'react-native';
import {openWalletPage} from '@libs/actions/PaymentMethods';
import {createDigitalGoogleWallet} from '@libs/actions/Wallet';
import Log from '@libs/Log';
import type {Card} from '@src/types/onyx';
Expand All @@ -10,29 +8,10 @@ function checkIfWalletIsAvailable(): Promise<boolean> {
return checkWalletAvailability();
}

function handleAddCardToWallet(card: Card, cardHolderName: string, cardDescription: string, onFinished?: () => void) {
getSecureWalletInfo()
.then((walletData: AndroidWalletData) => {
createDigitalGoogleWallet({cardHolderName, ...walletData})
.then((cardData: AndroidCardData) => {
addCardToGoogleWallet(cardData)
.then((status: TokenizationStatus) => {
if (status === 'success') {
Log.info('Card added to wallet');
openWalletPage();
} else {
onFinished?.();
}
})
.catch((error) => {
Log.warn(`addCardToGoogleWallet error: ${error}`);
Alert.alert('Failed to add card to wallet.', 'Please try again later.');
});
})

.catch((error) => Log.warn(`createDigitalWallet error: ${error}`));
})
.catch((error) => Log.warn(`getSecureWalletInfo error: ${error}`));
function handleAddCardToWallet(card: Card, cardHolderName: string): Promise<TokenizationStatus> {
return getSecureWalletInfo().then((walletData: AndroidWalletData) =>
createDigitalGoogleWallet({cardHolderName, ...walletData}).then((cardData: AndroidCardData) => addCardToGoogleWallet(cardData)),
);
}

function isCardInWallet(card: Card): Promise<boolean> {
Expand Down
20 changes: 6 additions & 14 deletions src/libs/Wallet/index.ios.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {addCardToAppleWallet, checkWalletAvailability, getCardStatusByIdentifier, getCardStatusBySuffix} from '@expensify/react-native-wallet';
import type {IOSCardData} from '@expensify/react-native-wallet';
import {Alert} from 'react-native';
import type {IOSCardData, TokenizationStatus} from '@expensify/react-native-wallet';
import {issuerEncryptPayloadCallback} from '@libs/actions/Wallet';
import Log from '@libs/Log';
import CONST from '@src/CONST';
Expand All @@ -10,33 +9,26 @@ function checkIfWalletIsAvailable(): Promise<boolean> {
return checkWalletAvailability();
}

function handleAddCardToWallet(card: Card, cardHolderName: string, cardDescription: string, onFinished?: () => void) {
function handleAddCardToWallet(card: Card, cardHolderName: string, cardDescription: string): Promise<TokenizationStatus> {
const data = {
network: CONST.COMPANY_CARDS.CARD_TYPE.VISA,
lastDigits: card.lastFourPAN,
cardDescription,
cardHolderName,
} as IOSCardData;

addCardToAppleWallet(data, issuerEncryptPayloadCallback)
.then(() => {
Log.info('Card added to wallet');
onFinished?.();
})
.catch((e) => {
Log.warn(`handleAddCardToWallet error: ${e}`);
Alert.alert('Failed to add card to wallet', 'Please try again later.');
});
return addCardToAppleWallet(data, issuerEncryptPayloadCallback);
}

function isCardInWallet(card: Card): Promise<boolean> {
if (card.state !== CONST.EXPENSIFY_CARD.STATE.OPEN) {
const panReferenceID = card.nameValuePairs?.expensifyCard_panReferenceID;
if (!panReferenceID) {
return Promise.resolve(false);
}

let callback = null;
if (card.token) {
callback = getCardStatusByIdentifier(card.token, CONST.COMPANY_CARDS.CARD_TYPE.VISA);
callback = getCardStatusByIdentifier(panReferenceID, CONST.COMPANY_CARDS.CARD_TYPE.VISA);
} else if (card.lastFourPAN) {
callback = getCardStatusBySuffix(card.lastFourPAN);
}
Expand Down
5 changes: 3 additions & 2 deletions src/libs/Wallet/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type {TokenizationStatus} from '@expensify/react-native-wallet';
import type {Card} from '@src/types/onyx';

function checkIfWalletIsAvailable(): Promise<boolean> {
return Promise.resolve(false);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function handleAddCardToWallet(_card: Card, _cardHolderName: string, _cardDescription: string, _onFinished?: () => void) {
Promise.reject(new Error('Add to wallet is not supported on this platform'));
function handleAddCardToWallet(_card: Card, _cardHolderName: string, _cardDescription: string, _onFinished?: () => void): Promise<TokenizationStatus> {
return Promise.reject(new Error('Add to wallet is not supported on this platform'));
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
4 changes: 4 additions & 0 deletions src/types/onyx/Card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ type Card = OnyxCommon.OnyxValueWithOfflineFeedback<{
/** Card expiration date */
expirationDate?: string;

/** Card's primary account identifier */
// eslint-disable-next-line @typescript-eslint/naming-convention
expensifyCard_panReferenceID?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Skalakid is there still a need for the expensifyCard_panReferenceID field here? I noticed it’s not currently used anywhere outside of nameValuePairs. If there’s no plan to use it at the top level, should we consider removing it to keep the type clean?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need it. In iOS's isCardInWallet wallet function, we are checking either using this value or using the card suffix. The card suffix isn't unique, there can be a situation where 2 cards have the same last 4 numbers. So, checking the state using panReferenceID is better in most situations. However, it's not always present, especially when you add the card manually threw Apple Wallet, so that why we are using the suffix listing too

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Thanks for clarifying 🚀 🚀 🚀


/** List of token reference ids */
// eslint-disable-next-line @typescript-eslint/naming-convention
expensifyCard_tokenReferenceIdList?: string[];
Expand Down