Fluxo de desenvolvimento de cartões da Carteira do Google

A API Google Wallet oferece um conjunto predefinido de tipos de cartão otimizados para casos de uso específicos, como vales-presente, cartões de embarque, ingressos de eventos e muito mais. Há também um tipo de cartão genérico para casos de uso em que um tipo específico de cartão não está disponível.

Neste artigo, queremos apresentar as etapas básicas necessárias para criar e emitir um cartão usando a API Google Wallet. Há várias maneiras de realizar algumas das etapas detalhadas abaixo, mas, de modo geral, todos os tipos de cartão são criados seguindo o mesmo fluxo de desenvolvimento básico.

Para conferir um tutorial detalhado sobre como criar um cartão, consulte os guias sobre Web, e-mail e SMS ou apps Android.

Para que servem

Uma classe de cartões define um conjunto de propriedades comuns em vários cartões, semelhante a um modelo. Por exemplo, se você estiver emitindo ingressos de um evento, a classe de cartões vai definir campos que são iguais em todos os ingressos, como nome, data e hora do evento.

Todo cartão emitido precisa referenciar uma classe de cartões. Também é necessário atribuir um código exclusivo a cada classe de cartões criada, que será usado para fazer referência a ela na criação de cartões.

Como isso acontece

Uma classe de cartões é definida no formato JSON e pode ser criada com a API REST da Google Wallet, o SDK do Android ou o Business Console da Carteira do Google.

Mostrar exemplo de classe de cartões

{
  "id": "ISSUER_ID.EVENT_CLASS_ID",
  "issuerName": "[TEST ONLY] Heraldic Event",
  "localizedIssuerName": {
    "defaultValue": {
      "language": "en-US",
      "value": "[TEST ONLY] Heraldic Event"
    }
  },
  "logo": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "LOGO_IMAGE_DESCRIPTION"
      }
    }
  },
  "eventName": {
    "defaultValue": {
      "language": "en-US",
      "value": "Google Live"
    }
  },
  "venue": {
    "name": {
      "defaultValue": {
        "language": "en-US",
        "value": "Shoreline Amphitheater"
      }
    },
    "address": {
      "defaultValue": {
        "language": "en-US",
        "value": "ADDRESS_OF_THE_VENUE"
      }
    }
  },
  "dateTime": {
    "start": "2023-04-12T11:30"
  },
  "reviewStatus": "UNDER_REVIEW",
  "hexBackgroundColor": "#264750",
  "heroImage": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "HERO_IMAGE_DESCRIPTION"
      }
    }
  }
}
    

Para que servem

Um objeto de cartões define as propriedades de um cartão exclusivo que será emitido para um usuário específico. Por exemplo, o objeto de cartões de um ingresso de evento define campos exclusivos para um ingresso específico, como o número do assento ou um QR code desse ingresso.

Quando um objeto de cartões é criado, a API Google Wallet armazena um novo cartão e o associa à sua conta de emissor. Esse cartão armazenado é uma combinação das propriedades exclusivas do objeto de cartões e das propriedades de modelo da classe de cartões associada.

Também é necessário atribuir um código exclusivo a cada objeto de cartões, que será usado para se referir a ele na emissão de um cartão.

Como isso acontece

Um objeto de cartões é definido no formato JSON e pode ser criado com a API REST da Carteira do Google ou o SDK do Android.

Mostrar exemplo de objeto de cartões

{
  "id": "ISSUER_ID.OBJECT_ID",
  "classId": "ISSUER_ID.EVENT_CLASS_ID",
  "state": "ACTIVE",
  "seatInfo": {
    "seat": {
      "defaultValue": {
        "language": "en-us",
        "value": "5"
      }
    },
    "row": {
      "defaultValue": {
        "language": "en-us",
        "value": "G"
      }
    },
    "section": {
      "defaultValue": {
        "language": "en-us",
        "value": "40"
      }
    },
    "gate": {
      "defaultValue": {
        "language": "en-us",
        "value": "3A"
      }
    }
  },
  "barcode": {
    "type": "QR_CODE",
    "value": "BARCODE_VALUE",
    "alternateText": ""
  }
}
    

Para que servem

