How to detect In-App Purchase's Status on Activity Result Method - android

I am testing In-App Purchase using Static References.
I am using the Static Reference android.test.purchased but i can't figure out how to get the response of the Test Purchase in my onActivityResult(...) Method.
Here is my onActivityResult(....) Method's Body:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Log.d("In-App", "Data = "+data.toString());
Log.d("In-App", "Request Code = "+requestCode);
Log.d("In-App", "Result Code = "+resultCode);
}
My Logcat says:
08-16 10:48:10.114: D/In-App(3889): Data = Intent { (has extras) }
08-16 10:48:10.114: D/In-App(3889): Request Code = 666
08-16 10:48:10.114: D/In-App(3889): Result Code = -1
Screen Shots of my Test Purchase:
1.
2.
The question is that, what extras should i extract from the Data Object in my onActivityResult(....) method, to detect the status of the current test purchase (Canceled, already purchased, Successfully accepted, etc) and the information about the product (JSON respnse)?
Any help is highly appreciated, thanks.

I have updated my onActivityResult(...) Method
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
//Purchased Status = Purchased
try {
//Product Details JSON
JSONObject jo = new JSONObject(purchaseData);
//Purchased Product ID
String sku = jo.getString("productId");
}
catch (JSONException e) {
e.printStackTrace();
}
}
else {
//Purchased Status = Not Purchased
}
This way i have got the purchase's status and the purchased product's details JSON.

First of all, you need a database to persist the orders. Second of all, when the user install the your app. You have to issue a RESTORE_TRANSACTIONS what the user has bought and insert the result into the local database. you can read more HERE.
EDITED:
For more details check out In-App Billing Integration

Related

Flutterwave Android payment integration - cannot process payment - error unable to retrieve transaction fee

I'm using Rave for the first time, it looked so flexible and easier to integrate, but along the line. I got stuck with testing, I'm using only card and bank payments methods.
when I choose the card to and enter some test cards from the test card link https://developer.flutterwave.com/reference#test-cards-1
I get 2 errors, => "unable to retrieve transaction fees" but in my logcat I see => " only test cards ree allowed," of which were using the test cards. And am also on staging mode which I assume is correct while testing with test keys.
When I use the bank tab I get some error in JSON toasted, but display later => "parents_limit not defined". Not just that I give this errors, I still found transactions of the bank payment types recorded on my dashboard. This confuses me more since I didn't get the payment success message so I can verify and give value to the customer.
I have integrated everything as per guideline in Rave docs, which calls my make payment. from https://github.com/Flutterwave/rave-android
variable for implementation
//online payment
String[] fullname;
String email = "";
String fName = "";
String lName = "";
String narration = "Payment for Riidit App activation";
String txRef;
String country = "NG";
String currency = "NGN";
private String mUsername, userID, mEmail;
the payment method
private void makePayment(int amount) {
txRef = email + " " + UUID.randomUUID().toString();
try {
fullname = mUsername.split(" ");
fName = fullname[0];
lName = fullname[1];
} catch (NullPointerException ex) {
ex.printStackTrace();
}
/*
Create instance of RavePayManager
*/
new RavePayManager(this).setAmount(amount)
.setCountry(country)
.setCurrency(currency)
.setEmail(email)
.setfName(fName)
.setlName(lName)
.setNarration(narration)
.setPublicKey(RiiditUtilTool.getPublicKey())
.setEncryptionKey(RiiditUtilTool.getEncryptionKey())
.setTxRef(txRef)
.acceptAccountPayments(true)
.acceptCardPayments(true)
.acceptMpesaPayments(false)
.acceptGHMobileMoneyPayments(false)
.onStagingEnv(false)
.allowSaveCardFeature(true)
.withTheme(R.style.DefaultTheme)
.initialize();
}
//called from below
private void payOnline()
{
makePayment(amount);
}
public void onActivateOnlineClick(View v) {
payOnline();
}
// expecting result of payment here either fail or success
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RaveConstants.RAVE_REQUEST_CODE && data != null) {
String message = data.getStringExtra("response");
if (resultCode == RavePayActivity.RESULT_SUCCESS) {
Toast.makeText(this, "SUCCESS " + message, Toast.LENGTH_LONG).show();
// get a PIN and SERIAL no when payment succeeds
getGetPinAndSerialForPaidUser();
} else if (resultCode == RavePayActivity.RESULT_ERROR) {
Toast.makeText(this, "ERROR " + message, Toast.LENGTH_LONG).show();
} else if (resultCode == RavePayActivity.RESULT_CANCELLED) {
Toast.makeText(this, "Payment CANCELLED " + message, Toast.LENGTH_LONG).show();
}
}
}
I want when this event is triggered, it will make the payment to using the value set in the amount and return status in the onActivityResult above where I can check and give value to the user
First of all make sure you are using the api keys which are for testing and if you are on staging mode(testing) then set this to true .onStagingEnv(true) and test after that.

