stripe / stripe-react-native

React Native library for Stripe.
https://stripe.dev/stripe-react-native
MIT License
1.27k stars 263 forks source link

Crash android when initPaymentSheet is initialized #603

Closed joaochiquitin closed 2 years ago

joaochiquitin commented 3 years ago

Describe the bug every time I start a payment intent for the first time, the app crashes, but the second time it doesn't crash, I don't know what it is, I've tried using timeout and stuff.

Expected behavior when the app starts for the first time does not crash, and need to start the app again.

Code:

async function initialisePaymentSheet() { setLoading(true);

try {
  console.log(paymentIntent, ephemeralKey, customer)

  await initPaymentSheet({
    customerId: customer,
    customerEphemeralKeySecret: ephemeralKey,
    paymentIntentClientSecret: paymentIntent,
    merchantDisplayName: "Word EIRELI.",
    merchantCountryCode: "brl",
    customFlow: true,
  }).then(({ error, paymentOption }) => {
    console.log(error, paymentOption);

    if (!error) {
      setPaymentSheetEnabled(true);
    } else {
      console.log(error.message);
    }

    if (paymentOption) {
      setPaymentMethod(paymentOption);
    }

  }).catch((error) => console.log(error));

} catch (error) {
  console.log("error", error);
} finally {
  setLoading(false);
}

};

useEffect(() => { initialisePaymentSheet(); }, []);

g-hamilton commented 3 years ago

Same here. I'm getting the same behaviour, and in addition, on the second try when initPaymentSheet() completes and I subsequently call presentPaymentSheet(), I get an error with code "Failed" and no explaining message so it's not at all helpful. This is only on Android for me - it works fine on iOS.

I'm in an"expo": "~41.0.1" project using "@stripe/stripe-react-native": "0.1.1"

joaochiquitin commented 3 years ago

i'm using expo too, but it is SDK 42. Yeah, here onlycrash in Android, but IOS works fine.

tiagodws commented 3 years ago

Having the same issue.

Crashlog (SDK 42.0.4):

10-13 21:28:27.614 30991 30991 D AndroidRuntime: Shutting down VM
10-13 21:28:27.614 30991 30991 E AndroidRuntime: FATAL EXCEPTION: main
10-13 21:28:27.614 30991 30991 E AndroidRuntime: Process: host.exp.exponent, PID: 30991
10-13 21:28:27.614 30991 30991 E AndroidRuntime: java.lang.RuntimeException: Error receiving broadcast Intent { act=abi42_0_0.host.exp.exponent.modules.api.components.reactnativestripesdk.FRAGMENT_CREATED_ACTION flg=0x10 } in abi42_0_0.host.exp.exponent.modules.api.components.reactnativestripesdk.StripeSdkModule$mPaymentSheetReceiver$1@a314b29
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1581)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.os.Handler.handleCallback(Handler.java:938)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:99)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:245)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:8004)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
10-13 21:28:27.614 30991 30991 E AndroidRuntime: Caused by: java.lang.NullPointerException: null cannot be cast to non-null type androidx.appcompat.app.AppCompatActivity
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at java.util.Objects.requireNonNull(Objects.java:245)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at abi42_0_0.host.exp.exponent.modules.api.components.reactnativestripesdk.StripeSdkModule$mPaymentSheetReceiver$1.onReceive(StripeSdkModule.kt:2)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1566)
10-13 21:28:27.614 30991 30991 E AndroidRuntime:    ... 8 more
joaochiquitin commented 3 years ago

in my case i just removed StripeProvider in App.tsx / js and it worked again, it was starting StripeProvider and initStripe together so it crashed.

tiagodws commented 3 years ago

in my case i just removed StripeProvider in App.tsx / js and it worked again, it was starting StripeProvider and initStripe together so it crashed.

Thanks for the info!

Here's also a reproducible example for whoever works on fixing this: https://snack.expo.dev/@charliecruzan/stripe-react-native-example

tiagodws commented 3 years ago

in my case i just removed StripeProvider in App.tsx / js and it worked again, it was starting StripeProvider and initStripe together so it crashed.

How do you give the publishableKey to Stripe, though? Even if I use initStripe instead of the provider, the app still crashes.

tiagodws commented 3 years ago

Issue also happens with Expo SDK 43.0.0-beta.3 and @stripe/stripe-react-native@0.2.2

SrBrahma commented 2 years ago

Any updates?

ReisMari commented 2 years ago

in my case i just removed StripeProvider in App.tsx / js and it worked again, it was starting StripeProvider and initStripe together so it crashed.

How do you give the publishableKey to Stripe, though? Even if I use initStripe instead of the provider, the app still crashes.

Hi! Did you find the answer?

