I am using current code for purchase for calling purchase intent
Bundle buyIntentBundle = mService.getBuyIntent(3, pContext.getPackageName(), "android.test.canceled", "inapp", "bGoa+V7g/yqDXv");
Set<String> allKeys = buyIntentBundle.keySet();
Object responseCode= buyIntentBundle.get("RESPONSE_CODE");
Object intent= buyIntentBundle.get("BUY_INTENT");
Log.i(TAG,"buyIntentBundle"+buyIntentBundle.keySet()+"responseCode"+responseCode+"intent"+intent);
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
if (pendingIntent != null) {
pContext.startIntentSenderForResult(pendingIntent.getIntentSender(), 2013, new Intent(), Integer.valueOf(0), Integer.valueOf(0),Integer.valueOf(0));
}
Now onActivityResult i am checking
if (requestCode == 2013) {
Log.i(TAG, "onactivity result called inside request code");
int responseCode = intent.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = intent.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = intent.getStringExtra("INAPP_DATA_SIGNATURE");
if (responseCode == Constants.BILLING_RESPONSE_RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
Toast.makeText(pContext, "You have bought the " + sku + ". Excellent choice, adventurer!", Toast.LENGTH_SHORT);
JSONObject o = new JSONObject(purchaseData);
String mOrderId = o.optString("orderId");
String mPackageName = o.optString("packageName");
String mSku = o.optString("productId");
long mPurchaseTime = o.optLong("purchaseTime");
int mPurchaseState = o.optInt("purchaseState");
String mDeveloperPayload = o.optString("developerPayload");
String mToken = o.optString("token", o.optString("purchaseToken"));
try {
mService.consumePurchase(3, pContext.getPackageName(), mToken);
} catch (RemoteException e) {
e.printStackTrace();
}//consumePurchase
}
catch (JSONException e) {
Toast.makeText(pContext, "Failed to parse purchase data.", Toast.LENGTH_SHORT);
e.printStackTrace();
}
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_USER_CANCELED) {
Toast.makeText(pContext, "User cancelled purchase.", Toast.LENGTH_SHORT);
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE) {
Toast.makeText(pContext, "Your Device doesn't support inapp billing.", Toast.LENGTH_SHORT);
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE) {
Toast.makeText(pContext, "Item is not available for billing.", Toast.LENGTH_SHORT);
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_DEVELOPER_ERROR) {
Toast.makeText(pContext, "Can't purchase item due to some developer error.", Toast.LENGTH_SHORT);
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ERROR) {
Toast.makeText(pContext, "Can't purchase item due to some error in response.", Toast.LENGTH_SHORT);
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
Toast.makeText(pContext, "You already own this item.", Toast.LENGTH_SHORT);
}else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED) {
Toast.makeText(pContext, "You don't own this item.", Toast.LENGTH_SHORT);
}
}
Since i am calling "android.test.canceled" so i should be getting BILLING_RESPONSE_RESULT_USER_CANCELED this response but it shows as payment successful and returns responseCode as BILLING_RESPONSE_RESULT_OK with no other parameter in that intent.getExtras.
I am trying static responses
http://developer.android.com/google/play/billing/billing_testing.html#billing-testing-static
Thanks & Regards!!
You are not checking:
if (resultCode == Activity.RESULT_OK) {
....
}
It's possible that the process does not complete successfully. And since the default value for responseCode in case that key "RESPONSE_CODE" is not present in intent is "0"....
int responseCode = intent.getIntExtra("RESPONSE_CODE", 0);
.... responseCode is initialized to Constants.BILLING_RESPONSE_RESULT_OK == > 0.
Try using:
int responseCode = intent.getIntExtra("RESPONSE_CODE", -1);
And add a final else block to handle -1.
Related
After a user has payed via PayPal on my android app I want the PaymentId to be displayed, with the state and the amount they have just payed. When i'm trying to get the id from the JSONObject it keeps saying "No value for id" when the id in the logcat has a value.
ID Has A Value As Shown
When I get to the line textViewId.setText(jsonObject.getString("id")); it jumps to the catch and displayed the error "No value for id". Even though in the logcat there is a value.
Below is my code.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == PAYPAL_REQUEST_CODE)
{
if (resultCode == RESULT_OK)
{
PaymentConfirmation confirmation = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
if (confirmation != null)
{
try
{
String paymentDetails = confirmation.toJSONObject().toString(4);
JSONObject jsonObject = new JSONObject(paymentDetails);
// String id = jsonObject.getString("id");
// String status = jsonObject.getString("state");
// startActivity(new Intent(getActivity(), PaymentDetails.class)
// .putExtra("PaymentDetails", paymentDetails)
// .putExtra("PaymentAmount", totalAmount + commisionAmount));
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
View mView = getLayoutInflater().inflate(R.layout.popup_payment_successful, null);
alertDialog.setTitle("Payment Successful");
alertDialog.setView(mView);
final AlertDialog dialog = alertDialog.create();
dialog.show();
TextView textViewId = mView.findViewById(R.id.textId);
TextView textViewAmount = mView.findViewById(R.id.textAmount);
TextView textViewStatus = mView.findViewById(R.id.textStatus);
jsonObject.has("id");
textViewId.setText(jsonObject.getString("id"));
textViewAmount.setText((int) (totalAmount + commisionAmount));
textViewStatus.setText(jsonObject.getString("state"));
} catch (JSONException e)
{
e.printStackTrace();
}
}
} else if (resultCode == Activity.RESULT_CANCELED)
{
Toast.makeText(getActivity(), "Cancel", Toast.LENGTH_SHORT).show();
}
} else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID)
{
Toast.makeText(getActivity(), "Invalid", Toast.LENGTH_SHORT).show();
}
}
Apparently your id is inside response jsonobject so do
JSONObject jsonObject = new JSONObject(paymentDetails);
JSONObject jsonObject1 = jsonObject.optJSONObject("response");// return null or found object
if(jsonObject1 != null){
String id = jsonObject1.optString("id",""); //return value or empty string
String status = jsonObject1.optString("state","");
}
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 using sandbox account and following the tutorial http://androiddevelopmentanddiscussion.blogspot.com/2014/05/paypal-integration-in-android.html
I have given the client id which i have achieved by logging into sandbox account from my selling tools->api access
Here is my code:
private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX;
// note that these credentials will differ between live & sandbox environments.
private static final String CONFIG_CLIENT_ID = "";
private static final int REQUEST_CODE_PAYMENT = 1;
private static final int REQUEST_CODE_FUTURE_PAYMENT = 2;
private static PayPalConfiguration config = new PayPalConfiguration()
.environment(CONFIG_ENVIRONMENT)
.clientId(CONFIG_CLIENT_ID)
// The following are only used in PayPalFuturePaymentActivity.
.merchantName(" ")
.merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
.merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));
PayPalPayment thingToBuy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, PayPalService.class);
intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
startService(intent);
}
public void onBuyPressed(View pressed) {
// PAYMENT_INTENT_SALE will cause the payment to complete immediately.
// Change PAYMENT_INTENT_SALE to PAYMENT_INTENT_AUTHORIZE to only authorize payment and
// capture funds later.
if(pressed.getId() == R.id.button1){
thingToBuy = new PayPalPayment(new BigDecimal("8"), "USD", "Painting 1", PayPalPayment.PAYMENT_INTENT_SALE);
}else if(pressed.getId() == R.id.button2){
thingToBuy = new PayPalPayment(new BigDecimal("4"), "USD", "Painting 2", PayPalPayment.PAYMENT_INTENT_SALE);
}
Intent intent = new Intent(MainActivity.this, PaymentActivity.class);
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);
startActivityForResult(intent, REQUEST_CODE_PAYMENT);
}
public void onFuturePaymentPressed(View pressed) {
Intent intent = new Intent(MainActivity.this, PayPalFuturePaymentActivity.class);
startActivityForResult(intent, REQUEST_CODE_FUTURE_PAYMENT);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PAYMENT) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm =
data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
if (confirm != null) {
try {
Log.i(TAG, confirm.toJSONObject().toString(4));
Log.i(TAG, confirm.getPayment().toJSONObject().toString(4));
Toast.makeText(
getApplicationContext(),
"PaymentConfirmation info received from PayPal", Toast.LENGTH_LONG)
.show();
} catch (JSONException e) {
Log.e(TAG, "an extremely unlikely failure occurred: ", e);
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i(TAG, "The user canceled.");
} else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
Log.i(TAG,"An invalid Payment or PayPalConfiguration was submitted. Please see the docs.");
}
} else if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) {
if (resultCode == Activity.RESULT_OK) {
PayPalAuthorization auth =
data.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
if (auth != null) {
try {
Log.i("FuturePaymentExample", auth.toJSONObject().toString(4));
String authorization_code = auth.getAuthorizationCode();
Log.i("FuturePaymentExample", authorization_code);
sendAuthorizationToServer(auth);
Toast.makeText(
getApplicationContext(),
"Future Payment code received from PayPal", Toast.LENGTH_LONG)
.show();
} catch (JSONException e) {
Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e);
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i("FuturePaymentExample", "The user canceled.");
} else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
Log.i(
"FuturePaymentExample",
"Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
}
}
}
private void sendAuthorizationToServer(PayPalAuthorization authorization) {
}
public void onFuturePaymentPurchasePressed(View pressed) {
// Get the Application Correlation ID from the SDK
String correlationId = PayPalConfiguration.getApplicationCorrelationId(this);
Log.i("FuturePaymentExample", "Application Correlation ID: " + correlationId);
// TODO: Send correlationId and transaction details to your server for processing with
// PayPal...
Toast.makeText(
getApplicationContext(), "App Correlation ID received from SDK", Toast.LENGTH_LONG)
.show();
}
#Override
public void onDestroy() {
// Stop service when done
stopService(new Intent(this, PayPalService.class));
super.onDestroy();
}
Here is the log message:
01-12 06:32:04.143: E/paypal.sdk(1778): request failure with http statusCode:401,exception:org.apache.http.client.HttpResponseException: Unauthorized
01-12 06:32:04.143: E/paypal.sdk(1778): request failed with server response:{"error":"invalid_client","error_description":"The client credentials are invalid"}
01-12 06:32:04.143: E/PayPalService(1778): invalid_client
I am new in this topic so explanation would be nice.
Use your sandbox credential (Client id) here.
private static final String CONFIG_CLIENT_ID = "";
Or follow below links:
Paypal integration using SDK
Paypal integration using gradle integration
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.
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.