Tarjetas de fidelidad. API de Google Pay para pases en ASP.NET

Las aplicaciones de almacenamiento de tarjetas bancarias han entrado rápidamente en nuestras vidas gracias a Apple Wallet y Google Pay. Ambas plataformas, además de la banca, también le permiten trabajar con otros tipos de tarjetas: tarjetas de fidelidad, tarjetas de regalo, boletos para eventos, tarjetas de embarque, etc.




Mientras trabajaba para una empresa que presta servicios a una red minorista bastante grande, tuve que integrar las tarjetas de fidelización de esta red en Apple Wallet y Google Pay. Y si tuvo que jugar con Apple Wallet solo porque la capa de integración es bastante multifuncional, entonces con Google Pay la mayor parte del esfuerzo y las células nerviosas se gastaron tratando de descubrir la documentación, encontrar las herramientas adecuadas y desarrollar la primera prueba de concepto. Aunque en general el resto del trabajo fue mucho más rápido que para Apple Wallet, pasé un día averiguando cómo iniciar el servicio, por lo que no me importaría si alguien escribió un artículo similar antes que yo.

1. Material


Las tarjetas de fidelización se representan mediante dos entidades: Clase de fidelización y Objeto de fidelización.

  • Loyalty Class es un tipo de plantilla para todas las tarjetas de fidelización. Contiene campos comunes a todos los mapas, como el color de fuente, enlaces a elementos de iconos, fondos, campos de texto, etc., una descripción completa se puede encontrar aquí: Loyaltyclass
  • Objeto de lealtad : una instancia de LoyaltyClass. También contiene los datos de una tarjeta específica de un cliente en particular: número de tarjeta, nombre, campos de texto adicionales. Descripción aquí: Loyaltyobject

Para recibir una tarjeta, el usuario debe seguir el enlace de formato
www.android.com/payapp/savetoandroidpay / {JWT} , donde JWT es un token que contiene JSON con datos de LoyaltyClass. Pero dado que la longitud de la URL tiene limitaciones, se recomienda que primero cree una Clase de lealtad si su estructura contiene muchos caracteres.

Si necesita actualizar el mapa debido a un cambio en la plantilla, los estilos, la necesidad de agregar o cambiar campos de texto, puede hacerlo utilizando la API. Solo es necesario completar una solicitud POST con la nueva versión del mapa, los servicios de Google sincronizan todas las aplicaciones de los usuarios que tienen este mapa.


2. Herramientas y documentación.


El problema resultó ser que todos los ejemplos en la documentación de Google Pay API for Passes eran exclusivamente para Java, PHP y Python, y la documentación en sí misma recomienda encarecidamente "usar bibliotecas de clientes para simplificar el proceso" de trabajar con la API.


Siguiendo este consejo, felizmente fui a Nuget, pero la biblioteca de Google Pay no estaba allí. Glory to Brin, la primera línea en Google para "google pay for pas dotnet" devolvió la página de bibliotecas de utilidades API de Google Pay para Pases , que encontró lo que necesitaba, aunque en el formato de archivo ZIP, en el que había un proyecto .net con una clase generada que es un contenedor de la API de Google Pay - API de Google Pay para la biblioteca de Passes Client


A juzgar por la presencia del archivo Google.Apis.Walletobjects.v1.1.9.2.00.nuspec en el proyecto, la implementación del paquete nuget todavía era parte de los planes del equipo de Google. Después de abrir este archivo en busca de documentación, no encontré nada concreto, y algunos enlaces que estaban en la sección de descripción se enviaron a páginas inexistentes.

3. Obtener token de acceso


Para comenzar a trabajar directamente con la API de Google Pay para Pases, debe obtener un token de acceso, para esto necesita:

  1. Tener una cuenta de comerciante de Google, que puede obtener aquí
  2. Cree una cuenta de servicio, obtenga un archivo con credenciales para ello: un documento json con detalles de la cuenta de servicio, que incluye identificador, correo electrónico, clave privada, etc. Como recomienda la documentación, debe almacenar este archivo en un lugar seguro.
  3. Vincular cuenta de comerciante y cuenta de servicio en Google Merchant Center

Con este archivo, puede iniciar sesión con la biblioteca Google.Apis.Auth.OAuth2 :

private await Task<string> GetOAuthToken() {         string serviceAccountFile = string.Empty;         serviceAccountFile = ConfigurationManager.AppSettings["GooglePayServiceAccountConfigPath"];        /*              Credential, GoogleCredential              Service Account,   ,      scopes API,             */         var credential = GoogleCredential.FromFile(serviceAccountFile)                            .CreateScoped(WalletobjectsService.Scope.WalletObjectIssuer);        /*        Access token        ,   GetAccessTokenForRequestAsync         ,               */         var token = async credential.UnderlyingCredential.GetAccessTokenForRequestAsync();         return token; } 

4. Crea un mapa


Para crear una tarjeta de fidelización, primero debe crear una Clase de fidelización. La clase de lealtad se puede crear utilizando la API y la interfaz web de Google Merchant Center. Se debe prestar atención al nombre de la clase, ya que este nombre debe ser único en la infraestructura de Google Pay.

