React-native-iap: finishTransactionIOS / finishTransaction对iOS无效

创建于 2020-02-19  ·  34评论  ·  资料来源: dooboolab/react-native-iap

版本的react-native-iap

4.4.1

本机版本

0.60.4

您遇到错误的平台(IOS或Android还是两者兼有?)

的iOS

预期行为

调用了finishTransactionIOS(purchaseId)或finishTransaction(purchase)进行订阅后,交易应完成,并且在下次启动时不会再次发送给应用程序。 如果对此有问题,我希望可以将某些内容返回给错误侦听器,或者返回finishTransaction函数之一的承诺,则不会发生任何事情。

Android似乎工作正常。

实际行为

除非调用clearTransactionIOS,否则每次启动都会发出事务,这似乎还有其他副作用。

经过测试的环境(仿真器?真实设备?)

真实设备

重现行为的步骤

  • 创建订阅产品。
  • 购买订阅
  • 模拟后端验证
  • 在该订阅上调用finishTransactionIOS或finishTransaction。 没有效果。

我已经尝试了很多不同的方式,无论我做什么,似乎都没有任何效果,除了清除交易,每次启动都会再次将购买发送给应用程序。 有什么想法吗?我可能正在做什么或理解错误?

ℹ needs more info 📱 iOS 🙏 help wanted 🚶🏻 stale

最有用的评论

@hyochan有关此问题的任何更新? 我们被困了很长时间,无法发布我们的应用程序。

所有34条评论

我有同样的问题。

您可以共享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有什么关系。

我的用例是

  1. 用户1将购买和保费利益应用于他们的帐户。
  2. 用户1退出
  3. 用户2登录

预期结果:

  • 用户1的交易不会通过购买监听程序发出

实际结果

  • 来自用户1的交易记录不会被清除并再次发出。 即使有新用户登录也可能导致不良数据。

这只是为什么要优先考虑此问题的一个示例。 感谢您阅读这篇冗长的评论...

同样在这里

与上述完全相同的问题,即使在断开沙箱/ itunes帐户,重新启动设备,重新安装应用程序之后,也似乎根本没有清除堆栈。

您能否验证finishTransactionRNIapIos.m文件中确实没有执行任何操作?
我刚刚检查了一下,它正确完成了交易。

请检查clearTransactionfinishTransactionWithIdentifier方法并尝试将所有日志放入其中。 尝试找到以下代码。

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上遇到此问题,其中finishTransactionIOSfinishTransaction都没有真正删除这些交易,这使我无法发布应用。 任何更新?

@hyochan尽管我绝对不精通Objective-C,但我在finishTransactionfinishTransactionWithIdentifier添加了一些日志,看来它们运行正常(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有关此问题的任何更新? 我们被困了很长时间,无法发布我们的应用程序。

嘿,看来这个问题最近没有任何活动。 问题是否已解决,还是仍然需要社区的关注? 如果没有其他活动,则可能已关闭此问题。 您也可以将此问题标记为“供讨论”或“良好的第一期”,我将其保留为开放状态。 感谢你的贡献。

此页面是否有帮助?
0 / 5 - 0 等级