Expo In App Purchase失效,我的代码哪里出问题了?
问题分析与修复方案
针对你使用Expo In App Purchase时遇到的「购买成功后指定代码未触发」问题,核心原因和修复方式如下:
核心问题:purchaseItemAsync的异步逻辑误解
Expo IAP的purchaseItemAsync在iOS平台下不会通过await直接返回购买结果,而是依赖purchaseUpdatedListener事件回调来通知购买状态。你的代码直接用await等待返回值,导致购买流程完成后,后续的console.log无法触发。
具体修复步骤
1. 添加购买状态监听器
在组件挂载时注册监听器,统一处理双平台的购买结果:
import { useEffect } from 'react'; import * as InAppPurchases from 'expo-in-app-purchases'; import { Alert } from 'react-native'; // 组件内部逻辑 useEffect(() => { const purchaseListener = InAppPurchases.purchaseUpdatedListener(({ responseCode, results }) => { if (responseCode === InAppPurchases.IAPResponseCode.OK) { results.forEach(purchase => { if (purchase.transactionState === InAppPurchases.IAPTransactionState.PURCHASED) { // 这里执行购买成功后的逻辑 console.log('Purchase successful'); console.log('Purchase:', purchase); // 手动结束交易,避免重复计费 InAppPurchases.finishTransactionAsync(purchase, true); } }); } else { Alert.alert('错误', '购买状态异常', [{ text: '确定' }]); } }); // 组件卸载时移除监听器,避免内存泄漏 return () => purchaseListener.remove(); }, []);
2. 调整handlePurchase的购买触发逻辑
移除await purchaseItemAsync后的直接处理代码,改为仅触发购买请求:
const handlePurchase = async (productId) => { try { setPressedItemId(productId); const items = [productId]; // 无需Platform.select,参数格式双平台通用 const { responseCode, results } = await InAppPurchases.getProductsAsync(items); console.log('Get products response:', responseCode); console.log('Products:', results[0]?.productId); // 加可选链避免空值报错 if (responseCode === InAppPurchases.IAPResponseCode.OK && results.length > 0) { const { productId } = results[0]; // 触发购买,无需await返回结果,由监听器处理后续逻辑 await InAppPurchases.purchaseItemAsync(productId, null, null, false); // 第四个参数设为false,避免自动结束交易导致监听器无法捕获状态 } else { console.log('Failed to get product information:', responseCode); Alert.alert('错误', '无法购买商品', [{ text: '确定' }]); } } catch (error) { console.log('Failed to purchase:', error); Alert.alert('错误', '无法购买商品', [{ text: '确定' }]); } finally { setPressedItemId(''); } };
额外注意事项
- iOS端需确保测试设备登录沙盒测试账号,且开发者后台已正确配置内购商品
- Android端
purchaseItemAsync可通过await返回结果,但统一用监听器处理能实现双平台逻辑一致 - 必须调用
finishTransactionAsync结束交易,否则会导致用户重复收到计费提示
内容的提问来源于stack exchange,提问作者Wilson
相关产品推荐
相关产品推荐

