Cartões de fidelidade. API do Google Pay para passes no ASP.NET

Os aplicativos de armazenamento de cartões bancários entraram rapidamente em nossas vidas graças à Apple Wallet e ao Google Pay. As duas plataformas, além do setor bancário, também permitem trabalhar com outros tipos de cartões - cartões de fidelidade, cartões-presente, ingressos para eventos, cartões de embarque, etc.




Enquanto trabalhava para uma empresa que atende uma rede de varejo bastante grande, tive que integrar os cartões de fidelidade dessa rede no Apple Wallet e no Google Pay. E se você tivesse que mexer na Apple Wallet apenas porque a camada de integração é bastante multifuncional, com o Google Pay a maior parte do esforço e as células nervosas foram gastas tentando descobrir a documentação, encontrar as ferramentas certas e desenvolver a primeira prova de conceito. Embora, em geral, o resto do trabalho tenha sido muito mais rápido do que para a Apple Wallet, passei um dia descobrindo como iniciar o serviço, por isso não me importaria se alguém escrevesse um artigo semelhante antes de mim.

1. Material


Os cartões de fidelidade são representados usando duas entidades - Classe de fidelidade e Objeto de fidelidade.

  • A classe de fidelidade é um tipo de modelo para todos os cartões de fidelidade. Ele contém campos comuns a todos os mapas, como cor da fonte, links para recursos de ícones, planos de fundo, campos de texto, etc., uma descrição completa pode ser encontrada aqui: Loyaltyclass
  • Objeto de lealdade - uma instância do LoyaltyClass. Ele também contém os dados de um cartão específico de um determinado cliente - número do cartão, nome, campos de texto adicionais. Descrição aqui: Loyaltyobject

Para receber um cartão, o usuário deve seguir o link de formato
www.android.com/payapp/savetoandroidpay / {JWT} , em que JWT é um token que contém JSON com dados LoyaltyClass. Porém, como o tamanho do URL tem limitações, é recomendável que você crie primeiro uma Classe de lealdade se sua estrutura contiver muitos caracteres.

Se você precisar atualizar o mapa devido a uma alteração no modelo, nos estilos, na necessidade de adicionar ou alterar os campos de texto, faça isso usando a API. Só é necessário atender a uma solicitação POST com a nova versão do mapa. Os serviços do Google sincronizam todos os aplicativos de usuários que possuem esse mapa.


2. Ferramentas e documentação


O problema era que todos os exemplos na documentação da API do Google Pay for Passes eram exclusivamente para Java, PHP e Python, e a própria documentação recomendava fortemente "usar bibliotecas de clientes para simplificar o processo" de trabalhar com a API.


Seguindo esse conselho, fui feliz para a pepita, mas a biblioteca do Google Pay não estava lá. Glory to Brin, a primeira linha do Google para “google pay for passes dotnet” retornou a página de bibliotecas de utilitários da API do Google Pay for Passes , que encontrou o que eu precisava, embora no formato de arquivo ZIP, no qual havia um projeto .net com uma classe gerada que é um wrapper para a biblioteca do Google Pay API - API do Google Pay para Passes Client .


A julgar pela presença do arquivo Google.Apis.Walletobjects.v1.1.9.2.00.nuspec no projeto, a implantação do pacote nuget ainda fazia parte dos planos da equipe do Google. Depois de abrir esse arquivo em busca de documentação, não encontrei nada concreto, e alguns links que estavam na seção de descrição foram enviados para páginas inexistentes.

3. Obtendo o token de acesso


Para começar a trabalhar diretamente com a API do Google Pay for Passes, você precisa obter um token de acesso, para isso:

  1. Tenha uma conta do comerciante do Google, que você pode obter aqui
  2. Crie uma conta de serviço, obtenha um arquivo com credenciais para ela - um documento json com detalhes da conta de serviço, incluindo identificador, email, chave privada etc. Como a documentação recomenda, você precisa armazenar este arquivo em um local seguro.
  3. Vincular conta de comerciante e conta de serviço no Google Merchant Center

Usando esse arquivo, você pode fazer login usando a 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. Crie um mapa


Para criar um cartão de fidelidade, você deve primeiro criar uma classe de fidelidade. A classe de lealdade pode ser criada usando a API e a interface da web do Google Merchant Center. Deve-se prestar atenção ao nome da turma, pois esse nome deve ser exclusivo na infraestrutura do Google Pay.

Depois de criar a classe de lealdade, você pode criar o objeto de lealdade. Para fazer isso, já precisaremos da biblioteca que adicionamos ao projeto anteriormente: crie um objeto de solicitação, especifique o token OAuth, transfira o objeto LoyaltyObject criado e execute a solicitação:

 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 neste exemplo é um DTO que armazena um modelo de mapa para um usuário, gerado por um serviço desenvolvido separado.

5. Atualização do mapa


Aqui, o princípio é o mesmo que ao criar: geramos uma solicitação, transferimos o objeto LoyaltyObject atualizado, executamos:

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

Depois de concluir a solicitação, o cartão nos aplicativos dos usuários que o instalam será atualizado após alguns segundos, se o dispositivo estiver na rede e tiver uma conexão com a Internet.



6. geração JWT


Para instalar o cartão, você deve redirecionar o usuário para o link www.android.com/payapp/savetoandroidpay / {JWT} . Uma descrição da estrutura do token pode ser encontrada neste link .


O token é assinado pelo RSA-SHA256 com uma assinatura que pode ser gerada usando o mesmo arquivo com credenciais da Conta de Serviço:

 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("=", ""); } } 

Conclusão


Neste artigo, abordamos o básico sobre como trabalhar com a API do Google Pay for Passes: configurar contas, conectar-se à API, criar a classe de lealdade e o objeto de lealdade.

Se o UFO favorecer, eu falarei separadamente sobre como trabalhar com a Apple Wallet (tudo é mais difícil em termos de implementação), como fazer a Apple Wallet fazer amizade com o Google Pay em um serviço da Web e não sentir dor.


Links úteis


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


All Articles