Google Pay
MeaPushProvisioning.GooglePay
helper interface provides methods to interact with Google Pay wallet.
Google Pay Push Provisioning API documentation:
Push Card
When MPP SDK is initialized, Issuer app can push provision card using MeaPushProvisioning.GooglePay.pushCard(...)
and MppCardDataParameters
. This method checks the state of Google Pay wallet and creates a new instance when necessary.
Backend generated opaque payment card (OPC) is received, and if the specific card is not added to Google Pay wallet already, it pushes the card to the Google Pay wallet via Google Push Provisioning API.
MeaPushProvisioning.GooglePay.pushCard(cardParams, "My Card", userAddress, getActivity(), new MppPushCardToGooglePayListener() {
@Override
public void onSuccess(String tokenReferenceId, String cardLastFourDigits, MppPaymentNetwork cardNetwork) {
...
}
@Override
public void onFailure(MppError mppError) {
...
}
});
Handle Google Pay Result Callbacks
Google Pay push provisioning results are returned through Activity.onActivityResult(int, int, Intent)
method. Application should forward these intermediate results to the MeaPushProvisioning.GooglePay.handlePushCardOnActivityResult(int, int, Intent, Activity)
method.
Final result of push provisioning is returned returned to 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 {
// Optionaly 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" are available as resizable bitmaps (NinePatch files) suitable for including in your layout: Google Pay Brand guidelines - Assets
Show or Hide Add to Google Pay Button
App is responsible to check and decide if "Add to Google Pay" should be shown or hidden for the user. Button should be shown only when card is not added to Google Pay already. MPP SDK provides the following methods to check if the specific card is already added to Google Pay wallet:
MeaPushProvisioning.GooglePay.checkWalletForCardSuffix(String cardSuffix, GooglePayRegisteredTokensListener listener)
- using card suffix, does not require network connection.MeaPushProvisioning.GooglePay.checkWalletForToken(MppPaymentNetwork paymentNetwork, String tokenId, GooglePayTokenListener listener)
- using pre-fetched token data, does not require network connection.MeaPushProvisioning.GooglePay.checkWalletForCardToken(MppCardDataParameters cardData, GooglePayTokenListener listener)
- using card data, requires network connection.
If the card exists in Google Pay wallet, these methods return a single item or a list of GooglePayTokenInfo
items that contains information about the specific Google Pay token, use getTokenId()
, getTokenState()
, getPaymentNetwork()
and isSelectedAsDefault()
methods to get the values.
Issuer app should hide "Add to Google Pay" button when card exists in Google Pay wallet. If methods above return null
, Issuer app should show "Add to Google Pay" button.
Use GooglePayTokenInfo.getTokenState()
to get additional info about the token state.
Managing Default NFC Payment App
Issuer app can check if Google Pay is set as default NFC payment app after push provisioning a card. This allows users to pay with Google Pay using their new cards. Check if Google Pay is set as default NFC payment app:
boolean result = MeaPushProvisioning.GooglePay.isDefaultPaymentApplication(getContext());
Set Google Pay as default NFC payment app:
MeaPushProvisioning.GooglePay.setAsDefaultPaymentApplication(getActivity(), SET_DEFAULT_PAYMENTS_REQUEST_CODE);
Getting Registered Tokens from Google Pay Wallet
There might be some use cases when Issuer app needs to get all registered tokens from Google Pay wallet, for example, yellow path use case. Method MeaPushProvisioning.GooglePay.getRegisteredTokens(...)
returns 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.
}
});
Continuing Yellow Path Through Push Provisioning
Issuer app should allow users to continue yellow path through push provisioning.
Issuer app should get the token of the selected card and check the token state. If token state matches value TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, card provisioning has entered yellow path. Once matching GooglePayTokenInfo
is available, use MeaPushProvisioning.GooglePay.tokenize(GooglePayTokenInfo, String, Activity, GooglePayTokenizeListener)
for continuing provisioning.
In general GooglePayTokenInfo
of the card can be fetched using MeaPushProvisioning.GooglePay.checkWalletForCardToken(...)
, however for some issuers or processors backend only provides active tokens and does not provide pending tokens that have entered yellow path. See sections below for each of the cases.
There are two options to activate a token in yellow path:
- Pass the pending token's
tokenReferenceId
into thetokenize(...)
method to restart the ID&V flow in Google Wallet. - Remotely activate the token through a server-side activation call.
Pending Tokens Available via Backend
After finding card with MeaPushProvisioning.GooglePay.checkWalletForCardToken(MppCardDataParameters cardData, GooglePayTokenListener listener)
in Google Pay wallet, check the state of the token. If token state matches TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, card push provisioning has entered yellow path and requires additional user authentication.
Show "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() == TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION) {
// Card token requires additional user authentication for yellow path, show Add to Google Pay button.
// When tapping button, call one of the activation options:
// - MeaPushProvisioning.GooglePay.activate(tokenUniqueReference, paymentNetwork)
// - 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 Google Pay wallet. Iterate all the TokenInfo
entities and match the selected card based on the last four digits. Once a matching token is found, check the state of the token. If token state matches TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, card push provisioning has entered yellow path and requires additional user authentication.
Show "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) {
MppPaymentNetwork paymentNetwork = MppPaymentNetwork.getPaymentNetwork(tokenInfo.getNetwork());
GooglePayTokenInfo googlePayTokenInfo = new GooglePayTokenInfo(tokenInfo.getIssuerTokenId(), tokenState, paymentNetwork, tokenInfo.getIsDefaultToken());
// Card token requires additional user authentication for yellow path, show Add to Google Pay button.
// When tapping button, call one of the activation options:
// - MeaPushProvisioning.GooglePay.activate(tokenUniqueReference, paymentNetwork)
// - MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, ...)
}
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 token(s) 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) {
MppPaymentNetwork paymentNetwork = MppPaymentNetwork.getPaymentNetwork(tokenInfo.getNetwork());
GooglePayTokenInfo googlePayTokenInfo = new GooglePayTokenInfo(tokenInfo.getIssuerTokenId(), tokenState, paymentNetwork, tokenInfo.getIsDefaultToken());
// Card token requires additional user authentication for yellow path, show Add to Google Pay button.
// When tapping button, call one of the activation options:
// - MeaPushProvisioning.GooglePay.activate(tokenUniqueReference, paymentNetwork)
// - MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, ...)
} else {
// Hide Add to Google Pay button.
}
}
}
@Override
public void onFailure(@NonNull MppError mppError) {
// Handle error
}
});
Using Tokenize
You should have implemented Handling Google Pay Result Callbacks.
// When Add to Google Pay button tapped.
MeaPushProvisioning.GooglePay.tokenize(googlePayTokenInfo, "My card", getActivity(), new GooglePayTokenizeListener() {
@Override
public void onSuccess() {
...
}
@Override
public void onFailure(@NonNull MppError mppError) {
...
}
});
Using Server-side Activation
You should have implemented Handling Google Pay Result Callbacks.
// When Add to Google Pay button tapped.
MeaPushProvisioning.GooglePay.activate(tokenUniqueReference, paymentNetwork, new MppActivateListener() {
@Override
public void onSuccess() {
...
}
@Override
public void onFailure(@NonNull MppError mppError) {
...
}
});
App-to-App Verification
Issuers can offer app-to-app verification as an option for completing a yellow path ID&V challenge when provisioning a token. App-to-app verification is configured through TSP.
When user selects a card for activation with app-to-app verification, Google Wallet invokes the issuer app by calling the Android Activity specified by the issuer through TSP configuration. Once the user has verified their identity, the issuer app passes control back to Google Wallet to finish the provisioning flow.
If the app is not installed on the user's device, Google Wallet opens the Play Store page for issuer's app. After installing the issuer app, the user needs to restart the flow.
Issuers can implement App-to-App Verification using one of the two methods:
- Obtaining activation code and passing to Google Wallet
- Server-side activation
Google Developers documentation: Google Pay App-to-app verification
TSP Settings
App-to-app verification is configured through TSP: TSP Settings Issuers must provide the following parameters to TSP to enable app-to-app verification. Google Pay receives these parameters from the TSP during the tokenization process and passes them to issuer app.
Parameter | Example | Description |
---|---|---|
Package name | com.example.bank | The package name (applicationId) identifies the issuer mobile app that Google Pay should call during when invoking the Intent to start the app to app flow. If the app is not installed on the cardholder's mobile device, the user will be prompted to install it from the Google Play Store. |
Action | com.example.bank.action.APP_TO_APP | When calling your app, we create an explicit Intent. The action must be provided in it's fully qualified form, including the package name. Also, the action must be specific for use in token activation. Action name varies by TSP. |
Extra text | This parameter is used to pass extra data that will be included in the Intent. It is typically a JSON structure, Base64-encoded. The value of this string is opaque to Google and will be provided as-is in the standard field EXTRA_TEXT. |
When user selects app-to-app verification, Google Wallet invokes the issuer app for user's identity verification. Once the user has been verified, the issuer app passes control back to Google Wallet to complete the provisioning flow.
Implementation
Issuer's app must do the following to provide app-to-app verification functionality:
1. Receive Android Intent from Google Wallet
When a user selects to verify their identity using the issuer's app, Google Wallet calls issuer's app using the package name, action and EXTRA_TEXT
configured and provided through TSP. App manifest should be updated to be able to receive the Intent
.
<activity android:name="AppToAppActivity">
<!-- Activity that handles APP_TO_APP actions -->
<intent-filter>
<action android:name="com.example.bank.action.APP_TO_APP"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
App-to-app verification action name varies by TSP. Consult TSP technical documentation to determine what action name should be used.
2. Validate calling Activity
Upon receiving the Intent
, use Activity.getCallingPackage()
to validate that the calling Activity
is actually Google Wallet:
// Validate caller is Google Wallet (Google Play Services)
if ("com.google.android.gms".equals(getCallingPackage())) {
// Proceed with token activation
} else {
// Abort token activation
}
3. Authenticate the cardholder
Use the standard issuer's app authentication to verify the user.
4. Activation
Application should determine the token in state TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION
, use method MeaPushProvisioning.GooglePay.getRegisteredTokens(...)
or MeaPushProvisioning.GooglePay.getTokenInfo(Intent, listener)
for the received Intent
, which extracts token data from EXTRA_TEXT
.
4.1. Activation Code
This method uses an activation code that is generated by the issuer and is validated by TSP.
Use specific MppCardDataParameters
and MeaPushProvisioning.GooglePay.getActivationCode(MppCardDataParameters, Context, MppActivationCodeListener)
method to get activation code to complete the provisioning flow. Received activation code should be used in the next step.
4.2. Server-side Activation
This method allows to activate the token using TSP APIs.
Use method MeaPushProvisioning.GooglePay.activate(tokenUniqueReference, paymentNetwork)
to activate the token.
5. Return the user to Google Wallet
User should be returned to Google Wallet with activate(Activity, activationCode)
method. Use activationCode
for Activation Code method or method without activationCode
argument for server-side activation.
MeaPushProvisioning.GooglePay.activate(activity, activationCode);
Decline activation with ActivationResult
on failure:
MeaPushProvisioning.GooglePay.declineActivation(currentActivity, ActivationResult.DECLINE);
Handle Google Pay Data Changed Events
Registering for data changed events allows an issuer app to re-query information about their digitized cards whenever the user makes a change in Google Pay wallet. MPP SDK will immediately call an 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.
GooglePayDataChangedListener
Only foreground applications are notified of the data changed events. Therefore, each application should update the token statuses not only by receiving GooglePayDataChangedListener
,
but also when the application launches or returns to the foreground.
GooglePayDataChangedListener listener = new GooglePayDataChangedListener() {
@Override
public void onDataChanged() {
// Reload data in UI.
}
};
MeaPushProvisioning.GooglePay.registerDataChangedListener(listener);
Stop listening data changed events by removing GooglePayDataChangedListener
.
MeaPushProvisioning.GooglePay.removeDataChangedListener(listener);
Debugging
Use dependency with -debug
suffix to enable MeaPushProvisioning
debugging and logging. See Gradle Configuration.
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 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