Implementation
Sequence Diagram
Requirements
Before starting implementation, you should have completed the Installation of the MPP (Mea Push Provisioning) SDK.
Main Interface
Initialize
To begin, your issuer app should initialize the MeaPushProvisioning instance.
if (!MeaPushProvisioning.isInitialized()) {
MeaPushProvisioning.initialize(this);
}
Card Data Parameters
Start the push provisioning flow by initializing an MppCardDataParameters
object with CardId
, CardSecret
, or EncryptedPan
. After initializing card data parameters, you can start push provisioning with the push card method.
CardId & CardSecret
String cardId = "<value>";
String cardSecret = "<value>";
MppCardDataParameters cardParams = MppCardDataParameters.withCardSecret(cardId, cardSecret);
EncryptedCardData
String encryptedCardData = "<value>";
String publicKeyFingerprint = "<value>";
String encryptedKey = "<value>";
String initialVector = "<value>";
MppCardDataParameters cardParams = MppCardDataParameters.withEncryptedPan(encryptedCardData,
publicKeyFingerprint,
encryptedKey,
initialVector);
INFO
You can find the guide for
encryptedCardData
generation in the Card Data Encryption manual.
Loading Configuration
The MPP SDK loads the mea_config
configuration file by default, but you can use a custom name. When defining a custom name for the configuration file, use MeaPushProvisioning.Configuration.loadConfig(String)
to load the configuration. Place the configuration file in your application resources res/raw
folder.
MeaPushProvisioning.Configuration.loadConfig("custom_config_name");
INFO
The MPP SDK throws
MppException
if the configuration file is missing, corrupted, or fails to load.
GooglePay Interface
The MeaPushProvisioning.GooglePay helper interface provides methods to interact with Google Pay wallet.
Google Pay Push Provisioning API documentation:
- Google TapAndPay
- Google Pay Issuers Guide
- Android Push Provisioning
- Google Pay Push Provisioning API
❇️ Useful Information
(Only authorized Google accounts can view this content.
)
If you have multiple Google accounts and can't open a link with your specific one, try adding?authuser=1
OR&authuser=1
to the end of the link. You can change1
to any index of your account. Example:https://developers.google.com/pay/issuers/apis/push-provisioning/android/whitelisting?authuser=3
Push Card
Once the MPP SDK is initialized, your issuer app can push provision a card using MeaPushProvisioning.GooglePay.pushCard(...)
and MppCardDataParameters
. This method checks the Google Pay wallet state and creates a new instance when necessary. A backend-generated opaque payment card (OPC) is received, and if the specific card isn't already added to Google Pay wallet, it pushes the card to Google Pay wallet via Google Push Provisioning API.
MeaPushProvisioning.GooglePay.pushCard(cardParams, "card display name", userAddress, getActivity(), new MppPushCardToGooglePayListener() {
@Override
public void onSuccess(String tokenReferenceId, String cardLastFourDigits, MppPaymentNetwork cardNetwork) {
...
}
@Override
public void onFailure(MppError mppError, int tapAndPayStatusCode) {
...
}
});
Handle Google Pay Result Callbacks
Google Pay push provisioning results are returned through the Activity.onActivityResult(int, int, Intent)
method. Your application should forward these intermediate results to the MeaPushProvisioning.GooglePay.handlePushCardOnActivityResult(int, int, Intent, Activity)
method. The final push provisioning result is returned to the MppPushCardToGooglePayListener
callback.
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (MeaPushProvisioning.GooglePay.handleOnActivityResult(requestCode, resultCode, data, this)) {
// Handled by MPP SDK, no action needed.
} else {
// Optionally handle results for other request codes.
}
}
Add to Google Pay Button
The Add to Google Pay button is used exclusively to initiate the Google Pay card provisioning flow from an issuer app.
The "Add to Google Pay" buttons are available as resizable bitmaps (NinePatch files) suitable for including in your layout: Google Pay Brand guidelines - Assets
Note: Using
Flutter
,React Native
, or another cross-platform app development framework? Check out Flutter-specific instructions here.

Show or Hide Add to Google Pay Button
Your app determines whether to show or hide the "Add to Google Pay" button for users. Only show the button when the card hasn't been added to Google Pay yet.
The MPP SDK provides the following methods to check if a specific card is already added to Google Pay wallet:
MeaPushProvisioning.GooglePay.checkWalletForCardSuffix(String cardSuffix, GooglePayRegisteredTokensListener listener)
- using card suffix, doesn't require network connection.MeaPushProvisioning.GooglePay.checkWalletForToken(MppPaymentNetwork paymentNetwork, String tokenId, GooglePayTokenListener listener)
- using pre-fetched token data, doesn't require network connection.MeaPushProvisioning.GooglePay.checkWalletForCardToken(MppCardDataParameters cardData, GooglePayTokenListener listener)
- using card data, requires network connection.
Example:
MppCardDataParameters cardParams = MppCardDataParameters.withCardSecret(cardId, cardSecret);
MeaPushProvisioning.GooglePay.checkWalletForCardToken(
cardParams,
new GooglePayTokenListener() {
@Override
public void onSuccess(@NonNull GooglePayTokenInfo googlePayTokenInfo) {
...
String tokenId = googlePayTokenInfo.getTokenId();
Boolean isTokenStateNeedIdentityVerification = googlePayTokenInfo.getTokenState() == GooglePayTokenState.TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION;
}
@Override
public void onFailure(@NonNull MppError mppError) {
...
}
}
);
If the card exists in the Google Pay wallet, these methods return a single item or a list of GooglePayTokenInfo
items containing information about the specific Google Pay token. Use getTokenId()
, getTokenState()
, getPaymentNetwork()
, and isSelectedAsDefault()
methods to get the values.
Your issuer app should hide the "Add to Google Pay" button when the card exists in the Google Pay wallet. If the methods above return null
, your issuer app should show the "Add to Google Pay" button.
Use GooglePayTokenInfo.getTokenState()
to get additional information about the token state.
Managing Default NFC Payment App
Getting Registered Tokens from Google Pay Wallet
There might be use cases when your issuer app needs to get all registered tokens from the Google Pay wallet, for example during yellow path cases. The method MeaPushProvisioning.GooglePay.getRegisteredTokens(...)
returns a list of TokenInfo
items related to the active wallet.
MeaPushProvisioning.GooglePay.getRegisteredTokens(new GooglePayRegisteredTokensListener() {
@Override
public void onSuccess(List<TokenInfo> tokenList) {
// Iterate list.
}
@Override
public void onFailure(MppError error) {
// Handle error.
}
});
Example of how to find a specific card by last 4 digits:
String cardLastFourDigits = "1234";
MeaPushProvisioning.GooglePay.getRegisteredTokens(new GooglePayRegisteredTokensListener() {
@Override
public void onSuccess(List<TokenInfo> tokenList) {
for (TokenInfo tokenInfo : tokenList) {
// Find matching card based on the last 4 digits.
if (cardLastFourDigits.equals(tokenInfo.getFpanLastFour())) {
GooglePayTokenState tokenState = GooglePayTokenState.getTokenState(tokenInfo.getTokenState());
MppPaymentNetwork paymentNetwork = MppPaymentNetwork.getPaymentNetwork(tokenInfo.getNetwork());
GooglePayTokenInfo googlePayTokenInfo = new GooglePayTokenInfo(tokenInfo.getIssuerTokenId(), tokenState, paymentNetwork, tokenInfo.getIsDefaultToken());
String tokenId = googlePayTokenInfo.getTokenId();
Boolean isTokenStateNeedIdentityVerification = googlePayTokenInfo.getTokenState() == GooglePayTokenState.TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION;
break;
}
}
}
@Override
public void onFailure(MppError error) {
...
}
});
Handling The Yellow Path During Push Provisioning
Your issuer app should allow users to continue yellow path through push provisioning.
Your issuer app should get the token of the selected card and check the token state. If the token state matches the value TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, card provisioning has entered yellow path. Once a matching GooglePayTokenInfo
is available, use MeaPushProvisioning.GooglePay.tokenize(GooglePayTokenInfo, String, Activity, GooglePayTokenizeListener)
to continue provisioning.
Generally, you can fetch the GooglePayTokenInfo
of the card using MeaPushProvisioning.GooglePay.checkWalletForCardToken(...)
. However, for some issuers or processors, their backend only provides active tokens and doesn't provide pending tokens that have entered yellow path. See the sections below for each case.
Pending Tokens Available via Backend
After finding a card with MeaPushProvisioning.GooglePay.checkWalletForCardToken(MppCardDataParameters cardData, GooglePayTokenListener listener)
in the Google Pay wallet, check the token state. If the token state is TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, card push provisioning has entered the yellow path and requires additional user authentication.
Show the "Add to Google Pay" button and call MeaPushProvisioning.GooglePay.tokenize(GooglePayTokenInfo, String, Activity, GooglePayTokenizeListener)
to continue push provisioning when the button is tapped.
MeaPushProvisioning.GooglePay.checkWalletForCardToken(cardDataParameters, new GooglePayTokenListener() {
@Override
public void onSuccess(@NonNull GooglePayTokenInfo googlePayTokenInfo) {
if (googlePayTokenInfo.getTokenState() == GooglePayTokenState.TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION) {
// Card token requires additional user authentication for yellow path, show Add to Google Pay button.
// When tapping button, call MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, ...).
}
else {
// Token already exists in Google Pay wallet and no action required from Issuer app, hide Add to Google Pay button.
}
}
@Override
public void onFailure(@NonNull MppError mppError) {
// Card token not found in Google Pay wallet, show Add to Google Pay button.
// When tapping button, call MeaPushProvisioning.GooglePay.pushCard(...).
}
});
Pending Tokens Not Available via Backend
Use MeaPushProvisioning.GooglePay.getRegisteredTokens(...)
to get all tokens provisioned in the Google Pay wallet. Iterate through all the TokenInfo
entities and match the selected card based on the last four digits. Once you find a matching token, check the token state. If the token state is TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, card push provisioning has entered yellow path and requires additional user authentication.
Show the "Add to Google Pay" button and call MeaPushProvisioning.GooglePay.tokenize(GooglePayTokenInfo, String, Activity, GooglePayTokenizeListener)
to continue push provisioning when the button is tapped.
MeaPushProvisioning.GooglePay.getRegisteredTokens(new GooglePayRegisteredTokensListener() {
@Override
public void onSuccess(@NonNull List<TokenInfo> tokenList) {
for (TokenInfo tokenInfo : tokenList) {
// Find matching card based on the last four digits.
if (CARD_LAST_FOUR_DIGITS.equals(tokenInfo.getFpanLastFour())) {
GooglePayTokenState tokenState = GooglePayTokenState.getTokenState(tokenInfo.getTokenState());
if (tokenState == GooglePayTokenState.TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION) {
// Card token requires additional user authentication for yellow path, show Add to Google Pay button.
// When tapping button, call MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, ...).
MppPaymentNetwork paymentNetwork = MppPaymentNetwork.getPaymentNetwork(tokenInfo.getNetwork());
GooglePayTokenInfo googlePayTokenInfo = new GooglePayTokenInfo(tokenInfo.getIssuerTokenId(), tokenState, paymentNetwork, tokenInfo.getIsDefaultToken());
}
else {
// Hide Add to Google Pay button.
}
break;
}
}
}
@Override
public void onFailure(@NonNull MppError error) {
// Handle error.
}
});
Alternatively, use MeaPushProvisioning.GooglePay.checkWalletForCardSuffix(cardSuffix, listener)
to get tokens with matching PAN suffix.
MeaPushProvisioning.GooglePay.checkWalletForCardSuffix(CARD_LAST_FOUR_DIGITS, new GooglePayRegisteredTokensListener() {
@Override
public void onSuccess(@NonNull List<TokenInfo> tokenInfoList) {
for (TokenInfo tokenInfo : tokenInfoList) {
GooglePayTokenState tokenState = GooglePayTokenState.getTokenState(tokenInfo.getTokenState());
if (tokenState == GooglePayTokenState.TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION) {
// Card token requires additional user authentication for yellow path, show Add to Google Pay button.
// When tapping button, call MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, ...).
MppPaymentNetwork paymentNetwork = MppPaymentNetwork.getPaymentNetwork(tokenInfo.getNetwork());
GooglePayTokenInfo googlePayTokenInfo = new GooglePayTokenInfo(tokenInfo.getIssuerTokenId(), tokenState, paymentNetwork, tokenInfo.getIsDefaultToken());
} else {
// Hide Add to Google Pay button.
}
}
}
@Override
public void onFailure(@NonNull MppError mppError) {
// Handle error
}
});
Using Tokenize
INFO
You should have implemented Handling Google Pay Result Callbacks.
// When Add to Google Pay button tapped AND card token requires additional user authentication for the yellow path.
MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, "card name", getActivity(), new GooglePayTokenizeListener() {
@Override
public void onSuccess() {
...
}
@Override
public void onFailure(@NonNull MppError mppError) {
...
}
});
App-to-App Verification with Activation Code
Handle Google Pay Data Changed Events
Registering for data changed events allows your issuer app to re-query information about digitized cards whenever the user makes a change in Google Pay wallet.
The MPP SDK will immediately call your issuer app callback whenever the following events occur:
- The active wallet changes (by changing the active account)
- The selected card of the active wallet changes
- Tokenized cards are added or removed from the active wallet
- The status of a token in the active wallet changes
INFO
GooglePayDataChangedListener
Only foreground applications are notified of data changed events. Therefore, each application should update token statuses not only by receivingGooglePayDataChangedListener
, but also when the application launches or returns to the foreground.
Register listener:
GooglePayDataChangedListener listener = new GooglePayDataChangedListener() {
@Override
public void onDataChanged() {
// Reload data in UI.
}
};
MeaPushProvisioning.GooglePay.registerDataChangedListener(listener);
Stop listening for data changed events by removing GooglePayDataChangedListener
:
MeaPushProvisioning.GooglePay.removeDataChangedListener(listener);
Testing in Sandbox Mode
By default, Google Pay works in production mode with real payments. During development and pre-production testing, you can reconfigure Google Pay to work in sandbox mode by placing a special file on your device. Once connected to sandbox, requests will be routed to Google's sandbox environment which connects to the TSP's sandbox environment.
Working in sandbox mode: Google Pay sandbox mode
Use the adb command to toggle sandbox mode. To turn sandbox mode on, add an empty file and reboot:
$ adb shell touch /sdcard/Download/android_pay_env_override_sandbox
$ adb reboot
To switch back to production mode, delete the file and reboot the device:
$ adb shell rm /sdcard/Download/android_pay_env_override_sandbox
$ adb reboot
References
Updated about 1 month ago