4.4.1
0.60.4
iOS
サブスクリプションに対してfinishTransactionIOS(purchaseId)またはfinishTransaction(purchase)を呼び出すと、トランザクションは終了し、次回の起動時にアプリに再度発行されないようにする必要があります。 これに問題があった場合、エラーリスナーに返されるか、finishTransaction関数の1つからの約束で、何も起こらないと思います。
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サンドボックスアカウントでデバッグ構成をテストしていると、基本的にサーバーからサーバーへの通知(Apple)から購入に関する通知が
`` `tsx
useEffect(()=> {
PurchaseUpdateSubscription.current = PurchaseUpdatedListener(
async(購入:InAppPurchase | SubscriptionPurchase)=> {
const receive = Purchase.transactionReceipt;
if(領収書){
{を試してください
myBackendHandler({
ユーザー、
購入、
});
const result = await RNIap.finishTransaction(purchase、false);
console.log( '結果'、結果);
} catch(e){
// TODO
}
}
}
);
return()=> {
if(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
_AppStoreサンドボックス環境を使用した実デバイス「iPhone6s」。_
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で何も返すことを意図していないため、undefinedを返すのは正しいことです。
私はいくつかのテストを行いましたが、私の場合、それらは正しく終了しているようです(単純なテスト、pendingTransactionsのプル、何もない場合は正常に機能しています)
@espenjansonExpoパッケージが適切に管理されていないと思われる理由がわかりません。 Expoはごく最近彼らのiapモジュールをリリースしたと思います。 iapを実装しているときにexpoにiapモジュールがあることを知っていたら、よく考えずに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でHD品質を確認してください)
@ziyoshams迅速な返信と、少し詳しく説明するリソースに感謝します。
しかし、最初に私がそれを出現させたとは思わない原因の1つを指摘したいと思います。
あなたが説明していることは私には論理的であるように思われ、私はこれが起こると思っていましたが、私を困惑させるのはこれです:
receipt validation
確認したとおり、製品Aの有効期限が切れています。
アプリを起動またはフォアグラウンドすると、製品Aの古い(前日からの)トランザクションが1つ届きます。
次に、次にアプリをフォアグラウンドにすると、製品Aの古い(前のトランザクションよりも少し新しいかもしれませんが、確かではありません)トランザクションを受け取ります。
別の前景、おそらく別の前景など。
サブスクリプションの有効期限がすでに切れている場合は、1つのアプリですべてを開始できると思います。
これも予想される動作ですか、それとも何か怪しいことが起こっていますか?
@zatloeri終了していないすべてのトランザクションは、期限切れになった場合でも、そのキューに表示されます。 毎月のサブスクリプションの場合、5分ごとにその領収書を取得する必要があります。 何かを購入して翌日アプリに戻った場合のように、同時に5〜6個のレシートを受け取ります。 これらのWWDCビデオを視聴することを強くお勧めします。 彼らはとても役に立ちます。
iOSでも同じ問題が発生しています。トランザクションが完了していないため、キューが空にならず、アプリが起動するたびにレシートが再表示されます。 サーバー側で受信を確認し、トランザクションを終了しました。 以下の私のコードを見てください
以下に私のコードのスニペットをいくつか挙げました...
`` `
RNIapをインポート、{
InAppPurchase、
製品、
PurchaseError、
サブスクリプション、
SubscriptionPurchase、
finishTransaction、
finishTransactionIOS、
PurchaseErrorListener、
PurchaseUpdatedListener、
clearTransactionIOS、
} from'react-native-iap ';
非同期componentDidMount(){
const result = await 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 = await RNIap.getSubscriptions(itemSubs);
PurchaseUpdateSubscription = PurchaseUpdatedListener(
非同期(購入)=> {
const receive = Purchase.transactionReceipt;
サブスクリプション= {
Subscription_id:get(this.props、 'subscriptionStore.subscription.id'、null)
};
if(Platform.OS === 'ios'){
サブスクリプション= {
...サブスクリプション、
order_id:get(purchase、 'transactionId'、null)、
Purchase_token:get(purchase、 'originalTransactionIdentifierIOS'、null)、
領収書:get(purchase、 'transactionReceipt'、null)、//(テキストに保存)
os: 'IOS'
}
} else if(Platform.OS === 'android'){
const data = JSON.parse(receipt);
サブスクリプション= {
...サブスクリプション、
order_id:get(data、 'orderId'、null)、
Purchase_token:get(data、 'purchaseToken'、null)、
os: 'ANDROID'
}
}
{を試してください
finishTransaction(purchase、false); //これは一時的なものです。後で成功するように配置されます。
this.props.notificationStore.showToast( '正常にサブスクライブしました。お待ちください...'、 '成功'、5000);
const resp = await this.props.subscriptionStore.onPurchase(subscription); //サーバー側でトランザクションを確認します。
if(resp.success){//成功応答
this.props.userStore.setUser({is_premium:1});
this.props.navigation.replace( 'FixFooter');
}
} catch(error){
console.log( "onPurchase APIエラー:"、エラー);
}
}
)
PurchaseErrorSubscription = PurchaseErrorListener(
非同期(エラー)=> {
console.log( '購入エラー:'、エラー);
}
)
}
/ * onPurchaseボタン* /
非同期onPurchase(){
{を試してください
const request = await RNIap.requestSubscription(Platform.OS === 'android'?
get(this.props、 'subscriptionStore.subscription.android_product_id'、null):
get(this.props、 'subscriptionStore.subscription.ios_product_id'、null))
} catch(error){
console.log( 'エラー:'、エラー)
}
}
@ sufyan297サーバーサイドコードのスニペットを共有していただけますか? 私も領収書の確認を設定しようとしていますが、Appleのドキュメントは非常に混乱しています
@ziyoshams expo iapモジュールfinishTransactionメソッドを使用してもnullになりますか?
@bcbcbcbcbcl私はexpoモジュールを使用していません。
私に+1それは未定義を返します
@hyochanこの問題に関する更新はありますか? 私たちはかなり長い間立ち往生していて、アプリを公開できません。
ねえ、最近この問題に関する活動はなかったようです。 問題は修正されましたか、それともコミュニティの注意が必要ですか? それ以上のアクティビティが発生しない場合、この問題は解決される可能性があります。 この問題に「ディスカッション用」または「良い最初の問題」というラベルを付けることもできます。開いたままにしておきます。 貢献していただきありがとうございます。
最も参考になるコメント
@hyochanこの問題に関する更新はありますか? 私たちはかなり長い間立ち往生していて、アプリを公開できません。