porque - ¿Estoy obteniendo los pasos correctos para verificar la suscripción de la aplicación de Android de un usuario?
porque no me aparecen algunas aplicaciones en play store (7)
Estoy creando una aplicación que no requiere una cuenta de usuario / inicio de sesión y permite al usuario comprar una suscripción. Quiero usar la API de Google Play Developer para verificar si un usuario tiene una suscripción comprada / activa. De toda la documentación, he reunido los siguientes pasos.
¿Son correctas, y podrías responder las dos preguntas en ellas?
- Cree una cuenta de servicio en la consola de Google API.
- Guarde la clave privada que recibí (¿dónde? Seguramente no en mi código / en el dispositivo como sugiere este código de muestra )
- Use la API de Google API para Java para crear y firmar un JWT con la clave privada (¿cómo? Los documentos me lo dan , pero eso no es un código Java ... ¿Qué hago con eso?)
- Construya una solicitud de token de acceso y obtenga acceso a la API
- La aplicación ahora puede enviar una solicitud GET a la API para averiguar si el usuario tiene una suscripción
- Cuando el token de acceso caduque, vuelva al paso 3.
Además, tengo un servicio web, aunque no sé nada sobre servicios web o programación de servicios web ... Solo sé lo suficiente para tener en cuenta que probablemente sea necesario utilizar aquí.
EDIT: estos pasos no fueron correctos Vea mi respuesta a continuación para los pasos correctos. Sin embargo, tenga en cuenta que esto solo se aplica al uso de una cuenta de servicio (porque no quería que un usuario tuviera que permitir explícitamente el acceso a la API)
Como resultado, mis pasos no fueron correctos. Me tomó semanas resolver esto y no parece estar documentado en ningún otro lugar. De nada:
Cree una cuenta de aplicación web en la consola de Google API . Coloque cualquier sitio web como "redireccionamiento de URI"; No importa ya que realmente no lo vas a usar. Obtendrá una ID de cliente y un secreto de cliente cuando cree la cuenta.
En un navegador en su computadora, vaya a
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=[YOUR REDIRECT URI]&client_id=[YOUR CLIENT ID]
y permitir el acceso cuando se le solicite.Mira en la barra de direcciones. Al final de la URI que ingresó originalmente, estará su token de actualización. Parece que
1/....
Necesitará este "código" en el siguiente paso. El token de actualización nunca caduca.Convierta este "código" en un "token de actualización"
https://accounts.google.com/o/oauth2/token?client_id=[YOUR CLIENT ID]&client_secret=[YOUR CLIENT SECRET]&code=[CODE FROM PREVIOUS STEP]&grant_type=authorization_code&redirect_uri=[YOUR REDIRECT URI]
ahttps://accounts.google.com/o/oauth2/token?client_id=[YOUR CLIENT ID]&client_secret=[YOUR CLIENT SECRET]&code=[CODE FROM PREVIOUS STEP]&grant_type=authorization_code&redirect_uri=[YOUR REDIRECT URI]
. Puede guardar el valor resultante directamente en su programa; nunca caduca a menos que sea revocado explícitamente. ( este paso insertado por @BrianWhite - ver comentarios ) Asegúrese de estar usando POST. (insertado por Gintas)En su código, envíe una solicitud HttpPost a
https://accounts.google.com/o/oauth2/token
con el BasicNameValuePairs"grant_type","refresh_token"
,"client_id",[YOUR CLIENT ID]
,"client_secret",[YOUR CLIENT SECRET]
,"refresh_token",[YOUR REFRESH TOKEN]
. Para ver un ejemplo mira here . Tendrá que hacer esto en un hilo separado, probablemente usando AsyncTask. Esto devolverá un objeto JSON.Obtenga el token de acceso del objeto JSON devuelto. Para ver un ejemplo mira here . Necesitará obtener la cadena "access_token". El token de acceso caduca en 1 hora.
En su código, envíe una solicitud HttpGet a
https://www.googleapis.com/androidpublisher/v1/applications/[YOUR APP''S PACKAGE NAME]/subscriptions/[THE ID OF YOUR PUBLISHED SUBSCRIPTION FROM YOUR ANDROID DEVELOPER CONSOLE]/purchases/[THE PURCHASE TOKEN THE USER RECEIVES UPON PURCHASING THE SUBSCRIPTION]?accesstoken="[THE ACCESS TOKEN FROM STEP 4]"
. Para ver un ejemplo mira here .
Como tiene un servicio web al que su aplicación puede llamar, le recomendaría que guarde su clave privada de forma segura en su servidor. Debería ver cómo mover la mayor parte de las cosas dentro de la aplicación para atender llamadas, vea este enlace . He implementado la suscripción en la aplicación, pero fue antes de que esta parte de la API saliera. Tuve que hacer mi propio registro y verificación de seguridad, pero parece que esta API hace la mayor parte de eso por usted, utilizando OAuth, aunque parece que todavía es responsable de almacenar la solicitud / verificación de suscripción.
Cuando se trata de firmar sus JWT con una biblioteca existente, parecen proporcionarle enlaces a una biblioteca java, una biblioteca Python y una biblioteca PHP. Depende de lo que esté escrito su servicio web o componente de servidor (el mío es C #, así que estoy usando RSACryptoServiceProvider) para verificar las compras firmadas. Están utilizando objetos JSON para la transferencia real de datos.
Es posible que malinterprete su pregunta, pero no veo una razón para que use los enlaces a los que hace referencia para que la facturación en la aplicación funcione correctamente. Esta página es mucho más útil:
http://developer.android.com/guide/google/play/billing/index.html
Puede probar la aplicación de demostración que incluyen (Dungeons - http://developer.android.com/guide/google/play/billing/billing_integrate.html#billing-download ). Utiliza productos (compras únicas) en lugar de suscripciones, pero debería poder modificar para probar lo que desea.
Creo que la clave, para usted, sería el método restoreTransactions que proporcionan en la muestra para ver si la cuenta de Google Play tiene alguna suscripción para su aplicación:
@Override
public void onRestoreTransactionsResponse(RestoreTransactions request, int responseCode) {
if (responseCode == BillingVars.OK) {
// Update the shared preferences so that we don''t perform a RestoreTransactions again.
// This is also where you could save any existing subscriptions/purchases the user may have.
SharedPreferences prefs = getSharedPreferences(my_prefs_file, Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(DB_INITIALIZED, true);
edit.commit();
} else {
Log.e(TAG, "RestoreTransactions error: " + responseCode);
}
}
No lo sé en 2012, pero en 2015 no debe realizar ninguno de estos pasos manualmente. Me costó mucho encontrar la documentación, así que estoy publicando aquí en caso de que ayude a alguien.
- Solo debe consultar las compras desde la aplicación desde su servidor por razones de seguridad, de lo contrario no puede confiar en ninguno de los 2 extremos del proceso de compra.
Ahora en el lado del servidor (creo que aún podría usar el mismo código de su aplicación si es absolutamente necesario), incluya la biblioteca de cliente google-api-services-androidpublisher
en su proyecto (consulte https://developers.google.com/api-client-library/java/apis/androidpublisher/v1 )
Como mencionó, necesita una cuenta de servicio con un archivo P12 (la biblioteca del cliente solo acepta archivos P12).
Luego, el siguiente código se autenticará y obtendrá la información de compra muy bien:
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(AndroidPublisherScopes.ANDROIDPUBLISHER);
Credential credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
.setServiceAccountId(googleServiceAccountId)
.setServiceAccountPrivateKeyFromP12File(new File(googleServicePrivateKeyPath))
.setServiceAccountScopes(scopes).build();
AndroidPublisher publisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential).build();
AndroidPublisher.Purchases purchases = publisher.purchases();
final Get request = purchases.get(packageName, productId, token);
final SubscriptionPurchase purchase = request.execute();
// Do whatever you want with the purchase bean
La información sobre la autenticación del cliente Java se puede encontrar aquí: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
Si alguien tiene problemas con el paso final de las publicaciones aceptadas (# 7), encontré ?access_token=
para trabajar en lugar de ?accessToken=
Lástima que el desbordamiento de pila no me permita hacer ese comentario directamente en el hilo ...
Si eres como yo y quieres hacer esto en PHP , aquí está el procedimiento para hacerlo ... Gracias a la respuesta de Kalina, solo me tomó tres días descubrir cómo funciona :).
Aquí va:
vaya a la consola de desarrolladores de Google https://console.developers.google.com/ y cree una aplicación web . Ponga ''developers.google.com/oauthplayground'' como una "redirección de URI"; Lo usará en el paso 2. Obtendrá un ID de cliente y un secreto de cliente cuando cree la cuenta. Asegúrate de tener la API de Google Play Android Developer agregada.
vaya a Google oauth2 playground https://developers.google.com/oauthplayground/ . Esta gran herramienta es tu mejor amigo para los próximos días. Ahora vaya a la configuración: asegúrese de que Usar sus propias credenciales de OAuth esté establecida. Solo entonces puede completar su ID de cliente y su secreto de cliente en el formulario a continuación.
En el campo de juego de Google oauth2, vaya al paso 1. Seleccione y autorice las API rellene el ámbito en el campo de entrada https://www.googleapis.com/auth/androidpublisher . No pude encontrar la API de Google Play Android Developer en la lista, tal vez se agreguen algún tiempo más tarde. Hit AUTORIZAR APIS . Haz la autorización que sigue.
En el campo de juego de Google oauth2, vaya al paso 2 Intercambie el código de autorización para los tokens . Si todo salió bien, verá un código de autorización que comienza con / 4. Si algo no salió bien, verifique el mensaje de error a la derecha. Ahora presionas ''actualizar token de acceso''. Copie el token de actualización ... comenzará con / 1 ...
¡Ahora siempre puedes obtener un token de acceso! aquí es cómo:
$url ="https://accounts.google.com/o/oauth2/token"; $fields = array( "client_id"=>"{your client id}", "client_secret"=>"{your client secret}", "refresh_token"=>"{your refresh token 1/.....}", "grant_type"=>"refresh_token" ); $ch = curl_init($url); //set the url, number of POST vars, POST data curl_setopt($ch, CURLOPT_POST,count($fields)); curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //execute post $lResponse_json = curl_exec($ch); //close connection curl_close($ch);
Ahora tienes un ACCESS TOKEN hooray ... el JSON se verá así:
"access_token" : "{the access token}", "token_type" : "Bearer", "expires_in" : 3600
¡Finalmente estás listo para pedirle algo a google! Aquí está cómo hacerlo:
$lAccessToken = "{The access token you got in}" ;
$lPackageNameStr = "{your apps package name com.something.something}";
$lURLStr = "https://www.googleapis.com/androidpublisher/v1.1/applications/$lPackageNameStr/subscriptions/$pProductIdStr/purchases/$pReceiptStr";
$curl = curl_init($lURLStr);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$curlheader[0] = "Authorization: Bearer " . $lAccessToken;
curl_setopt($curl, CURLOPT_HTTPHEADER, $curlheader);
$json_response = curl_exec($curl);
curl_close($curl);
$responseObj = json_decode($json_response,true);
El JSON devuelto contendrá dos marcas de tiempo, initiationTimestampMsec y validUntilTimestampMsec en el momento en que la suscripción sea válida. ¡Ambos son el nr de milisegundos para agregar a la fecha 1/1/1970!
Usuarios de .NET: Espero que esta respuesta salve a alguien un montón de pena.
Como @Christophe Fondacci señaló en 2015, la solución aceptada funcionó muy bien hace unos años. Ahora es 2017 y el proceso es mucho más fácil y rápido .
Mi caso de uso es validar las suscripciones en la aplicación, donde mi aplicación móvil envía información de compra de suscripción a mi servidor RESTful, que a su vez se comunica con Google para validar una compra de suscripción.
La estrategia es crear una cuenta de servicio que operará en su nombre.
- Inicie sesión en su consola de Google Play Dev y haga clic en la aplicación que está configurando.
- Configuración de visita -> acceso API
- En Cuentas de servicio , presione el botón Crear cuenta de servicio .
A partir de enero de 2017, aparecerá un cuadro de diálogo con instrucciones para configurar una cuenta de servicio. El diálogo te lleva a la Consola API de Google; desde allí,
A) Haga clic en Crear cuenta de servicio
B) Crea el nombre de la cuenta de servicio que tenga sentido. Ya que estamos interesados en acceder a los Servicios para editores de Android, elegí "publicador".
C) Para Role, simplemente elija algo; puede cambiarlo más tarde.
D) Elija "Proporcionar nueva clave privada" y elija P12 para implementaciones de .Net. ¡No pierdas este archivo!
5) Ahora que ha terminado con el número 4, verá su nueva cuenta de servicio en la lista; haga clic en "Conceder acceso" para habilitarlo.
6) Pulse en el enlace "Ver permisos". Debe modificar los permisos en función de sus necesidades y API.
Para validar las compras dentro de la aplicación, visite Cog-> Modificar permisos y habilite los permisos GLOBAL "Visibilidad" y "Administrar pedidos".
OK en este punto, ya has configurado todo en el final de Google. Ahora para configurar su servidor para cosas del servidor. Recomiendo crear una aplicación de consola .Net para probar su implementación y luego descargarla cuando sea necesario.
1) Agregue la biblioteca de clientes de Android Publisher desde Nuget
PM> Install-Package Google.Apis.AndroidPublisher.v2
2) Agregue el archivo P12 a la raíz de su proyecto
3) Cambie las propiedades de P12 para que "Acción de compilación" sea "Contenido" y "Copiar en el directorio de salida" a "Copiar si es más nuevo".
4) Implemente algo como esto para probar su acceso y afinar.
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Services;
using Google.Apis.Auth.OAuth2;
using Google.Apis.AndroidPublisher.v2;
...
public Task<SubscriptionPurchase> GetSubscriptionPurchase(string packageName, string productId, string purchaseToken)
{
var certificate = new X509Certificate2(
"{{your p12 file name}}",
"{{ your p12 secret }}",
X509KeyStorageFlags.Exportable
);
var credentials = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer("{{ your service account email }}")
{
Scopes = new[] { AndroidPublisherService.Scope.Androidpublisher }
}.FromCertificate(certificate))
;
var service = new AndroidPublisherService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "my server app name",
});
return service.Purchases.Subscriptions.Get(packageName, productId, purchaseToken).ExecuteAsync();
}
Buena suerte, espero que esto ayude a alguien.
Fuentes: