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.
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();
}
---------------------
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:
bp.listOwnedProducts() is empty.
In my buy button:
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
BillingProcessor
(singleton or not)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: