Google Play 开发者 API - 查询购买令牌返回无效值

2022-09-01 23:45:40

我正在尝试设置网络服务来查询 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<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似乎适用于第一次调用,并且购买Token就在订单信息之外。给出无效值错误的原因是什么?

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

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

我还交换了使用Google Client API,因为它看起来更干净,手动创建请求。

感谢您的帮助和回复


答案 1

首先,我想与您分享什么是400错误请求,以及发生它的真正原因是什么?

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

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

资源链接:标准错误响应

您的问题:

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

根源:

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

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

因此,访问令牌具有到期时间。到期时间后,访问令牌将不起作用。

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

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

溶液:

因此,首先需要吊销令牌。然后将刷新令牌保存在长期存储中,只要它们保持有效,就可以继续使用它们。

当您使用刷新令牌时,您需要将 http post 请求更改为https://accounts.google.com/o/oauth2/tokenhttps://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. 用户可以通过访问“帐户设置”来撤消访问权限
  2. 应用程序还可以以编程方式撤销授予它的访问权限。

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

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

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

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

资源链接:

  1. 脱机访问、使用刷新令牌和吊销令牌

答案 2

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

然后我使用真实的产品ID,将我的应用程序发布为alpha到Google Play,并将发布apk旁加载到我的设备中,现在一切都按预期工作。

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


推荐