React-native-iap: PurchaseUpdatedListener在应用启动时仅被调用一次,并且在requestSubscription调用之后从未调用

创建于 2020-04-21  ·  22评论  ·  资料来源: dooboolab/react-native-iap

版本的react-native-iap

4.4.6

本机版本

0.61.5

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

ios

预期行为

每次调用requestSubscription之后,每次调用purchaseUpdatedListener

实际行为

PurchaseUpdatedListener在应用启动时仅被调用一次,并且在requestSubscription调用之后从未调用

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

真实设备

重现行为的步骤

只需遵循自述文件并尝试请求订阅

📱 iOS 🕵️‍♂️ need more investigation 🙏 help wanted

最有用的评论

遇到与我未添加initConnection()调用相同的问题。
自述文件似乎只是在此处用粗体部分进行了更新:

initConnection()在iOS上,它将仅调用canMakePayments方法并返回值__,这是侦听器正常工作所必需的。__

我认为应该删除“在iOS上,它将仅调用canMakePayments”这一部分,并且还将initConnection()添加到基本示例中

我真的坚信它是可选的,因为在示例中它不是

在注册购买监听器之前添加initConnection()对我来说已经解决了,所以这可能与#1002和#756有关

所有22条评论

还有其他人有同样的问题吗? @Strate您给finishTransaction打电话

@hyochan是的,但实际上此调用在应用程序重启后发生

@hyochan我已经尝试过expo-in-app-purchase软件包,并且没有这样的问题-evrything似乎很好

