In the previous library as we were getting Inventory object, how can we get it from billing library version 1.0?
How can we get developer payload, which we are getting in Purchase object?
For reference :
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
}
Note : I am referencing from the library code - https://github.com/googlesamples/android-play-billing
As with the older version of google play billing library, inventory object contains devloperPayload field which is useful to verify user authenticity. But now google devs suggested changing the approach, and user verification with developerPayload has to be handled on the own application/server side, instead of google play billing response.
Here is the link for more details regarding this issue: https://issuetracker.google.com/issues/63381481
Related
I know as of May 2015 google changed how they handle your app in draft mode -
In a few cases, you can test Google Play functionality with an unpublished app. For example, you can test an unpublished app's in-app billing support by using static responses, special reserved product IDs that always return a specific result (like "purchased" or "refunded").
My question is can you use IabHelper.queryInventoryAsync() on your prouducts in draft mode. I know to do a purchase you have to use reserved product id but what about query? This question stems from the fact that I am returning null when I get Inventory back from my Listener.
final String SKU_VERBAL_HINT = "verbal_00.thisthat";
// compute your public key and store it in base64EncodedPublicKey
mHelper = new IabHelper(this, base64EncodedPublicKey);
// enable debug logging (for a production application, you should set this to false).
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d("Issue", "Problem setting up In-app Billing: " + result);
}else{
//List<String> additionalSkuList = new ArrayList<String>();
//additionalSkuList.add(SKU_VERBAL_HINT);
String[] moreSkus = {SKU_VERBAL_HINT};
mHelper.queryInventoryAsync(true, Arrays.asList(moreSkus),
mQueryFinishedListener);
Log.d("Issue", "No Problem setting up in-app billing " + result);
}
}
});
mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{
if (result.isFailure()) {
// handle error
return;
}
**-------->FAILS HERE, null inventory** String verbalPrice =
inventory.getSkuDetails(SKU_VERBAL_HINT).getPrice();
String verbal2 = verbalPrice;
// update the UI
}
};
Check out this answer. Draft apps are not supported.
BlockquoteDraft Apps are No Longer Supported
Previously, you could publish a "draft" version of your app for testing. This functionality is no longer supported. Instead, there are two ways you can test how a pre-release app functions on the Google Play store:
You can publish an app to the alpha or beta distribution channels. This makes the app available on the Google Play store, but only to the testers you put on a "whitelist".
In a few cases, you can test Google Play functionality with an unpublished app. For example, you can test an unpublished app's in-app billing support by using static responses, special reserved product IDs that always return a specific result (like "purchased" or "refunded").
Blockquote
https://stackoverflow.com/a/24866513/2192015
From this is sounds like the app has to be published to the alpha or beta channel to do testing.
http://developer.android.com/google/play/billing/billing_testing.html#draft_apps
I'm having problems to handle in-app billing inventory on devices with multiple accounts.
DEVICE 1:
only one account on the device (user = X)
logged with account X on google play
logged with account X on google play games
purchase done (sku = remove_ads)
DEVICE 2:
three accounts on the device (users = X, Y, Z)
logged with account X on google play
logged with account X on google play games
querying inventory
The code to handle the query inventory response is this:
#Override
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
if (result.isFailure()) {
Log.d("billing", "inventory: failed (" + result.mMessage + ")");
return;
}
Log.d("billing", "inventory: remove_ads purchased=" + inventory.hasPurchase("remove_ads");
}
The logcat output on DEVICE 1 is:
inventory: remove_ads purchased=true
And the logcat output on DEVICE 2 is:
inventory: remove_ads purchased=false
What am I missing? Thanks!
It was my mistake, this is what happened:
Test purchase done using DEVICE 1 on the published version (release signature), purchase done successfully.
I started working on the next version (debug signature) using DEVICE 1, but as the purchase was done on this device, google play billing cached the response and it returned true when I queried the inventory.
After a while I started working using DEVICE 2, then the google play billing was not returning anything when I queried the inventory, because the purchase was not cached and the APK signature didn't match.
It all started working when I signed the APK with the release signature and tested it on DEVICE 2.
Conclusion: pay more attention with the signature and beware of cached responses
What I have Done
I have implemented the in-app purchasing feature in my app successfully and it is working in DEBUG mode perfectly.
What I Want
Now as the purchase (one time only) has been made, now I need to enable some features in my app based on this.
1) If the purchase is not made, some features will be disabled.
2) After making the purchase, some features will be enabled.
I want to know how can I query or remember that the purchase has been made and the features should be enabled. What is the correct way of doing this.
Thanks.
Check the developer guide for in-app billing, especially the Query Purchased Items section.
There's also IabHelper class which is a wrapper around the in-app billing API to make things a little bit easier. Here's a snippet of code using the IabHelper.
IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// handle error here
}
else {
// does the user have the premium upgrade?
mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
// update UI accordingly
}
}
};
When the user buys a product, I use a webservice to verify the purchase,to protect from replay attacks, I add a (nonce) developer payload to the purchase.
It works as expected.
But what about restoring transactions?
I can get the signed data and signature and every other info from the local inventory(by calling queryPurchases() in IabHelper), but I can't set a new developer payload anywhere, so I can't verify it on my webservice.
How do I do a restore transactions safely?
Help would be greatly appreciated...
edit: should I just stick to iab v2 for restoring transactions?
So, as far as I know, this is an unresolved security issue which compromises the security of in app billing api v3.
There is no way of securely (verifying with a webservice) restoring a purchase in in app billing api v3.
As of this writing, the Google Play Billing Library sample App retrieves the developer payload for verification when querying for purchased items. The code looks like this:
// 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.");
.
.
.
// 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"));
.
.
.
}
I'm working on a In App Store on my app, I used AndroidBillingLibrary by robotmedia,
when I purchase android.test.purchased using the library the response is OK, all the data I need is in there.
The problem is, when I switched to Android In-App Billing v3 this is all received from the response, no signatures.
{"packageName":"com.my.sampleapp","orderId":"transactionId.android.test.purchased","productId":"android.test.purchased","developerPayload":"","purchaseTime":0,"purchaseState":0,"purchaseToken":"inapp:com.my.sampleapp:android.test.purchased"}
I followed exactly this sample https://developer.android.com/training/in-app-billing/preparing-iab-app.html#GetSample but there's no signatures. I even run the given sample app by Google but no luck.
I put my Base64-encoded RSA public key correctly in
mHelper = new IabHelper(this, myPublicKey);
and this is my purchase code mHelper.launchPurchaseFlow(this, itempackage, 10001, mPurchaseFinishedListener);
OnIabPurchaseFinishedListener mPurchaseFinishedListener = new OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.i("Billing", "purchasing: " + result.getMessage());
if (result.isFailure()) {
Log.i("Billing", "Error purchasing: " + result);
return;
} else if (purchase.getSku().equals("android.test.purchased")) {
Log.i("Billing - signature", purchase.getSignature());
consumeItems();
} else {
Log.i("Billing", "Error purchasing: " + result);
}
}
};
Somehow my mPurchaseFinishedListener is not receiving anything after the purchase but the protected void onActivityResult(int requestCode, int resultCode, Intent data) is receiving something but there's no signature.
Any solutions to this?
It's weird that v2 is receiving signatures and v3 is not.
You don't get signatures for the test IDs, android.test.purchased, etc.
You'll receive signatures with real purchases.
As was said by Rawkode, you no longer get signatures for test purchases (android.test.*). I took the dive and uploaded my app to the market place (just didn't publish it) using my real products.
Low and behold signatures started to be returned! I recommend amending any server side validation you are using to skip the signature check when the data contains an android.test.* item id.
What you mean by Signatures? Is that Subscriptions? Or an in-app item (consumable or not)?
Because in-App Billing v3 does not support subscriptions at the moment, if you want that feature you have to use v2 (https://developer.android.com/google/play/billing/billing_overview.html). Also, make sure your item is marked as "a managed item" on your developer console (for Billing v3).
Sorry if I misunderstood. Also, try enabling the debug mode on your IabHelper instance, this will provide you a better overview of your problem.
mHelper.enableDebugLogging(true, "YOURTAG");
I suggest taking a look at the implementation guide on the Developers website:
https://developer.android.com/google/play/billing/billing_integrate.html
There's also sample code there.