Para emitir um cartão para um usuário, uma classe e um objeto de cartões precisam ser codificados em um JSON Web Token (JWT). O formato JWT é um padrão comum e aberto para representar declarações entre duas partes. No caso de emitir cartões com a API Google Wallet, os JWTs são usados para enviar uma declaração de que um usuário tem o direito de acessar um cartão específico associado à sua conta de emissor.

Quando um JWT é enviado à API Google Wallet, os dados codificados são usados para identificar um cartão específico e emiti-lo ao usuário. Se o cartão já foi emitido, esses dados também permitem que a API Google Wallet identifique que o cartão é uma cópia para que não seja adicionado à Carteira do Google mais de uma vez.

Como isso acontece

Os JWTs são definidos no formato JSON com base na especificação JWT. Para definir um JWT para emitir um cartão com a API Google Wallet, forneça as informações sobre o cartão que você quer emitir na propriedade payload do JWT.

Mostrar exemplo de JWT

{
  "iss": "issuer@example.com",
  "aud": "google",
  "typ": "savetowallet",
  "iat": 1696877738,
  "origins": [
    "www.example.com"
  ],
  "payload": {
    "eventTicketObjects": [
      {
        "id": "ISSUER_ID.LOYALTY_OBJECT_SUFFIX"
      }
    ]
  }
}
    

Para que servem

Todos os JWTs enviados à API Google Wallet para emitir um cartão precisam ser assinados com as credenciais que você forneceu anteriormente no Business Console da Carteira do Google. A assinatura usa suas credenciais para criptografar o JWT para manter a segurança dos cartões e permitir que a API Google Wallet autentique se os detalhes do cartão codificados são válidos e associados à sua conta de emissor.

Como isso acontece

As bibliotecas de cliente da Carteira do Google e o SDK do Android oferecem métodos convenientes para assinar seus JWTs. Existem também inúmeras bibliotecas de código aberto disponíveis que lidam com a complexidade da assinatura de código para que você possa escolher.

Para quem usa a API REST da Carteira do Google para emitir cartões, o JWT é assinado com uma chave da conta de serviço do Google Cloud. Se você usa o SDK da Carteira do Google para Android, o SDK processa automaticamente a assinatura do JWT com a impressão digital SHA-1 do certificado de assinatura do app.

Para proteger suas credenciais, os JWTs só devem ser assinados no servidor ou usando o SDK da Carteira do Google para Android no app.

Mostrar um exemplo de assinatura de código

Java

  // Create the JWT as a HashMap object
  HashMap claims = new HashMap();
  claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail());
  claims.put("aud", "google");
  claims.put("origins", Arrays.asList("www.example.com"));
  claims.put("typ", "savetowallet");

  // Create the Google Wallet payload and add to the JWT
  HashMap payload = new HashMap();
  payload.put("eventTicketObjects", Arrays.asList(newObject));
  claims.put("payload", payload);

  // Google Cloud service account credentials are used to sign the JWT
  Algorithm algorithm =
      Algorithm.RSA256(
          null, (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey());
  String token = JWT.create().withPayload(claims).sign(algorithm);
        

Node.JS

  // Create the JWT claims
  let claims = {
    iss: this.credentials.client_email,
    aud: 'google',
    origins: ['www.example.com'],
    typ: 'savetowallet',
    payload: {
      eventTicketObjects: [newObject]
    },
  };

  // The service account credentials are used to sign the JWT
  let token = jwt.sign(claims, this.credentials.private_key, { algorithm: 'RS256' });
        

Python

  # Create the JWT claims
  claims = {
      'iss': self.credentials.service_account_email,
      'aud': 'google',
      'origins': ['www.example.com'],
      'typ': 'savetowallet',
      'payload': {
          # The listed classes and objects will be created
          'eventTicketObjects': [new_object]
      }
  }

  # The service account credentials are used to sign the JWT
  signer = crypt.RSASigner.from_service_account_file(self.key_file_path)
  token = jwt.encode(signer, claims).decode('utf-8')
        

Para que servem

Depois de criar um JWT assinado, você já pode emitir seu cartão para um usuário da Carteira do Google. Para isso, é necessário apresentar ao usuário o botão "Adicionar à Carteira do Google" ou link. Quando um usuário clica no botão ou hiperlink, o JWT assinado é enviado à API Google Wallet, que o descriptografa usando suas credenciais salvas. Depois que a assinatura JWT for autenticada, o cartão será emitido para o usuário salvar na Carteira do Google.

Como isso acontece

Para criar um cartão "Adicionar à Carteira do Google" Para um app Android, use o SDK da Carteira do Google para Android, que oferece métodos para gerar o botão. Para todas as outras plataformas, incluindo Web, e-mail e mensagens de texto, crie um hiperlink no formato https://pay.google.com/gp/v/save/<signed_jwt>. Sempre que possível, é melhor entregar esse link ao usuário como um "Adicionar à Carteira do Google" .

Para mais informações sobre como usar o botão "Adicionar à Carteira do Google", , consulte as diretrizes da promoção de marca da API Google Wallet

Mostrar código de exemplo

  https://pay.google.com/gp/v/save/<signed_jwt>
        

SDK do Android

  private lateinit var walletClient: PayClient
  private val addToGoogleWalletRequestCode = 1000
  private lateinit var addToGoogleWalletButton: View

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    walletClient = Pay.getClient(this)
    addToGoogleWalletButton.setOnClickListener {
      walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
    }
  }
        

