Android可消耗内购isAcknowledged始终为false问题求助
React Native IAP可消耗商品购买后
acknowledged未更新及错误码8问题修复 核心问题定位
- 购买监听回调中错误使用外部
currentPurchase变量,而非回调传入的实时purchase实例,导致操作的不是当前完成的交易 - 错误码8对应Android端商品已被拥有(
ERROR_ITEM_ALREADY_OWNED),因可消耗商品未被正确消耗,重复购买时触发该错误 finishTransaction执行后打印的是原purchase对象副本,不会自动更新acknowledged状态,需重新查询交易状态确认
具体修复方案
1. 修正购买监听逻辑(Home.tsx)
将回调内的currentPurchase替换为传入的purchase实例,确保操作当前触发的交易:
import { purchaseUpdatedListener, finishTransaction, Purchase } from 'react-native-iap'; useEffect(() => { const subscriptionListener = purchaseUpdatedListener( async (purchase: Purchase) => { // 仅处理购买成功的交易(purchaseState=0代表成功) if (purchase.purchaseState === 0) { try { // 优先将收据发送至服务器验证(必须在消耗前执行,避免验证失败无法回滚) // await sendReceiptToServer(purchase.transactionReceipt); // 执行可消耗商品的交易完成/消耗操作 await finishTransaction({ purchase, isConsumable: true, }); console.log('交易已成功消耗'); // 如需确认状态,可调用getAvailablePurchases重新查询 } catch (error) { console.error('完成交易失败:', error); } } }, ); return () => { subscriptionListener.remove(); }; }, []);
2. 处理Android端未消耗的遗留交易(App.tsx)
在初始化阶段主动处理未消耗的可消耗商品,避免错误码8:
import { clearTransactionIOS, endConnection, flushFailedPurchasesCachedAsPendingAndroid, initConnection, getAvailablePurchases, } from 'react-native-iap'; useEffect(() => { const initIAP = async () => { try { await initConnection(); if (Platform.OS === 'android') { await flushFailedPurchasesCachedAsPendingAndroid(); // 主动查询并处理未消耗的可消耗商品 const purchasedItems = await getAvailablePurchases(); for (const item of purchasedItems) { // 替换为你的虚拟币商品ID,仅处理成功状态的交易 if (item.productId === 'coins_pack_1' && item.purchaseState === 0) { try { // await sendReceiptToServer(item.transactionReceipt); await finishTransaction({ purchase: item, isConsumable: true, }); } catch (e) { console.error('处理遗留交易失败:', e); } } } } else { await clearTransactionIOS(); } } catch (error) { console.log('初始化IAP失败: ', error); } }; initIAP(); return () => { endConnection(); }; }, []);
3. 优化购买请求逻辑(BuyCoins.tsx)
完善错误处理,针对错误码8给出提示:
import { requestPurchase } from 'react-native-iap'; const handleProductPurchase = async (sku: string) => { try { setIsLoading(true); const params = Platform.OS === 'android' ? { skus: [sku] } : { sku, andDangerouslyFinishTransactionAutomaticallyIOS: false }; await requestPurchase(params); } catch (error) { errorLog({ message: '发起购买失败', error }); // 针对Android错误码8,提示用户自动处理未消耗商品 if (Platform.OS === 'android' && (error as any).code === 8) { console.log('检测到未消耗的商品,正在自动处理'); // 可手动触发一次遗留交易查询处理 } } finally { setIsLoading(false); } };
关键注意事项
- 收据验证优先:调用
finishTransaction前必须将交易收据发送至服务器验证,防止恶意伪造购买 - 不依赖原对象状态:
finishTransaction执行后,原purchase对象的acknowledged不会自动更新,需通过getAvailablePurchases重新查询 - 测试环境配置:使用Google Play测试账号时,确保商品配置为可消耗型,且测试账号已加入许可列表
内容的提问来源于stack exchange,提问作者Chaudhry Talha
相关产品推荐
相关产品推荐

