無法從 Google Play Android Developer API 取得訂閱資訊

我正在尝试使用适用于 Java 的 Google API 客户端库来获取有关用户在我的 Android 应用中购买的订阅的信息。以下是我现在的做法:

HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();

GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                    .setJsonFactory(JSON_FACTORY)
                    .setServiceAccountId(GOOGLE_CLIENT_MAIL)
                    .setServiceAccountScopes("https://www.googleapis.com/auth/androidpublisher")
                    .setServiceAccountPrivateKeyFromP12File(new File(GOOGLE_KEY_FILE_PATH))
                    .build();

Androidpublisher publisher = new Androidpublisher.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).
                    setApplicationName(GOOGLE_PRODUCT_NAME).
                    build();

Androidpublisher.Purchases purchases = publisher.purchases();
Get get = purchases.get("XXXXX", subscriptionId, token);
SubscriptionPurchase subscripcion = get.execute(); //Exception returned here

GOOGLE_CLIENT_MAIL是来自 Google Console 的 API Access 的电子邮件地址。 是从 API 访问下载的 p12 文件。
是品牌信息中的产品名称。
在Google APIS Console中,启用了“Google Play Android Developer API”服务。GOOGLE_KEY_FILE_PATHGOOGLE_PRODUCT_NAME

我得到的是:

{
  "code" : 401,
  "errors" : [ {
    "domain" : "androidpublisher",
    "message" : "This developer account does not own the application.",
    "reason" : "developerDoesNotOwnApplication"
  } ],
  "message" : "This developer account does not own the application."
}

我非常感谢你对这个问题的帮助...


答案 1

我让它工作!我遵循的步骤:

先决条件

在开始之前,我们需要生成一个刷新令牌。首先,我们必须创建一个 API 控制台项目:

  1. 转到 API 控制台并使用您的 Android 开发者帐户(与 Android 开发者控制台中用于上传 APK 的帐户相同)登录。
  2. 选择“创建项目”。
  3. 转到左侧导航面板中的“服务”。
  4. 打开 Google Play Android Developer API
  5. 接受服务条款。
  6. 转到左侧导航面板中的 API 访问。
  7. 选择“创建 OAuth 2.0 客户端 ID”:
    • 在第一页上,您需要填写产品名称,但不是必需的徽标。
    • 在第二页上,选择“Web 应用程序”并设置重定向 URI 和 Javascript 源。我们稍后将使用它作为重定向 URI。
  8. 选择“创建客户端 ID”。请记住“客户端 ID”“客户端密码”,我们稍后将使用它们。

因此,现在我们可以生成刷新令牌:

  1. 转到以下 URI(请注意,重定向 URI 必须与客户端 ID 中输入的值完全匹配,包括任何尾部反斜杠):

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=REDIRECT_URI&client_id=CLIENT_ID

  1. 选择“出现提示时允许访问”。
  2. 浏览器将使用代码参数重定向到您的重定向URI,该参数看起来类似于4 / eWdxD7b-YSQ5CNNb-c2iI83KQx19.wp6198ti5Zc7dJ3UXOl0T3aRLxQmbwI。复制此值。

使用以下命令创建主类:

public static String getRefreshToken(String code)
{

    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/token");
    try 
    {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(5);
        nameValuePairs.add(new BasicNameValuePair("grant_type",    "authorization_code"));
        nameValuePairs.add(new BasicNameValuePair("client_id",     GOOGLE_CLIENT_ID));
        nameValuePairs.add(new BasicNameValuePair("client_secret", GOOGLE_CLIENT_SECRET));
        nameValuePairs.add(new BasicNameValuePair("code", code));
        nameValuePairs.add(new BasicNameValuePair("redirect_uri", GOOGLE_REDIRECT_URI));
        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        org.apache.http.HttpResponse response = client.execute(post);
        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuffer buffer = new StringBuffer();
        for (String line = reader.readLine(); line != null; line = reader.readLine())
        {
            buffer.append(line);
        }

        JSONObject json = new JSONObject(buffer.toString());
        String refreshToken = json.getString("refresh_token");                      
        return refreshToken;
    }
    catch (Exception e) { e.printStackTrace(); }

    return null;
}

GOOGLE_CLIENT_ID,并且是以前的值。GOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URI

最后,我们有刷新令牌!此值不会过期,因此我们可以存储在某个站点中,例如属性文件。

