Impossible d'obtenir les informations d'abonnement à partir de L'API de développeur Android de Google Play

j'essaie D'utiliser la bibliothèque Client APIs de Google pour Java pour obtenir des informations sur les abonnements des utilisateurs achetés sur mon application android. Voici comment je fais pour l'instant:

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 est l'adresse e-mail de L'accès API à partir de la Console Google. GOOGLE_KEY_FILE_PATH est le fichier P12 téléchargé depuis L'accès API.

GOOGLE_PRODUCT_NAME est le nom du Produit tiré de l'information sur l'image de marque.

Dans Google APIS Console le Service "Google Play Android Developer API" est permettre.

Ce que j'obtiens est:

{
  "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."
}

j'apprécie vraiment votre aide pour ce problème...

23
demandé sur Jonathan Naguin 2012-06-20 12:14:03

5 réponses

je l'ai eu à travailler! Les étapes que j'ai suivies:

condition préalable

avant de démarrer, nous devons générer un jeton de rafraîchissement. Pour ce faire, nous devons d'abord créer un projet de console APIs:

  1. Aller à l' Console APIs et connectez-vous avec votre développeur Android compte (le même que celui utilisé dansDéveloppeur Android Console télécharger l'APK).
  2. Sélectionnez Créer un projet.
  3. aller aux Services dans le panneau de navigation de gauche.
  4. tournez le Google Play Android Developer API.
  5. accepter les conditions de Service.
  6. allez à accès API dans le panneau de navigation de gauche.
  7. sélectionnez Créer un ID client 2.0:
    • Sur la première page, vous aurez besoin de remplir le nom du produit, mais un le logo n'est pas nécessaire.
    • Sur la deuxième page, sélectionnez application web et régler le redirect URI et les origines Javascript. Nous l'utiliserons plus tard L'URI de redirection.
  8. sélectionnez Créer un numéro d'identification de client. Gardez à l'esprit l' Identification du Client et Secret Client, nous les utiliserons plus tard.

ainsi, maintenant nous pouvons générer le jeton de rafraîchissement:

  1. aller à L'URI suivant (notez que L'URI de redirection doit correspondre exactement à la valeur entrée dans l'ID du client, y compris toute traînée les barres obliques inverses):

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. sélectionnez Autoriser l'accès lorsqu'on vous le demande.
  2. le navigateur sera redirigé vers votre URI de redirection avec un code paramètre, qui ressemblera à 4 / eWdxD7b-YSQ5CNNb-c2iI83KQx19.wp6198ti5Zc7dJ3UXOl0T3aRLxQmbwI. Copie de cette valeur.

Créer une classe principale avec:

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_SECRET et GOOGLE_REDIRECT_URI sont les valeurs précédemment.

Enfin, nous avons notre actualiser jeton! Cette valeur n'expire pas, donc nous pouvons stocker dans un site, comme un fichier de propriété.

accès à L'API de développeur Android de Google Play

  1. Obtenir le jeton d'accès. Nous aurons besoin de notre précédemment refresh token:

    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. maintenant, nous pouvons accéder à L'API Android. Je suis intéressant, dans le délai d'expiration d'un abonnement, donc:

    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;
    

    }

Et c'est tout!

Certaines étapes sont à partir de https://developers.google.com/android-publisher/authorization.

41
répondu Jonathan Naguin 2012-10-03 14:42:29

greffer sur Jonathan Naguin de la grande réponse, voici un nodejs version de l'obtention de l'actualisation et de jeton d'accès:

//This script is to retreive a refresh token and an access token from Google API. 
//NOTE: The refresh token will only appear the first time your client credentials are used. 
//      I had to delete my client id within api console and create a new one to get the refresh token again.

//This is the downloaded json object from Google API Console. Just copy and paste over the template below.
var googleJson = {"web":{"auth_uri":"","client_secret":"","token_uri":"","client_email":"","redirect_uris":[""],"client_x509_cert_url":"","client_id":"","auth_provider_x509_cert_url":"","javascript_origins":[""]}};

