Since one year I develop android apps. I thought it’s time now to do the next step and implement the billing system. Before I implement this new feature in my main app I thought it’s better to test it.
Last week i developed a test app the same app (with v3 billing system) like my main app (without v3 billing system). I published it and installed on my Samsung Note via Google Play. I was being able to buy and to subscribe. And it worked well.
So I deactivated the test app, copied the whole billing methods in my main app, changed the Base64 coded public RSA key and published it.
After installation and start, the app crashed every time. And the reason is only the billing system because the recent version works without the billing system well. Of course I could replace my main app with a new app which do the same like my main app, but I would lose all my user, my statistics and comments until now.
Do you know why my app cannot install the billing system with the RSA key?
Which other reasons could be responsible for this Situation?
what happens in onCreate:
mHelper = new IabHelper(this, base64EncodedPublicKey);
// enable debug logging (for a production application, you should set this to false).
mHelper.enableDebugLogging(false);
// Start setup. This is asynchronous and the specified listener
// will be called once setup completes.
Log.d(TAG, "Starting setup.");
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;
}
// Hooray, IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
and what happens in line 960:
public IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished .");
if (result.isFailure()) {
complain("Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
// Purchase premium monthly
Purchase purchase = inventory.getPurchase(Constants.PREMIUM);
if(purchase.getPurchaseState() == Purchase.PURCHASED_SUCCESSFULLY && verifyDeveloperPayload(purchase)){
isPremium = true;
}else{
isPremium = false;
updatePremium(purchase.getPurchaseState());
}
Log.d(TAG, "User " + (isPremium ? "HAS" : "DOES NOT HAVE") + " premium surebets for 32 days.");
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
}
};
Related
I am trying to verify whether product is purchased or not from store.
For that I have used the below code :
mHelper.queryInventoryAsync(mGotInventoryListener);
And call back is as mentioned below :
IabHelper.QueryInventoryFinishedListener 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()) { // This fails in our case**
complain("Failed to query inventory: " + result);
return;
}
}
};
But every time I am getting same error as shown in below attached screen.
I have tried with below mentioned steps but failed to get success.
"base64EncodedPublicKey" verified from our google play account where app is launched in alpha testing mode
Application is signed with release keystore
"base64EncodedPublicKey" - copied to notepad first and then copy to java file (read somewhere in blogs for this solution) , but that has not work for me.
Can anybody suggest for the same. Please let me know if I need to add something in order to solve this issue?
Are you trying to purchase android.test.purchased or another item? If you are using android.test.purchased, check this answer, it should answer your question: Android in app purchase: Signature verification failed
Found the solution :)
There was an issue with registering a broadcast receiver.
Plese find below code of startSetup method which is registering broadcast receiver that was missing from the following snippet.
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
} mBroadcastReceiver = new IabBroadcastReceiver(MainActivity.this);
IntentFilter broadcastFilter = new IntentFilter(IabBroadcastReceiver.ACTION);
registerReceiver(mBroadcastReceiver, broadcastFilter);
// Hooray, IAB is fully set up! }});
I have setup three Managed items in my developer account for in-app purchases, and my app is currently in the Beta channel on the Play Store.
I want to test the in-app purchase across two devices that use the same Google account -- but am finding that only the device that makes the purchase is correctly finding the purchase. The second device, using the same Google account, does not find the purchase.
Should test account billing work across any device that uses the same Google account?
I'm using the Billing helper libraries and here's my code at start-up to check for purchases:
ActivityStartUp.java
#Override
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess())
{
LOGD(TAG, "In-app Billing setup failed: " + result);
startApplication();
}
else
{
LOGD(TAG, "In-app Billing is set up OK");
// Query In-App billing for purchases
mHelper.queryInventoryAsync(new QueryInventoryFinishedListener()
{
#Override
public void onQueryInventoryFinished(IabResult result, Inventory inv)
{
if (inv.hasPurchase(Globals.ITEM1_SKU) ||
inv.hasPurchase(Globals.ITEM2_SKU) ||
inv.hasPurchase(Globals.ITEM3_SKU))
{
// Store PRO purchase state
AccountUtils.setProVersion(ActivityStartUp.this, true);
LOGD(TAG, "Ad-free. User has purchased the Upgrade :)");
}
else
{
// Store PRO purchase state
AccountUtils.setProVersion(ActivityStartUp.this, false);
LOGD(TAG, "Using the free version, with Ads");
}
// Start the application
startApplication();
}
});
}
}
I am currently working on in app purchase in my application, when it launches I have always the error code -1003 querying owned items response signature verification failed when I arrive in IabHelper.QueryInventoryFinishedListener method.
I currently uses the example version of Google "Trivial Drive", I guess my signature is correct because I get to buy much when I use android.app.purchassed ...
The key seems correct to me because when I click like to buy a product that tells me that the publisher can not buy the product which is normal in itself (If I put anything I have another error saying the product does not exist). For cons, I have the same error when I put the test product "android.test.purchasse" then I should be able to test with it.
I made a purchase with android.test.purchasse there and I can not reset if you have already succeeded I'm interested.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// load game data
loadData();
String base64EncodedPublicKey = "MY_KEY_BASE64";
PublicKey key = Security.generatePublicKey(base64EncodedPublicKey);
// Create the helper, passing it our context and the public key to verify signatures with
Log.d(TAG, "Creating IAB helper.");
mHelper = new IabHelper(this, base64EncodedPublicKey);
// enable debug logging (for a production application, you should set this to false).
mHelper.enableDebugLogging(true);
// Start setup. This is asynchronous and the specified listener
// will be called once setup completes.
Log.d(TAG, "Starting setup.");
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;
// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
}
// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener 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("Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
if(inventory.hasPurchase(SKU_GAS))
{
Toast.makeText(getApplicationContext(),"PREMIUM",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"NOT PREMIUM", Toast.LENGTH_SHORT).show();
}
// 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"));
// Do we have the infinite gas plan?
Purchase infiniteGasPurchase = inventory.getPurchase(SKU_INFINITE_GAS);
mSubscribedToInfiniteGas = (infiniteGasPurchase != null && verifyDeveloperPayload(infiniteGasPurchase));
Log.d(TAG, "User " + (mSubscribedToInfiniteGas ? "HAS" : "DOES NOT HAVE")
+ " infinite gas subscription.");
if (mSubscribedToInfiniteGas) mTank = TANK_MAX;
// Check for gas delivery -- if we own gas, we should fill up the tank immediately
Purchase gasPurchase = inventory.getPurchase(SKU_GAS);
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)) {
Log.d(TAG, "We have gas. Consuming it.");
mHelper.consumeAsync(inventory.getPurchase(SKU_GAS), mConsumeFinishedListener);
return;
}
updateUi();
setWaitScreen(false);
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
}
};
Have you ever been concerned? I see no way out for this bug help from you will be appreciated.
thank you
You need to create a test account, and put it in the playstore admin page.
I am currently trying to configure my app for in app purchase, but it just won't work. Every time I try to start the purchase flow it says "This version of the applications is not configured for billing through Google Play". I am quite sure that I walked through al necessary steps to make it work. I also tested SKU-Id "android.test.purchased", which works fine.
base64EncodedPublicKey is def. correct and exactly teh same like the code from the developer console
I did not forget <uses-permission android:name="com.android.vending.BILLING" /> in my manifest
I have applied the google account that I am using on my testing device as a tester account in the developer console
I am using the exactly same APK on my device an in the developer console. I installed it on my device via adb -d install
So any ideas what I could have done wrong?
This is my code:
(onCreate)
base64EncodedPublicKey
iabHelper = new IabHelper(this, base64EncodedPublicKey);
iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
#Override
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(PURCHASE_TAG, "Problem setting up In-app Billing: " + result);
} else if (result.isSuccess()){
// Hooray, IAB is fully set up!
Log.d(PURCHASE_TAG, "Setup completed: " + result);
iabHelper.queryInventoryAsync(true, null, queryFinishedListener);
}
}
});
(onActivityResult)
if (iabHelper.handleActivityResult(requestCode, resultCode, data)) {
Log.d("TAG", "onActivityResult handled by IABUtil.");
return;
}
(Button click for starting burchase flow)
if(isPremium){
saveImageToGallery(imageState.image);
} else if (iabHelper != null) {
iabHelper.flagEndAsync();
purchaseItem(SKU_TEST);
(purchaseItem())
private void purchaseItem(String sku) {
iabHelper.launchPurchaseFlow(this, sku, 10001,
purchaseFinishedListener);
}
(listeners)
IabHelper.QueryInventoryFinishedListener
queryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{
if (result.isFailure()) {
// handle error
return;
} else if (result.isSuccess()){
Log.d("$$$$$$$$$$$$$$$", "" + result);
}
}
};
IabHelper.OnIabPurchaseFinishedListener purchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (result.isFailure()) {
Log.d("ERROR_TAG", "Error purchasing: " + result);
return;
}
else if (purchase.getSku().equals(SKU_TEST)) {
// give user access to premium content and update the UI
isPremium = purchase.getSku().equals(SKU_TEST);
}
}
};
I think you should check the key store you signed your apk. You must use same key store for apk that has uploaded to Google Play and test.
I hade the same problem, I fixed it by:
Go to play store developer console
Settings > Manage Testers, then add your another test email, not the one you use in publishing apps.
Again under Developer Console, Account Details (scroll down) > License Testing and add the emails of your users who will test your
app.
On your device, login in play store with one of the test emails 3 you allowed.
Launch you app and make in app purchase. There should be fixed.
more https://developer.android.com/google/play/billing/billing_testing.html
Summary:
I am working on an app which has IAB, and that when the purchase is finished through the OnConsumeFinishedListener, it will save through SharePreference that the user has paid for the additional function (the function wont be depleted).
Users are able to buy again for the same product.
Code:
// Called when consumption is complete
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener()
{
public void onConsumeFinished(Purchase purchase, IabResult result)
{
Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result);
if (mHelper == null) return;
if (result.isSuccess())
{
Toast.makeText(InAppBillingActivity.this, "Thank you!!", Toast.LENGTH_SHORT).show();
if ((purchase.getSku().equals(ITEM_SKU10))) {countQ(10);}
buy10Button.setEnabled(true);
}
else
{
// handle error
}
Log.d(TAG, "End consumption flow.");
}
};
public void countQ(int Q)
{
SharedPreferences settings = this.getSharedPreferences("MyApp",0);
if (Q==10)
{
SharedPreferences settings1 = this.getSharedPreferences("MyApp",0);
SharedPreferences.Editor e1 = settings1.edit();
e1.putBoolean("userpaid", true);
e1.commit();
}
Question:
I see that users are able to cancel their purchase. In that way, saving through Sharepreference that the user has paid for additional functions will have loophole? The user can first purchase to make the sharepreference to become true and then cancel the purchase order?
In that way, how can be the process be improved? Checking the inventory seem not possible as the additional function is consumed in the IAB process.
It seems a little odd that you have a non-consumable item that can be purchased multiple times. The idea is generally that an item that can be purchased multiple times is consumable.
To answer your question IAB purchases cannot be cancelled like an app purchase can, the 15 minute refund window is removed and the purchase is non-refundable unless they contact you and you decide to issue a refund manually.