4.4.1
0.60.4
的iOS
调用了finishTransactionIOS(purchaseId)或finishTransaction(purchase)进行订阅后,交易应完成,并且在下次启动时不会再次发送给应用程序。 如果对此有问题,我希望可以将某些内容返回给错误侦听器,或者返回finishTransaction函数之一的承诺,则不会发生任何事情。
Android似乎工作正常。
除非调用clearTransactionIOS,否则每次启动都会发出事务,这似乎还有其他副作用。
真实设备
我已经尝试了很多不同的方式,无论我做什么,似乎都没有任何效果,除了清除交易,每次启动都会再次将购买发送给应用程序。 有什么想法吗?我可能正在做什么或理解错误?
我有同样的问题。
您可以共享ackResult
吗?
try {
const ackResult = await finishTransaction(purchase);
console.log('ackResult', ackResult);
} catch (ackErr) {
console.warn('ackErr', ackErr);
}
@hyochan
就我而言:
ackResult undefined
@hyochan
就我而言:
ackResult undefined
同样在这里
同样在我的情况下,返回值是不确定的(具有沙箱用户的真实设备)。
它看起来与#366有关。 同样对于ios
finishTransaction
不会返回任何内容。
你们都可以专注于#366并回来进行更新吗?
它看起来与#366有关。 同样对于
ios
finishTransaction
不会返回任何内容。
你们都可以专注于#366并回来进行更新吗?
只是要澄清一下-因为#366是关于测试的,您是否建议在不需要clearTransactionIOS的情况下在生产中可以正常工作?
@hyochan当我基本上使用沙盒帐户测试调试配置时,我从服务器收到有关购买的服务器通知(苹果)。 问题是,过了一段时间,我的客户侦听器又收到了有关购买的另一条通知,但具有不同的transactionId,即使购买操作仅发生了一次,也似乎正确完成了先前的交易很麻烦。 在Android上,一切正常,我认为与#366无关,因为我没有任何问题可以使用沙盒帐户测试购买过程。
tsx
useEffect(()=> {
PurchaseUpdateSubscription.current = PurchaseUpdatedListener(
异步(购买:InAppPurchase | SubscriptionPurchase)=> {
常量收据= Purchase.transactionReceipt;
如果(收到){
尝试{
等待myBackendHandler({
用户,
购买,
});
const result =等待RNIap.finishTransaction(purchase,false);
console.log('result',result);
}抓住(e){
// 去做
}
}
}
);
return()=> {
如果(purchaseUpdateSubscription.current){
PurchaseUpdateSubscription.current.remove();
PurchaseUpdateSubscription.current = null;
}
};
},[]);
``
嘿,团队,感谢您在此库上所做的所有辛勤工作,它确实使我们的生活更加轻松。 我之所以发表评论,是因为这个问题尚未解决,并且看不到未结算的旧交易与#366有什么关系。
我的用例是
预期结果:
实际结果
这只是为什么要优先考虑此问题的一个示例。 感谢您阅读这篇冗长的评论...
同样在这里
与上述完全相同的问题,即使在断开沙箱/ itunes帐户,重新启动设备,重新安装应用程序之后,也似乎根本没有清除堆栈。
您能否验证finishTransaction
在RNIapIos.m
文件中确实没有执行任何操作?
我刚刚检查了一下,它正确完成了交易。
请检查clearTransaction
或finishTransactionWithIdentifier
方法并尝试将所有日志放入其中。 尝试找到以下代码。
RCT_EXPORT_METHOD(clearTransaction) {
NSArray *pendingTrans = [[SKPaymentQueue defaultQueue] transactions];
NSLog(@"\n\n\n *** clear remaining Transactions. Call this before make a new transaction \n\n.");
for (int k = 0; k < pendingTrans.count; k++) {
[[SKPaymentQueue defaultQueue] finishTransaction:pendingTrans[k]];
}
-(void)finishTransactionWithIdentifier:(NSString *)transactionIdentifier {
SKPaymentQueue *queue = [SKPaymentQueue defaultQueue];
for(SKPaymentTransaction *transaction in queue.transactions) {
if([transaction.transactionIdentifier isEqualToString:transactionIdentifier]) {
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
}
}
我无法将这个问题向前推进,因为我不知道发生了什么。 我希望有人可以在他们的环境中调试东西并分享🙏
有关此问题的任何更新?
,我也遇到了这个问题。
同样在这里finishTransactionIOS / finishTransaction这在IOS中不起作用
我似乎也经历过同样的事情。
IAP的购买已成功完成,但是对finishTransaction
的最终调用返回undefined
。
// Finish transaction
const ackResult = await finishTransaction(purchase);
console.log("Ack result: ", ackResult); // Ack result: undefined
_使用App Store沙箱环境的“ iPhone 6s”真实设备。
finishTransaction的预期结果是什么? undefined
是一个好的结果,还是我应该期望其他的东西?
我也在iOS上遇到此问题,其中finishTransactionIOS
或finishTransaction
都没有真正删除这些交易,这使我无法发布应用。 任何更新?
@hyochan尽管我绝对不精通Objective-C,但我在finishTransaction
和finishTransactionWithIdentifier
添加了一些日志,看来它们运行正常(id正在传递和匹配)。 我唯一能想到的是[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
实际上没有连接到StoreKit并完成交易吗? 我真的不知道从这里去哪里,但希望这对您调试有帮助
您是否还在处理来自App Store的订阅状态通知? 就我而言,在确保服务器正确处理所有通知事件并以200响应之前,我一直遇到此问题。
@espenjanson有趣。 不,我不是。 但实际上我昨天才切换到expo的InAppPurchases模块,现在一切正常。
@lachlanglen没关系。 这仅仅是运气(?)之类的罢工。 构建了该应用程序的另一个版本,问题再次出现。 想做同样的事情,但有点担心博览会回购协议维护得不好。
我正在研究它,它的返回值是未定义的,这是正确的,因为finishTransactions调用并不意味着返回obj-c中的任何内容。
我已经进行了一些测试,就我而言,它似乎正确完成了它们(简单的测试,拉出未决的交易,如果没有,则工作正常)
@espenjanson我不知道是什么使您认为Expo软件包的维护
有什么办法可以解决这个问题?
即使有新的沙箱用户,我也已经在TestFlight上对其进行了测试,但这种情况一直在发生。
我的purchaseUpdateListener
继续收到“旧”交易。
我正在使用自动更新订阅,因此呼叫finishTransaction(purchase,false)
。
调用的结果是undefined
。
任何人都可以提供解决方法或解释这种情况的原因吗?
@zatloeri这显然是期望的行为。 我花了一段时间才意识到这一点。 App Store将在StoreKit中放入新的续费收据,以触发观察者。 您应该处理该收据并完成交易。
https://developer.apple.com/videos/play/wwdc2018/705/
https://developer.apple.com/videos/play/wwdc2020/10671
(在Safari中观看高清质量)
@ziyoshams感谢您的快速答复以及我将在稍后介绍的资源。
但是首先,我只想指出一件事,因为我认为我没有使它变得有说服力。
您所描述的内容对我来说似乎是合乎逻辑的,我希望这会发生,但令我困惑的是:
产品A已过期receipt validation
。
当我启动或前台应用时,我收到产品A的一笔旧交易(从前一天开始)。
然后,下次我再次使该应用程序前台时,我又收到了产品A的另一笔旧交易(可能比之前的不确定,可能是新的交易)。
在另一个前景,可能在另一个前景,依此类推。
如果订阅已经过期,我希望所有这些都可以在一个应用程序上启动。
这也是预期的行为吗,还是发生了一些可疑的事情?
@zatloeri每个尚未完成的事务都会显示在该队列中,即使它已过期也是如此。 对于每月订阅,您应该每5分钟左右收到该收据。 就像您购买东西然后第二天再回到应用程序一样,您将同时获得5-6张收据。 我强烈建议您观看那些WWDC视频。 他们是如此有帮助。
我在iOS上遇到同样的问题,交易未完成,因此,每次启动应用程序时,队列都不会空着,收据也重新出现。 我已经在服务器端验证了收据,然后完成了交易。 请在下面查看我的代码
我在下面提到了我的代码片段...
```
导入RNIap,{
在应用程序内购买,
产品,
PurchaseError,
订阅,
订阅购买,
finishTransaction,
finishTransactionIOS,
PurchaseErrorListener,
PurchaseUpdatedListener,
clearTransactionIOS,
}来自“ react-native-iap”;
异步componentDidMount(){
const result =等待RNIap.initConnection();
const itemSubs = Platform.select({
安卓: [
get(this.props,'subscriptionStore.subscription.android_product_id',null)
],
ios:[
get(this.props,'subscriptionStore.subscription.ios_product_id',null)
]
});
const subscriptions =等待RNIap.getSubscriptions(itemSubs);
PurchaseUpdateSubscription = PurchaseUpdatedListener(
异步(购买)=> {
常量收据= Purchase.transactionReceipt;
让订阅= {
subscription_id:get(this.props,'subscriptionStore.subscription.id',null)
};
如果(Platform.OS ==='ios'){
订阅= {
...订阅,
order_id:get(purchase,'transactionId',null),
Purchase_token:get(购买,“ originalTransactionIdentifierIOS”,null),
收据:get(purchase,'transactionReceipt',null),//(将其存储在TEXT中)
os:'IOS'
}
}否则,如果(Platform.OS ==='android'){
const data = JSON.parse(receipt);
订阅= {
...订阅,
order_id:get(data,'orderId',null),
Purchase_token:get(数据,“ purchaseToken”,null),
os:'ANDROID'
}
}
尝试{
finishTransaction(purchase,false); //这里是临时的,以后会成功使用。
this.props.notificationStore.showToast('已成功订阅。请稍候...','success',5000);
const resp =等待this.props.subscriptionStore.onPurchase(subscription); //在服务器端验证交易。
if(resp.success){//成功响应
this.props.userStore.setUser({is_premium:1});
this.props.navigation.replace('FixFooter');
}
} catch(错误){
console.log(“ onPurchase API错误:”,错误);
}
}
)
PurchaseErrorSubscription = PurchaseErrorListener(
异步(错误)=> {
console.log('购买错误:',错误);
}
)
}
/ * on购买按钮* /
异步onPurchase(){
尝试{
const request =等待RNIap.requestSubscription(Platform.OS ==='android'吗?
get(this.props,'subscriptionStore.subscription.android_product_id',null):
get(this.props,'subscriptionStore.subscription.ios_product_id',null))
} catch(错误){
console.log('错误:',错误)
}
}
@ sufyan297您可以从服务器端代码中共享一个代码段吗? 我也在尝试设置收据验证工具,但Apple的文件非常混乱
@ziyoshams您是否还使用expo iap模块finishTransaction方法获得null?
@bcbcbcbcbcl我没有使用expo模块。
+1给我返回未定义
@hyochan有关此问题的任何更新? 我们被困了很长时间,无法发布我们的应用程序。
嘿,看来这个问题最近没有任何活动。 问题是否已解决,还是仍然需要社区的关注? 如果没有其他活动,则可能已关闭此问题。 您也可以将此问题标记为“供讨论”或“良好的第一期”,我将其保留为开放状态。 感谢你的贡献。
最有用的评论
@hyochan有关此问题的任何更新? 我们被困了很长时间,无法发布我们的应用程序。