草庐IT

java - Google Play Developer API - 查询购买 token 返回无效值

coder 2023-08-27 原文

我正在尝试设置一个网络服务来查询 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,因为它看起来比手动创建请求更简洁。

感谢帮助和回复

最佳答案

First I want to share with you what is 400 bad request and what is the real cause for occuring it?

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

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

资源链接: Standard Error Responses

您的问题:

您的代码运行正常并返回相关的 json 文件作为输出。但是过了一段时间后,想获取购买信息时就不行了。它给出错误消息 “HTTP/1.1 400 Bad Request”

根本原因:

对于刷新 token ,响应总是包含一个新的访问 token 。响应如下所示:

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

因此,访问 token 有一个到期时间。过期后,访问 token 将失效。

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

因此,就您而言,您已经超过了创建刷新 token 的限制。

解决方案:

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

由于您正在使用刷新 token ,因此您需要将 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<NameValuePair> params = new ArrayList<NameValuePair>();
...............
...............

撤销程序:

有两种撤销方式。

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

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

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

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

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.

资源链接:

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

关于java - Google Play Developer API - 查询购买 token 返回无效值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35019357/

有关java - Google Play Developer API - 查询购买 token 返回无效值的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  5. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

    似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

  6. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  7. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  8. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  9. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