Google Play Developer API - 查询购买令牌返回无效值 [英] Google Play Developer API - Query purchase token returns Invalid Value

查看:299
本文介绍了Google Play Developer API - 查询购买令牌返回无效值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  HTTP / 1.1 400错误请求
{
错误:{
错误:[
{
domain:global,
reason:invalid,
message:无效值
}

code:400,
message:无效值
}
}

这是我试过的:


  • href =https://console.developers.google.com =noreferrer> https://console.developers.google.com 启用了Google Play Android开发人员API

  • 为类型Web应用程序创建oAuth 2.0 client_id和client_secret
  • 以帐户所有者身份登录,我生成了一个refresh_token

  • https://play.google.com/apps/publish 我进入了设置 - > API访问并链接了项目我的应用程序



代码明智的是,我使用了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>();
...............
...............



撤销程序:



有两种撤销方式。


  1. 用户可以通过访问帐户设置

  2. 应用程序也可以以编程方式撤消对其的访问。 b

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

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

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


    注意:如果撤销成功处理,那么响应的状态码
    为200.对于错误条件,状态码400是
    ,并返回一个错误代码。




    资源链接:




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


    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:

    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.

    1. A user can revoke access by visiting Account Settings
    2. 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:

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

    这篇关于Google Play Developer API - 查询购买令牌返回无效值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