Skip to content

[BUG] PaymentSheet cannot show Google Pay in Test environment: existingPaymentMethodRequired is hard-coded true #13968

Description

@maclt

Summary

PaymentSheet cannot show the Google Pay button in GooglePayEnvironment.Test, because it probes Google with existingPaymentMethodRequired = true and offers no way to change that. On a physical device with a Google account holding eligible cards, Google answers false to that request in Test — and true to the identical request in Production.

Removing only that flag makes the Test-environment request answer true, the button renders, and a test payment completes. That is the advice given in #7230, but PaymentSheet provides no way to follow it.

This is the same problem as #9548 (closed after the reporter switched Google accounts) and flutter-stripe/flutter_stripe#2108 (closed as an emulator limitation). Neither explanation applies here: real device, and the same account works in Production.

Environment

  • stripe-android 23.1.0 (via flutter_stripe 12.6.0, which pins ext.stripe_version = '23.1.+')
  • Physical Pixel 6a, Google Play services present, Google account signed in
  • Google account holds Visa + MastercardallowedCardNetworks ["AMEX","DISCOVER","MASTERCARD","VISA"] satisfied, no JCB dependency
  • Stripe account: US, charges_enabled, google_pay available with display_preference = on (verified via GET /v1/payment_method_configurations)
  • Flow: PaymentSheet, non-deferred, PaymentIntent with payment_method_types: ["card"], server-created CustomerSession

Steps to reproduce

  1. Configure PaymentSheet with PaymentSheet.GooglePayConfiguration(environment = Environment.Test, …) and a pk_test key.
  2. Present the sheet on a real device signed into a Google account that has a Visa/Mastercard.
  3. No Google Pay row. Logcat (app is debuggable, so RealUserFacingLogger prints):
W/StripeSdk: Google Pay API check failed.
W/StripeSdk: Possible reasons:
W/StripeSdk: - Google Play service is not available on this device.
W/StripeSdk: - Google account is not signed in on this device.

Both stated reasons are false on this device.

  1. Change only environment to Environment.Production, keeping everything else identical → the row renders. (The payment then fails with OR_BIBED_06 "Invalid stripe:publishableKey for current environment", as expected for a test key — but the readiness answer flipped.)

Evidence that the flag is the cause

Swapping the availability client — the same seam used by FakeGooglePayRepositoryRule in your instrumentation tests — and re-sending the request with existingPaymentMethodRequired removed:

GooglePayRepository.googlePayAvailabilityClientFactory =
    object : GooglePayAvailabilityClient.Factory {
        override fun create(paymentsClient: PaymentsClient) =
            object : GooglePayAvailabilityClient {
                override suspend fun isReady(request: IsReadyToPayRequest): Boolean {
                    val relaxed = JSONObject(request.toJson())
                        .apply { remove("existingPaymentMethodRequired") }
                    return paymentsClient
                        .isReadyToPay(IsReadyToPayRequest.fromJson(relaxed.toString()))
                        .await()
                }
            }
    }

Result on the same device, same account, still Environment.Test and pk_test:

  • isReadyToPaytrue
  • Google Pay row renders in PaymentSheet
  • Test payment completes successfully

So nothing about the account, the device, the cards or the Stripe account is at fault; the single differing input is that one flag.

Why this matters beyond dev convenience

Google requires screenshots of a working integration in the Test environment to grant production access. With PaymentSheet unable to render the button in Test, and Production refusing test keys, an integration can end up unable to produce the screenshots needed to be allowed into Production. #9548 raised exactly this loop.

Requests

  1. Let PaymentSheet.GooglePayConfiguration set existingPaymentMethodRequired, or send it as false when environment == Test (per your own guidance in [BUG] [Google Pay] Google pay no show in test environment #7230). Test-environment readiness has no bearing on whether a real user can pay.
  2. Surface the underlying failure. DefaultGooglePayRepository.isReadyAsync() funnels every failure through runCatching { … }.getOrDefault(false) and logs the reason with Logger.getInstance(BuildConfig.DEBUG), which is off in the released AAR — so integrators only ever see the generic two-reason UserFacingLogger message, neither reason being the actual cause. Routing GOOGLE_PAY_IS_READY_API_CALL / GOOGLE_PAY_JSON_REQUEST_PARSING through UserFacingLogger would turn a multi-day investigation into one log line.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    triagedIssue has been reviewed by Stripe and is being tracked internally

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions