简体   繁体   中英

android in app purchase - Articel already owned issue

I have just implemented the in app billing functionality in my app. I only have one product to unlock all premium features.
The purchase itself works, but after the purchase flow, my code obviously isn't able to recognise the success of the purchase, because there appears a complain window right after purchase saying "Articel already owned" . So somehow the purchase flow is not recogniced to be successful. After i restart the app, the pro features are unlocked, because the querying of the inventory says, the pro features have been bought. I am out of ideas, so here is my code:

 // SKUs for our products: the premium upgrade (non-consumable)

String SKU_PREMIUM;

// (arbitrary) request code for the purchase flow

final int RC_REQUEST = 10001;

// The helper object
IabHelper mHelper;

// Provides purchase notification while this app is running
public IabBroadcastReceiver mBroadcastReceiver;
IabHelper.QueryInventoryFinishedListener mGotInventoryListener;
AppCompatActivity activity;
private String payload;

public InAppBillingHelper(AppCompatActivity context, final IabBroadcastReceiver.IabBroadcastListener contextBroadcastListener, String base64EncodedPublicKey,String skuPremium, boolean debug){
    //String base64EncodedPublicKey = "VALENTIN_HERR_SCHAFKOPF_RECHENHELFER";
    this.activity = context;
    SKU_PREMIUM = skuPremium;
    // Create the helper, passing it our context and the public key to verify signatures with
    Log.d(TAG, "Creating IAB helper.");
    mHelper = new IabHelper(context, base64EncodedPublicKey);

    // enable debug logging (for a production application, you should set this to false).
    mHelper.enableDebugLogging(debug);

    // Start setup. This is asynchronous and the specified listener
    // will be called once setup completes.
    Log.d(TAG, "Starting setup.");

    // Listener that's called when we finish querying the items and subscriptions we own
    mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
            Log.d(TAG, "Query inventory finished.");

            // Have we been disposed of in the meantime? If so, quit.
            if (mHelper == null) return;

            // Is it a failure?
            if (result.isFailure()) {
                complain("Fehler bei der Bestimmung der App-Lizenz: " + result);
                // TODO analyse results and output it to the user
                return;
            }

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

            // Do we have the premium upgrade?
            Purchase premiumPurchase = inventory.getPurchase(SKU_PREMIUM);
            mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
            Log.d(TAG, "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));
       }

            updateUi();
            setWaitScreen(false);
            Log.d(TAG, "Initial inventory query finished; enabling main UI.");
        }
    };

    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
            Log.d(TAG, "Setup finished.");

            if (!result.isSuccess()) {
                // Oh noes, there was a problem.
                complain("Problem setting up in-app billing: " + result);
                return;
            }
            // Have we been disposed of in the meantime? If so, quit.
            if (mHelper == null) return;

            mBroadcastReceiver = new IabBroadcastReceiver(contextBroadcastListener);
            IntentFilter broadcastFilter = new IntentFilter(IabBroadcastReceiver.ACTION);
            try {
                activity.registerReceiver(mBroadcastReceiver, broadcastFilter);
            }catch (Exception e)
            {}
            // IAB is fully set up. Now, let's get an inventory of stuff we own.
            Log.d(TAG, "Setup successful. Querying inventory.");
            try {
                mHelper.queryInventoryAsync(mGotInventoryListener);
            } catch (IabHelper.IabAsyncInProgressException e) {
                complain("Error querying inventory. Another async operation in progress.");
            }
        }
    });
}


public void receivedBroadcast() {
    // Received a broadcast notification that the inventory of items has changed
    Log.d(TAG, "Received broadcast notification. Querying inventory.");
    try {
        mHelper.queryInventoryAsync(mGotInventoryListener);
    } catch (IabHelper.IabAsyncInProgressException e) {
        complain("Error querying inventory. Another async operation in progress.");
    }
}


// User clicked the "Upgrade to Premium".
public void handlePremiumPurchase() {
    Log.d(TAG, "Upgrade button clicked; launching purchase flow for upgrade.");
    setWaitScreen(true);

    payload = "";

    try {
        mHelper.launchPurchaseFlow(activity, SKU_PREMIUM, RC_REQUEST,
                mPurchaseFinishedListener, payload);
    } catch (IabHelper.IabAsyncInProgressException e) {
        complain("Error launching purchase flow. Another async operation in progress.");
        setWaitScreen(false);
    }catch (NullPointerException e)
    {
        complain("Fehler beim Kaufversuch. Stelle sicher, dass mit einem Google Konto im PlayStore angemeldet bist und eine stabile Internetverbindung besteht." +
                "Versuche es nach noch einmal." +
                "");
        setWaitScreen(false);
    }
}

public boolean isPremium() {
    return mIsPremium;
}

public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
    if (mHelper == null) return false;

    // Pass on the activity result to the helper for handling
    if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
        // Todo handle
    }
    else {
        Log.d(TAG, "onActivityResult handled by IABUtil.");
    }
    return true;
}

/** Verifies the developer payload of a purchase. */
boolean verifyDeveloperPayload(Purchase p) {
    String payload = p.getDeveloperPayload();

    // Todo payload string verification

    return true;//payload.equals(this.payload);
}

// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
        Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);

        // if we were disposed of in the meantime, quit.
        if (mHelper == null) return;

        if (result.isFailure()) {
            if(result.getResponse() == IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED)
            {
                mIsPremium = true;
                updateUi();
                //complain("Du besitzt bereits das Premium Paket auf einem deiner angemeldeten Google Konten.");
            }
            else {
                complain("Fehler beim Kauf: " + result);
            }
            setWaitScreen(false);
            return;
        }
        if (!verifyDeveloperPayload(purchase)) {
            complain("Error purchasing. Authenticity verification failed.");
            setWaitScreen(false);
            return;
        }

        Log.d(TAG, "Purchase successful.");

        if (purchase.getSku().equals(SKU_PREMIUM)) {
            // bought the premium upgrade!
            Log.d(TAG, "Purchase is premium upgrade. Congratulating user.");
            alert("Danke für das Premium Upgrade! Ich wünsche dir weiterhin viel Spaß bei der Nutzung!");
            mIsPremium = true;
            updateUi();
            setWaitScreen(false);
        }

    }
};

Btw: The code is a modified version of the **trivial drive* example. Thanks in advance!

Although it's not the cleanest solution, just query the inventory again if you have a "already owned error". Then update the UI only according to the inventory query result

Thanks @DerAdler . I implemented it just the way you said and it worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM