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

Fid*_*Fid 21 java google-play

我正在尝试设置一项网络服务来查询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"
   }
}
Run Code Online (Sandbox Code Playgroud)

这是我尝试过的:

代码方面,我使用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");
Run Code Online (Sandbox Code Playgroud)

来自此的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...
Run Code Online (Sandbox Code Playgroud)

返回:

{  
    "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"
}
Run Code Online (Sandbox Code Playgroud)

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

{  
"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
}
Run Code Online (Sandbox Code Playgroud)

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

{  
"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...
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

感谢您的帮助和回复

Sky*_*ker 11

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

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

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

资源链接: 标准错误响应

你的问题:

您的代码正常运行并返回相关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",
}
Run Code Online (Sandbox Code Playgroud)

因此,访问令牌有一个到期时间.在到期时间之后,访问令牌将无法工作.

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

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

解:

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

当您使用刷新令牌时,您需要将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>();
...............
...............
Run Code Online (Sandbox Code Playgroud)

撤销程序:

有两种方法可以撤销.

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

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

curl https://accounts.google.com/o/oauth2/revoke?token={token}
Run Code Online (Sandbox Code Playgroud)

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

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

资源链接:

  1. 离线访问,使用刷新令牌和撤消令牌