joaochiquitin commented 2 years ago
import React, { useEffect, useState } from 'react';

import { ActivityIndicator, ScrollView, StyleSheet, Text } from 'react-native';

import { initStripe } from '@stripe/stripe-react-native';

interface Props {
  paymentMethod?: string;
  onInit?(): void;
}

const PaymentScreen: React.FC<Props> = ({
  paymentMethod,
  children,
  onInit,
}) => {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function initialize() {
      const publishableKey = 'pk_test_KEY.....';

      await initStripe({
        publishableKey,
        merchantIdentifier: 'merchant.com.stripe.react.native',
        urlScheme:
          paymentMethod === 'wechat_pay' ? undefined : 'stripe-example',
        setUrlSchemeOnAndroid: true,
      });
      setLoading(false);
      onInit?.();
    }

    initialize();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return loading ? (
    <ActivityIndicator size="large" style={StyleSheet.absoluteFill} />
  ) : (
    <ScrollView
      accessibilityLabel="payment-screen"
      style={styles.container}
      keyboardShouldPersistTaps="always"
    >
      {children}
      {/* eslint-disable-next-line react-native/no-inline-styles */}
      <Text style={{ opacity: 0 }}>appium fix</Text>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,

    paddingTop: 20,
    paddingHorizontal: 16,
  },
});

export default PaymentScreen;

later i wrap in

<PaymentScreen paymentMethod="Cart" onInit={initialisePaymentSheet}>
             <ButtonPay
                  variant="primary"
                  loading={loading}
                  title={
                    paymentMethod ? (
                      <View style={{ flexDirection: "row", alignItems: "center" }}>
                        <Image
                          source={{
                            uri: `data:image/png;base64,${paymentMethod.image}`,
                          }}
                          style={{ width: 26, height: 20 }}
                        />
                        <Text
                          style={{
                            color: "#000",
                            fontSize: 16,
                            fontWeight: "600",
                            marginLeft: 12,
                          }}
                        >
                          {paymentMethod.label}
                        </Text>
                      </View>
                    ) : (
                      "Choose a card"
                    )
                  }
                  disabled={!paymentSheetEnabled}
                  onPress={choosePaymentOption}
                />
              </PaymentScreen>
jordzawada commented 2 years ago

I tried moving the stripe provider to a higher level component, but my initPaymentSheet is still crashing on the first call. After re-opening the app it seems to work fine. What's interesting is I cannot console log any information before initPaymentSheet . Ex;

const initializePaymentSheet = async () => { console.log('going to initPaymentSheet'); await initPaymentSheet({ keys ids blah blah blah }) }

the console log is never hit unless I block out initPaymentSheet

"@stripe/stripe-react-native": "0.2.2", "expo": "^43.0.0",

"2022-03-07 16:00:32.653 26182-26182/host.exp.exponent E/AndroidRuntime: FATAL EXCEPTION: main Process: host.exp.exponent, PID: 26182 java.lang.NullPointerException: null cannot be cast to non-null type androidx.appcompat.app.AppCompatActivity at java.util.Objects.requireNonNull(Objects.java:228) at abi43_0_0.host.exp.exponent.modules.api.components.reactnativestripesdk.StripeSdkModule$mPaymentSheetReceiver$1.onReceive(StripeSdkModule.kt:2) at f.t.a.a.a(LocalBroadcastManager.java:12) at f.t.a.a$a.handleMessage(LocalBroadcastManager.java:3) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)"

SrBrahma commented 2 years ago

It's still happening to me. I fear this will happen on Prod.

jordzawada commented 2 years ago

It's still happening to me. I fear this will happen on Prod.

It has happened on a prod app built with eas-build for me.

SamuelNavarro commented 2 years ago

Same behaviour that @jordzawada Any updates?

panacotar commented 2 years ago

I actually can see the console.logs added before initPaymentSheet, but it will still crash the app. stripe-react-native was installed using expo install and I'm using initStripe function to initialize he app.

"@stripe/stripe-react-native": "0.1.4",
"expo": "~42.0.1"

We'll have to go live with our app soon, are there any solutions for this?

charliecruzan-stripe commented 2 years ago

This was fixed in https://github.com/stripe/stripe-react-native/pull/788, sorry for the late notice! Fix is available in 0.2.4 and above

SrBrahma commented 2 years ago

@charliecruzan-stripe Could you add it to 0.2.3 somehow? I can't move to 0.2.4 due to https://github.com/stripe/stripe-react-native/issues/812. Using Expo EAS. It would also fit my case if you know about an EAS Config Plugin to change the targetSdkVersion, that will probably fix it.

charliecruzan-stripe commented 2 years ago

If one doesn't already exist, you can write an EAS Config Plugin to update the targetSdkVersion- https://docs.expo.dev/guides/config-plugins/#default-mods