Unable to get updated Purchase object after Acknowledging the purchase in new Google billing Api 2.0

I am implementing the new billing API 2.0 which has this purchase acknowledge method.
Earlier i was using AIDL for my purchase and i had following use case is that i used to pass developer payload during initiating purchase and used to get back my developer payload in the response as a part of purchase object.
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
MY_SKU, "subs", developerPayload);
PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
// Start purchase flow (this brings up the Google Play UI).
// Result will be delivered through onActivityResult().
startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(),
Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}
and in my on on activity result i used to get purchase object
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku + ". Excellent choice,
adventurer!");
}
catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
This purchase object has a developer payload which i send to the server for verification.
Now in the new API the developer payload can be added only after purchase is completed or when we consume a purchase, so the problem is after purchase is acknowledged i need the updated purchase object but how to get it?
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.setDeveloperPayload(/* my payload */)
.build();
client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
}
In acknowledgePurchaseResponseListener i get only the response code whether it is success or failure. But i need to updated purchase object object with developerPayload and isAcknowledged flag true.
Is there a way to do so? Could not find anything in documentation.
The local cache of purchases is updated by the time your acknowledgePurchaseResponseListener is called so you can query the purchase from the cache using https://developer.android.com/reference/com/android/billingclient/api/BillingClient.html#querypurchases. We will consider adding the update purchase to the listener for a future library release to make this more convenient.

Android InAppBilling PurchaseStatusAPI

I want to establish a content provider server whose different contents have to be bought using the Android InAppBilling API. If a mobile user buys an item he gets a unique purchase token. If the user wants to download some content from my server I can use that token to check if the purchase is valid and thus the user is allowed to download the content.
But how do I check if that purchase token really belongs to the user my server is talking to? Is there an existing authentication mechanism?
as you can see at the end of image there are "response code" you can use it like developer docs
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku + ". Excellent choice,
adventurer!");
}
catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
if not enough also you can check In-app Billing Reference (IAB Version 3)
well I am trying to help not a prof..

InAppBilling V3 - "purchaseData" and "dataSignature" are null when purchasing subscription item

I have a problem purchasing subsciption items with the new InAppBilling V3
Here's my IABHelper's handleActivityResult method:
public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result;
if (requestCode != mRequestCode)
return false;
checkSetupDone("handleActivityResult");
// end of async purchase operation
flagEndAsync();
if (data == null) {
Log.e(TAG + "Null data in IAB activity result.");
result = new IabResult(IABHELPER_BAD_RESPONSE, "Null data in IAB result");
if (mPurchaseListener != null)
mPurchaseListener.onIabPurchaseFinished(result, null);
return true;
}
int responseCode = getResponseCodeFromIntent(data);
String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);\
...
purchaseData and dataSignature are null after that code, and as a result, the purchase flow can't be completed.
When Im trying to purchase in-app items, all works well. purchaseData and dataSignature aren't null.
This guy seem to had the same problem:
Google Play In-App Purchase returns error code -1008: null puchaseData or dataSignature
but it doesn't work for me, Im still getting null for the both fields.
What am I doing wrong? thanks in advance!
I only solved this problem, testing in REAL case. I published the app and sign with one test account, and get valid responses.

