Google Play Developer API - токен покупки запроса возвращает недопустимое значение
Я пытаюсь настроить веб-сервис для запроса покупок в 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"
}
}
Вот что я попробовал:
- Созданный проект на https://console.developers.google.com/ включил "Google Play Android Developer API"
- Создал oAuth 2.0 client_id и client_secret для веб-приложения типа
- Войдите в систему как владелец учетной записи, я сгенерировал refresh_token
- В https://play.google.com/apps/publish я зашел в Настройки -> Доступ к API и связал проект с моим приложением.
Код мудрый, я использовал 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
}
Теперь я хочу получить информацию о покупке. У меня есть информация о покупке как таковая:
{
"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
Я также поменялся местами, чтобы использовать клиентский API Google, так как он выглядел намного чище, чем создание запросов вручную.
Спасибо за помощь и ответы
2 ответа
Сначала я хочу поделиться с вами тем, что 400 неверных запросов и какова реальная причина их возникновения?
Ответ: Это указывает на то, что запрос был недействительным. Например, отсутствует родительский идентификатор или недопустимая комбинация запрошенных измерений или метрик.
Рекомендованное действие: Вам нужно внести изменения в запрос API, чтобы он работал.
Ссылка на ресурс: стандартные сообщения об ошибках
Твоя проблема:
Ваш код работал правильно и возвращал связанный json
файл в качестве вывода. Но через некоторое времяit is not working when you want to get information about purchase
, Выдает сообщение об ошибке "HTTP/1.1 400 Bad Request"
Первопричина:
Для токена обновления ответ всегда содержит новый токен доступа. Ответ показан ниже:
{
"access_token":"1/fFBGRNJru1FQd44AzqT3ZgXXXXXX",
"expires_in":3920,
"token_type":"Bearer",
}
Итак, токен доступа имеет время истечения. после истечения срока действия токен доступа не будет работать.
Есть и другое ограничение. Существуют ограничения на количество токенов обновления, которые будут выпущены; один лимит для каждой комбинации клиент / пользователь и другой для пользователя для всех клиентов.
Итак, в вашем случае вы уже превысили лимит создания токенов обновления.
Решение:
Итак, сначала нужно отозвать токен. Затем сохраните токены обновления в долговременном хранилище и продолжайте использовать их, пока они остаются действительными.
Поскольку вы используете токен обновления, вам нужно изменить 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>();
...............
...............
Процедура отзыва:
Есть 2 способа отзыва.
- Пользователь может отозвать доступ, зайдя в настройки аккаунта
- Приложение также может программно аннулировать предоставленный ему доступ.
Чтобы программно отозвать токен, ваше приложение отправляет запрос https://accounts.google.com/o/oauth2/revoke
и включает токен в качестве параметра:
curl https://accounts.google.com/o/oauth2/revoke?token={token}
token
может быть токеном доступа или токеном обновления. Если токен является токеном доступа и имеет соответствующий токен обновления, токен обновления также будет аннулирован.
NB. Если отзыв успешно обработан, то код состояния ответа равен 200. Для условий ошибки возвращается код состояния 400 вместе с кодом ошибки.
Ссылка на ресурс:
Это случилось со мной, когда я тестировал со статическими ответами, т.е. использовал зарезервированные идентификаторы продуктов для тестирования (например, android.test.purchased
). Решение SkyWalker не помогло в этом случае.
Затем я использовал реальные идентификаторы продуктов, опубликовал свое приложение как альфа-версию в google play и загрузил apk релиза на свое устройство, и теперь все работает как положено.
Внимательно прочитайте главу " Настройка для тестовых покупок" в документации Google, чтобы правильно подготовить свое приложение и аккаунт к тестированию.
Проверьте это, чтобы увидеть запрос и ответ API. Нужна помощь с API Explorer
API: https://www.googleapis.com/androidpublisher/v1.1/applications/packageName/subscriptions/subscriptionId/purchases/token
Параметры запроса:
packageName:PACKAGE_NAME
subscriptionId: SUBSCRIPTION_ID
токен:PURCHASE_TOKEN