diff --git a/CHANGELOG.md b/CHANGELOG.md
index a8228d1be8..f4850e947f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,7 @@
     * Remove overload constructors, `setListener, and `onActivityResult` from `GooglePayClient`
     * Change `GooglePayClient#requestPayment` parameters and rename to 
       `GooglePayClient#createPaymentAuthRequest`
+    * Change `GooglePayIsReadyToPayCallback` parameters
     * Add `GooglePayClient#tokenize` 
     * Remove `merchantId` from `GooglePayRequest`
     * Change `GooglePayGetTokenizationParametersCallback` parameters
diff --git a/Demo/src/main/java/com/braintreepayments/demo/GooglePayFragment.java b/Demo/src/main/java/com/braintreepayments/demo/GooglePayFragment.java
index dff2f82c41..cf273a6922 100644
--- a/Demo/src/main/java/com/braintreepayments/demo/GooglePayFragment.java
+++ b/Demo/src/main/java/com/braintreepayments/demo/GooglePayFragment.java
@@ -14,8 +14,12 @@
 
 import com.braintreepayments.api.GooglePayClient;
 import com.braintreepayments.api.GooglePayLauncher;
+import com.braintreepayments.api.GooglePayPaymentAuthRequest;
+import com.braintreepayments.api.GooglePayReadinessResult;
 import com.braintreepayments.api.GooglePayRequest;
+import com.braintreepayments.api.GooglePayResult;
 import com.braintreepayments.api.PaymentMethodNonce;
+import com.braintreepayments.api.UserCanceledException;
 import com.google.android.gms.wallet.ShippingAddressRequirements;
 import com.google.android.gms.wallet.TransactionInfo;
 import com.google.android.gms.wallet.WalletConstants;
