React-native-iap: 支払い方法がまだ存在しないときに支払い方法がライブで追加された場合のiOSアプリ内購入の失敗

作成日 2018年10月31日  ·  27コメント  ·  ソース: dooboolab/react-native-iap

react-native-iapのバージョン

react-native-iap": "^2.3.17

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

iOS

予想される行動

finishTransactionが呼び出されている場合にのみ支払いが行われます

実際の動作

クレジットカードなどのお支払い方法を追加した後、金額を検出しています。
しかし、 RNIap.buyProductWithoutFinishTransaction(sku)メソッドに到達しました。

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

実デバイス-iPhone6s

動作を再現する手順

  • デバイスのAppleアカウントが、支払い方法がなしまたは無効な支払いの詳細に設定されていることを確認してください
  • アプリを介してアプリ内購入を行う
  • ユーザーは、有効な支払い方法を追加するために[アカウント設定]ページに移動します
  • お支払い方法は有料ですが、下記のコードで取引領収書が届きません
ComponentDidMount(){
     await RNIap.initConnection();
     await RNIap.consumeAllItems();
     const prod = await RNIap.getProducts(product);

} 

  async componentWillUnmount() {
       RNIap.endConnection()
}

buyProduct(sku){
await RNIap.clearTransaction();

RNIap.buyProductWithoutFinishTransaction(sku)
.then(purchase => {
  // not reached
 if(calltoserverisSuccess){
    RNIap.finishTransaction();
 }
})
.catch(error => {
 // code enters catch case if ever
}}
📱 iOS 🙏 help wanted

最も参考になるコメント

これについてはappleに連絡する必要があると思いますが、 sandbox環境で再現できない別のテストケースがあるのは本当にひどいようです。 問題を理解したい人のために、私は画面を記録しました、そしてあなたはここでクリップを見ることができ@anandwahedこれについてもアップルに連絡できますか? 彼らはそれほど協力的ではないことを私は知っているので、より多くの人々が彼らと接触する方が良いです。 この問題を解決するために集まってみましょう。

全てのコメント27件

申し訳ありませんが、コードに多くの構文エラーがあるようです。 リポジトリ内のサンプルプロジェクトを参照して、最初にコードと比較してください。

@dooboolab
返信ありがとうございます。ここに投稿されているコードは単なる例であり、実際のアプリケーションで使用されているものとは異なります。
私は問題が何であるかを説明しようとします

  1. componentDidMount

    • RNIap.initConnection();呼び出すことによって開始された接続

    • 次に、 RNIap.getProducts(product)呼び出すことにより、商品がフェッチされ、状態で保存されます。

  1. ユーザーが購入ボタンをクリックしたとき

    • RNIap.clearTransaction();は、保留中のトランザクションが残っていないことを確認するためだけに呼び出されます。
    • RNIap.buyProductWithoutFinishTransaction(sku)が成功した場合に呼び出され、サーバーが成功した場合にtrueを指定すると、アプリケーションサーバーへの呼び出しがトリガーされ、 RNIap.finishTransaction();が呼び出されて支払いが完了します。
  2. componentWillUnmount()

    • RNIap.endConnection()接続を終了します。

ユーザーがすでに支払い方法を追加している場合、このプロセスは正常に機能します。 ユーザーが支払い方法を追加していない場合、支払い方法のページを追加する必要があり、 RNIap.finishTransaction();に達する前に金額が請求されます

詳細をありがとう。 あなたの問題は今明らかになっています。 cc @JJMoon

@JJMoon

@ zohaibahmed-22これはサンドボックスのテストケースですか?

@JJMoonいいえ、実際の環境の場合です。

このエラーは、ユーザーがログアウト状態にあるか、クレジットカード情報がない場合に発生することを理解しています。
メソッドが正常に機能する場合、このエラーの原因は別の場所にあります。
このアクションを準備する必要があります。これにより、アプリ、viewDidDisappearなどが終了します。
サンドボックスモードでは、この症状は多少異なる方法で発生します。
新しいサンドボックスアカウントを作成し、最初の購入が機能しない場合。
2回目は、デバイスはログイン状態で正常に動作します。
このエラーの手がかりはありません。

@dooboolab@JJMoonも、iOSコードをupdateTransactionsメソッドでは、 SKPaymentTransactionStateDeferredまたはSKPaymentTransactionStateFailed失敗メッセージを受け取ったときに、 finishTransaction想定していません。

多くの場合、上記のスレッド6431で説明したように、 SKPaymentTransactionStateFailed結果の後にSKPaymentTransactionStatePurchasedが続きます。 Objective-Cコードについてはよくわかりませんので、失敗時にトランザクションをクリアするかどうかを確認してください。

@anandwahed私はあなたに同意します。 それは私のせいです。 そのために残念。
私はAppleのスレッドを調べて、問題を処理します。

@anandwahed失敗したときにfinish transactionに行くのが正しい方法だと思います。 このスレッドを調べてください。 https://stackoverflow.com/questions/11008636/inapp-purchase-skpaymentqueue-finish-transaction-doesnt-work
失敗した場合はレシートがありませんので、ご購入商品はお申込みいただけません。 そして、仕上げ取引は必ずしも「購入」を意味するわけではありません。
その間、スレッド6431を調査します。

スレッド6431(https://forums.developer.apple.com/thread/6431#14562)を読みました
一番下の行。 2015年以降問題は解決されていません。うわー。
この「ストアキットフロー」効果を処理するには、2つの異なる方法があります。

  1. ユーザーアラートを表示しません。
  2. 結果を表示します。

そして私は2つのことを学びました。
A.失敗した場合はfinishTransactionする必要があります。 (私は常にオプションの有無にかかわらず推測します)
B. Storekitフローは、レシートの両方で失敗と成功をもたらします。 (悪いです)

このスレッドを読んで、この問題に戻ることをお勧めします。

どちらを選ぶか(1か2)、それはあなた自身だと思います。
障害対応のためにコールバックが必要になる場合があります。

@JJMoonは、

@ maxs15私はそれを意味しませんでした。 混乱してすみません。
StoreKitフローは、どの購入でも発生する可能性があります。 これはiOSの問題であり、このモジュールではありません。
今のところ、私にも手がかりはありません。 これは、ネイティブiOSアプリで発生します。 正しい?
私たちは自由な時間にもっと掘り下げます。

今日、私はこの問題を生成したので、この問題をデバッグしようとしました。 支払いfinishTransanctionは完了しましたが、payMethodが変更されたときにcallback取得していません。 console.log書き込みをデバッグしようとしましたが、 dev環境で実際の請求をテストできませんreal purchase debugできるように、このプロセスをデバッグする方法を誰かに提案してもらえますか? これをsandboxモードで使用する必要がありますか? サンドボックスで完全に機能しているので、これをデバッグする方法がわかりません。 これは非常に消極的です。

これを修正することは非常に重要だと思うので、いくつかのアイデアを集めましょう。

サンドボックス以外のユーザーで購入しようとすると、常にこのエラーが発生します。

@hyochan実サーバー(自分のサーバー)に接続する場合、デバッグモードかリリースモードかは関係ありません。 2つの選択肢があると思います。

  1. Xcodeのデバッグモードで実際のデバイスで実行します。 JSコンソールログを使用します。
  2. Xcodeのリリースモードで実際のデバイスで実行します。 Objective-cコードでNSLogを使用します。
    どちらの方法でも機能するはずです。

@JJMoonええ、私はすでにそれを理解しましたが、それでも私はiosでライブ購入テストを行うことができませんでした。 このスタックオーバーフローは本当ですか? では、どうすればこの問題を解決できますか? ライブ購入をテストする必要があります。

この問題に直面している人は誰でも、私は彼ら全員がそうしていると確信しています、この問題にどのように遭遇するかについて私たちに考えを教えてください。 問題のタイトルに記載されているin-app purchase fail when payment method added live 。 どうすればこれをデバッグできますか? @anandwahedこの問題についてアップルに連絡したことはありますか?

@hyochanいいえ、Appleサポートには連絡していません。

これについてはappleに連絡する必要があると思いますが、 sandbox環境で再現できない別のテストケースがあるのは本当にひどいようです。 問題を理解したい人のために、私は画面を記録しました、そしてあなたはここでクリップを見ることができ@anandwahedこれについてもアップルに連絡できますか? 彼らはそれほど協力的ではないことを私は知っているので、より多くの人々が彼らと接触する方が良いです。 この問題を解決するために集まってみましょう。

今日、私たちはアップルから回答を受け取りました。 failure後にコールバックが再び返される場合があります。 #348で回避策に取り組んでいますが、これは非常に厄介な問題になる可能性があります。

この問題の回避策を作成しようとして、 2.4.0-beta1にリリースしました。 PR #348がこのバージョンに追加されており、この機能のreadmeも確認でき

私はこれをライブ購入でテストしましたが、機能しているようです。 ただし、リスナーを追加する必要があるのは、失敗があった場合のみであることに注意してください。そうしないと、リスナーが複製されて成功する可能性があります。

みんな、この問題に時間を費やしてくれてありがとう! 🙏

addAdditionalSuccessPurchaseListenerIOS使用法については、現在のドキュメントをより明確にする必要があると思います。 それは私が#414で対処しようとしたものです。

しかし、これはAPIの改善の余地も残していると思います。 いわゆる「ストアキットフロー」にうまく対応できるAPIの変更について話し合うことを歓迎しますか? たとえば、RxJSを使用している可能性があります。

const observable = RNIap.buyProduct('com.example.coins100')
                        .subscribe(
                            purchase => console.log(purchase), // successful payment
                            err => console.log(err) // err.code and err.message are available
                        )

または、iOSの追加サブスクリプションをより適切に隠す何か別のものですか?

@Edgpaezこれはすばらしいことですが、 androidで行われる購入の動作が変わります。 このモジュールのversion 32019調査できるといいのですが。

こんにちは@ hyochan 、AFAICT、パッケージの内部動作を変更する必要はありません。公開インターフェースのみを変更します。 BuyItemByTypeメソッドでindex.jsでその上にRxを少し追加するだけです。

たとえば、これはindex.jsにあります。

export const buyProduct = (sku) => Platform.select({
  android: () => Observable.of(RNIapModule.buyItemByType(ANDROID_ITEM_TYPE_IAP, sku, null, 0)), // returns an observable that emits when the RNIapModule.buyItemByType promise resolves
  ios: ... // ios would do the same but taking into account the usage of addAdditionalSuccessPurchaseListenerIOS
})();

私の目標は、この特定の実装ではなく、「ストアキットフロー」に固有の詳細を非表示にすることです。
これは良い考えだと思いますか?
PRに興味がありますか?

@Edgpaezわかりました。 詳細がわかりました。 ただし、 RxJS追加することは、それがなくてもカバーできると思うので、 featureを実装するには少し多すぎると感じます。

また、以下は何か違うと思います。

RNIap.buyProduct('com.example.coins100')
                        .subscribe(
                            purchase => console.log(purchase), // successful payment
                            err => console.log(err) // err.code and err.message are available
                        )

以下のような2つのアイテムについてbuyProductを呼び出すと、

RNIap.buyProduct('com.example.coins100');
RNIap.buyProduct('com.example.coins200');

どちらが最初に終了するかは保証できないため、これをネイティブでsendEventからJSまで処理する必要があると思います。

実装は次のようになります。

RNIap.buyProduct('com.example.coins100');
RNIap.buyProduct('com.example.coins200');

// receiving events
const subs =  RNIap.purchaseUpdateListener(purchase => {
  ...
});

見逃したことがあれば教えてください。

#423でさらに議論を処理しましょう

このページは役に立ちましたか?
0 / 5 - 0 評価