React-native-iap: PurchaseUpdatedListenerは、アプリの起動時に1回だけ呼び出され、requestSubscription呼び出しの後に呼び出されることはありません

作成日 2020年04月21日  ·  22コメント  ·  ソース: dooboolab/react-native-iap

react-native-iapのバージョン

4.4.6

react-nativeのバージョン

0.61.5

エラーに直面したプラットフォーム(IOSまたはAndroid、あるいはその両方?)

ios

予想される行動

purchaseUpdatedListener requestSubscription呼び出し後、毎回purchaseUpdatedListener呼び出されます

実際の動作

PurchaseUpdatedListenerは、アプリの起動時に1回だけ呼び出され、requestSubscription呼び出しの後に呼び出されることはありません

テストされた環境(エミュレーター?実デバイス?)

実デバイス

動作を再現する手順

readmeに従って、サブスクリプションをリクエストしてみてください

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

最も参考になるコメント

initConnection()呼び出しを追加しなかったのと同じ問題がありました。
READMEは、ここの太字部分で更新されたようです。

initConnection() iOSでは、canMakePaymentsメソッドを呼び出すだけで、リスナーが正しく機能するために必要な値__を返します。__

この部分「iOSでは、単にcanMakePaymentsを呼び出す」を削除し、基本的な例にinitConnection()を追加する必要があると思います。

例に含まれていなかったので、オプションであると本当に確信しました

購入リスナーを登録する前にinitConnection()追加すると、これが修正されたので、これはおそらく#1002と#756に関連しています。

全てのコメント22件

他に同じ問題を抱えている人はいますか? @StratefinishTransaction電話しましたか?

@hyochanはい、しかし実際にはこの呼び出しはアプリの再起動後に発生します

@hyochan expo-in-app-purchaseパッケージを試しましたが、このような問題はありません-evrythingは問題ないようです

@Strateあなたのコードを見たいです。 自分でエラーを見つけることができません:(

この問題は絶対に腹立たしいです。 これが当てはまらない以前のバージョンはありますか?

他に同じ問題を抱えている人はいますか? @StratefinishTransaction電話しましたか?

購入はfinishTransactionの議論であるため、これはどのように可能でしょうか? したがって、finishTransactionに渡す引数を取得するには、イベントリスナーが必要です。

@Sophrinix finishTransactionはpurchaseUpdatedListener内で呼び出されると予想されます

@hyochan申し訳ありませんが、現在実際のコードがないようです。 expo-in-app-purchaseモジュールに切り替えました。 @Sophrinixでも同じ問題が発生しているよう

ところで、私のコードには特別なことは何もありませんでした。アプリが起動したらすぐにリスナーを登録し、readmeに従ってください。

これは回帰であることがわかります。

次のバージョンを使用すると、すべてが機能します。

"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.3.4から4.4.3までは問題なく動作しますが、問題は4.4.4から始まります。

4.3.4から4.4.3までは問題なく動作しますが、問題は4.4.4から始まります。

ここでも同じですが、4.4.8から4.4.3にダウングレードされ、現在は機能しています。

他に同じ問題を抱えている人はいますか? @StratefinishTransaction電話しましたか?

4.4.0でも同じ問題が発生しています。 purchaseErrorSubscriptionを含め、どのイベントリスナーも呼び出されていません

ダウングレードについて読んでください、私はそれを試してみようとしています...

編集:これは深刻な問題です。理由は次のとおりです。

  • サーバー処理のために購入が送信されるのを防ぎます
  • 誰かが購入をキャンセルしたときの状態のロールバックを防ぎます。

4.3.0が機能していることも確認できます。

RN0.62.2とreact-native-iap4.4.8で数日間同じ問題が発生しました
initConnection()見逃したのは、おそらくREADMEの例から欠落しているためです。

4.4.8にアップグレードしたときにiOSで同じ問題が発生し、一部のサブスクリプションが完了しませんでした。 今のところ、4.4.3にダウングレードすると問題が解決しました。 initConnection()は必須ですか? ドキュメントはそうではないように思わせます

initConnection()呼び出しを追加しなかったのと同じ問題がありました。
READMEは、ここの太字部分で更新されたようです。

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()がREADMEのサンプルコードに含まれていないため、多くの人がエラーに遭遇しています。 私はここにそれを追加しました:#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;

お役に立ててうれしいです。 これは6月から生産されています。
ある時点でObservableからこれに変更されました(typescriptは使用していません)

      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 評価

関連する問題

sanilcgs picture sanilcgs  ·  3コメント

Symyon picture Symyon  ·  5コメント

jvandenaardweg picture jvandenaardweg  ·  4コメント

bakedbean picture bakedbean  ·  5コメント

schumannd picture schumannd  ·  3コメント