React Native非Expo集成Stripe 调用presentPaymentSheet崩溃
问题原因及修复方案
你遇到的presentPaymentSheet调用即崩溃的问题,由以下几个常见错误共同导致,按优先级修复即可:
- 最高优先级:PaymentSheet初始化缺失必填参数:你使用的
@stripe/stripe-react-native@0.12.0版本中,initPaymentSheet强制要求传入merchantDisplayName参数,缺失该参数时原生端渲染支付组件会触发空指针直接闪退,和你描述的故障现象完全吻合。 - 接口调用逻辑错误:你的前端
fetchPaymentSheetParams方法仅请求了create_customer单一接口,该接口仅返回客户对象,不可能返回EphemeralKey、SetupIntent数据。你提到前端能拿到三个参数,大概率是测试阶段的mock数据或临时返回结构不符合要求,正式逻辑下三个参数需要基于同一个customerId串行生成,不能分开调用。 - Stripe API版本不匹配:你后端生成EphemeralKey时硬编码的
StripeVersion = "2020-08-27"和客户端0.12.0版本SDK绑定的API版本不兼容,EphemeralKey的版本号必须和客户端SDK的内置版本完全一致,否则会出现签名校验失败、参数解析异常触发崩溃。0.12.0版本对应的Stripe API版本为2022-08-01。 - 根组件配置缺失:代码中没有看到Stripe全局Provider配置,非Expo裸RN环境下必须在根组件包裹StripeProvider并传入pk开头的公钥,否则SDK初始化不完整,调用支付方法时必然异常。
分步修复操作
第一步:补全根组件Stripe配置
在App入口组件外层包裹StripeProvider,传入你的Stripe公钥:
import { StripeProvider } from '@stripe/stripe-react-native'; import CheckoutScreen from './CheckoutScreen'; export default function App() { return ( <StripeProvider publishableKey="替换为你自己的pk开头的Stripe公钥"> <CheckoutScreen /> </StripeProvider> ); }
第二步:重构后端接口
废弃三个分散的独立接口,写一个聚合接口一次性返回支付页所需的全部参数,同时修正EphemeralKey版本号:
public IActionResult GetPaymentSheetInitParams() { StripeConfiguration.ApiKey = _appSettings.StripeApiSecret; // 生成客户 var customerService = new CustomerService(); var customer = customerService.Create(new CustomerCreateOptions { Description = "Test Customer" }); // 生成临时密钥,版本必须和客户端SDK匹配 var ephKeyService = new EphemeralKeyService(); var ephemeralKey = ephKeyService.Create(new EphemeralKeyCreateOptions { StripeVersion = "2022-08-01", Customer = customer.Id }); // 生成SetupIntent var setupService = new SetupIntentService(); var setupIntent = setupService.Create(new SetupIntentCreateOptions { Customer = customer.Id }); // 按前端需要的结构返回 return Ok(new { customer = new { id = customer.Id }, ephemeralKey = new { secret = ephemeralKey.Secret }, setupIntent = new { clientSecret = setupIntent.ClientSecret } }); }
第三步:修正前端支付逻辑
修改前端请求地址,补全initPaymentSheet的必填参数,增加异常捕获:
import { useStripe } from '@stripe/stripe-react-native'; import React, { useEffect, useState } from 'react'; import { View, Button, Alert } from 'react-native'; function CheckoutScreen() { const { initPaymentSheet, presentPaymentSheet } = useStripe(); const [loading, setLoading] = useState(false); const fetchPaymentSheetParams = async () => { // 替换为新写的聚合接口地址 const response = await fetch(`${environment.stripeurl}/getPaymentSheetInitParams`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, }); return response.json(); }; const initializePaymentSheet = async () => { try { const { setupIntent, ephemeralKey, customer } = await fetchPaymentSheetParams(); const { error } = await initPaymentSheet({ customerId: customer.id, customerEphemeralKeySecret: ephemeralKey.secret, setupIntentClientSecret: setupIntent.clientSecret, merchantDisplayName: "替换为你的APP/商户名称", // 必传参数,缺失必崩 allowsDelayedPaymentMethods: true }); if (!error) setLoading(true); else Alert.alert('初始化失败', error.message); } catch (err) { console.log('支付初始化异常', err); } }; const openPaymentSheet = async () => { const { error } = await presentPaymentSheet(); if (error) Alert.alert(`Error code: ${error.code}`, error.message); else Alert.alert('Success', '支付方式绑定成功'); }; useEffect(() => { initializePaymentSheet(); }, []); return ( <View> <Button disabled={!loading} title="绑定支付方式" onPress={openPaymentSheet} /> </View> ); } export default CheckoutScreen;
第四步:原生端缓存清理
- Android端:进入android目录执行
./gradlew clean,重新build运行,确认minSdkVersion >= 21 - iOS端:进入ios目录执行
pod install --repo-update,重新安装依赖后运行
如果以上操作完成后仍存在崩溃,直接用Android Studio/Xcode连接设备读取原生崩溃日志,90%以上的同类崩溃都是漏传
merchantDisplayName、StripeProvider未配置、API版本不匹配这三个原因导致。
内容的提问来源于stack exchange,提问作者Taha Shahzad
相关产品推荐
相关产品推荐

