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
相关产品推荐
相关产品推荐