@@ -38,11 +42,13 @@ public View onCreateView(@NonNull LayoutInflater inflater,
         googlePayClient = new GooglePayClient(requireContext(), super.getAuthStringArg());
         googlePayLauncher = new GooglePayLauncher(this,
                 paymentAuthResult -> googlePayClient.tokenize(paymentAuthResult,
-                        (paymentMethodNonce, error) -> {
-                            if (error != null) {
-                                handleError(error);
-                            } else {
-                                handleGooglePayActivityResult(paymentMethodNonce);
+                        (googlePayResult) -> {
+                            if (googlePayResult instanceof GooglePayResult.Failure) {
+                                handleError(((GooglePayResult.Failure) googlePayResult).getError());
+                            } else if (googlePayResult instanceof GooglePayResult.Success){
+                                handleGooglePayActivityResult(((GooglePayResult.Success) googlePayResult).getNonce());
+                            } else if (googlePayResult instanceof GooglePayResult.Cancel) {
+                                handleError(new UserCanceledException("User canceled Google Pay"));
                             }
                         }));
 
@@ -53,8 +59,8 @@ public View onCreateView(@NonNull LayoutInflater inflater,
     public void onResume() {
         super.onResume();
 
-        googlePayClient.isReadyToPay(requireActivity(), (isReadyToPay, e) -> {
-            if (isReadyToPay) {
+        googlePayClient.isReadyToPay(requireActivity(), (googlePayReadinessResult) -> {
+            if (googlePayReadinessResult instanceof GooglePayReadinessResult.ReadyToPay) {
                 googlePayButton.setVisibility(View.VISIBLE);
             } else {
                 showDialog(
@@ -99,8 +105,14 @@ public void launchGooglePay(View v) {
                 .addAllowedCountryCodes(Settings.getGooglePayAllowedCountriesForShipping(activity))
                 .build());
 
-        googlePayClient.createPaymentAuthRequest(googlePayRequest,
-                (paymentAuthRequest, error) -> googlePayLauncher.launch(paymentAuthRequest));
+        googlePayClient.createPaymentAuthRequest(googlePayRequest, (paymentAuthRequest) -> {
+            if (paymentAuthRequest instanceof GooglePayPaymentAuthRequest.ReadyToLaunch) {
+                googlePayLauncher.launch(
+                        ((GooglePayPaymentAuthRequest.ReadyToLaunch) paymentAuthRequest).getRequestParams());
+            } else if (paymentAuthRequest instanceof GooglePayPaymentAuthRequest.Failure) {
+                handleError(((GooglePayPaymentAuthRequest.Failure) paymentAuthRequest).getError());
+            }
+        });
     }
 
     private void handleGooglePayActivityResult(PaymentMethodNonce paymentMethodNonce) {
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayActivityResultContract.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayActivityResultContract.java
index bb7c8d6e3a..a4a45e7cb0 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayActivityResultContract.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayActivityResultContract.java
@@ -16,11 +16,11 @@
 import com.google.android.gms.wallet.AutoResolveHelper;
 import com.google.android.gms.wallet.PaymentData;
 
-class GooglePayActivityResultContract extends ActivityResultContract<GooglePayPaymentAuthRequest, GooglePayPaymentAuthResult> {
+class GooglePayActivityResultContract extends ActivityResultContract<GooglePayPaymentAuthRequestParams, GooglePayPaymentAuthResult> {
 
     @NonNull
     @Override
-    public Intent createIntent(@NonNull Context context, GooglePayPaymentAuthRequest input) {
+    public Intent createIntent(@NonNull Context context, GooglePayPaymentAuthRequestParams input) {
         return new Intent(context, GooglePayActivity.class)
                 .putExtra(EXTRA_ENVIRONMENT, input.getGooglePayEnvironment())
                 .putExtra(EXTRA_PAYMENT_DATA_REQUEST, input.getPaymentDataRequest());
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayClient.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayClient.java
index b5c488ac09..5d536ea8b9 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayClient.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayClient.java
@@ -97,25 +97,24 @@ public void isReadyToPay(@NonNull final FragmentActivity activity,
         try {
             Class.forName(PaymentsClient.class.getName());
         } catch (ClassNotFoundException | NoClassDefFoundError e) {
-            callback.onResult(false, null);
+            callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(null));
             return;
         }
 
         braintreeClient.getConfiguration((configuration, e) -> {
             if (configuration == null) {
-                callback.onResult(false, e);
+                callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(e));
                 return;
             }
 
             if (!configuration.isGooglePayEnabled()) {
-                callback.onResult(false, null);
+                callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(null));
                 return;
             }
 
             //noinspection ConstantConditions
             if (activity == null) {
-                callback.onResult(false,
-                        new IllegalArgumentException("Activity cannot be null."));
+                callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(new IllegalArgumentException("Activity cannot be null.")));
                 return;
             }
 
@@ -169,9 +168,9 @@ public void getTokenizationParameters(
     }
 
     /**
-     * Start the Google Pay payment flow. This will return a {@link GooglePayPaymentAuthRequest} that will
-     * be used to present Google Pay payment sheet in
-     * {@link GooglePayLauncher#launch(GooglePayPaymentAuthRequest)}
+     * Start the Google Pay payment flow. This will return {@link GooglePayPaymentAuthRequestParams} that are
+     * used to present Google Pay payment sheet in
+     * {@link GooglePayLauncher#launch(GooglePayPaymentAuthRequestParams)}
      *
      * @param request  The {@link GooglePayRequest} containing options for the transaction.
      * @param callback {@link GooglePayPaymentAuthRequestCallback}
@@ -181,39 +180,37 @@ public void createPaymentAuthRequest(@NonNull final GooglePayRequest request,
         braintreeClient.sendAnalyticsEvent("google-payment.selected");
 
         if (!validateManifest()) {
-            callback.onResult(null, new BraintreeException(
-                    "GooglePayActivity was " + "not found in the " + "Android " +
-                            "manifest, or did not have a theme of R.style.bt_transparent_activity"));
+            callback.onGooglePayPaymentAuthRequest(new GooglePayPaymentAuthRequest.Failure(new BraintreeException(
+                    "GooglePayActivity was not found in the Android " +
+                            "manifest, or did not have a theme of R.style.bt_transparent_activity")));
             braintreeClient.sendAnalyticsEvent("google-payment.failed");
             return;
         }
 
         //noinspection ConstantConditions
         if (request == null) {
-            callback.onResult(null, new BraintreeException(
-                    "Cannot pass null " + "GooglePayRequest to " + "requestPayment"));
+            callback.onGooglePayPaymentAuthRequest(new GooglePayPaymentAuthRequest.Failure(new BraintreeException(
+                    "Cannot pass null GooglePayRequest to requestPayment")));
             braintreeClient.sendAnalyticsEvent("google-payment.failed");
             return;
         }
 
         if (request.getTransactionInfo() == null) {
-            callback.onResult(null, new BraintreeException(
-                    "Cannot pass null " + "TransactionInfo to" + " requestPayment"));
+            callback.onGooglePayPaymentAuthRequest(new GooglePayPaymentAuthRequest.Failure(new BraintreeException(
+                    "Cannot pass null TransactionInfo to requestPayment")));
             braintreeClient.sendAnalyticsEvent("google-payment.failed");
             return;
         }
 
         braintreeClient.getConfiguration((configuration, configError) -> {
-            if (configuration == null) {
-                callback.onResult(null, configError);
+            if (configuration == null && configError != null) {
+                callback.onGooglePayPaymentAuthRequest(new GooglePayPaymentAuthRequest.Failure(configError));
                 return;
             }
 
             if (!configuration.isGooglePayEnabled()) {
-                callback.onResult(null, new BraintreeException(
-                        "Google Pay " +
-                                "is not enabled for your Braintree account," +
-                                " or Google Play Services are not configured correctly."));
+                callback.onGooglePayPaymentAuthRequest(new GooglePayPaymentAuthRequest.Failure(new BraintreeException(
+                        "Google Pay is not enabled for your Braintree account, or Google Play Services are not configured correctly.")));
                 return;
             }
 
@@ -223,10 +220,10 @@ public void createPaymentAuthRequest(@NonNull final GooglePayRequest request,
             PaymentDataRequest paymentDataRequest =
                     PaymentDataRequest.fromJson(request.toJson());
 
-            GooglePayPaymentAuthRequest intent =
-                    new GooglePayPaymentAuthRequest(getGooglePayEnvironment(configuration),
+            GooglePayPaymentAuthRequestParams params =
+                    new GooglePayPaymentAuthRequestParams(getGooglePayEnvironment(configuration),
                             paymentDataRequest);
-            callback.onResult(intent, null);
+            callback.onGooglePayPaymentAuthRequest(new GooglePayPaymentAuthRequest.ReadyToLaunch(params));
 
         });
 
@@ -235,7 +232,7 @@ public void createPaymentAuthRequest(@NonNull final GooglePayRequest request,
     void tokenize(PaymentData paymentData, GooglePayTokenizeCallback callback) {
         try {
             JSONObject result = new JSONObject(paymentData.toJson());
-            callback.onResult(GooglePayCardNonce.fromJSON(result), null);
+            callback.onGooglePayResult(new GooglePayResult.Success(GooglePayCardNonce.fromJSON(result)));
             braintreeClient.sendAnalyticsEvent("google-payment.nonce-received");
         } catch (JSONException | NullPointerException e) {
             braintreeClient.sendAnalyticsEvent("google-payment.failed");
@@ -244,9 +241,9 @@ void tokenize(PaymentData paymentData, GooglePayTokenizeCallback callback) {
                 String token =
                         new JSONObject(paymentData.toJson()).getJSONObject("paymentMethodData")
                                 .getJSONObject("tokenizationData").getString("token");
-                callback.onResult(null, ErrorWithResponse.fromJson(token));
+                callback.onGooglePayResult(new GooglePayResult.Failure(ErrorWithResponse.fromJson(token)));
             } catch (JSONException | NullPointerException e1) {
-                callback.onResult(null, e1);
+                callback.onGooglePayResult(new GooglePayResult.Failure(e1));
             }
         }
     }
@@ -258,7 +255,7 @@ void tokenize(PaymentData paymentData, GooglePayTokenizeCallback callback) {
      * method should be invoked to tokenize the payment method to retrieve a
      * {@link PaymentMethodNonce}
      *
-     * @param paymentAuthResult the result of {@link GooglePayLauncher#launch(GooglePayPaymentAuthRequest)}
+     * @param paymentAuthResult the result of {@link GooglePayLauncher#launch(GooglePayPaymentAuthRequestParams)}
      * @param callback        {@link GooglePayTokenizeCallback}
      */
     public void tokenize(GooglePayPaymentAuthResult paymentAuthResult,
@@ -269,10 +266,11 @@ public void tokenize(GooglePayPaymentAuthResult paymentAuthResult,
         } else if (paymentAuthResult.getError() != null) {
             if (paymentAuthResult.getError() instanceof UserCanceledException) {
                 braintreeClient.sendAnalyticsEvent("google-payment.canceled");
-            } else {
-                braintreeClient.sendAnalyticsEvent("google-payment.failed");
+                callback.onGooglePayResult(GooglePayResult.Cancel.INSTANCE);
+                return;
             }
-            callback.onResult(null, paymentAuthResult.getError());
+            braintreeClient.sendAnalyticsEvent("google-payment.failed");
+            callback.onGooglePayResult(new GooglePayResult.Failure(paymentAuthResult.getError()));
         }
     }
 
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayInternalClient.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayInternalClient.java
index 8ee7ab7729..19a8f0cbdf 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayInternalClient.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayInternalClient.java
@@ -1,11 +1,8 @@
 package com.braintreepayments.api;
 
-import androidx.annotation.NonNull;
 import androidx.fragment.app.FragmentActivity;
 
 import com.google.android.gms.common.api.ApiException;
-import com.google.android.gms.tasks.OnCompleteListener;
-import com.google.android.gms.tasks.Task;
 import com.google.android.gms.wallet.IsReadyToPayRequest;
 import com.google.android.gms.wallet.PaymentsClient;
 import com.google.android.gms.wallet.Wallet;
@@ -18,14 +15,16 @@ void isReadyToPay(FragmentActivity activity, Configuration configuration, IsRead
                 new Wallet.WalletOptions.Builder()
                         .setEnvironment(getGooglePayEnvironment(configuration))
                         .build());
-        paymentsClient.isReadyToPay(isReadyToPayRequest).addOnCompleteListener(new OnCompleteListener<Boolean>() {
-            @Override
-            public void onComplete(@NonNull Task<Boolean> task) {
-                try {
-                    callback.onResult(task.getResult(ApiException.class), null);
-                } catch (ApiException e) {
-                    callback.onResult(false, e);
+        paymentsClient.isReadyToPay(isReadyToPayRequest).addOnCompleteListener(task -> {
+            try {
+                Boolean isReady = task.getResult(ApiException.class);
+                if (isReady) {
+                    callback.onGooglePayReadinessResult(GooglePayReadinessResult.ReadyToPay.INSTANCE);
+                } else {
+                    callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(null));
                 }
+            } catch (ApiException e) {
+                callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(e));
             }
         });
     }
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayIsReadyToPayCallback.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayIsReadyToPayCallback.java
index f5870c4bfe..e9111d671b 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayIsReadyToPayCallback.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayIsReadyToPayCallback.java
@@ -1,6 +1,5 @@
 package com.braintreepayments.api;
 
-import androidx.annotation.Nullable;
 import androidx.fragment.app.FragmentActivity;
 
 /**
@@ -11,8 +10,7 @@
 public interface GooglePayIsReadyToPayCallback {
 
     /**
-     * @param isReadyToPay true if Google Pay is ready; false otherwise.
-     * @param error an exception that occurred while checking if Google Pay is ready
+     * @param googlePayReadinessResult
      */
-    void onResult(boolean isReadyToPay, @Nullable Exception error);
+    void onGooglePayReadinessResult(GooglePayReadinessResult googlePayReadinessResult);
 }
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayLauncher.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayLauncher.java
index a23c46b13c..c31da0d01b 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayLauncher.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayLauncher.java
@@ -14,7 +14,7 @@
 public class GooglePayLauncher {
 
     @VisibleForTesting
-    ActivityResultLauncher<GooglePayPaymentAuthRequest> activityLauncher;
+    ActivityResultLauncher<GooglePayPaymentAuthRequestParams> activityLauncher;
 
     private static final String GOOGLE_PAY_RESULT = "com.braintreepayments.api.GooglePay.RESULT";
 
@@ -36,7 +36,7 @@ public GooglePayLauncher(@NonNull FragmentActivity activity,
                 new GooglePayActivityResultContract(), callback::onResult);
     }
 
-    public void launch(GooglePayPaymentAuthRequest googlePayPaymentAuthRequest) {
-        activityLauncher.launch(googlePayPaymentAuthRequest);
+    public void launch(GooglePayPaymentAuthRequestParams googlePayPaymentAuthRequestParams) {
+        activityLauncher.launch(googlePayPaymentAuthRequestParams);
     }
 }
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequest.kt b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequest.kt
new file mode 100644
index 0000000000..33378c80f0
--- /dev/null
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequest.kt
@@ -0,0 +1,17 @@
+package com.braintreepayments.api
+
+/**
+ * A request used to launch the Venmo app for continuation of the Google Pay flow.
+ */
+sealed class GooglePayPaymentAuthRequest {
+
+    /**
+     * The request was successfully created and is ready to be launched by [GooglePayLauncher]
+     */
+    class ReadyToLaunch(val requestParams: GooglePayPaymentAuthRequestParams) : GooglePayPaymentAuthRequest()
+
+    /**
+     * There was an [error] creating the request
+     */
+    class Failure(val error: Exception) : GooglePayPaymentAuthRequest()
+}
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestCallback.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestCallback.java
index e454e4164d..4f278ba610 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestCallback.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestCallback.java
@@ -1,13 +1,10 @@
 package com.braintreepayments.api;
 
-import androidx.annotation.Nullable;
-
 /**
  * Callback to handle result from
  * {@link GooglePayClient#createPaymentAuthRequest(GooglePayRequest, GooglePayPaymentAuthRequestCallback)}
  */
 public interface GooglePayPaymentAuthRequestCallback {
 
-    void onResult(@Nullable GooglePayPaymentAuthRequest paymentAuthRequest,
-                  @Nullable Exception error);
+    void onGooglePayPaymentAuthRequest(GooglePayPaymentAuthRequest paymentAuthRequest);
 }
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequest.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestParams.java
similarity index 71%
rename from GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequest.java
rename to GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestParams.java
index 5151789f77..06126cda7a 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequest.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayPaymentAuthRequestParams.java
@@ -6,14 +6,14 @@
 
 /**
  * Used to request Google Pay payment authorization via
- * {@link GooglePayLauncher#launch(GooglePayPaymentAuthRequest)}
+ * {@link GooglePayLauncher#launch(GooglePayPaymentAuthRequestParams)}
  */
-public class GooglePayPaymentAuthRequest {
+public class GooglePayPaymentAuthRequestParams {
 
     private final int googlePayEnvironment;
     private final PaymentDataRequest paymentDataRequest;
 
-    GooglePayPaymentAuthRequest(int googlePayEnvironment, @NonNull PaymentDataRequest paymentDataRequest) {
+    GooglePayPaymentAuthRequestParams(int googlePayEnvironment, @NonNull PaymentDataRequest paymentDataRequest) {
         this.googlePayEnvironment = googlePayEnvironment;
         this.paymentDataRequest = paymentDataRequest;
     }
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayReadinessResult.kt b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayReadinessResult.kt
new file mode 100644
index 0000000000..8ea5fadfbe
--- /dev/null
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayReadinessResult.kt
@@ -0,0 +1,19 @@
+package com.braintreepayments.api
+
+/**
+ * Result of [GooglePayClient.isReadyToPay]
+ */
+sealed class GooglePayReadinessResult {
+
+    /**
+     * The Google Pay API is supported and set up on this device. Show the Google Pay button for
+     * Google Pay.
+     */
+    object ReadyToPay : GooglePayReadinessResult()
+
+    /**
+     * The Google Pay API is supported or not set up on this device, or there was an issue [error]
+     * determining readiness.
+     */
+    class NotReadyToPay(val error: Exception?) : GooglePayReadinessResult()
+}
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayResult.kt b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayResult.kt
new file mode 100644
index 0000000000..5139e55174
--- /dev/null
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayResult.kt
@@ -0,0 +1,22 @@
+package com.braintreepayments.api
+
+/**
+ * Result of tokenizing a Google Pay payment method
+ */
+sealed class GooglePayResult {
+
+    /**
+     * The Google Pay flow completed successfully. This [nonce] should be sent to your server.
+     */
+    class Success(val nonce: PaymentMethodNonce) : GooglePayResult()
+
+    /**
+     * There was an [error] in the Google Pay flow.
+     */
+    class Failure(val error: Exception) : GooglePayResult()
+
+    /**
+     * The user canceled the Google Pay flow.
+     */
+    object Cancel : GooglePayResult()
+}
diff --git a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayTokenizeCallback.java b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayTokenizeCallback.java
index 581dc46d16..8999129d16 100644
--- a/GooglePay/src/main/java/com/braintreepayments/api/GooglePayTokenizeCallback.java
+++ b/GooglePay/src/main/java/com/braintreepayments/api/GooglePayTokenizeCallback.java
@@ -10,9 +10,7 @@
 public interface GooglePayTokenizeCallback {
 
     /**
-     * @param paymentMethodNonce {@link PaymentMethodNonce}
-     * @param error              an exception that occurred while processing Google Pay activity
-     *                           result
+     * @param googlePayResult {@link PaymentMethodNonce}
      */
-    void onResult(@Nullable PaymentMethodNonce paymentMethodNonce, @Nullable Exception error);
+    void onGooglePayResult(@Nullable GooglePayResult googlePayResult);
 }
diff --git a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayActivityResultContractUnitTest.java b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayActivityResultContractUnitTest.java
index 3dcc56de9b..bfd506c17b 100644
--- a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayActivityResultContractUnitTest.java
+++ b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayActivityResultContractUnitTest.java
@@ -39,8 +39,8 @@ public void createIntent_returnsIntentWithExtras() {
 
         PaymentDataRequest paymentDataRequest = PaymentDataRequest.fromJson(googlePayRequest.toJson());
 
-        GooglePayPaymentAuthRequest
-                intentData = new GooglePayPaymentAuthRequest(1, paymentDataRequest);
+        GooglePayPaymentAuthRequestParams
+                intentData = new GooglePayPaymentAuthRequestParams(1, paymentDataRequest);
 
         Context context = ApplicationProvider.getApplicationContext();
 
diff --git a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java
index 4e9ad809c9..321f8dab3a 100644
--- a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java
+++ b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java
@@ -7,7 +7,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
@@ -153,7 +152,7 @@ public void isReadyToPay_returnsFalseWhenGooglePayIsNotEnabled() {
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
 
         sut.isReadyToPay(activity, null, readyToPayCallback);
-        verify(readyToPayCallback).onResult(false, null);
+        verify(readyToPayCallback).onGooglePayReadinessResult(any(GooglePayReadinessResult.NotReadyToPay.class));
     }
 
     @Test
@@ -175,10 +174,12 @@ public void isReadyToPay_whenActivityIsNull_forwardsErrorToCallback() {
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
         sut.isReadyToPay(null, null, readyToPayCallback);
 
-        ArgumentCaptor<Exception> captor = ArgumentCaptor.forClass(Exception.class);
-        verify(readyToPayCallback).onResult(eq(false), captor.capture());
+        ArgumentCaptor<GooglePayReadinessResult> captor = ArgumentCaptor.forClass(GooglePayReadinessResult.class);
+        verify(readyToPayCallback).onGooglePayReadinessResult(captor.capture());
 
-        Exception exception = captor.getValue();
+        GooglePayReadinessResult result = captor.getValue();
+        assertTrue(result instanceof GooglePayReadinessResult.NotReadyToPay);
+        Throwable exception = ((GooglePayReadinessResult.NotReadyToPay) result).getError();
         assertTrue(exception instanceof IllegalArgumentException);
         assertEquals("Activity cannot be null.", exception.getMessage());
     }
@@ -228,9 +229,11 @@ public void createPaymentAuthRequest_callsBackIntentData() throws JSONException
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
 
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         assertEquals(WalletConstants.ENVIRONMENT_TEST, intent.getGooglePayEnvironment());
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
@@ -350,8 +353,11 @@ public void createPaymentAuthRequest_includesATokenizationKeyWhenPresent() throw
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -398,8 +404,11 @@ public void createPaymentAuthRequest_doesNotIncludeATokenizationKeyWhenNotPresen
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -495,14 +504,18 @@ public void createPaymentAuthRequest_whenMerchantNotConfigured_returnsExceptionT
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
         sut.createPaymentAuthRequest(baseRequest, intentDataCallback);
 
-        ArgumentCaptor<Exception> captor = ArgumentCaptor.forClass(
-                Exception.class);
-        verify(intentDataCallback).onResult(isNull(), captor.capture());
+        ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
+                GooglePayPaymentAuthRequest.class);
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
 
-        assertTrue(captor.getValue() instanceof BraintreeException);
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.Failure);
+        Exception exception = ((GooglePayPaymentAuthRequest.Failure) request).getError();
+
+        assertTrue(exception instanceof BraintreeException);
         assertEquals(
                 "Google Pay is not enabled for your Braintree account, or Google Play Services are not configured correctly.",
-                captor.getValue().getMessage());
+                exception.getMessage());
     }
 
     @Test
@@ -531,8 +544,11 @@ public void createPaymentAuthRequest_whenSandbox_setsTestEnvironment() throws JS
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -567,8 +583,11 @@ public void createPaymentAuthRequest_whenProduction_setsProductionEnvironment()
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -606,8 +625,11 @@ public void createPaymentAuthRequest_withGoogleMerchantName_sendGoogleMerchantNa
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -647,8 +669,11 @@ public void createPaymentAuthRequest_whenGooglePayCanProcessPayPal_tokenizationP
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -693,8 +718,11 @@ public void createPaymentAuthRequest_whenPayPalDisabledByRequest_tokenizationPro
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -739,8 +767,11 @@ public void createPaymentAuthRequest_whenPayPalDisabledInConfigurationAndGoogleP
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -786,8 +817,11 @@ public void createPaymentAuthRequest_usesGooglePayConfigurationClientId() throws
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -840,8 +874,11 @@ public void createPaymentAuthRequest_whenGooglePayConfigurationLacksClientId_tok
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -886,8 +923,11 @@ public void createPaymentAuthRequest_whenConfigurationContainsElo_addsEloAndEloD
 
         ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
                 GooglePayPaymentAuthRequest.class);
-        verify(intentDataCallback).onResult(captor.capture(), isNull());
-        GooglePayPaymentAuthRequest intent = captor.getValue();
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
+
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.ReadyToLaunch);
+        GooglePayPaymentAuthRequestParams intent = ((GooglePayPaymentAuthRequest.ReadyToLaunch) request).getRequestParams();
 
         PaymentDataRequest paymentDataRequest = intent.getPaymentDataRequest();
         JSONObject paymentDataRequestJson = new JSONObject(paymentDataRequest.toJson());
@@ -927,11 +967,13 @@ public void createPaymentAuthRequest_whenRequestIsNull_forwardsExceptionToListen
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
         sut.createPaymentAuthRequest(null, intentDataCallback);
 
-        ArgumentCaptor<Exception> captor = ArgumentCaptor.forClass(
-                Exception.class);
-        verify(intentDataCallback).onResult(isNull(), captor.capture());
+        ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
+                GooglePayPaymentAuthRequest.class);
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
 
-        Exception exception = captor.getValue();
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.Failure);
+        Exception exception = ((GooglePayPaymentAuthRequest.Failure) request).getError();
         assertTrue(exception instanceof BraintreeException);
         assertEquals("Cannot pass null GooglePayRequest to requestPayment", exception.getMessage());
     }
@@ -960,11 +1002,13 @@ public void createPaymentAuthRequest_whenManifestInvalid_forwardsExceptionToList
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
         sut.createPaymentAuthRequest(baseRequest, intentDataCallback);
 
-        ArgumentCaptor<Exception> captor = ArgumentCaptor.forClass(
-                Exception.class);
-        verify(intentDataCallback).onResult(isNull(), captor.capture());
+        ArgumentCaptor<GooglePayPaymentAuthRequest> captor = ArgumentCaptor.forClass(
+                GooglePayPaymentAuthRequest.class);
+        verify(intentDataCallback).onGooglePayPaymentAuthRequest(captor.capture());
 
-        Exception exception = captor.getValue();
+        GooglePayPaymentAuthRequest request = captor.getValue();
+        assertTrue(request instanceof GooglePayPaymentAuthRequest.Failure);
+        Exception exception = ((GooglePayPaymentAuthRequest.Failure) request).getError();
         assertTrue(exception instanceof BraintreeException);
         assertEquals("GooglePayActivity was not found in the Android " +
                         "manifest, or did not have a theme of R.style.bt_transparent_activity",
@@ -1003,11 +1047,14 @@ public void tokenize_withCardToken_returnsGooglePayNonce() {
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
         sut.tokenize(pd, activityResultCallback);
 
-        ArgumentCaptor<PaymentMethodNonce> captor =
-                ArgumentCaptor.forClass(PaymentMethodNonce.class);
-        verify(activityResultCallback).onResult(captor.capture(), isNull());
+        ArgumentCaptor<GooglePayResult> captor =
+                ArgumentCaptor.forClass(GooglePayResult.class);
+        verify(activityResultCallback).onGooglePayResult(captor.capture());
 
-        assertTrue(captor.getValue() instanceof GooglePayCardNonce);
+        GooglePayResult result = captor.getValue();
+
+        assertTrue(result instanceof GooglePayResult.Success);
+        assertTrue(((GooglePayResult.Success) result).getNonce() instanceof GooglePayCardNonce);
     }
 
     @Test
@@ -1038,11 +1085,13 @@ public void tokenize_withPayPalToken_returnsPayPalAccountNonce() {
         GooglePayClient sut = new GooglePayClient(braintreeClient, internalGooglePayClient);
         sut.tokenize(pd, activityResultCallback);
 
-        ArgumentCaptor<PaymentMethodNonce> captor =
-                ArgumentCaptor.forClass(PaymentMethodNonce.class);
-        verify(activityResultCallback).onResult(captor.capture(), (Exception) isNull());
+        ArgumentCaptor<GooglePayResult> captor =
+                ArgumentCaptor.forClass(GooglePayResult.class);
+        verify(activityResultCallback).onGooglePayResult(captor.capture());
 
-        assertTrue(captor.getValue() instanceof PayPalAccountNonce);
+        GooglePayResult result = captor.getValue();
+        assertTrue(result instanceof GooglePayResult.Success);
+        assertTrue(((GooglePayResult.Success) result).getNonce() instanceof PayPalAccountNonce);
     }
 
     // endregion
@@ -1065,13 +1114,14 @@ public void tokenize_whenPaymentDataExists_returnsResultToListener_andSendsAnaly
         sut.tokenize(googlePayPaymentAuthResult, activityResultCallback);
 
         verify(braintreeClient).sendAnalyticsEvent(eq("google-payment.authorized"));
-        ArgumentCaptor<PaymentMethodNonce> captor =
-                ArgumentCaptor.forClass(PaymentMethodNonce.class);
-        verify(activityResultCallback).onResult(captor.capture(), isNull());
-
-        PaymentMethodNonce nonce = captor.getValue();
-        JSONObject result = new JSONObject(paymentData.toJson());
-        PaymentMethodNonce expectedNonce = GooglePayCardNonce.fromJSON(result);
+        ArgumentCaptor<GooglePayResult> captor =
+                ArgumentCaptor.forClass(GooglePayResult.class);
+        verify(activityResultCallback).onGooglePayResult(captor.capture());
+
+        GooglePayResult result = captor.getValue();
+        assertTrue(result instanceof GooglePayResult.Success);
+        PaymentMethodNonce nonce = ((GooglePayResult.Success) result).getNonce();
+        PaymentMethodNonce expectedNonce = GooglePayCardNonce.fromJSON(new JSONObject(paymentDataJson));
         assertEquals(nonce.getString(), expectedNonce.getString());
     }
 
@@ -1089,7 +1139,13 @@ public void tokenize_whenErrorExists_returnsErrorToListener_andSendsAnalytics()
         sut.tokenize(googlePayPaymentAuthResult, activityResultCallback);
 
         verify(braintreeClient).sendAnalyticsEvent(eq("google-payment.failed"));
-        verify(activityResultCallback).onResult(null, error);
+
+        ArgumentCaptor<GooglePayResult> captor = ArgumentCaptor.forClass(GooglePayResult.class);
+        verify(activityResultCallback).onGooglePayResult(captor.capture());
+
+        GooglePayResult result = captor.getValue();
+        assertTrue(result instanceof GooglePayResult.Failure);
+        assertEquals(error, ((GooglePayResult.Failure) result).getError());
     }
 
     @Test
@@ -1107,7 +1163,12 @@ public void tokenize_whenUserCanceledErrorExists_returnsErrorToListener_andSends
         sut.tokenize(googlePayPaymentAuthResult, activityResultCallback);
 
         verify(braintreeClient).sendAnalyticsEvent(eq("google-payment.canceled"));
-        verify(activityResultCallback).onResult(null, userCanceledError);
+
+        ArgumentCaptor<GooglePayResult> captor = ArgumentCaptor.forClass(GooglePayResult.class);
+        verify(activityResultCallback).onGooglePayResult(captor.capture());
+
+        GooglePayResult result = captor.getValue();
+        assertTrue(result instanceof GooglePayResult.Cancel);
     }
 
     // endregion
diff --git a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayInternalClientUnitTest.kt b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayInternalClientUnitTest.kt
index e863dd5b9e..5966ba453d 100644
--- a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayInternalClientUnitTest.kt
+++ b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayInternalClientUnitTest.kt
@@ -117,9 +117,8 @@ class GooglePayInternalClientUnitTest {
         every { paymentsClient.isReadyToPay(isReadyToPayRequest) } returns SuccessfulBooleanTask(true)
 
         val sut = GooglePayInternalClient()
-        sut.isReadyToPay(activity, configuration, isReadyToPayRequest) { isReadyToPay, error ->
-            assertTrue(isReadyToPay)
-            assertNull(error)
+        sut.isReadyToPay(activity, configuration, isReadyToPayRequest) { readyToPayResult ->
+            assertTrue(readyToPayResult is GooglePayReadinessResult.ReadyToPay)
             countDownLatch.countDown()
         }
         countDownLatch.await()
@@ -136,9 +135,10 @@ class GooglePayInternalClientUnitTest {
         every { paymentsClient.isReadyToPay(isReadyToPayRequest) } returns failedTask
 
         val sut = GooglePayInternalClient()
-        sut.isReadyToPay(activity, configuration, isReadyToPayRequest) { isReadyToPay, error ->
-            assertFalse(isReadyToPay)
-            assertSame(expectedError, error)
+        sut.isReadyToPay(activity, configuration, isReadyToPayRequest) { readyToPayResult ->
+            assertTrue(readyToPayResult is GooglePayReadinessResult.NotReadyToPay)
+            assertSame(expectedError, (readyToPayResult as GooglePayReadinessResult.NotReadyToPay)
+                .error)
             countDownLatch.countDown()
         }
         countDownLatch.await()
diff --git a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayLauncherUnitTest.java b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayLauncherUnitTest.java
index cd75c36898..4b3bc8ab19 100644
--- a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayLauncherUnitTest.java
+++ b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayLauncherUnitTest.java
@@ -26,7 +26,7 @@
 public class GooglePayLauncherUnitTest {
 
     @Mock
-    ActivityResultLauncher<GooglePayPaymentAuthRequest> activityLauncher;
+    ActivityResultLauncher<GooglePayPaymentAuthRequestParams> activityLauncher;
 
     private GooglePayLauncherCallback callback;
 
@@ -46,7 +46,7 @@ public void constructor_createsActivityLauncher() {
                 callback);
 
         verify(activityResultRegistry).register(eq(expectedKey), same(lifecycleOwner),
-                Mockito.<ActivityResultContract<GooglePayPaymentAuthRequest, GooglePayPaymentAuthResult>>any(),
+                Mockito.<ActivityResultContract<GooglePayPaymentAuthRequestParams, GooglePayPaymentAuthResult>>any(),
                 Mockito.any());
     }
 
@@ -61,8 +61,8 @@ public void launch_launchesActivity() {
 
         PaymentDataRequest paymentDataRequest =
                 PaymentDataRequest.fromJson(googlePayRequest.toJson());
-        GooglePayPaymentAuthRequest
-                intentData = new GooglePayPaymentAuthRequest(1, paymentDataRequest);
+        GooglePayPaymentAuthRequestParams
+                intentData = new GooglePayPaymentAuthRequestParams(1, paymentDataRequest);
         ActivityResultRegistry activityResultRegistry = mock(ActivityResultRegistry.class);
         FragmentActivity lifecycleOwner = new FragmentActivity();
 
diff --git a/GooglePay/src/test/java/com/braintreepayments/api/MockGooglePayInternalClientBuilder.java b/GooglePay/src/test/java/com/braintreepayments/api/MockGooglePayInternalClientBuilder.java
index e28b103194..228efa2ba1 100644
--- a/GooglePay/src/test/java/com/braintreepayments/api/MockGooglePayInternalClientBuilder.java
+++ b/GooglePay/src/test/java/com/braintreepayments/api/MockGooglePayInternalClientBuilder.java
@@ -29,17 +29,14 @@ MockGooglePayInternalClientBuilder isReadyToPayError(Exception isReadyToPayError
     GooglePayInternalClient build() {
         GooglePayInternalClient googlePayInternalClient = mock(GooglePayInternalClient.class);
 
-        doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                GooglePayIsReadyToPayCallback callback = (GooglePayIsReadyToPayCallback) invocation.getArguments()[3];
-                if (isReadyToPayError != null) {
-                    callback.onResult(false, isReadyToPayError);
-                } else {
-                    callback.onResult(isReadyToPay, null);
-                }
-                return null;
+        doAnswer((Answer<Void>) invocation -> {
+            GooglePayIsReadyToPayCallback callback = (GooglePayIsReadyToPayCallback) invocation.getArguments()[3];
+            if (isReadyToPayError != null) {
+                callback.onGooglePayReadinessResult(new GooglePayReadinessResult.NotReadyToPay(isReadyToPayError));
+            } else {
+                callback.onGooglePayReadinessResult(GooglePayReadinessResult.ReadyToPay.INSTANCE);
             }
+            return null;
         }).when(googlePayInternalClient).isReadyToPay(any(FragmentActivity.class), any(Configuration.class), any(IsReadyToPayRequest.class), any(GooglePayIsReadyToPayCallback.class));
 
         return googlePayInternalClient;
diff --git a/v5_MIGRATION_GUIDE.md b/v5_MIGRATION_GUIDE.md
index 881a23e789..ce998d64a4 100644
--- a/v5_MIGRATION_GUIDE.md
+++ b/v5_MIGRATION_GUIDE.md
@@ -176,10 +176,21 @@ class MyActivity : FragmentActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
 +       // can initialize clients outside of onCreate if desired
 -       initializeClients()
+
+-       googlePayClient.isReadyToPay(this) { isReadyToPay, error ->
++       googlePayClient.isReadyToPay(this) { readinessResult ->
++           if (readinessResult is GooglePayReadinessResult.ReadyToPay) {
++                // show Google Pay button 
++           }
++        }
+        
 +       googlePayLauncher = GooglePayLauncher(this) { paymentAuthResult ->
-+            googlePayClient.tokenize(paymentAuthResult) { paymentMethodNonce, error ->
-+                error?.let { /* handle error */ }
-+                paymentMethodNonce?.let { /* handle nonce */ }
++            googlePayClient.tokenize(paymentAuthResult) { googlePayResult ->
++               when (googlePayResult) {
++                   is GooglePayResult.Failure -> { /* handle error */ }
++                   is GooglePayResult.Cancel -> { /* handle cancel */ }
++                   is GooglePayResult.Success -> { /* handle nonce */ }
++               }
 +            }
 +       }
     }
@@ -193,9 +204,12 @@ class MyActivity : FragmentActivity() {
     
     fun onGooglePayButtonClick() {
 -       googlePayClient.requestPayment(activity, request)
-+       googlePayClient.createPaymentAuthRequest(this, request) { paymentAuthRequest, error ->
-+            error?.let { /* handle error */ }
-+            paymentAuthRequest?.let { googlePayLauncher.launch(it) }
++       googlePayClient.createPaymentAuthRequest(this, request) { paymentAuthRequest ->
++           when (paymentAuthRequest) {
++            is GooglePayPaymentAuthRequest.Failure -> { /* handle error */ }
++            is GooglePayPaymentAuthRequest.ReadyToLaunch -> { 
++               googlePayLauncher.launch(paymentAuthRequest.params) 
++            }
 +       }
     }