Google Play Developer API – 查询购买代币会返回无效值

我正在尝试设置一项网络服务来查询Google Play购买。 我们会为客户存储订单信息,此服务会调用Google Play API来查询订阅详情。

每当我尝试查询购买时,它都会给我错误:

HTTP/1.1 400 Bad Request { "error":{ "errors":[ { "domain":"global", "reason":"invalid", "message":"Invalid Value" } ], "code":400, "message":"Invalid Value" } } 

这是我尝试过的:

  • 在https://console.developers.google.com中创建了一个项目,启用了“Google Play Android Developer API”
  • 为类型Web应用程序创建了oAuth 2.0 client_id和client_secret
  • 以帐户所有者身份登录后,我生成了一个refresh_token
  • 在https://play.google.com/apps/publish中,我转到了设置 – > API访问并将项目链接到我的应用

代码方面,我使用refresh_token来获取access_token:

 String refreshToken = "1/ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX"; HttpPost request = new HttpPost("https://accounts.google.com/o/oauth2/token"); List params = new ArrayList(); 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并获取响应:

 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... 

返回:

 { "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" } 

现在,我想获得有关购买的信息。 我有购买的信息:

 { "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 } 

现在,我想获得有关购买的信息。 我有购买的信息:

 { "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... 

由于packageName / productId和access_token似乎适用于第一次调用,而purchaseToken正好在订单信息之外。 什么是无效值错误?

任何帮助表示赞赏 – 不知道还有什么可以尝试。 谢谢!

更新:我通过并validation了所有的软件包名称和帐户设置真正的问题似乎是我正在打的服务。 我将其切换为: https : //www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/purchaseToken

我还交换使用Google客户端API,因为手动创建请求更加清晰。

感谢您的帮助和回复

首先,我想与您分享400个不良请求是什么,发生它的真正原因是什么?

Ans:表示查询无效。 例如,缺少父ID或请求的维度或指标的组合无效。

推荐的操作:您需要更改API查询才能使其正常工作。

资源链接: 标准错误响应

你的问题:

您的代码正常运行并返回相关的json文件作为输出。 但经过一段时间后, it is not working when you want to get information about purchaseit is not working when you want to get information about purchase 。 它给出错误消息“HTTP / 1.1 400 Bad Request”

根本原因:

对于刷新令牌,响应始终包含新的访问令牌。 回复如下所示:

 { "access_token":"1/fFBGRNJru1FQd44AzqT3ZgXXXXXX", "expires_in":3920, "token_type":"Bearer", } 

因此,访问令牌有一个到期时间。 到期时间后,访问令牌将无法正常工作。

还有另一个限制。 将发布的刷新令牌数量有限制; 每个客户端/用户组合一个限制,所有客户端的每个用户另一个限制。

因此,在您的情况下, 您已经超越了创建刷新令牌的限制。

解:

因此,您首先需要撤消令牌。 然后在长期存储中保存刷新令牌,并继续使用它们,只要它们保持有效。

当您使用刷新令牌时,您需要将http发布请求https://accounts.google.com/o/oauth2/token更改为https://www.googleapis.com/oauth2/v4/token

所以你的代码将如下所示:

 String refreshToken = "1/ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX"; HttpPost request = new HttpPost("https://www.googleapis.com/oauth2/v4/token"); List params = new ArrayList(); ............... ............... 

撤销程序:

有两种方法可以撤销。

  1. 用户可以通过访问“ 帐户设置”来撤消访问权限
  2. 应用程序也可以以编程方式撤销对其的访问权限。

要以编程方式撤消令牌,您的应用程序会向https://accounts.google.com/o/oauth2/revoke发出请求,并将令牌作为参数包含在内:

 curl https://accounts.google.com/o/oauth2/revoke?token={token} 

token可以是访问令牌或刷新令牌。 如果令牌是访问令牌并且它具有相应的刷新令牌,则刷新令牌也将被撤销。

注意:如果成功处理了吊销,则响应的状态代码为200.对于错误条件,将返回状态代码400以及错误代码。

资源链接:

  1. 脱机访问,使用刷新令牌和撤消令牌

当我使用静态响应进行测试时,即使用保留的产品ID进行测试(如android.test.purchased )时,就会发生这种情况。 在这种情况下,SkyWalker的解决方案没有帮助。

然后我使用了真实的产品ID,将我的应用程序发布为alpha到谷歌播放并将发布apk侧载到我的设备中,现在一切都按预期工作。

请务必仔细阅读Google文档中的设置测试购买章节, 以便正确准备您的应用和帐户以进行测试。