【问题标题】:Google Play Developer API - Query purchase token returns Invalid ValueGoogle Play Developer API - 查询购买令牌返回无效值
【发布时间】:2016-05-03 08:12:09
【问题描述】:

我正在尝试设置一个网络服务来查询 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"
   }
}

这是我尝试过的:

代码方面,我使用了 refresh_token 来获取 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");

这里的 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
}

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 正好在订单信息之外。什么是无效值错误?

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

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

我还改用了 Google Client API,因为它看起来比手动创建请求更简洁。

感谢您的帮助和回复

【问题讨论】:

  • 同样的问题,你解决了吗?
  • 同样的问题,你解决了吗?@Fid @Antoine 。按照第一个答案,我有同样的错误。
  • 我认为我的有效载荷不正确,但我不记得具体是哪一部分。
  • 拯救了我的一天!还需要把url改成“订阅”。
  • 你的问题解决了吗?

标签: java google-play


【解决方案1】:

首先我想和大家分享一下什么是400 bad request,什么是 发生的真正原因?

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

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

资源链接: Standard Error Responses

你的问题:

您的代码运行正常并返回相关的json 文件作为输出。但过了一段时间,it 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 post请求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<NameValuePair> params = new ArrayList<NameValuePair>();
...............
...............

撤销程序:

有两种撤销方式。

  1. 用户可以通过访问Account Settings撤销访问权限
  2. 应用程序还可以通过编程方式撤销授予它的访问权限。

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

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

token 可以是访问令牌或刷新令牌。如果token是访问token并且有对应的刷新token,那么刷新token也会被撤销。

N.B:如果撤销成功处理,则状态码 的响应是 200。对于错误条件,状态代码 400 是 连同错误代码一起返回。

资源链接:

  1. Offline access, Using refresh token and Revoke a token

【讨论】:

  • 嗨~@SkyWalker,我用了你的方法,但同样的错误,还有什么要尝试的吗?
  • @wawa 请查看我的另一个答案:stackoverflow.com/a/36266696/2293534 并查看本教程:developers.google.com/identity/protocols/OAuth2#basicsteps。希望它能澄清你的概念。
  • 嗨〜@SkyWalker,仔细检查你的两个答案,但我仍然得到错误:“错误”:{“错误”:[{“域”:“全球”,“原因”:“无效", "message": "无效值" } ], "code": 400, "message": "无效值" } 我该怎么办?
  • @wawa 我认为它是令牌过期问题。所以,我有一些问题1. Have you revoked your token yet? 2. Have your token not used more than 6 months? 3. Have you changed your password? 4. How much time you have token request? If it already over 25 times, creating a new token automatically invalidates the oldest token without warning. 另一种方式:如果可能,仅出于测试目的,您可以使用新邮件创建一个新令牌并检查它是否正常工作。您可以阅读令牌过期:developers.google.com/identity/protocols/OAuth2#expiration
  • 嗨~ @SkyWalker 谢谢你的回复。我撤销了我的 refresh_token 并创建了新的 refresh_token ,然后创建了新的 access_token ,然后请求购买信息,也返回“400 Invalid Value”。我没有更改了我的密码,也没有超过 25 次。
【解决方案2】:

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

然后我使用真实的产品 ID,将我的应用作为 Alpha 版发布到 google play 并将发布 apk 侧加载到我的设备中,现在一切都按预期工作了。

请务必仔细阅读谷歌文档中的 Setting Up for Test Purchases 章节,以正确准备您的应用和帐户以进行测试。

【讨论】:

    【解决方案3】:

    查看此内容以查看 API 请求和响应。需要API Explorer的帮助

    API: https://www.googleapis.com/androidpublisher/v1.1/applications/packageName/subscriptions/subscriptionId/purchases/token
    

    请求参数:

    包名:PACKAGE_NAME

    subscriptionId:SUBSCRIPTION_ID

    代币:PURCHASE_TOKEN

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 2018-02-13
      • 2014-07-28
      • 1970-01-01
      • 2018-03-06
      • 2014-03-08
      • 2014-03-25
      相关资源
      最近更新 更多