5.0.1
0.63.3
iOS
PurchaseUpdatedListener没有被多次调用
PurchaseUpdatedListener在启动时被多次调用,有时甚至在两次调用之间
真实设备(测试飞行和AppStore中的iOS 14、13)
(导航器组件)
const itemSkus = ['01', '02'];
const processNewPurchase = async (purchase) => {
const { productId, transactionReceipt } = purchase;
if (transactionReceipt !== undefined && transactionReceipt) {
//backend call with fetch - validating receipt
if (data.ack === 'success') {
console.log('finished');
await finishTransaction(purchase);
} else if (data.ack === 'failure') {
props.setProcessing(false);
console.log('error');
}
}
};
const getProductsIAP = useCallback(async () => {
await clearProductsIOS();
await clearTransactionIOS();
try {
const result = await initConnection();
const products = await getProducts(itemSkus);
props.setProducts(products);
console.log('result', result);
} catch (err) {
console.warn(err.code, err.message);
}
purchaseUpdateSubscription = purchaseUpdatedListener(
async (purchase) => {
const receipt = purchase.transactionReceipt;
console.log('purchaseUpdatedListener');
if (receipt) {
try {
await processNewPurchase(purchase);
} catch (ackErr) {
console.log('ackErr', ackErr);
}
} else {
console.log('purchaseUpdatedListener error: receipt');
}
},
);
purchaseErrorSubscription = purchaseErrorListener(
(error: PurchaseError) => {
console.log('purchaseErrorListener', error);
console.log(JSON.stringify(error));
},
);
setLoading(false);
}, []);
useEffect(() => {
getProductsIAP();
return () => {
if (purchaseUpdateSubscription) {
purchaseUpdateSubscription.remove();
purchaseUpdateSubscription = null;
}
if (purchaseErrorSubscription) {
purchaseErrorSubscription.remove();
purchaseErrorSubscription = null;
}
};
}, []);
活动会触发相同的购买结果吗?
是的,它以成功的结果/收据触发。 如果没有当前收据,它也会触发,但在验证服务器上失败。
您能否检查一下是否重新渲染了组件? 当组件重新呈现并且侦听器偶尔启动几次时,会出现很多问题。 好吧,这应该放任自流,但是我们需要重提您的案子。
好吧,这是“ NavigatorContainer”,表示我正在设置不同的状态,更新内容等。 但
但这就是为了-退订听众/避免这种情况。
useEffect(() => {
getProductsIAP();
return () => {
if (purchaseUpdateSubscription) {
purchaseUpdateSubscription.remove();
purchaseUpdateSubscription = null;
}
if (purchaseErrorSubscription) {
purchaseErrorSubscription.remove();
purchaseErrorSubscription = null;
}
};
}, []);
好吧,这是“ NavigatorContainer”,表示我正在设置不同的状态,更新内容等。 但是只渲染一个然后“渲染”以更新不同的状态,道具...
但这就是为了-退订听众/避免这种情况。
useEffect(() => { getProductsIAP(); return () => { if (purchaseUpdateSubscription) { purchaseUpdateSubscription.remove(); purchaseUpdateSubscription = null; } if (purchaseErrorSubscription) { purchaseErrorSubscription.remove(); purchaseErrorSubscription = null; } }; }, []);
是的,我也提到了这一点。 刚刚分享了我记得的上一个问题。 我们需要繁殖。
同样,清除事务或尝试使用其他testflight帐户也可能会有所帮助。
const getProductsIAP = useCallback(async () => {
await clearProductsIOS();
await clearTransactionIOS();
.....
在TestFlight,生产和其他设备中进行了测试。
不同的帐户?
是的,结果相同。
奇怪的。 您还可以在我们的IapExample
项目中尝试代码段吗?
我有以下行为。
1)用户购买IAP。
2)purchaseUpdatedListener被调用。
3)用户卸载应用程序。
4)用户返回到应用程序。
5)purchaseUpdatedListener被触发并进入循环。
我正在使用类,但看不到任何重新渲染。
我在“ react-native-iap”:“ 4.4.1”和“ react-native”:“ 0.63.3”。
我曾尝试升级到5.0.0,但是我却得到了相同的行为。
我有以下行为。
- 用户购买IAP。
- PurchaseUpdatedListener被调用。
- 用户卸载应用程序。
- 用户返回到应用程序。
- PurchaseUpdatedListener触发并形成循环。
我正在使用类,但是看不到任何重复。
我处于“ react-native-iap”:“ 4.4.1”和“ react-native”:“ 0.63.3”。
我尝试更新到5.0.0,但是得到了相同的行为。
你好一个问题。 您找到解决方案了吗?
还是同样的问题。 看来purchaseUpdatedListener已损坏。 请尽快修复此问题。 找不到解决方案。
有与此相同的问题。 几个月不固定怎么可能? 这不是关键问题,还是有人找到了解决方法? 同样,如果有帮助,我想我只是将设备从iOS 13升级到iOS 14时才遇到此问题。据我所知,它在iOS 13上运行正常,但我可能会误会。
同样的问题在这里。
我注意到,每次我保存代码并热加载应用程序时,都会发生这种情况。
在这种情况下,将根组件卸载,然后重新安装。
这是我的useIap()
钩子
const useIap=()=>{
const purchaseUpdateSubscription = useRef<EmitterSubscription[]>([]);
const purchaseErrorSubscription = useRef<EmitterSubscription[]>([]);
const init = useCallback(async () => {
console.taggedLog(logTag, 'call iap init');
await RNIap.initConnection();
await RNIap.flushFailedPurchasesCachedAsPendingAndroid();
purchaseUpdateSubscription.current.push(RNIap.purchaseUpdatedListener(async purchase => {
console.taggedLog(logTag, 'purchaseUpdatedListener', purchase);
try {
await finalizePurchase(purchase);
} catch (err) {
handleFailedPurchase();
}
}));
// use array to be sure to not accidentally overwrite subscriptions and lose access to them.
// being an array I can always iterate and call `remove` on them
purchaseErrorSubscription.current.push(RNIap.purchaseErrorListener(error => {
handleFailedPurchase(error);
}));
updateProducts();
return clear;
}, []);
const clear = useCallback(() => {
console.taggedLog(logTag, 'clearing all');
clearPurchaseEventListeners();
}, [clearPurchaseEventListeners]);
const clearPurchaseEventListeners = useCallback(() => {
console.taggedLog(logTag, 'clearing purchase event listener', purchaseUpdateSubscription.current.length, purchaseErrorSubscription.current.length);
purchaseUpdateSubscription.current.forEach(sub => sub.remove());
purchaseErrorSubscription.current.forEach(sub => sub.remove());
purchaseUpdateSubscription.current = [];
purchaseErrorSubscription.current = [];
}, []);
return {init,clear}
}
然后我在根组件中使用此代码
const iap=useIap();
useEffect(() => {
console.log("root component mounted");
iap.init();
return () => {
console.log("root component unmounted");
iap.clear();
};
}, []);
根组件可能碰巧被卸载并重新安装,但是调用了clear
方法,并且我还看到了日志“清除购买事件监听器”,1,1,这意味着它将清除它们。
即使在这种情况下,采购文件purchaseUpdatedListener仍然被多次调用,例如
有什么办法吗?
有同样的问题。
它甚至在不同的屏幕中调用。
有任何更新吗?
对我来说也是一样。 下一次初始化时,它将调用过去的收据。
我遇到了同样的问题,我意识到发生了同样的事情,因为我没有正确地组装和拆卸组件,从而使多个监听器同时打开。
componentWillUnmount() {
if (this.purchaseUpdateSubscription) {
this.purchaseUpdateSubscription.remove();
this.purchaseUpdateSubscription = null;
}
}
每次购买和拆卸组件时,都必须在组装组件时删除侦听器/订阅并添加新组件。
在Android上不会发生此错误,为什么? 我不知道,但是因为它可以在Android上运行,所以会让您认为错误出在iOS而非代码中。
一个可能的解决方法,测试我注意到它有时会显示过去的收据(发送给服务器),所以我要做的就是立即存储收到的每个通知的transactionId,因此,您始终首先检查数据库是否已处理该transactionId,是否因此,如果没有,则忽略(重复),然后继续。 如果通知首先到达应用程序(而不是服务器),则可以放置一些逻辑来控制此操作,即,在单击某个按钮等之后,您应该只收到1。
经过广泛的测试后,它停止了复制,过了一会儿。
是的,有一些粗略的解决方法,但是它们都很漂亮....
请解决此问题。 自2020年10月以来,这绝对是一个至关重要的重大项目错误。
只有一种解决方案,可以使用:Revenuecat;)
有什么办法吗?
收入猫
最有用的评论
还是同样的问题。 看来purchaseUpdatedListener已损坏。 请尽快修复此问题。 找不到解决方案。