@Strate我想看你的代码。 我自己找不到任何错误:(

这个问题绝对令人发指。 是否有不是这种情况的先前版本?

还有其他人有同样的问题吗? @Strate您给finishTransaction打电话

由于购买是finishTransaction中的一个参数,这怎么可能? 因此,您需要事件监听器来获取传递给finishTransaction的参数。

@Sophrinix finishTransaction有望在purchaseUpdatedListener内部调用

@hyochan对不起,但看来我现在没有实际的代码,我切换到expo-in-app-purchase模块。 看起来@Sophrinix遇到相同的问题。

顺便说一句,我的代码中没有什么特别的:应用程序启动后立即注册侦听器,然后按照自述文件进行操作。

事实证明,这是一种回归。

如果使用以下版本,则一切正常:

"react": "16.8.1",
"react-native": "^0.59.10",
"react-native-iap": "4.3.0",

问题是当您尝试使用react-native-iap 4.4.4和版本的react-native之前的0.60

@Sophrinix我刚刚尝试过requestPurchase在我这边,一切似乎都正常。 您能否分享一些代码?

另外,请再次检查您是否致电initConnection 。 这是最近更新中的重要更改,现在必须像android一样在iOS调用它。

我确认还原到4.3.0是可行的。 我一直在使用最新版本,在调试超过1小时的过程中一直试图找到问题。

如果我可以添加,从4.4.3 4.3.44.4.3工作正常,则问题出在4.4.4

如果我可以添加,从4.4.3 4.3.44.4.3工作正常,则问题出在4.4.4

同样在这里,从4.4.8降级到4.4.3,现在可以使用了!

还有其他人有同样的问题吗? @Strate您给finishTransaction打电话

我在4.4.0上遇到了同样的问题-没有调用purchaseErrorSubscription

刚读过有关降级的信息,我将尝试...

编辑:这是一个严重的问题,因为:

  • 它可以防止购买交易被发送到服务器进行处理
  • 当有人取消购买时,它可以防止状态回滚。

我还可以确认4.3.0在工作。

我在RN 0.62.2和react-native-iap 4.4.8上遇到了相同的问题几天
我以某种方式错过了initConnection()可能是因为自述文件中的示例缺少了它

升级到4.4.8时,iOS上出现了相同的问题,导致某些订阅未完成。 降级到4.4.3可以解决此问题。 是否必须使用initConnection()? 该文档使它看起来好像不是

遇到与我未添加initConnection()调用相同的问题。
自述文件似乎只是在此处用粗体部分进行了更新:

initConnection()在iOS上,它将仅调用canMakePayments方法并返回值__,这是侦听器正常工作所必需的。__

我认为应该删除“在iOS上,它将仅调用canMakePayments”这一部分,并且还将initConnection()添加到基本示例中

我真的坚信它是可选的,因为在示例中它不是

在注册购买监听器之前添加initConnection()对我来说已经解决了,所以这可能与#1002和#756有关

我使用的是4.4.9,这张票所描述的问题也正在发生。
侦听器仅在启动时被调用,但是如果我设置它然后执行购买,则不会调用它。
在查看react-native-iap/index.ts并弄清楚那是内部发生的情况之后,我直接订阅了本地事件来解决了该问题。
这可以随时进行,并且会持续下去。 (只需确保仅完成一次)

import { NativeModules, NativeEventEmitter } from 'react-native';
import { Observable } from 'rxjs/Observable';

const purchaseEvent = Observable.fromEvent(
  new NativeEventEmitter(NativeModules.RNIapIos),
  'purchase-updated'
);
const purchaseSubscription = purchaseEvent.subscribe((transactionData) => {
  // Trigger server receipt validation here...
});
const errorEvent = Observable.fromEvent(
  new NativeEventEmitter(NativeModules.RNIapIos),
  'purchase-error'
);
const errorSubscription = errorEvent.subscribe((errorData) => {
  // Handle errors here...
});

许多人遇到错误,因为initConnection()不在自述文件的示例代码中。 我在这里添加了它:#1088,但是如果有人可以再次检查我的代码,将不胜感激。 (我仍然没有使我的代码完全正常运行,因此我对此不太有信心...)

我在v5.1.1上也遇到了这个问题。 initConnection不能解决。 侦听器回调永远不会在PurchaseUpdate上触发。 虽然可以在android上正常工作。 我的解决方法是像@mrozanski一样使用Observables。

import React, { useContext, useEffect, useState } from 'react';
import { Alert, EmitterSubscription, Platform, NativeEventEmitter,
    NativeModules } from 'react-native';
import { connect } from 'react-redux';
import RNIap, {
    InAppPurchase,
    PurchaseError,
    SubscriptionPurchase,
    purchaseErrorListener,
    purchaseUpdatedListener,
} from 'react-native-iap';
import { Observable, Subscription } from 'rxjs';

const RNIAPEvent = new NativeEventEmitter(NativeModules.RNIapIos);
const purchaseObservable = new Observable((subscriber) => {
    RNIAPEvent.addListener('purchase-updated', (event) => {
        subscriber.next(event);
    })
})

const RNIAPErrorEvent = new NativeEventEmitter(NativeModules.RNIapIos);
const purchaseErrorObservable = new Observable((subscriber) => {
    RNIAPErrorEvent.addListener('purchase-error', (event) => {
        subscriber.next(event);
    })
})


const Wrapper = ({ ...props }) => {

    let purchaseUpdateSubscription: EmitterSubscription | Subscription | null = null;
    let purchaseErrorSubscription: EmitterSubscription | Subscription | null = null;

    const validateTransaction = async (purchase: SubscriptionPurchase) => {    
        return new Promise(async (resolve) => {
              //resolve(validationResponseFromYourBackend)
        }
    }

    const handleSubEvent = async (purchase: InAppPurchase | SubscriptionPurchase) => {
        const receipt = purchase.transactionReceipt;
        const purchaseToken = purchase.purchaseToken
        if (receipt) {
            try {
                const result = await validateTransaction(purchase);
                if (result.status === 200) {
                    RNIap.acknowledgePurchaseAndroid(purchaseToken).then(() => {
                        RNIap.finishTransaction(purchase, false)
                        .then(() => giveYourUserValue())
                        .catch((e) => {
                            //
                        })
                    })
                }
            } catch (err) {
                //
            }
        }
    }


    useEffect(() => {
        RNIap.initConnection()
            .then(() => {
                RNIap.flushFailedPurchasesCachedAsPendingAndroid().catch(() => {
                    // exception
                    })
                .then(() => {
                    if (Platform.OS === 'ios') {
                        //Documented implementation has issues purchaseUpdatedListener callback
                        purchaseUpdateSubscription = purchaseObservable.subscribe((purchase) => {
                            console.log('purchase observable', purchase)
                            handleSubEvent(purchase);
                        });

                        purchaseErrorSubscription = purchaseErrorObservable.subscribe((error) => {
                            console.log('purchaseErrorListener', error);
                        })

                    } else {
                        //for android use the documented method. Callbacks work.
                        purchaseUpdateSubscription = purchaseUpdatedListener(
                            (purchase: InAppPurchase | SubscriptionPurchase) => {
                                handleSubEvent(purchase);
                            }

                        );
                        purchaseErrorSubscription = purchaseErrorListener(
                            (error: PurchaseError) => {
                               console.log('purchaseErrorListener', error);
                            },
                        );
                    }

                })
            })
        return () => {
              // clear your listeners
             //eg if Subscription purchaseErrorSubscription.unsubscribe() 
            //eg if EmitterSubscription purchaseErrorSubscription.remove() 
        }
    }, []);

    return (
        <InAppSubContext.Provider
            value={{
                someValueYouWantPassedDown: 'theValue'
            }}
        >
            {props.children}
        </InAppSubContext.Provider>
    )
}

const mapState = (state) => ({ someProps: 'yeah' });

const InAppSubscriptionManager = connect(mapState)(Wrapper);

export default InAppSubscriptionManager;

现在,您可以使用此代码将应用包装到App.tsx


import InAppSubscriptionManager from './path/to/inAppSubscriptionManager';
const App = () => {

    return (
        <Provider store={store}>
                <InAppSubscriptionManager>

                    <AppNavigator />

                </InAppSubscriptionManager>
        </Provider>
    );
}

export default App;

很高兴它有所帮助。 自六月以来,我们已经开始生产该产品。
在某些时候它确实从Observable变为了(我们没有使用打字稿)

      const purchaseEvent = new NativeEventEmitter(NativeModules.RNIapIos);
      const subscription = purchaseEvent.addListener(
        'purchase-updated',
        transactionData => {
          console.log('IAP-LOG purchase-updated');
          dispatch(validateRecepit(transactionData));
        }
      );
      const errorSubscription = purchaseEvent.addListener(
        'purchase-error',
        data => {
          crashlytics().log(`Purchase error ${JSON.stringify(data)}`);
          console.log('IAP-LOG purchase-error', data);
        }
      );
    };
此页面是否有帮助?
0 / 5 - 0 等级