访问 Google Play Android Developer API

  1. 获取访问令牌。我们将需要我们之前的刷新令牌:

    private static String getAccessToken(String refreshToken){
    
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/token");
    try 
    {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
        nameValuePairs.add(new BasicNameValuePair("grant_type",    "refresh_token"));
        nameValuePairs.add(new BasicNameValuePair("client_id",     GOOGLE_CLIENT_ID));
        nameValuePairs.add(new BasicNameValuePair("client_secret", GOOGLE_CLIENT_SECRET));
        nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    
        org.apache.http.HttpResponse response = client.execute(post);
        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuffer buffer = new StringBuffer();
        for (String line = reader.readLine(); line != null; line = reader.readLine())
        {
            buffer.append(line);
        }
    
        JSONObject json = new JSONObject(buffer.toString());
        String accessToken = json.getString("access_token");
    
        return accessToken;
    
    }
    catch (IOException e) { e.printStackTrace(); }
    
    return null;
    

    }

  2. 现在,我们可以访问 Android API。我对订阅的到期时间很感兴趣,所以:

    private static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    private static JsonFactory JSON_FACTORY = new com.google.api.client.json.jackson2.JacksonFactory();
    
    private static Long getSubscriptionExpire(String accessToken, String refreshToken, String subscriptionId, String purchaseToken){
    
    try{
    
        TokenResponse tokenResponse = new TokenResponse();
        tokenResponse.setAccessToken(accessToken);
        tokenResponse.setRefreshToken(refreshToken);
        tokenResponse.setExpiresInSeconds(3600L);
        tokenResponse.setScope("https://www.googleapis.com/auth/androidpublisher");
        tokenResponse.setTokenType("Bearer");
    
        HttpRequestInitializer credential =  new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setClientSecrets(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
                .build()
                .setFromTokenResponse(tokenResponse);
    
        Androidpublisher publisher = new Androidpublisher.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).
                setApplicationName(GOOGLE_PRODUCT_NAME).
                build();
    
        Androidpublisher.Purchases purchases = publisher.purchases();
        Get get = purchases.get(GOOGLE_PACKAGE_NAME, subscriptionId, purchaseToken);
        SubscriptionPurchase subscripcion = get.execute();
    
        return subscripcion.getValidUntilTimestampMsec();
    
    }
    catch (IOException e) { e.printStackTrace(); }
    return null;
    

    }

仅此而已!

有些步骤来自 https://developers.google.com/android-publisher/authorization


答案 2

您可以使用 和 库。com.google.api-clientgoogle-api-services-androidpublisher

首先转到Google开发人员控制台上的项目(https://console.developers.google.com)

  • API 和身份验证 -> API
  • 启用“Google Play Android Developer API”
  • 转到“凭据” - >创建新的客户端 ID
  • 选择服务帐户
  • 创建客户机标识
  • 将 p12 文件保存在安全的地方

然后将刚刚为服务帐户生成的电子邮件地址添加到您的Google Play开发者控制台(https://play.google.com/apps/publish/)

  • 设置 - >用户和权限 - >邀请新用户
  • 粘贴电子邮件帐户@developer.gserviceaccount.com
  • 选择“查看财务报告”
  • 发送邀请

现在进入代码。将以下依赖项添加到 pom.xml 文件中:

<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.18.0-rc</version>
</dependency>
<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client-jackson2</artifactId>
    <version>1.18.0-rc</version>
</dependency>
<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-androidpublisher</artifactId>
    <version>v1.1-rev25-1.18.0-rc</version>
</dependency>

然后首先验证签名:

byte[] decoded = BASE64DecoderStream.decode(KEY.getBytes());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(decoded));
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
if (sig.verify(BASE64DecoderStream.decode(signature.getBytes())))
{
    // Valid
}

如果签名验证提取订阅详细信息:

// fetch signature details from google
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(jsonFactory)
    .setServiceAccountId(ACCOUNT_ID)
    .setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/androidpublisher"))
    .setServiceAccountPrivateKeyFromP12File(new File("key.p12"))
    .build();

AndroidPublisher pub = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential)
    .setApplicationName(APPLICATION_NAME)
    .build();
AndroidPublisher.Purchases.Get get = pub.purchases().get(
    APPLICATION_NAME,
    PRODUCT_ID,
    token);
SubscriptionPurchase subscription = get.execute();
System.out.println(subscription.toPrettyString());

这将通过生成 JWT 令牌来处理所有令牌问题,因此您不必自己处理它。


推荐