I try to make Google Play Billing Service via com.android.billingclient:billing-dp1 library. I try starting the billing process by calling:
billingClient.launchBillingFlow(activity, params);
So the question is how to pass "developerPayload" argument to this flow? Both launchBillingFlow and it's params argument don't contain such a field.
Recently I opened an issue on the developers' page and they answered the following:
I just discovered that developerPayload doesn't always work. In several instances, for example when using a promo code, a later call to getPurchases() will not include the information that was sent. This limitation makes developerPayload useless. Google's official stance is that it should NOT be used for security purposes even though a bunch of documentation and the official Trivial Drive example say otherwise. Hope this saves you some time.
See details here
You cannot, if you look at the sources of BillingClientImpl you'll see this:
buyIntentBundle =
mService.getBuyIntent(3, mContext.getPackageName(), newSku, skuType, null);
The Last null is the developerPayload:
Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
String developerPayload);
So, no implementation for developerPayload yet.
Is the InitiatePurchase command used in billing? Because you pass the developerPayload in the InitiatePurchase command...
string developerPayload = "the info you are passing in the developerPayload";
m_storeController.InitiatePurchase (product, developerPayload);
That's it.
Related
I am trying to implement google pay for the first time. I am having a challenge of how to specify the the gateway and gatewayMarchantId.
What I have is google console a account and don't know where to find this information.
private static JSONObject getTokenizationSpecification() throws JSONException {
JSONObject tokenizationSpecification = new JSONObject();
tokenizationSpecification.put("type", "PAYMENT_GATEWAY");
tokenizationSpecification.put(
"parameters",
new JSONObject()
.put("gateway", "example")
.put("gatewayMerchantId", "exampleGatewayMerchantId"));
return tokenizationSpecification;
}
what do I replace example and gatewayMerchantId with for my payment to work?
Google Pay uses your preferred gateway (see supported processors as of today) to process the payment. To do that, you need to specify the identification details of the gateway. You can typically find these inside of your processor/gateway's online console. You can see an example of how that looks like in the TokenizationSpecification reference.
If you also need production access to Google Pay, you can do that using the following form. The team will get back to you as quickly as possible after you do that. Once you have production access, you'll be granted a merchant identifier that you can use to perform payments in your production environment. Note that this identifier is Google Pay specific only, and you need it in addition to your gateway merchant identifier.
Hope it helps.
I've implemented Google In-App Billing V3 in my app and i did my first test purchase. Now, as seen that i want it consumable, but if i click the "Purchase" button again i receive an error, i'm wondering how and where to insert "consumePurchase". I've been all day long on my computer searching on every thread, but i'm making confusion with old versions of the same. From what i saw, i need to call consumePurchase after the successfully purchased item AND when the activity is created, but i can't figure out how to do it.
Is this the one and only line of code?
int response = mService.consumePurchase(3, getPackageName(), token);
If so, what is "token"?
P.s. the consumable items are: 50, 150 and 300 coins that the user can buy to take a little advantage in the game.
Aaah, so confusing for me :/
As stated in the official documentetion: https://developer.android.com/google/play/billing/billing_reference.html
The response intent to the purchase includes several fields, one of them being:
INAPP_PURCHASE_DATA A String in JSON format that contains details
about the purchase order. See table 4 for a description of the JSON
fields.
Inside that JSON, you have several fields, also explained in that page, the one you are looking for is:
purchaseToken A token that uniquely identifies a purchase for a given
item and user pair.
All these is quite easy to follow from the official sample application, which I recommend you to download and try out, also to check the code.
Ok, i solved. Instead of using:
int response = mService.consumePurchase(3, getPackageName(), token);
follow this thread:
mService.consumePurchase(3, packageName, purchaseToken) always returns RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
Well I have read lots of time about "developer payload" But I am not clearly understand, what for "developer payload" used for. So I am trying to use this as blank like this:
public void onUpgradeAppButtonClicked(String SKU) {
Log.d(TAG,"Upgrade button clicked; launching purchase flow for upgrade.");
/*
* TODO: for security, generate your payload here for verification. See
* the comments on verifyDeveloperPayload() for more info. Since this is
* a SAMPLE, we just use an empty string, but on a production app you
* should carefully generate this.
*/
String payload = "";
mHelper.launchPurchaseFlow(this, SKU, RC_REQUEST,
mPurchaseFinishedListener, payload);
}
And this:
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
return true;
}
So I have make a image. for 3 Situations. I want to learn what will happen after condition
Yes the most possible shit occurs at scenario 2.
But how many users are on scenario 2? I think it would be not many. Most people don't share their devices.
But I'm thinking about another crack possibility if this payload string left empty. It would be easy to crack it down.
The only thing makes me mad is this thing should be on Google API side. Google's job to verify and make sure who purchased the item. Why we need our own server?
You should pass in a string token that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user.
Think of this as a receipt. If a customer came in and wanted to return an item or warranty, you'd want to be darned sure that receipt wasn't printed at home. Using this token will help prevent fraud.
It's not required, but it is advised. According to the docs you can send an empty string, though I'm not sure about null. It's advisable for security reasons though. You can use the payload to verify that the purchase was made by the user that you intended, for instance. See the billing Security Best Practices
All,
I am writing an android app and i am trying to use Google+ as my account manager.
I have followed excellent article here and i am prompted to sign into google+ and I event get a token back.
The problem is that the token does not appear to be a JWT ( i know this because there are only 2 dotted parts to the name instead of 3 and that when I pass the "token" to the java referenced in the same article I get an exception suggesting that the all is not well with the token :
com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:76)
at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
at com.google.api.client.json.webtoken.JsonWebSignature$Parser.parse(JsonWebSignature.java:473)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.parse(GoogleIdToken.java:57)
at Checker.check(Checker.java:34)
The code looks like this :-
String scope = "oauth2:server:client_id:";
scope += scope_; // my client id in the web section
scope += ":api_scope:";
String googleauth;
googleauth ="https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login";
scope+=googleauth;
try
{
String token = GoogleAuthUtil.getToken(act_, s_account, scope);
....
The application does ask for verification and I permit it (and call getToken again as you are supposed to).
But the token appears to be unusable, its bound to be something silly, but as yet I cannot see what.
Regards
Not sure what the problem is, but I've read in several places that you need to put some sort of workaround in place to make it work with the Google authentication. You can have a look at http://www.trajano.net/2014/07/parsing-the-json-web-token-in-java/
Hope this helps
We want to be able to associate app users with real transactions done.The problem is that we have the user’s email address on application back end side, and we track user purchase amounts, but when we go into the Google Wallet transactions we have no way of knowing which transaction/s belong to that user. We need a solution for this, because even if we have the user's email, we cannot search transactions by email address.
Is it possible to update the receipt numbers we are sending in the API to include the Google Wallet Receipt number instead of the time stamp ?
Please, provide us your suggestions.
I thought the answer would lie in the postback facility. That gives google's user ID and order number. However, I didn't see how to convert either of those to an email address for sending the digital good just purchased.
BTW. I rejected doing the fulfilment client side as that seemed insecure. If I'm wrong about that then why would they offer the postback facility?
... then I realised, we could do part of it client and part server side.
I guessed that something comes back from the client-side success callback.
success: function(result) {
console.log('success',result.response.orderId);
complete(result.response.orderId);
},
So, I now have the google's orderId on the client side and there I know the user's ID. So my complete() function can send the orderId and our userId to the server which can then match this with successful payment orderId from the postback (which happens first) and fulfil the order.
Yes, this is inelegant, but I believe it to be a secure solution.
Maybe slightly more elegant is to use the [sellerData] property in the submission payload to contain our user ID and order ref. We then have more items to match after the success callback has happened. I think I'll hold off delivering the digital good until all those checks have been completed.
What I do not understand is why cannot this kind of suggestion (or a better one) be found in the wallet tutorial?
Paul
My answer here refers to the previous answer provided:
Totally agree on "why cannot this kind of suggestion (or a better one) be found in the wallet tutorial?".
Your suggested solution does not seem to be very secured (to say the least). You want the client to send you their username/email/client-id in the Success callback... This means that anyone will be able to send you their ID, even if they did not make a purchase. They can add a random order-ID and hope to get a match (and then repeat the process many times in order to increase the chances).
My guess is that the username/email/client-id lies somewhere in the request object sent from Google to the postback URL (your server's doPost routine). But I have the feeling that you need to add something in the JWT generated in your Purchase function before it is passed to the google.payments.inapp.buy routine.
Looking for an answer myself...
Here is a possible solution, although I have not yet tested it myself:
Download the 'zip' file from: https://code.google.com/p/wallet-online-quickstart-java/downloads/list
Take the entire 'com' folder and add it to your project source folder (sorry, I have not been able to find a JAR for this package). Then, add the following code to your servlet:
...
import com.google.wallet.online.jwt.JwtResponseContainer;
import com.google.wallet.online.jwt.util.JwtGenerator;
import com.google.wallet.online.jwt.JwtResponse;
...
public void doPost(HttpServletRequest request, HttpServletResponse response) ...
{
try
{
String maskedWalletJwt = request.getParameter("maskedWalletJwt");
JwtResponseContainer jwtResponseContainer = JwtGenerator.jwtToJava(JwtResponseContainer.class, maskedWalletJwt, SellerSecret);
JwtResponse jwtResponse = jwtResponseContainer.getResponse();
String email = jwtResponse.getEmail();
...
}
}
One thing I'm not so sure about, is request.getParameter("maskedWalletJwt").
You might have to add this parameter when calling the google.payments.inapp.buy routine.