Google Play Developer API - 查询购买令牌返回无效值 [英] Google Play Developer API - Query purchase token returns Invalid Value
问题描述
我正在设置一项网络服务来查询Google Play购买。我们存储客户的订单信息,此服务将调用Google Play API来查询订阅详细信息。
每当我尝试查询购物时,它都会给我提供错误:
HTTP / 1.1 400错误请求
{
错误:{
错误:[
{
domain:global,
reason:invalid,
message:无效值
}
,
code:400,
message:无效值
}
}
这是我试过的:
代码明智的是,我使用了refresh_token来获取access_token:
字符串refreshToken =1 / ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX;
HttpPost请求=新的HttpPost(https://accounts.google.com/o/oauth2/token);
列表< NameValuePair> params = new ArrayList< NameValuePair>();
params.add(new BasicNameValuePair(client_id,client_id));
params.add(new BasicNameValuePair(client_secret,client_secret));
params.add(new BasicNameValuePair(refresh_token,refreshToken));
params.add(new BasicNameValuePair(grant_type,refresh_token));
request.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
JSONObject json = new JSONObject(body);
String accessToken = json.getString(access_token);
这个函数的access_token可以工作,因为我可以调用这个API并获得响应:
字符串url = String.format(https://www.googleapis.com/androidpublisher/v2/applications/%s/inappproducts /%s,packageName,productId);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader(Authorization,Bearer+ accessToken);
HttpResponse response = client.execute(get);
//解析响应等...
返回:
{
packageName:com.my.app,
sku:com.my.app。
status:active,
purchaseType:subscription,
defaultPrice:{
// ...
}
,
列表:{
en-US:{
title:My App Premium,
description:My应用程序
},
defaultLanguage:en-US,
subscriptionPeriod:P1Y
}
现在,我想获取有关购买的信息。我有一个购买信息:
{
可以是访问令牌或刷新令牌。如果令牌是访问令牌并且它具有相应的刷新令牌,则刷新令牌也将被撤销。
orderId:GPA.1111-1111- 1111-11111,
packageName:com.my.app,
productId:com.my.app.premium,
purchaseTime:1452801843877,
purchaseState:0,
developerPayload: XXXXXXXd9261023a407ae5bb6ab8XXXXXXX,
purchaseToken: xxxxxxxxxxxxxx.YY-J123o12-xxxxxxxxxxxxxxxmYRk2itBkNdlXhyLMjXsxxxxxxxxxxxxLfBxabaAjKbeBC0PVhHnHd1DDbFkgZtbQxxk5pDIAH3xBHu8HrcWfRgewAYnFeW9xxxxxxxxxxxxxC5TDjcBL8fhf,
autoRenewing:真
$ b现在,我想获得有关购买的信息。我有一个购买信息:
{
orderId:GPA.1111-1111- 1111-11111,
packageName:com.my.app,
productId:com.my.app.premium,
purchaseTime:1452801843877,
purchaseState:0,
developerPayload: XXXXXXXd9261023a407ae5bb6ab8XXXXXXX,
purchaseToken: xxxxxxxxxxxxxx.YY-J123o12-xxxxxxxxxxxxxxxmYRk2itBkNdlXhyLMjXsxxxxxxxxxxxxLfBxabaAjKbeBC0PVhHnHd1DDbFkgZtbQxxk5pDIAH3xBHu8HrcWfRgewAYnFeW9xxxxxxxxxxxxxC5TDjcBL8fhf,
autoRenewing:真
}
String url = String.format(https://www.googleapis.com/androidpublisher/v2/applications/%s/purchases/products/%s/tokens/%s ,packageName,productId,purchaseToken);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader(Authorization,Bearer+ accessToken);
HttpResponse response = client.execute(get);
//解析响应等...
由于packageName / productId和access_token似乎为第一个电话工作,并且purchaseToken正确无误。什么是给无效值的错误?
任何帮助表示赞赏 - 不知道还有什么要尝试。
更新:
我经历了所有的软件包名称和帐户设置验证
真正的问题似乎是我打的服务。我将它切换为:
https: //www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/purchaseToken
我也换成使用谷歌客户端API,因为它更清洁手动创建请求。
感谢您的帮助和回复
解决方案
首先,我想和大家分享什么是 400错误请求,发生错误的真正原因是什么? / p>
回答:表示查询无效。例如,家长标识缺失或者所请求的维度或指标组合无效。
推荐的操作:您需要更改API查询以便使用。
资源链接: 标准错误响应
您的问题:
您的代码正常运行并返回相关的
json
文件作为输出。但经过一段时间后,在您想要获取有关购买
的信息时无法使用。它发出错误消息HTTP / 1.1 400错误请求
根本原因:
<对于刷新令牌,响应始终包含一个新的访问令牌。答案如下:
{
access_token:1 / fFBGRNJru1FQd44AzqT3ZgXXXXXX,
expires_in:3920,
token_type:承载者,
}
因此,访问令牌有一个到期时间。在到期之后,访问令牌将不起作用。
另外还有一个限制。刷新令牌的数量会有限制,每个客户/用户组合的一个限制,以及所有客户端的另一个用户。
因此,就您的情况而言,您已经越过了创建刷新令牌的限制。
解决方案:
所以,你首先需要撤消令牌。然后将刷新标记保存在长期存储中,只要它们保持有效,就继续使用它们。
当您使用刷新令牌时,您需要更改http发布请求
https://accounts.google.com/o/oauth2/token
至https://www.googleapis.com/oauth2/v4 /令牌
所以你的代码如下所示:
String refreshToken =1 / ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX;
HttpPost请求=新的HttpPost(https://www.googleapis.com/oauth2/v4/token);
列表< NameValuePair> params = new ArrayList< NameValuePair>();
...............
...............
撤销程序:
有两种撤销方式。
- 用户可以通过访问帐户设置
- 应用程序也可以以编程方式撤消对其的访问。 b
要以编程方式撤消令牌,您的应用程序向
https://accounts.google.com/o/oauth2/revoke
发出请求,并将令牌作为参数:
卷曲https://accounts.google.com/o/oauth2/revoke?token={token}
令牌
注意:如果撤销成功处理,那么响应的状态码
为200.对于错误条件,状态码400是
,并返回一个错误代码。
资源链接:
I am trying to set up a web service to query Google Play purchases. We store the order information for customers and this service would call Google Play API to query the subscription details.
Every time i try to query a purchase, it gives me the error:
HTTP/1.1 400 Bad Request { "error":{ "errors":[ { "domain":"global", "reason":"invalid", "message":"Invalid Value" } ], "code":400, "message":"Invalid Value" } }
Here is what I tried:
- Created a project in https://console.developers.google.com enabled the "Google Play Android Developer API"
- Created an oAuth 2.0 client_id and client_secret for type Web application
- Logged in as the account owner, I generated a refresh_token
- In https://play.google.com/apps/publish I went to Settings -> API Access and linked the the project to my app
Code wise, I used the refresh_token to get an access_token:
String refreshToken = "1/ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX";
HttpPost request = new HttpPost("https://accounts.google.com/o/oauth2/token");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("client_id", client_id));
params.add(new BasicNameValuePair("client_secret", client_secret));
params.add(new BasicNameValuePair("refresh_token", refreshToken));
params.add(new BasicNameValuePair("grant_type", "refresh_token"));
request.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
JSONObject json = new JSONObject(body);
String accessToken = json.getString("access_token");
The access_token from this works because i can call this API with it and get the response back:
String url = String.format("https://www.googleapis.com/androidpublisher/v2/applications/%s/inappproducts/%s", packageName, productId);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader("Authorization", "Bearer " + accessToken);
HttpResponse response = client.execute(get);
// parse response etc...
This returns:
{
"packageName":"com.my.app",
"sku":"com.my.app.premium",
"status":"active",
"purchaseType":"subscription",
"defaultPrice":{
//...
}
},
"listings":{
"en-US":{
"title":"My App Premium",
"description":"My App"
}
},
"defaultLanguage":"en-US",
"subscriptionPeriod":"P1Y"
}
Now, I want to get informatoin about a purchase. I have a information from a purchase as such:
{
"orderId":"GPA.1111-1111-1111-11111",
"packageName":"com.my.app",
"productId":"com.my.app.premium",
"purchaseTime":1452801843877,
"purchaseState":0,
"developerPayload":"XXXXXXXd9261023a407ae5bb6ab8XXXXXXX",
"purchaseToken":"xxxxxxxxxxxxxx.YY-J123o12-xxxxxxxxxxxxxxxmYRk2itBkNdlXhyLMjXsxxxxxxxxxxxxLfBxabaAjKbeBC0PVhHnHd1DDbFkgZtbQxxk5pDIAH3xBHu8HrcWfRgewAYnFeW9xxxxxxxxxxxxxC5TDjcBL8fhf",
"autoRenewing":true
}
Now, I want to get informatoin about a purchase. I have a information from a purchase as such:
{
"orderId":"GPA.1111-1111-1111-11111",
"packageName":"com.my.app",
"productId":"com.my.app.premium",
"purchaseTime":1452801843877,
"purchaseState":0,
"developerPayload":"XXXXXXXd9261023a407ae5bb6ab8XXXXXXX",
"purchaseToken":"xxxxxxxxxxxxxx.YY-J123o12-xxxxxxxxxxxxxxxmYRk2itBkNdlXhyLMjXsxxxxxxxxxxxxLfBxabaAjKbeBC0PVhHnHd1DDbFkgZtbQxxk5pDIAH3xBHu8HrcWfRgewAYnFeW9xxxxxxxxxxxxxC5TDjcBL8fhf",
"autoRenewing":true
}
String url = String.format("https://www.googleapis.com/androidpublisher/v2/applications/%s/purchases/products/%s/tokens/%s",packageName, productId, purchaseToken);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader("Authorization", "Bearer " + accessToken);
HttpResponse response = client.execute(get);
// parse response etc...
Since the packageName / productId and access_token seem to work for the first call, and the purchaseToken is right out of the order info. What is giving the invalid value error?
Any help appreciated - not sure what else to try. Thanks!
UPDATE: I went through and validated all the package names and account setup The real issue seemed to be the service i was hitting. I switched it to: https://www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/purchaseToken
I also swapped to use the Google Client API as it was much cleaner looking that manually creating requests.
Thanks for help and replies
First I want to share with you what is 400 bad request and what is the real cause for occuring it?
Ans: It indicates that the query was invalid. E.g., parent ID was missing or the combination of dimensions or metrics requested was not valid.
Recommended Action: You need to make changes to the API query in order for it to work.
Resource Link: Standard Error Responses
Your problem:
Your code was running properly and returning related json
file as output. But after a period,it is not working when you want to get information about purchase
. It gives error message "HTTP/1.1 400 Bad Request"
Root cause:
For refresh token, the response always includes a new access token. A response is shown below:
{
"access_token":"1/fFBGRNJru1FQd44AzqT3ZgXXXXXX",
"expires_in":3920,
"token_type":"Bearer",
}
So, access token has a expiry time. after a expiry time, the access token will not work.
There is another restriction also. There are limits on the number of refresh tokens that will be issued; one limit per client/user combination, and another per user across all clients.
So, in your case, you have already crossed your limit of creating refresh token.
Solution:
So, you first need to revoke the token. Then save refresh tokens in long-term storage and continue to use them as long as they remain valid.
As you are using refresh token, then you need to change the http post request https://accounts.google.com/o/oauth2/token
to https://www.googleapis.com/oauth2/v4/token
So your code will be look like below:
String refreshToken = "1/ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX";
HttpPost request = new HttpPost("https://www.googleapis.com/oauth2/v4/token");
List<NameValuePair> params = new ArrayList<NameValuePair>();
...............
...............
Revoking procedure:
There are 2 ways for revoking.
- A user can revoke access by visiting Account Settings
- It is also possible for an application to programmatically revoke the access given to it.
To programmatically revoke a token, your application makes a request to https://accounts.google.com/o/oauth2/revoke
and includes the token as a parameter:
curl https://accounts.google.com/o/oauth2/revoke?token={token}
The token
can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token will also be revoked.
N.B: If the revocation is successfully processed, then the status code of the response is 200. For error conditions, a status code 400 is returned along with an error code.
Resource Link:
这篇关于Google Play Developer API - 查询购买令牌返回无效值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!