You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Stripe SDK真机构建调用presentPaymentSheet崩溃问题

React Native + Stripe 真机构建时调用presentPaymentSheet崩溃问题

使用React Native和Stripe SDK开发的应用,在Expo Go及development build中运行正常,但在真机构建时调用presentPaymentSheet()会直接崩溃,抛出java.lang.IllegalStateException,卡片输入界面无法弹出。

相关代码

import { useStripe } from '@stripe/stripe-react-native';
const { initPaymentSheet, presentPaymentSheet, confirmPaymentSheetPayment } = useStripe();

useEffect(() => {
    if (isInactive(user)) {
      initializePayment().catch(err => {
        console.error("Failed to initialize payment", err);
      });
    }
  }, [subscriptionSecret, customerId])

const initializePayment = async (): Promise<void> => {
    setIsLoading(true);
    try {
      if (subscriptionSecret) {
        const { error } = await initPaymentSheet({
          customerId: customerId,
          paymentIntentClientSecret: subscriptionSecret,
          merchantDisplayName: 'a',
          customFlow: true, 
        });
        if (error) {
          console.log('Failed to initialize payment sheet', error);
          alert('支払いの初期化エラーが発生しました。もう一度やり直してください。');
        } else {
          console.log('initialize succeeded');
        }
      }
    } catch (e) {
      console.error('An error occurred:', e);
      alert('予期せぬエラーが発生しました。');
    } finally {
      setIsLoading(false);
    }
  };

const handlePay = async (): Promise<void> => {
    try {
      if (!paymentIntentClientSecret) return;
      const { error } = await presentPaymentSheet();

      if (error) {
        console.error('Payment failed', error);
        alert('Payment error occurred, please try again.');
        return;
      } else {
        console.log('Payment succeeded');
      }
    } catch (e) {
      console.log(e)
      return;
    } 
    try {
      setIsLoading(true)
      const { error: confirmError } = await confirmPaymentSheetPayment();
      console.log('error', confirmError);
      if (confirmError) {
        Alert.alert(`error  code: ${confirmError.code}`, confirmError.message);
      } else {
        // (payment success handling code)
      }
    } catch (e) {
      console.error(e)
      alert('Payment error occurred, please try again.');
    } finally {
      setIsLoading(false)
    }
}

错误日志

Exception java.lang.IllegalStateException:
  at com.stripe.android.paymentsheet.flowcontroller.DefaultFlowController.presentPaymentOptions (DefaultFlowController.kt:225)
  at com.reactnativestripesdk.PaymentSheetFragment.present (PaymentSheetFragment.kt:157)
  at com.reactnativestripesdk.StripeSdkModule.presentPaymentSheet (StripeSdkModule.kt:176)
  at java.lang.reflect.Method.invoke
  at com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java:372)
  at com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java:188)
  at com.facebook.jni.NativeRunnable.run
  at android.os.Handler.handleCallback (Handler.java:907)
  at android.os.Handler.dispatchMessage (Handler.java:105)
  at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java:27)
  at android.os.Looper.loop (Looper.java:216)
  at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:228)
  at java.lang.Thread.run (Thread.java:784)

依赖版本

- "expo": "~48.0.21"
- "@stripe/stripe-react-native": "0.23.3"
- "react-native": "0.71.14"

解决方案

1. 确保PaymentSheet初始化完成后再调用present

真机构建的异步时序比Expo Go更严格,需添加状态变量跟踪初始化状态,避免未完成初始化时调用presentPaymentSheet():

// 添加状态变量
const [isPaymentSheetInitialized, setIsPaymentSheetInitialized] = useState(false);

// 在initializePayment的成功回调中设置状态
const initializePayment = async (): Promise<void> => {
    setIsLoading(true);
    try {
      if (subscriptionSecret && customerId) { // 同时校验customerId
        const { error } = await initPaymentSheet({
          customerId: customerId,
          paymentIntentClientSecret: subscriptionSecret,
          merchantDisplayName: 'a',
          customFlow: true, 
        });
        if (error) {
          console.log('Failed to initialize payment sheet', error);
          alert('支払いの初期化エラーが発生しました。もう一度やり直してください。');
          setIsPaymentSheetInitialized(false);
        } else {
          console.log('initialize succeeded');
          setIsPaymentSheetInitialized(true);
        }
      } else {
        setIsPaymentSheetInitialized(false);
      }
    } catch (e) {
      console.error('An error occurred:', e);
      alert('予期せぬエラーが発生しました。');
      setIsPaymentSheetInitialized(false);
    } finally {
      setIsLoading(false);
    }
  };

// 在handlePay中先检查初始化状态
const handlePay = async (): Promise<void> => {
    if (!isPaymentSheetInitialized || !paymentIntentClientSecret) return;
    // ... 后续代码
}

2. 添加Stripe SDK的混淆规则

真机构建启用ProGuard/R8混淆时,可能破坏Stripe SDK内部方法,需在android/app/proguard-rules.pro中添加:

-keep class com.stripe.android.** { *; }
-keep class com.reactnativestripesdk.** { *; }

3. 升级Stripe SDK版本到兼容版本

当前使用的@stripe/stripe-react-native0.23.3与Expo 48存在兼容性问题,升级到0.24.x或更高稳定版本(如0.24.0),确保版本与Expo 48匹配。

4. 验证参数有效性

确认真机构建环境中subscriptionSecret和customerId均为有效非空值,生产环境的Stripe密钥和参数可能与开发环境不同,排查是否存在参数为空或无效的情况。

5. 测试非自定义流程

暂时将customFlow设为false,测试是否还会崩溃,排除自定义流程导致的逻辑问题。

内容的提问来源于stack exchange,提问作者user42195

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:27:32