Intereting Posts
Изменить приоритет собственного потока на Android в c / c ++ Студия Android после переименования пакета, который он выбрал. Не найдено соответствующего клиента Где появилась кнопка «Создать AndroidManifest.xml» в Qt Creator 3.3.0? Как создать собственный просмотрщик PDF для Android? Лучшие практики для соглашений об именах ID в Android? Отображать огромные изображения в Android Как создать папку изображений приложения для отображения в галерее Android Как записывать файлы в папку с ресурсами или необработанную папку в Android? Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565 Объявление атрибутов стиля в Android Android – с помощью runOnUiThread для изменения пользовательского интерфейса из потока Неплохая практика использования отрицательных полей в Android? Apache HttpClient получить добавить заголовок диапазона байтов? Поместите значения ENUM в android spinner? Что точно выполняет FragmentManager и FragmentTransaction?

Не удалось получить информацию о подписке из API разработчика Google Play для Android

Я пытаюсь использовать клиентскую библиотеку API Google API для Java, чтобы получить информацию о подписках пользователей, приобретенных в моем приложении для 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 – это адрес электронной почты из Access API из Google Консоли. GOOGLE_KEY_FILE_PATH – это файл GOOGLE_KEY_FILE_PATH загруженный из Access API.
GOOGLE_PRODUCT_NAME – это имя продукта из информации о брендинге.
В консоли Google APIS включена служба «API разработчика Android для Google Play».

Я получаю:

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

Я очень ценю вашу помощь в этом вопросе …

Solutions Collecting From Web of "Не удалось получить информацию о подписке из API разработчика Google Play для Android"

Я заработал! Последующие шаги:

необходимое условие

Перед запуском нам нужно создать токен обновления. Для этого сначала нужно создать проект консоли API:

  1. Перейдите в Консоль API и войдите в свою учетную запись разработчика Android (та же учетная запись, что и в Android Developer Console для загрузки APK).
  2. Выберите «Создать проект».
  3. Перейдите в Службы в левой панели навигации.
  4. Включите API разработчика Google Play для Android .
  5. Примите Условия использования.
  6. Перейдите в API-интерфейс на левой панели навигации.
  7. Выберите Создать идентификатор клиента OAuth 2.0:
    • На первой странице вам нужно будет указать название продукта, но логотип не требуется.
    • На второй странице выберите веб-приложение и установите URL- адрес перенаправления URI и Javascript. Мы будем использовать его позже URI перенаправления.
  8. Выберите «Создать идентификатор клиента». Имейте в виду идентификатор клиента и секрет клиента , мы будем использовать их позже.

Итак, теперь мы можем сгенерировать токен обновления:

  1. Перейдите к следующему URI (обратите внимание, что URI перенаправления должен точно соответствовать значению, указанному в идентификаторе клиента, включая любые обратные косые обратные косые черты):

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_SECRET и GOOGLE_REDIRECT_URI – это ранее значения.

Наконец, у нас есть токен обновления! Это значение не истекает, поэтому мы можем хранить его на каком-то сайте, например, в файле свойств.

Доступ к API разработчика Google Play для Android

  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. Теперь мы можем получить доступ к API Android. Мне интересен срок действия подписки, поэтому:

     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 .

Чтобы ответить на большой ответ Джонатана Нагуина, вот версия nodejs для получения токена обновления и доступа:

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

Вы можете использовать библиотеки com.google.api-client и google-api-services-androidpublisher .

Сначала перейдите в проект на консоли разработчика Google ( https://console.developers.google.com )

  • API и Auth -> API
  • Включить «API разработчика Android для Google Play»
  • Перейдите в учетные данные -> Создать новый идентификатор клиента
  • Выберите учетную запись службы
  • Создать идентификатор клиента
  • Сохраните файл 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, чтобы вам не пришлось самостоятельно его обрабатывать.

Для тех, кто хочет проверить статус подписки на AppEngine от Google на Java, вот мой рабочий пример, основанный на многих кодах, найденных на SO. Я провел пару дней, чтобы решить многие ошибки, вызванные нехваткой опыта. Я вижу много предложений по проверке статуса подписки на сервере, но мне нелегко было делать это на AppEngine. Без ответов, найденных на SO, я не мог придумать это.

Шаг 1

Сначала нам нужно пройти раздел «Предварительное условие», который был найден на ответе Джонатана Нагуина, пока вы не получите код из веб-браузера. Теперь у вас есть;

  • ID клиента
  • Секрет клиента
  • Перенаправление URI
  • код

готов.

Обратите внимание, что мы запускаем все коды, показанные ниже в AppEngine. И я использовал регистратор, как это.

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

Шаг 2

Нам нужно получить токен обновления. Выполните код, показанный ниже, после замены [YOUR CLIENT ID], [YOUR CLIENT SECRET], [YOUR CODE], [YOUR REDIRECT URI] с вашей строкой.

 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; } 

Поскольку токен обновления не истекает, мы можем сохранить его где-то или просто жесткий код в нашем коде. (Нам нужно только запустить код выше, чтобы получить токен обновления.)

Шаг 3

Нам нужно получить токен доступа. Выполните код, показанный ниже, после замены [YOUR CLIENT ID], [YOUR CLIENT SECRET], [YOUR REFRESH TOKEN] с вашей строкой.

 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; } 

Шаг 4

То, что я хотел знать, только истекает UTC подписки. Приведенный ниже код возвращает expired UTC, 0 при обнаружении ошибки. Вам необходимо указать имя вашего пакета, идентификатор продукта (= идентификатор подписки), токен доступа, полученный на шаге 3, и купить токен, найденный в ваших данных о покупке.

 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; } 

Идентификатор продукта или идентификатор подписки – это строка, найденная на консоли разработчика. Элемент вашей подписки отображается с столбцом name / id. Похоже на это.

 Description of item(product id) 

Последний шаг (забавная часть)

Теперь у нас есть все компоненты для проверки подлинности подписки. Мне это понравилось. Вам необходимо заменить [ВАШЕ ПАКЕТНОЕ ИМЯ], [ВАШ ИДЕНТИФИКАТОР ПРОДУКТА] с вашим.

Вам необходимо предоставить данные о покупке, которые вы можете получить с помощью Purchase # getOriginalJson (), найденного в коде 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; } 

Примечание для отладки

Google возвращает строку JSON для ответа. Если код не работает должным образом, запись строки JSON может помочь понять, что не так.

Я надеюсь, что это помогает кому-то.

Я уверен, что вам нужно использовать свой идентификатор клиента, а не адрес электронной почты. Это выглядит так: 37382847321922.apps.googleusercontent.com

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

 client_id=<the client ID token created in the APIs Console> 

И я уверен, что вам не нужен файл P12. Вам нужно только

 client_secret=<the client secret corresponding to the client ID> 

Сначала попробуйте выполнить это вручную из командной строки с помощью «wget».