flutter_stripe icon indicating copy to clipboard operation
flutter_stripe copied to clipboard

Custom payment sheet appearance on android doesn't work (iOS ok)

Open elmdecoste opened this issue 1 year ago • 1 comments

Describe the bug We are using the built-in PaymentSheetAppearance class to style the sheet when presenting it to users. On iOS this works fine and is styled correctly, but on Android we receive platform errors where the parameters such as border radius can't be parsed because the incorrect data types are being sent over the platform channel.

It appears that borderRadius and borderWidth are the main offenders here. The shadows and other colors appear to be having problems as well though

To Reproduce

  1. Create a payment sheet with custom styling
  2. See errors in the console as well as the styling failing to be applied

Expected behavior The styling should be applied properly via the styling configuration object

Smartphone / tablet

  • Device: Pixel 4A
  • OS: Android 12
  • Package version: 4.0.0
  • Flutter version 3.0.5

Additional context Our styling object:

PaymentSheetAppearance(
      colors: PaymentSheetAppearanceColors(
        background: theme.neutral.shade0,
        primary: theme.primary,
        componentBorder: theme.neutral.shade200,
        componentDivider: theme.neutral.shade300,
        componentText: theme.neutral.shade800,
        primaryText: theme.neutral.shade900,
        error: theme.red,
        icon: theme.neutral.shade600,
      ),
      shapes: PaymentSheetShape(
        borderWidth: 1.0,
        borderRadius: 11.0,
        shadow: PaymentSheetShadowParams(
          offset: const PaymentSheetShadowOffset(
            x: 0.0,
            y: -2.0,
          ),
          opacity: 0.1,
          color: theme.neutral.shade900,
        ),
      ),
      primaryButton: PaymentSheetPrimaryButtonAppearance(
        shapes: PaymentSheetPrimaryButtonShape(
          blurRadius: 4.0,
          shadow: PaymentSheetShadowParams(
            opacity: 0.1,
            color: theme.neutral.shade900,
          ),
        ),
        colors: PaymentSheetPrimaryButtonTheme(
          light: PaymentSheetPrimaryButtonThemeColors(
            background: theme.blue,
            text: Colors.white,
          ),
          dark: PaymentSheetPrimaryButtonThemeColors(
            background: theme.blue,
            text: Colors.white,
          ),
        ),
      ),
    );

Stack Traces

