anjlab / android-inapp-billing-v3

A lightweight implementation of Android In-app Billing Version 3
Other
2.19k stars 536 forks source link

Bug: ITEM_ALREADY_OWNED error #363

Open blood73 opened 6 years ago

blood73 commented 6 years ago

Do you want to request a feature or report a bug?

bug.

What is the current behavior?

Consumable In-App.

Steps to reproduce:

Start purchase flow. Press "Buy" button on Google Play dialog. Quickly disable ALL connections on smartphone. As result you will see, that product successfully bought, but consume isn't finished. Then, if you will try to bought the same product: ITEM_ALREADY_OWNED code 7 error.

As result, user can't buy this product. I've tried "adb shell pm clear com.android.vending" in terminal and restarting the device and clear Google Play data. Nothing can get it out of this state. I can fix thi only with new Gmail account, rename In-App or refund this product and wait a few hours.

In code:

@Override
    public void onPurchaseHistoryRestored() {
        for (String sku : bp.listOwnedProducts()) {
            logD(TAG, "Owned Managed Product: " + sku);
                bp.consumePurchase(sku);
        }
    }

bp.listOwnedProducts() is empty.

In my buy button:

if (bp.isPurchased(MILEAGE_1)) {
     bp.consumePurchase(MILEAGE_1);
 } else {
    bp.purchase(this, MILEAGE_1, settings.getSSAD());
}

bp.isPurchased(MILEAGE_1) is false

no

bp = new BillingProcessor(this, App.getPublicKey(), ApiPurchaseVerifier.getMerchantId(), this);
bp.initialize();

The full code:

public class MileageInappActivity extends BaseActivity implements BillingProcessor.IBillingHandler, AsyncResponse {

    BillingProcessor bp;

    private static final String MILEAGE_1 = "mileage_1";
    private static final String AD_FREE = "ad_free";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mileage_inapp);
        ButterKnife.bind(this);
        setupToolbar();

        bp = new BillingProcessor(this, App.getPublicKey(), ApiPurchaseVerifier.getMerchantId(), this);
        bp.initialize();
    }

    @Override
    public void onBillingInitialized() {
        /*
         * Called when BillingProcessor was initialized and it's ready to purchase
         */

        bp.loadOwnedPurchasesFromGoogle();
        bp.listOwnedProducts();

    }

    @Override
    public void onProductPurchased(String productId, TransactionDetails details) {
        /*
         * Called when requested PRODUCT ID was successfully purchased
         */

        bp.consumePurchase(productId);

        ArrayList<String> passing = new ArrayList<String>();
        passing.add(details.purchaseInfo.responseData);

        ApiPurchaseVerifier apiPurchaseVerifier = new ApiPurchaseVerifier();
        apiPurchaseVerifier.delegate = MileageInappActivity.this;
        apiPurchaseVerifier.execute(passing);

        bp.loadOwnedPurchasesFromGoogle();
    }

    @Override
    public void onBillingError(int response, Throwable e) {
        /*
         * Called when some error occurred. See Constants class for more details
         *
         * Note - this includes handling the case where the user canceled the buy dialog:
         * errorCode = Constants.BILLING_RESPONSE_RESULT_USER_CANCELED
         */

        logD(TAG, "in-app error: " + Integer.toString(response));
    }

    @Override
    public void onPurchaseHistoryRestored() {
        /*
         * Called when purchase history was restored and the list of all owned PRODUCT ID's
         * was loaded from Google Play
         */
        for (String sku : bp.listOwnedProducts()) {
            logD(TAG, "Owned Managed Product: " + sku);
                bp.consumePurchase(sku);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (!bp.handleActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    @Override
    public void processFinish(boolean result) {

        bp.loadOwnedPurchasesFromGoogle();

        if (result) {
            mSnackbar = Snackbar.make(mainContent, MileageInappActivity.this.getResources().getString(R.string.inapp_success), Snackbar.LENGTH_INDEFINITE)
                    .setAction("Action", null)
                    .setDuration(2000);
            mSnackbar.show();
        } else {
            logD(TAG, "in-app error");
        }
    }
    private static ArrayList<String> getInAppSkus() {
        final ArrayList<String> skus = new ArrayList<>();
        skus.addAll(Arrays.asList(MILEAGE_1);
        return skus;
    }

    @OnClick(R.id.card_1)
    protected void onClickCard1() {
        final RunCounts settings = new RunCounts();

        if (bp.isPurchased(MILEAGE_1)) {
            bp.consumePurchase(MILEAGE_1);
        } else {
            bp.purchase(this, MILEAGE_1, settings.getSSAD());
        }
    }

    private void updateMileageCount() {
        ArrayList<String> passing = new ArrayList<String>();
        getUserData = new GetUserData();
        getUserData.execute(passing);
    }

    @Override
    public void onDestroy() {
        dismissProgressDialog();
        if (bp != null) {
            bp.release();
        }
        super.onDestroy();
    }
---------------------
Redbu11dev commented 5 years ago

I can confirm that. It seems like something is cached. Works again after a day or two.

alneil commented 5 years ago

resolved yet?