React Native iOS内购requestPurchase异常:支付弹窗重复弹出
解决React Native iOS内购弹窗重复弹出问题
问题描述
使用react-native-iap实现iOS内购时,支付弹窗可正常唤起,但点击购买按钮后弹窗关闭随即重新弹出,无法完成正常交易流程。
核心原因
iOS内购流程要求:当交易完成(或进入可处理状态)后,必须调用finishTransaction告知App Store该交易已处理完毕。若未执行此步骤,App Store会持续重试触发交易,导致弹窗重复弹出。你的代码仅发起了购买请求,但未监听并处理currentPurchase状态,也未完成交易收尾操作。
解决方案
添加监听currentPurchase的副作用,当交易状态更新时,完成订单验证(可选但推荐)并调用finishTransaction结束交易。
修改后的完整代码片段
const items = Platform.select({ ios: ["item_25", "item_55", "item_155"], android: [""], })
import { PurchaseError } from 'react-native-iap'; const { connected, subscriptions, getSubscriptions, getProducts, products, currentPurchase, finishTransaction, purchaseHistory, getPurchaseHistory, requestPurchase } = useIAP(); const handleGetProducts = async () => { setGetPlaning(true); try { await getProducts({ skus: items }); } catch (error) { errorLog({ message: "handleGetProducts", error }); } }; useEffect(() => { handleGetProducts(); }, [connected]); // 新增:监听并处理完成的交易 useEffect(() => { const processTransaction = async () => { if (!currentPurchase) return; try { // 可选:将交易凭证发送到后端验证(生产环境必须) // const receipt = currentPurchase.transactionReceipt; // await fetch('你的订单验证接口', { // method: 'POST', // body: JSON.stringify({ receipt }) // }); // 必须调用:结束交易,避免重复触发弹窗 await finishTransaction({ purchase: currentPurchase }); console.log('交易处理完成'); } catch (error) { console.error('交易处理失败:', error); } }; processTransaction(); }, [currentPurchase, finishTransaction]); const handlePurchase = async (productId) => { setLoading(true); try { await requestPurchase({ sku: productId, }); setLoading(false); } catch (error) { setLoading(false); if (error instanceof PurchaseError) { console.error({ message: `[${error.code}]: ${error.message}`, error }); } else { console.error({ message: "handlePurchase", error }); } } };
<Button color={colors.black} size="large" loading={loading} style={{ marginTop: theme.SIZES.BASE }} onPress={() => handlePurchase('item_25')}> <Text color={colors.white} size={20} bold>Purchase</Text> </Button>
额外注意事项
- 沙盒测试必须使用苹果官方沙盒账号,禁止用真实账号测试。
- 若交易处于pending状态(如需要家长验证),不要调用
finishTransaction,待交易完成后再处理。 - 生产环境必须保留订单验证步骤,防止恶意伪造交易。
内容的提问来源于stack exchange,提问作者appleman
相关产品推荐
相关产品推荐