SrBrahma commented 2 years ago

If one doesn't already exist, you can write an EAS Config Plugin to update the targetSdkVersion- https://docs.expo.dev/guides/config-plugins/#default-mods

Unfortunately I still have no experience with EAS plugins and I can't find a way to get this done :/ Looks like it's said in https://docs.expo.dev/guides/config-plugins/#android-gradle-files, but can't progress further.

jordzawada commented 2 years ago

I have tried 0.2.4, 0.3.0, and 0.4.0, and I am still getting NullPointerException crash on first try.

I DID upgrade expo to SDK 44 tho. I couldn't EAS build android in SDK 43 because stripe 0.2.4+ required api level 31.

I will retest 0.4.0 on prod to make sure it does not happen there...once I get EAS to build

charliecruzan-stripe commented 2 years ago

How have you tried 0.2.4 and above if you can't build due to the required API level?

jordzawada commented 2 years ago

How have you tried 0.2.4 and above if you can't build due to the required API level?

"expo start" builds fine. I cannot EAS build to make apk stuff.

charliecruzan-stripe commented 2 years ago

expo start is going to use Expo's bundled-in version of @stripe/stripe-react-native- https://github.com/expo/expo/blob/sdk-44/packages/expo/bundledNativeModules.json - which is 0.2.3, which would explain why you're still getting the crash there

SrBrahma commented 2 years ago

@jordzawada @charliecruzan-stripe actually when he does expo start, even if he installed 0.4.0, he is still using the < 0.2.4 previous installed version native code.

By using EAS, the packages native codes are only updated when he EAS builds again.

I know and use this linked .json in one of my projects. It only says the officially supported packages versions for the said Expo SDK, it's used on expo install to install the supported version instead of the latest one, if they differ.

jordzawada commented 2 years ago

I do get an warning saying:

"Opening developer tools in the browser... Some dependencies are incompatible with the installed expo package version:

When I run expo start.

SrBrahma commented 2 years ago

@jordzawada This is because Expo checks the installed package versions with the linked .json and warns if they differ.

Anyway you won't get it working. The Stripe native code will only get installed after a new EAS build, and you won't be able to do it due to Android SDK incompatibility.

jordzawada commented 2 years ago

@SrBrahma Does that mean there is no way to upgrade react native/expo/eas build in a way that builds onto API 31?

charliecruzan-stripe commented 2 years ago

The only case where you're limited is if you have an Expo managed workflow project where you do not have access to your native projects (you only have access to the Javascript), otherwise you can edit your Android SDK version.

If you do have an Expo managed workflow project, then to change your Android SDK version (or anything else in your native projects) you need to use a Config Plugin, which Expo provides documentation for here: https://docs.expo.dev/guides/config-plugins/

jordzawada commented 2 years ago

@charliecruzan-stripe I am going to have to look at that Config Plugin. I still haven't ejected yet as I don't have access to a Mac to do dev work on iOS native stuff.

SrBrahma commented 2 years ago

@jordzawada, check this, solution for EAS: https://forums.expo.dev/t/change-targetsdkversion-for-stripe-react-native-0-2-4/62534/2?u=srbrahma

I still haven't tested it, but I will soon.

jordzawada commented 2 years ago

@SrBrahma I think that fix worked. It's hard to test the crash after an EAS build because I can't always reset the app like I can on expo.

I did have to change the minSdkversion to compileSDKversion

SrBrahma commented 2 years ago

Good to know! Just being able to use the latest stripe is already good enough for me. Maybe you should also change targetSdkVersion, as mentioned here?

panacotar commented 2 years ago

The only case where you're limited is if you have an Expo managed workflow project where you do not have access to your native projects (you only have access to the Javascript), otherwise you can edit your Android SDK version.

If you do have an Expo managed workflow project, then to change your Android SDK version (or anything else in your native projects) you need to use a Config Plugin, which Expo provides documentation for here: https://docs.expo.dev/guides/config-plugins/

Thanks for pointing it out. I tried version 0.2.4, but still crashes the app as you said here. I still don't understand how to change the Android SDK version. The project is using the Expo managed workflows and I never worked with config plugins in Expo or bare workflow. Is it from the android gradle files? Do you have any code which I can use to do this?

SrBrahma commented 2 years ago

@DariusPirvulescu, if you use basic Expo (no EAS), you can't make this Android SDK version change. Config plugins are only for EAS. Maybe you can try to use Payment Form to avoid this error, or use EAS, or await some good months until Expo changes its Android SDK from 30 to 31 😬

SrBrahma commented 2 years ago

Here is the EAS plugin to get it working:

https://forums.expo.dev/t/change-targetsdkversion-for-stripe-react-native-0-2-4/62534/4