android-inapp-billing-v3 icon indicating copy to clipboard operation
android-inapp-billing-v3 copied to clipboard

Bug: ITEM_ALREADY_OWNED error

Open blood73 opened this issue 6 years ago • 2 comments

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

  • which version of library you use 1.0.44

  • was it working in previous versions? Don't know

  • do you use fragments or not

no

  • how do you instanciate BillingProcessor (singleton or not)
bp = new BillingProcessor(this, App.getPublicKey(), ApiPurchaseVerifier.getMerchantId(), this);
bp.initialize();
  • which device/OS version do you use for testing (or its an emulator) Samsung S8, Android 8.0. Sony Xperia Z1, Android 5.1.1

  • have you uploaded it to Google Play or not (if yes, when which channel: Prod/Beta/Alpha) Production ( signed the app and testing with real cards)

  • do you test with real products, or with a testing onces (e.g. android.test.purchased) Real products.

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();
    }
---------------------

blood73 avatar Sep 06 '18 12:09 blood73

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

Redbu11dev avatar Mar 15 '19 11:03 Redbu11dev

resolved yet?

alneil avatar Oct 08 '19 11:10 alneil