web-dev-qa-db-ja.com

Androidアプリ内課金:注文のキャンセル後も購入状態は「購入済み」のままです

現在、InApp請求メカニズムをテストしています(InApp Billingバージョン3 APIを使用しているため、TrivialDriveの例を参考にしています)。

プレミアムバージョンへのアップグレードである管理アイテムが1つあります。

現在、テストアカウントでアイテムを購入することはできますが、その後Googleチェックアウトで注文全体をキャンセルすると、コードはアイテムが購入されたためプレミアム機能を付与することを示しています。

MainActivityで購入を確認する方法は次のとおりです。課金API v3を使用すると、必要に応じてアドホックで購入を照会できることを理解したため、購入状態をローカルに保存しません。

@Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();

        iabHelper = new IabHelper(this, Helper.getPKey());
        iabHelper.enableDebugLogging(true);

        iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {

            @Override
            public void onIabSetupFinished(IabResult result) {
                Log.d("IAB", "SETUP FINISHED");

                if(!result.isSuccess())
                {
                    Log.d("IAB", "SETUP NOT OK");
                    return;
                }
                else
                    Log.d("IAB", "SETUP OK");

                iabHelper.queryInventoryAsync(
                    new QueryInventoryFinishedListener() {

                        @Override
                        public void onQueryInventoryFinished(IabResult result, Inventory inv) {
                            Log.d("IAB", "Query inventory finished.");
                            if (result.isFailure()) {
                                Log.d("IAB","Failed to query inventory: " + result);
                                return;
                            }

                            Log.d("IAB", "Query inventory was successful.");

                            // Do we have the premium upgrade?
                            boolean mIsPremium = inv.hasPurchase(Helper.premiumSku);
                            Purchase p = inv.getPurchase(Helper.premiumSku);
                            if(p != null)
                                Log.d("IAB PURCHASE STATE", IabHelper.getResponseDesc(p.getPurchaseState()));
                            else
                                Log.d("IAB PURCHASE STATE", "Purchase is null");

                            Log.d("IAB", "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));


                        }
                    }                       

                );              
            }
        });       
    }

GetPurchaseState = 0を取得し続けます。これは、注文をキャンセルしてから1時間後でも、購入済みであることを意味します。どうして?

43
Toni Kanoni

約12時間待って、ここで提案されているすべてを試した後、私はまだ同じ問題に直面していました。私にとってのトリックは、次のadbコマンドでした:

adb Shell pm clear com.Android.vending

9
lalit_sam

私はこれが1年前であることを知っていますが、提示された答え/ヒントはどれも私を助けてくれなかったので、自分のソリューションを追加すると思いました。

最初に、私は同じ問題を経験していました。つまり、テスト購入を行い、キャンセルし、有効な購入を示す購入状態を受け取りました。

忘れていたのは、最近Google Play Developer Consoleの設定ペインの「License Test Response」フィールドを「RESPOND_NORMALLY」から「LICENSED」に切り替えたことです。

「RESPOND_NORMALLY」に切り替えた後、キャンセルされた購入の購入状態は正しく返されました。

だから、あなたは何日も待つ前にそれをチェックしたいかもしれません

7
Jannon

この問題は、同じアカウントで別のデバイスでアプリを使用する場合にも発生します。アイテムは購入後、デバイスが再起動されるまで(営業時間後でも)受け取られません。もう一度購入しようとすると、Googleウォレットのダイアログに「既にアイテムを所有しています」と表示されます。 iabHelperからの戻りコードは「キャンセルされたユーザー」のままであるため、購入アクティビティからの実際の応答は返されず、デバッグログに書き込まれます。

else if (resultCode == Activity.RESULT_CANCELED) {
        logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
        result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
        if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
    }

そのため、このGoogle請求ダイアログに対応することはできません。ダイアログに「アイテムは既に所有されています」と表示されていても、常に同じ結果IABHELPER_USER_CANCELEDが表示されます。

編集:

私はこれで修正します:

else if (resultCode == Activity.RESULT_CANCELED) {
        logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
        if(responseCode == 7) 
            result = new IabResult(BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED, "Item already owned.");
        else                                                                                             
            result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
        if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
    }

したがって、請求ダイアログからの応答が「アイテムが既に所有されている」として7である場合、リスナーに報告します。

5
Kedu

ステップ1.約10分待ちます。 「キャンセルされた注文」が表示されるまで配信されました。 Googleウォレットで。

Sep 15 11:28 AM Cancelled注文は配達されました。

Sep 15 11:18 AMキャンセル済みこの注文をキャンセルしました。理由:キャンセルのお客様からのリクエスト。

手順2.デバイスでテストGoogleアカウントをログアウトし、再度ログインします。

少なくともそれで私の問題は解決しました。

5
pinux

使用できるのは、購入データのautoRenewingフィールドです。 ドキュメント によると:

autoRenewing:サブスクリプションが自動的に更新されるかどうかを示します。 trueの場合、サブスクリプションはアクティブであり、次の請求日に自動的に更新されます。 falseの場合、ユーザーがサブスクリプションをキャンセルしたことを示します

そして、このフィールドはキャンセル後すぐに更新されます。

3
Elyess Abouda

trivialdrivesampleの参照コードが正しく表示されている場合、アプリ請求の公式参照プロジェクトにとっては恥ずべきことです。

購入== nullの場合、購入されたことがないことを意味します。実際の情報を取得するには、電話する必要があります

purchase.getPurchaseState()

ここ に従って

purchaseState注文の購入状態。可能な値は、0(購入済み)、1(キャンセル済み)、2(払い戻し済み)、または3(期限切れ、サブスクリプション購入のみ)です。

1
tmanthey

Google公式ドキュメントで既に十分に回答されています。ここに言葉をコピーします。

ユーザーが定期購入をキャンセルした場合、Google Playは現在の請求サイクルの払い戻しを提供しません。代わりに、ユーザーは現在の請求サイクルが終了するまでキャンセルされたサブスクリプションにアクセスでき、サブスクリプションはその時点で終了します。たとえば、ユーザーが月間サブスクリプションを購入し、サイクルの15日目にキャンセルした場合、Google Playは30日目(または月によっては他の日)の終わりまでサブスクリプションが有効であると見なします。

それですべて説明できるはずです。 getPurchase()は、現在のサブスクリプションサイクルが終了するまで購入データを返します。

1
user1938357

ドキュメント(IAB API v2)で次のセクションを見つけましたが、これがIAB API v3に使用できるかどうかはわかりません。それでもブロードキャストは送信される可能性があります。

「... Google PlayがGoogleウォレットから払い戻し通知を受信すると、アプリケーションはIN_APP_NOTIFYブロードキャストインテントを受信できます。この場合、Google PlayはIN_APP_NOTIFYメッセージをアプリケーションに送信します。アプリケーションは、アプリケーションが開始したREQUEST_PURCHASEメッセージ。最終的に、アプリケーションは、返金されたアイテムに関する情報を含むPURCHASE_STATE_CHANGEDメッセージを受信します。文字列は2に設定されます。」

from: http://developer.Android.com/google/play/billing/v2/api.html#billing-action-notify

0
mvandillen