getting scan result when using zxing?

I am currently using the Zxing library in my app. After scanning the bar code of a book for example, how do I get things like the image, description, etc. from the scan result.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch(requestCode) {
case IntentIntegrator.REQUEST_CODE:
if (resultCode == RESULT_OK) {
IntentResult scanResult =
IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
} else if (resultCode == RESULT_CANCELED) {
showDialog("failed", "You messed up");
}
}
}
Thanks for your help
Zxing scans a variety of barcodes/QR codes, so the first thing you need to do is figure out if its a product UPC or a QR code:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
String response = data.getAction();
if(Pattern.matches("[0-9]{1,13}", response)) {
// response is a UPC code, fetch product meta data
// using Google Products API, Best Buy Remix, etc.
} else {
// QR code - phone #, url, location, email, etc.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(response));
startActivity(intent);
}
}
}
There are a number of web services available that will return product meta data given a UPC code. A fairly comprehensive one would be Google's Search API for Shopping. For example, you can get a json representations of the product with UPC = 037988482481 with an URL that looks like this:
https://www.googleapis.com/shopping/search/v1/public/products?country=US&key=your_key_here&restrictBy=gtin:037988482481
You'll need to replace "your_key_here" with your Google API key.
Best Buy also offers a RESTful products API for all of the products they carry which is searchable by UPC code.
You'll want to use an AsyncTask to fetch the product metadata once you have the UPC.
You dont need the 'IntentResult' or 'IntentIntegrator' for that.
You can do this:
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "PRODUCT_MODE");
startActivityForResult(intent, 0);
And then in onActivityResult:
if (requestCode == 0) {
if ((resultCode == RESULT_CANCELED) || (resultCode == -1000)) {
Toast.makeText(WebViewActivity.this, "Nothing captured",
Toast.LENGTH_SHORT).show();
} else {
String capturedQrValue = data.getStringExtra("barcode_data");
}
}
With this you scan the barcode, now there is in the Zxing code another library that uses Google API for looking up that ISBN.
In the class Intents.java you have the info of what extras the intent needs and the class ISBNResultHandler shows what is the result.
Hope it helps someone in the future.
You can check what the Android ZXing app does. The source for the Android client is in: ZXing Android client source code. For ISBN numbers, the source code for handling that is: Android ZXing app's ISBN Result Handler code
For product and book search, the Android code invokes these two functions from ResultHandler.java:
// Uses the mobile-specific version of Product Search, which is formatted for small screens.
final void openProductSearch(String upc) {
Uri uri = Uri.parse("http://www.google." + LocaleManager.getProductSearchCountryTLD() +
"/m/products?q=" + upc + "&source=zxing");
launchIntent(new Intent(Intent.ACTION_VIEW, uri));
}
final void openBookSearch(String isbn) {
Uri uri = Uri.parse("http://books.google." + LocaleManager.getBookSearchCountryTLD() +
"/books?vid=isbn" + isbn);
launchIntent(new Intent(Intent.ACTION_VIEW, uri));
}
In your onActivityResult do like following code
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if(result != null) {
if(result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
String qrCode=result.getContents();
}
} else {
// This is important, otherwise the result will not be passed to the fragment
super.onActivityResult(requestCode, resultCode, data);
}
You haven't called result.getContents().
I just want to add that if you want to be able to press back without a RuntimeException surround your if statement with a try catch block. so:
try{
/// get scanned code here
} catch(RuntimeException e) {
e.getStackTrace();
{
Hope that helped the inevitable crash you would face without it.

Categories

Resources