//Retrieved from OAuth
var code            = ''; // Retrieved from the response of the URL generated by printGoogleAuthUrl(). You will need to be logged in as your publisher. Copy and paste the generated url. Copy the code parameter into this variable.
var refreshToken    = ''; // Retrieved from the printRefreshToken() function call. Requires the code variable to be filled out.
var accessToken     = ''; // Retrieved from the printAccessToken() function call. Requires the refreshToken variable to be filled out.


var querystring = require('querystring');
var https = require('https');
var fs = require('fs');

function printGoogleAuthUrl()
{
    console.log("https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=" + googleJson.web.redirect_uris[0] + "&client_id=" + googleJson.web.client_id);
}

function printRefreshToken()
{
    var post_data = querystring.stringify({
        'grant_type'    : 'authorization_code',
        'client_id'     : googleJson.web.client_id,
        'client_secret' : googleJson.web.client_secret,
        'code'          : code,
        'redirect_uri'  : googleJson.web.redirect_uris[0]
    });

    var post_options = {
      host: 'accounts.google.com',
      port: '443',
      path: '/o/oauth2/token',
      method: 'POST',
      headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': post_data.length
        }
    };

    var post_req = https.request(post_options, function(res) {
        res.setEncoding('utf8');
        var data = "";
        res.on('data', function (chunk) {
            data += chunk;
        });

        res.on('end', function(){
            var obj = JSON.parse(data);
            if(obj.refresh_token)
            {
                refreshToken = obj.refresh_token;
            }
            else
            {
                console.log("No refresh token found. I had to clear the web client id in Google Api Console and create a new one. There might be a better way here.");
            }   

            console.log(data);

        });
    });

    post_req.write(post_data);
    post_req.end();
}

function printAccessToken()
{
    var post_data = querystring.stringify({
        'grant_type'    : 'refresh_token',
        'client_id'     : googleJson.web.client_id,
        'client_secret' : googleJson.web.client_secret,
        'refresh_token' : refreshToken
    });

    var post_options = {
      host: 'accounts.google.com',
      port: '443',
      path: '/o/oauth2/token',
      method: 'POST',
      headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': post_data.length
        }
    };

    var post_req = https.request(post_options, function(res) {
        res.setEncoding('utf8');
        var data = "";
        res.on('data', function (chunk) {
            data += chunk;
        });

        res.on('end', function(){
            var obj = JSON.parse(data);
            if(obj.access_token)
                accessToken = obj.access_token;
            else
                console.log("No access token found.");

            console.log(data);

        });
    });

    post_req.write(post_data);
    post_req.end();
}

printGoogleAuthUrl();
//printRefreshToken();  
//printAccessToken();
4
répondu KoboldAtWork 2014-02-04 20:23:42

pour ceux qui veulent vérifier le statut d'abonnement sur L'AppEngine de Google avec Java, voici mon exemple de travail basé sur de nombreux codes trouvés sur SO. J'ai passé quelques jours à résoudre de nombreuses erreurs dues au manque d'expérience. Je vois beaucoup de suggestions pour vérifier l'état d'abonnement sur le serveur, mais il n'était pas facile pour moi de faire sur AppEngine. Sans réponses trouvées sur SO, Je ne pouvais pas venir avec ceci.

Etape 1

nous devons d'abord passer par "condition préalable" article trouvé sur Jonathan Naguin réponse, jusqu'à ce que vous obtenez code à partir du navigateur web. Maintenant que vous avez;

  • Identification du Client
  • Secret Client
  • Redirect URI
  • code

prêt.

notez que nous exécutons tous les codes ci-dessous sur AppEngine. Et j'ai utilisé logger comme ça.

static final Logger log = Logger.getLogger(MyClassName.class.getName());