Después de crear la Clase de lealtad, puede crear el Objeto de lealtad. Para hacer esto, ya necesitará la biblioteca que agregamos al proyecto anteriormente: cree un objeto de solicitud, especifique el token OAuth, transfiera el objeto LoyaltyObject creado y ejecute la solicitud:

 public GooglePayApiService() { // ,    Merchant Account IssuerId = ConfigurationManager.AppSettings["GooglePayIssuerId"]; _wobService = new WalletobjectsService(); } private async Task<LoyaltyObject> ConvertLoyaltyObjectFromTemplate(GooglePayPassTemplate template) { string id = $"{IssuerId}.{template.SerialNumber}"; string loyaltyClassName = ConfigurationManager.AppSettings["GooglePayStoreCardClassName"];     var loyaltyClass = await GetLoyaltyClass(loyaltyClassName); var result =  new LoyaltyObject { Id = id, AccountName = template.AccountName,          Barcode = new Barcode          {          AlternateText = template.BarcodeText,               Value = template.SerialNumber,               Type = "pdf417"          },          Kind = "walletObject#loyaltyObject",          ClassId = loyaltyClass.Id,          ClassReference = loyaltyClass,          State = "active"     };     return result; } private async Task<LoyaltyObject> CreateLoyaltyObject(LoyaltyObject loyaltyObject) { var saveRequest = _wobService.Loyaltyobject.Insert(loyaltyObject); saveRequest.OauthToken = await GetOAuthToken(); var savedObject = await saveRequest.ExecuteAsync(); return savedObject; } 

GooglePayPassTemplate en este ejemplo es un DTO que almacena una plantilla de mapa para un usuario, que es generada por un servicio desarrollado por separado.

5. Actualización del mapa


Aquí el principio es el mismo que al crear: generamos una solicitud, transferimos el objeto LoyaltyObject actualizado, ejecutamos:

 private async Task<LoyaltyObject> UpdateLoyaltyObject(LoyaltyObject loyaltyObject) { var updateRequest = _wobService.Loyaltyobject.Update(loyaltyObject, loyaltyObject.Id);           updateRequest.OauthToken = await GetOAuthToken(); var savedObject = await updateRequest.ExecuteAsync(); return savedObject; } 

Después de completar la solicitud, la tarjeta en las aplicaciones de los usuarios que la tienen instalada se actualizará después de unos segundos, si el dispositivo está en la red y tiene una conexión a Internet.



6. generación JWT


Para instalar la tarjeta, debe redirigir al usuario al enlace www.android.com/payapp/savetoandroidpay / {JWT} . Puede encontrar una descripción de la estructura del token en este enlace .


El token está firmado por RSA-SHA256 con una firma que se puede generar utilizando el mismo archivo con credenciales de cuenta de servicio:

 public static class JwtHelper { public static string CreateJwtForLoyaltyObject(LoyaltyObject loyaltyObject) { /*       credential   ,         */ ServiceAccountCredential credential; var now = DateTime.UtcNow; DateTime unixEpoch = new DateTime(1970, 01, 01); // 1970-01-01 00:00:00 UTC var secondsSinceEpoch = (int)Math.Round((now - unixEpoch).TotalSeconds); string serviceAccountFile = serviceAccountFile = ConfigurationManager.AppSettings["GooglePayServiceAccountConfigPath"]; using (var fs = new FileStream(serviceAccountFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { credential = ServiceAccountCredential.FromServiceAccountData(fs); } /*    JwtPayload,     payload-a  JWT */ var jwtPayload = new JwtPayload { iat = secondsSinceEpoch, iss = credential.Id, payload = new JwtInternalPayload { loyaltyObjects = new[] { new LoyaltyObjectPayload { id = loyaltyObject.Id } } } }; string header = @"{""alg"":""RS256"",""typ"":""JWT""}"; string payload = JsonConverter.SerializeObject(jwtPayload); string base64Header = EscapedBase64(Convert.ToBase64String(Encoding.UTF8.GetBytes(header))); string base64Payload = EscapedBase64(Convert.ToBase64String(Encoding.UTF8.GetBytes(payload))); //        Signature string signature = EscapedBase64(credential.CreateSignature( Encoding.UTF8.GetBytes($"{base64Header}.{base64Payload}") )); var token = $"{base64Header}.{base64Payload}.{signature}"; return token; } private static string EscapedBase64(string base64) { return base64.Replace('+', '-') .Replace('/', '_') .Replace("=", ""); } } 

Conclusión


En este artículo, revisamos los conceptos básicos para trabajar con la API de Google Pay para Pases: configurar cuentas, conectarse a la API, crear la Clase de lealtad y el Objeto de lealtad.

Si el OVNI lo favorece, le contaré por separado acerca de cómo trabajar con Apple Wallet (todo es más difícil en términos de implementación), cómo hacer amigos de Apple Wallet con Google Pay en un servicio web y no sentir dolor.


Enlaces utiles


Source: https://habr.com/ru/post/es434486/


All Articles