Depois que o usuário salvar o cartão emitido, ele vai aparecer no app Carteira do Google com todos os outros cartões salvos.

Como criar objetos e classes de cartões no JWT

Os objetos de cartões e classes de cartões podem ser criados com antecedência usando a API REST da Carteira do Google ou o SDK do Android. Depois de criados, eles são usados para emitir cartões usando como referência o documento de identificação.

Como alternativa, também é possível criar classes e objetos de cartões "bem na hora" incorporando o JSON diretamente no JWT que é usado para emitir o cartão para um usuário. Nesse método, os objetos de cartões e classes de cartões são criados pela API Google Wallet quando o JWT assinado é enviado usando um botão "Adicionar à Carteira do Google" ou link.

Por exemplo, veja a seguir um JWT com uma nova classe de cartões e um objeto de cartões definidos usando as propriedades payload.eventTicketClasses e payload.eventTicketObjects. Observe que essas propriedades são matrizes. Portanto, elas podem aceitar um ou mais objetos de cartões ou classes de cartões. Também é possível especificar apenas um novo objeto de cartões no JWT que faça referência a uma classe de cartões existente pelo ID.

Mostrar exemplo de JWT

  {
    "iss": "issuer@example.com",
    "aud": "google",
    "typ": "savetowallet",
    "iat": 1696877738,
    "origins": [
      "www.example.com"
    ],
    "payload": {
      "eventTicketClasses": [{
        "id": "ISSUER_ID.EVENT_CLASS_ID",
        "issuerName": "[TEST ONLY] Heraldic Event",
        "localizedIssuerName": {
          "defaultValue": {
            "language": "en-US",
            "value": "[TEST ONLY] Heraldic Event"
          }
        },
        "logo": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "LOGO_IMAGE_DESCRIPTION"
            }
          }
        },
        "eventName": {
          "defaultValue": {
            "language": "en-US",
            "value": "Google Live"
          }
        },
        "venue": {
          "name": {
            "defaultValue": {
              "language": "en-US",
              "value": "Shoreline Amphitheater"
            }
          },
          "address": {
            "defaultValue": {
              "language": "en-US",
              "value": "ADDRESS_OF_THE_VENUE"
            }
          }
        },
        "dateTime": {
          "start": "2023-04-12T11:30"
        },
        "reviewStatus": "UNDER_REVIEW",
        "hexBackgroundColor": "#264750",
        "heroImage": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "HERO_IMAGE_DESCRIPTION"
            }
          }
        }
      }],
      "eventTicketObjects": [{
        "id": "ISSUER_ID.OBJECT_ID",
        "classId": "ISSUER_ID.EVENT_CLASS_ID",
        "state": "ACTIVE",
        "seatInfo": {
          "seat": {
            "defaultValue": {
              "language": "en-us",
              "value": "5"
            }
          },
          "row": {
            "defaultValue": {
              "language": "en-us",
              "value": "G"
            }
          },
          "section": {
            "defaultValue": {
              "language": "en-us",
              "value": "40"
            }
          },
          "gate": {
            "defaultValue": {
              "language": "en-us",
              "value": "3A"
            }
          }
        },
        "barcode": {
          "type": "QR_CODE",
          "value": "BARCODE_VALUE",
          "alternateText": ""
        }
      }]
    }
  }