Etape 2

nous devons obtenir un jeton de rafraîchissement. Exécuter le code ci-dessous après avoir remplacé [Votre ID CLIENT], [votre secret CLIENT], [votre CODE], [votre URI de redirection] avec votre chaîne de caractères.

private String getRefreshToken()
{
    try
    {
        Map<String,Object> params = new LinkedHashMap<>();
        params.put("grant_type","authorization_code");
        params.put("client_id",[YOUR CLIENT ID]);
        params.put("client_secret",[YOUR CLIENT SECRET]);
        params.put("code",[YOUR CODE]);
        params.put("redirect_uri",[YOUR REDIRECT URI]);

        StringBuilder postData = new StringBuilder();
        for(Map.Entry<String,Object> param : params.entrySet())
        {
            if(postData.length() != 0)
            {
                postData.append('&');
            }
            postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
            postData.append('=');
            postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
        }
        byte[] postDataBytes = postData.toString().getBytes("UTF-8");

        URL url = new URL("https://accounts.google.com/o/oauth2/token");
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.getOutputStream().write(postDataBytes);

        BufferedReader  reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        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 ex)
    {
        log.severe("oops! " + ex.getMessage());
    }
    return null;
}

puisque le jeton de rafraîchissement n'expirera pas, nous pouvons le sauvegarder quelque part ou simplement en code dur dans notre code. (Nous n'avons besoin d'exécuter le code ci-dessus qu'une seule fois pour obtenir un jeton de rafraîchissement.)

Etape 3

nous devons obtenir un jeton d'accès. Exécutez le code ci-dessous après avoir remplacé [votre ID CLIENT], [votre secret CLIENT], [votre jeton de rafraîchissement] par votre chaîne.

