My app using in-app billing v3 (UNMANAGED PRODUCT) and fully test with a signed apk, it works perfect on my android phone. After i release to production, got one purchase today, its my first purchase, but no signature received! i use my test account purchase again, got signature, but how come this buyer device submit blank signature to me?! Weird!
i check my Google Wallet records, its Green color icon, mean "The customer's credit card was successfully charged"! Im following the implementation below:
http://developer.android.com/google/play/billing/billing_integrate.html
#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!");
/////////////////////////////////////////////////////////
// submit 'purchaseData' and 'dataSignature' to my server
/////////////////////////////////////////////////////////
}
catch (JSONException e) {
//alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
my server only receive purchaseData but dataSignature is blank. anyone can help ? in what case will cause this issue?
make sure if you haven't change in the RC_REQUEST constants then it should be 10001 instead of 1001, and if you have manually changed it then you have to change the constants for these three code.
Constants:
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 10001;
Purchase Request:
mHelper.launchPurchaseFlow(this, SKU_GAS, RC_REQUEST,
mPurchaseFinishedListener, payload_consumeItem);
onActivityResult:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + ","
+ data);
if (mHelper == null)
return;
if (requestCode == 10001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
Log.d("INAPP_PURCHASE_DATA", ">>>" + purchaseData);
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
Log.d("INAPP_DATA_SIGNATURE", ">>>" + dataSignature);
String continuationToken = data
.getStringExtra("INAPP_CONTINUATION_TOKEN");
Log.d("INAPP_CONTINUATION_TOKEN", ">>>" + continuationToken);
if (resultCode == RESULT_OK) {
try {
Log.d("purchaseData", ">>>" + purchaseData);
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();
}
} else if (resultCode == RESULT_CANCELED) {
// } else if (resultCode == RESULT_CANCELED) {
Toast.makeText(AppMainTest.this,
"Sorry, you have canceled purchase Subscription.",
Toast.LENGTH_SHORT).show();
} else if (resultCode == IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
Toast.makeText(AppMainTest.this, "Item already owned",
Toast.LENGTH_SHORT).show();
}
}
}
Let me know it will solve your problem or not.
Hope it will solve your problem.
Related
I want to get nonce from server. i wrote backend in PHP that will giving token. after receiving token PaymentMethodNonce returning null.
I want to get nonce from server.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
PaymentMethodNonce nonce = result.getPaymentMethodNonce();
String stringNonce = nonce.getNonce();
Log.d("mylog", "Result: " + stringNonce);
// Send payment price with the nonce
// use the result to update your UI and send the payment method nonce to your server
paramHash = new HashMap<>();
paramHash.put("couponPrice", couponPrice);
paramHash.put("nonce", stringNonce);
sendPaymentDetails();
} else if (resultCode == Activity.RESULT_CANCELED) {
// the user canceled
Log.d("mylog", "user canceled");
} else {
// handle errors here, an exception may be available in
Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
Log.d("mylog", "Error : " + error.toString());
}
}
}
DropInResultobject is result. That is returning null but that should be some valid information
Here's the answer:
val result = intent.getParcelableExtra<DropInResult>(DropInResult.EXTRA_DROP_IN_RESULT)
return null
I am using in app purchase option in my application. After subscription completed , I could not able to get a Purchase data , data signeture and toen those things.But the payment was succeessfull for all the time. I release my apk in Beta testing account.
I was getting error like this:
IabResult: IAB returned null purchaseData or dataSignature (response: -1008:Unknown error)
Here's my relevant code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
billingHelper.handleActivityResult(requestCode, resultCode, data);
}
handleActivityResult Method:
public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result;
if (requestCode != mRequestCode)
return false;
checkSetupDone("handleActivityResult");
Log.d("handleactivity","strat");
// end of async purchase operation
flagEndAsync();
if (data == null) {
logError("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);
if (resultCode == Activity.RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) {
logDebug("Successful resultcode from purchase activity.");
logDebug("Purchase data: " + purchaseData);
logDebug("Data signature: " + dataSignature);
logDebug("Extras: " + data.getExtras());
if (purchaseData == null || dataSignature == null) {
logError("BUG: either purchaseData or dataSignature is null.");
logDebug("Extras: " + data.getExtras().toString());
result = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature");
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(result, null);
}
return true;
}
Purchase purchase = null;
try {
purchase = new Purchase(purchaseData, dataSignature);
String sku = purchase.getSku();
// Verify signature
if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) {
logError("Purchase signature verification FAILED for sku " + sku);
result = new IabResult(IABHELPER_VERIFICATION_FAILED, "Signature verification failed for sku " + sku);
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(result, purchase);
}
return true;
}
logDebug("Purchase signature successfully verified.");
} catch (JSONException e) {
logError("Failed to parse purchase data.");
e.printStackTrace();
result = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data.");
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(result, null);
}
return true;
}
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Success"), purchase);
}
}
else if (resultCode == Activity.RESULT_OK) {
// result code was OK, but in-app billing response was not OK.
logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode));
if (mPurchaseListener != null) {
result = new IabResult(responseCode, "Problem purchashing item.");
mPurchaseListener.onIabPurchaseFinished(result, null);
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(result, null);
}
}
else {
logError("Purchase failed. Result code: " + Integer.toString(resultCode)
+ ". Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response.");
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(result, null);
}
}
return true;
}
Logcat output:
E/SIAPv3: In-app billing error: BUG: either purchaseData or dataSignature is null.
D/SIAPv3: Extras: Bundle[{RESPONSE_CODE=0}]
E/Michael: onIabPurchaseFinished
D/Onpurchasefinished: start
E/Michael: Try to print NULL object
E/Michael: IabResult: IAB returned null purchaseData or dataSignature (response: -1008:Unknown error)
When a Subscription expires it no longer appears in the list of purchases.
See the docs "The getPurchases() method does not return failed or expired subscriptions."
I am new to in-app purchase system. I just watched some tutorials, then implemented in-app purchase. However, when my in-app purchase was successful, it did not run my code. Does it have to run the following code?:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString(inappid);
Toast.makeText(
MainActivity.this,
"You have bought the " + sku
+ ". Excellent choice,adventurer!",
Toast.LENGTH_LONG).show();
writeInApp("1");
playGroundMain.bonus_pop_up(R.drawable.rich_big, "\"VIP Монстр\"");
playGroundMain.reWriteBonus("1", 6);
} catch (JSONException e) {
System.out.println("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
I've made a fair few apps with the payment system, you should take a look at this listener
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener()
{
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d(TAG, "Consumption finished. JSON: " + purchase.getOriginalJson() + ", signature: " + purchase.getSignature());
if (mHelper == null) return;
if (result.isSuccess())
{
Log.i(TAG, "BOUGHT THE ITEM :-)")
}
else
{
Log.e(TAG, "Error while consuming: " + result);
}
Log.d(TAG, "End consumption flow.");
}
};
you could add this listener in the consumeAsync function of the IabHelper like so:
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener()
{
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (purchase.getSku().equals(SKU_21500))
{
// bought 21500 credits
Log.d(TAG, "Purchase is 21500 credits. Starting credits consumption.");
try
{
mHelper.consumeAsync(purchase, mConsumeFinishedListener);
}
catch (IabHelper.IabAsyncInProgressException e)
{
Log.d(TAG, "Error consuming 21500 credits. Another async operation in progress.");
return;
}
}
}
}
And then you can put the "mPurchaseFinishedListener" in the "launchPurchaseFlow " function as so:
mHelper.launchPurchaseFlow(activity, item, REQUEST_CODE, mPurchaseFinishedListener);
REQUEST_CODE being 10001
Hope this helps!
If you are trying to do a non-consumable inapp purchase the code is fine.
When doing test purchases sometimes the onActivityResult() does not gets called. In a real purchase this may not happen.
To handle the purchase in that case you have to check result code == user already owns this item //resultCode 7, so that the user will not have to pay again in a situation like this.
When purchasing an item through google store using a test user, is there some kind of parameter that points out that this specific purchase was done by a test user?
Yes there is. Firstly read this official document
The variable you are looking for is called
productId
Check the following code. If payment is successful then,display that product(which you define).
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
entryFee.setVisibility(View.GONE);
paymentButton.setVisibility(View.GONE);
paymentText.setVisibility(View.GONE);
teamTextField.setVisibility(View.VISIBLE);
btn.setVisibility(View.VISIBLE);
aSwitch.setVisibility(View.VISIBLE);
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
Toast.makeText(
CreateLeague.this,
"You have bought the " + sku
+ ". Excellent choice,adventurer!",
Toast.LENGTH_LONG).show();
} catch (JSONException e) {
Toast.makeText(
CreateLeague.this,
"Failed to make purchase",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}
}
Hope this is going to be helpful.
Whenever starting payment service everything is ok but in activity result got Error
on activity result
RESULT_OK = 0 and resultCode =-1 as expect in sample example but i don't know where is going to wrong..
if (Navigator.REQUEST_PASSPORT_PURCHASE == requestCode) {
if (RESULT_OK == resultCode) {
dealWithSuccessfulPurchase();
} else {
dealWithFailedPurchase();
}
}
there is control goes in else statment ..
check my below code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + ","
+ data);
if (mHelper == null)
return;
if (requestCode == 10001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
Log.d("INAPP_PURCHASE_DATA", ">>>" + purchaseData);
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
Log.d("INAPP_DATA_SIGNATURE", ">>>" + dataSignature);
String continuationToken = data
.getStringExtra("INAPP_CONTINUATION_TOKEN");
Log.d("INAPP_CONTINUATION_TOKEN", ">>>" + continuationToken);
if (resultCode == RESULT_OK) {
try {
Log.d("purchaseData", ">>>"+purchaseData);
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();
}
} else if (resultCode == RESULT_CANCELED) {
// } else if (resultCode == RESULT_CANCELED) {
Toast.makeText(AppMainTest.this,
"Sorry, you have canceled purchase Subscription.",
Toast.LENGTH_SHORT).show();
} else if (resultCode == IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
Toast.makeText(AppMainTest.this, "Item already owned",
Toast.LENGTH_SHORT).show();
}
}
}
Hope it will solve your problem.