W/Bundle  (20050): Key borderRadius expected Integer but value was a java.lang.Double.  The default value 0 was returned.
W/Bundle  (20050): Attempt to cast generated internal exception:
W/Bundle  (20050): java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
W/Bundle  (20050): 	at android.os.BaseBundle.getInt(BaseBundle.java:1077)
W/Bundle  (20050): 	at android.os.BaseBundle.getInt(BaseBundle.java:1059)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.getFloatOr(PaymentSheetAppearance.kt:108)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildShapes(PaymentSheetAppearance.kt:62)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildPaymentSheetAppearance(PaymentSheetAppearance.kt:17)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetFragment.onViewCreated(PaymentSheetFragment.kt:67)
W/Bundle  (20050): 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3019)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1758)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488)
W/Bundle  (20050): 	at android.os.Handler.handleCallback(Handler.java:938)
W/Bundle  (20050): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/Bundle  (20050): 	at android.os.Looper.loopOnce(Looper.java:201)
W/Bundle  (20050): 	at android.os.Looper.loop(Looper.java:288)
W/Bundle  (20050): 	at android.app.ActivityThread.main(ActivityThread.java:7870)
W/Bundle  (20050): 	at java.lang.reflect.Method.invoke(Native Method)
W/Bundle  (20050): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
W/Bundle  (20050): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
W/Bundle  (20050): Key borderRadius expected Float but value was a java.lang.Double.  The default value 0.0 was returned.
W/Bundle  (20050): Attempt to cast generated internal exception:
W/Bundle  (20050): java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float
W/Bundle  (20050): 	at android.os.BaseBundle.getFloat(BaseBundle.java:1145)
W/Bundle  (20050): 	at android.os.Bundle.getFloat(Bundle.java:892)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.getFloatOr(PaymentSheetAppearance.kt:108)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildShapes(PaymentSheetAppearance.kt:62)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildPaymentSheetAppearance(PaymentSheetAppearance.kt:17)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetFragment.onViewCreated(PaymentSheetFragment.kt:67)
W/Bundle  (20050): 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3019)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1758)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488)
W/Bundle  (20050): 	at android.os.Handler.handleCallback(Handler.java:938)
W/Bundle  (20050): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/Bundle  (20050): 	at android.os.Looper.loopOnce(Looper.java:201)
W/Bundle  (20050): 	at android.os.Looper.loop(Looper.java:288)
W/Bundle  (20050): 	at android.app.ActivityThread.main(ActivityThread.java:7870)
W/Bundle  (20050): 	at java.lang.reflect.Method.invoke(Native Method)
W/Bundle  (20050): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
W/Bundle  (20050): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
W/Bundle  (20050): Key borderWidth expected Integer but value was a java.lang.Double.  The default value 0 was returned.
W/Bundle  (20050): Attempt to cast generated internal exception:
W/Bundle  (20050): java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
W/Bundle  (20050): 	at android.os.BaseBundle.getInt(BaseBundle.java:1077)
W/Bundle  (20050): 	at android.os.BaseBundle.getInt(BaseBundle.java:1059)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.getFloatOr(PaymentSheetAppearance.kt:108)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildShapes(PaymentSheetAppearance.kt:63)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildPaymentSheetAppearance(PaymentSheetAppearance.kt:17)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetFragment.onViewCreated(PaymentSheetFragment.kt:67)
W/Bundle  (20050): 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3019)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1758)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488)
W/Bundle  (20050): 	at android.os.Handler.handleCallback(Handler.java:938)
W/Bundle  (20050): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/Bundle  (20050): 	at android.os.Looper.loopOnce(Looper.java:201)
W/Bundle  (20050): 	at android.os.Looper.loop(Looper.java:288)
W/Bundle  (20050): 	at android.app.ActivityThread.main(ActivityThread.java:7870)
W/Bundle  (20050): 	at java.lang.reflect.Method.invoke(Native Method)
W/Bundle  (20050): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
W/Bundle  (20050): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
W/Bundle  (20050): Key borderWidth expected Float but value was a java.lang.Double.  The default value 0.0 was returned.
W/Bundle  (20050): Attempt to cast generated internal exception:
W/Bundle  (20050): java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float
W/Bundle  (20050): 	at android.os.BaseBundle.getFloat(BaseBundle.java:1145)
W/Bundle  (20050): 	at android.os.Bundle.getFloat(Bundle.java:892)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.getFloatOr(PaymentSheetAppearance.kt:108)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildShapes(PaymentSheetAppearance.kt:63)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetAppearanceKt.buildPaymentSheetAppearance(PaymentSheetAppearance.kt:17)
W/Bundle  (20050): 	at com.reactnativestripesdk.PaymentSheetFragment.onViewCreated(PaymentSheetFragment.kt:67)
W/Bundle  (20050): 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3019)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1758)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701)
W/Bundle  (20050): 	at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488)
W/Bundle  (20050): 	at android.os.Handler.handleCallback(Handler.java:938)
W/Bundle  (20050): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/Bundle  (20050): 	at android.os.Looper.loopOnce(Looper.java:201)
W/Bundle  (20050): 	at android.os.Looper.loop(Looper.java:288)
W/Bundle  (20050): 	at android.app.ActivityThread.main(ActivityThread.java:7870)
W/Bundle  (20050): 	at java.lang.reflect.Method.invoke(Native Method)
W/Bundle  (20050): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
W/Bundle  (20050): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Screenshot showing failed styling application: Screenshot_20220808-095910

elmdecoste avatar Aug 08 '22 15:08 elmdecoste

Thanks - it will be fixed in the next version. Please note that the warnings will still appear but the styling will work.

jonasbark avatar Aug 17 '22 07:08 jonasbark