private String getAccessToken()
{
    try
    {
        Map<String,Object> params = new LinkedHashMap<>();
        params.put("grant_type","refresh_token");
        params.put("client_id",[YOUR CLIENT ID]);
        params.put("client_secret",[YOUR CLIENT SECRET]);
        params.put("refresh_token",[YOUR REFRESH TOKEN]);

        StringBuilder postData = new StringBuilder();
        for(Map.Entry<String,Object> param : params.entrySet())
        {
            if(postData.length() != 0)
            {
                postData.append('&');
            }
            postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
            postData.append('=');
            postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
        }
        byte[] postDataBytes = postData.toString().getBytes("UTF-8");

        URL url = new URL("https://accounts.google.com/o/oauth2/token");
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.getOutputStream().write(postDataBytes);

        BufferedReader  reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        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 (Exception ex)
    {
        log.severe("oops! " + ex.getMessage());
    }
    return null;
}

Etape 4

ce que je voulais savoir, c'est que L'abonnement vient à expiration UTC. Le Code affiché ci-dessous retourne UTC, 0 lorsque l'erreur est trouvée. Vous devez fournir le nom de votre paquet, l'id du Produit (=ID d'abonnement), le jeton d'accès que vous avez obtenu à L'Étape 3 et le jeton d'achat que vous avez trouvé dans vos données d'achat.

private long getExpireDate(String packageName,String productId,String accessToken,String purchaseToken)
{
    try
    {
        String charset = "UTF-8";
        String query = String.format("access_token=%s",URLEncoder.encode(accessToken,charset));

        String path = String.format("https://www.googleapis.com/androidpublisher/v1/applications/%s/subscriptions/%s/purchases/%s",packageName,productId,purchaseToken);
        URL url = new URL(path + "?" + query);
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        connection.setRequestProperty("Accept-Charset",charset);
        connection.setRequestMethod("GET");

        BufferedReader  reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        StringBuffer buffer = new StringBuffer();
        for(String line = reader.readLine(); line != null; line = reader.readLine())
        {
            buffer.append(line);
        }

        JSONObject json = new JSONObject(buffer.toString());
        return json.optLong("validUntilTimestampMsec");
    }
    catch (Exception ex)
    {
        log.severe("oops! " + ex.getMessage());
    }
    return 0;
}

Remarque: l'id du produit ou de l'id d'abonnement est une chaîne est trouvée sur le développeur de la console. Votre article d'abonnement apparaît avec la colonne Nom/id. Il ressemble à ceci.

Description of item(product id)

la Dernière étape (partie amusante)

Maintenant, nous avons tous les composants pour vérifier l'abonnement est valide ou pas. J'ai fait comme cela. Vous devez remplacer [votre nom D'Emballage], [votre numéro de produit] par le vôtre.

vous devez fournir les données d'achat que vous pouvez obtenir avec L'achat#getOriginalJson() trouvé dans le code iabHelper.

private boolean checkValidSubscription(String purchaseData)
{
    String purchaseToken;
    JSONObject json;
    try
    {
        json = new JSONObject(purchaseData);
    }
    catch (JSONException e)
    {
        log.severe("purchaseData is corrupted");
        return true;    // false positive
    }
    purchaseToken = json.optString("purchaseToken");
    if(purchaseToken.length() == 0)
    {
        log.severe("no purchase token found");
        return true;    // false positive
    }
    String accessToken = getAccessToken();
    if(accessToken == null)
    {
        return true;    // false positive
    }
    long expireDate = getExpireDate([YOUR PACKAGE NAME],[YOUR PRODUCT ID],accessToken,purchaseToken);
    if(expireDate == 0)
    {
        log.severe("no expire date found");
        return true;    // false positive
    }
    expireDate += 86400000l;    // add one day to avoid mis judge
    if(expireDate  < System.currentTimeMillis())
    {
        log.severe("subscription is expired");
        return false;
    }
    // just for log output
    long leftDays = (expireDate - System.currentTimeMillis()) / 86400000l;
    log.info(leftDays + " days left");
    return true;
}

Note pour le débogage

Google renvoie la chaîne JSON pour réponse. Si le code ne fonctionne pas comme prévu, la journalisation de la chaîne JSON peut aider à comprendre ce qui ne va pas.

j'espère que cela aide quelqu'un.

4
répondu Tomcat 2015-04-19 11:23:48

Vous pouvez utiliser com.google.api-client et google-api-services-androidpublisher bibliothèques.

aller D'abord au projet sur Google developer console (https://console.developers.google.com)

  • APIs & Auth - > APIs
  • activer "Google Play Android Developer API"
  • aller à justificatifs D'identité -> créer un nouveau code D'identification de Client
  • Sélectionnez le compte de service
  • Créer un ID de client
  • Enregistrez le fichier p12 quelque part sûr

puis ajoutez l'adresse email générée pour le compte de service à votre console de développeur google play (https://play.google.com/apps/publish/)

  • Paramètres -> Comptes et droits des utilisateurs -> inviter un nouvel utilisateur
  • Coller @developer.gserviceaccount.com compte de messagerie
  • sélectionner"voir les rapports financiers"
  • envoyer l'invitation

maintenant au code. Ajouter les dépendances suivantes à votre POM.fichier 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>

puis validez d'abord la signature:

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
}

Si la signature vérifie récupérer les détails de l'abonnement:

// 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());

cela réglera tous les problèmes de token en générant un token JWT pour que vous n'ayez pas à le gérer vous-même.

3
répondu Miha Hribar 2014-06-17 13:08:39

je suis presque sûr que vous devez utiliser votre ID Client, pas l'adresse email. Il ressemble à ceci: 37382847321922.apps.googleusercontent.com

https://developers.google.com/android-publisher/authorization

client_id=<the client ID token created in the APIs Console>
client_secret=<the client secret corresponding to the client ID>

essayez de le faire manuellement à partir de la ligne de commande en premier, avec 'wget'.

-1
répondu Chloe 2012-07-04 21:24:30