Integra la API de la Billetera de Google para digitalizar pases en Android.

1. Antes de comenzar

La API de la Billetera de Google te permite interactuar con usuarios a través de diferentes tipos de pases predefinidos: tarjetas de lealtad, ofertas, tarjetas de regalo, entradas para eventos, boletos de transporte público y tarjetas de embarque. Todos estos pases incluyen campos y funciones específicas de casos de uso. Sin embargo, reconocemos que estas opciones podrían no adaptarse a todos los casos de uso, por lo que creamos un tipo de pase genérico. Como su nombre lo indica, el tipo de pase genérico debe usarse cuando tu caso de uso no se ajusta a ninguno de los otros tipos especializados. Estos son algunos ejemplos de casos de uso para el tipo de pase genérico:

  • Pases de estacionamiento
  • Tarjetas de membresía de biblioteca
  • Cupones de saldo
  • Tarjetas de membresía de gimnasio
  • Tarjetas de seguros
  • Reservas de diversos tipos

Puedes usar pases genéricos para cualquier caso de uso que se pueda presentar al usuario en forma de tarjeta con un máximo de tres filas de información, un código de barras opcional y una sección de detalles opcional, siempre y cuando cumplas con nuestra Política de Uso Aceptable.

La API de la Billetera de Google te permite crear lo siguiente:

  • Clases de pases. Piensa en las clases de pases como plantillas con información común que comparten todos tus pases pertenecientes a un programa o un evento. Todos los objetos de pase pertenecen a una clase.
  • Los objetos de pase tienen un propósito concreto asociado con tu actividad como empresa y tus usuarios (p. ej., tarjeta de estacionamiento, tarjeta de membresía de gimnasio). Cada uno de estos elementos está asociado con una clase definida anteriormente y hereda propiedades comunes de ella.

En este codelab, te proporcionaremos una clase predefinida y te guiaremos para que definas el JSON de un objeto de pase. Además se incluirá el botón "Agregar a la Billetera de Google" en tu app para Android, que permitirá a los usuarios guardar el pase en su Billetera de Google.

Para obtener más información sobre la API de la Billetera de Google o sobre cómo agregar el botón "Agregar a la Billetera de Google" a una app para Android, consulta la documentación para desarrolladores de la Billetera de Google.

Requisitos previos

  • Una computadora que tenga Android Studio instalado
  • Capacidad de crear y ejecutar un proyecto en Android Studio.
  • Tener Git instalado

Qué aprenderás

  • Cómo agregar el SDK de la Billetera de Google a tu aplicación para Android.
  • Cómo comprobar si la API de Billetera está disponible.
  • Cómo implementar una IU, que permite al usuario agregar un pase a su Billetera de Google.

2. Prepárate

Crea una cuenta de entidad emisora temporal

A fin de crear pases para tu usuario, primero debes crear una cuenta de emisor, habilitar la API de la Billetera y, luego, crear una clase. Puedes hacer todo esto a través de la Business Console de Google Pay. Sin embargo, el acceso a esa función solo se otorga una vez que se completa el proceso de aprobación, por lo que, para este codelab, crearemos una cuenta de entidad emisora temporal y una clase de pase para ti.

  1. Haz clic en Crear una cuenta de entidad emisora temporal y una clase de muestra.
  1. Anota el ID de la entidad emisora y el ID de la clase, ya que los necesitarás en los próximos pasos.

Clona el repositorio de Git

Clona el repositorio de Git, que contiene el proyecto de Android que editarás, con el siguiente comando:

git clone -b wallet-lab git@github.com:google-pay/android-quickstart.git

Abre en Android Studio

Abre Android Studio, selecciona "Open" en la pantalla de bienvenida y selecciona la carpeta kotlin en el repositorio clonado recientemente para abrirla como proyecto.

3. Agrega el SDK de la Billetera de Google a tu aplicación

El proyecto de Android contiene una actividad vacía que editaremos en breve, pero primero agregaremos el SDK de la Billetera de Google como dependencia. En Android Studio, selecciona la secuencia de comandos "build.gradle" de nivel de módulo y agrega las siguientes líneas a la sección dependencies:

dependencies {
    ...
    implementation 'com.google.android.gms:play-services-pay:16.0.3'
}

Una vez que lo hagas, haz clic en el botón "Sync Project" de Gradle, en la parte superior derecha de Android Studio.

4. Agrega el botón "Agregar a Billetera de Google"

A continuación, agregarás el botón "Agregar a la Billetera de Google" a la actividad. Los elementos del botón ya se agregaron al proyecto, solo debes agregarlos a tu archivo de diseño. Para ello, te recomendamos crear un diseño independiente con el botón:

add_to_google_wallet_button.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:clickable="true"
    android:focusable="true"
    android:layout_width="match_parent"
    android:layout_height="48sp"
    android:background="@drawable/add_to_google_wallet_button_background_shape"
    android:contentDescription="@string/add_to_google_wallet_button_content_description">
    <ImageView
        android:layout_width="227dp"
        android:layout_height="26dp"
        android:layout_gravity="center"
        android:duplicateParentState="true"
        android:src="@drawable/add_to_google_wallet_button_foreground"/>
</FrameLayout>

Así es como se ve el botón:

Luego, inclúyelo en tu archivo de diseño:

<include
    android:id="@+id/addToGoogleWalletButton"
    layout="@layout/add_to_google_wallet_button"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:layout_marginTop="10dp"/>

5. Comprueba si la API está disponible

Ahora es momento de programar. Abre el archivo en el que realizarás llamadas con la API de la Billetera de Google en Android Studio (el archivo CheckoutActivity.kt si usas la aplicación de ejemplo) y crea una instancia de un objeto PayClient como miembro de tu clase. Este objeto te ayuda a realizar llamadas a la API de la Billetera de Google. El método getClient recibe el contexto de la clase de creación de instancias, en este caso, la actividad de llamada.

private lateinit var walletClient: PayClient

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    walletClient = Pay.getClient(this)
    ...
}

A continuación, asegúrate de que el SDK y la aplicación de la Billetera de Google estén disponibles en el dispositivo. Crea un método nuevo en la clase (p. ej.: fetchCanUseGoogleWalletApi) para determinar si la API de la Billetera de Google está disponible y otra para reaccionar como resultado al mostrar el botón "Agregar a la Billetera de Google" (si la API está disponible):

private fun fetchCanUseGoogleWalletApi() {
    walletClient
        .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
        .addOnSuccessListener { status ->
            if (status == PayApiAvailabilityStatus.AVAILABLE)
                layout.passContainer.visibility = View.VISIBLE
        }
        .addOnFailureListener {
             // Hide the button and optionally show an error message
        }
}

Por último, llama al método fetchCanUseGoogleWalletApi en el método onCreate para determinar si la API de la Billetera de Google está disponible:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    ...
    fetchCanUseGoogleWalletApi()
}

Ahora, deberías ver el botón "Agregar a la Billetera de Google" en tu IU cuando ejecutes la aplicación:

6. Agrega un pase a la Billetera de Google

Ahora que ya verificaste que la API de la Billetera de Google está disponible, puedes solicitar a tus usuarios que agreguen pases a la Billetera. Antes de hacerlo, tómate un momento para revisar el pase que se creó en este taller:

Este diseño utiliza la flexibilidad de pases genéricos para crear un objeto que funcione como una insignia de identidad y, al mismo tiempo, admite un desafío que invita a los participantes a acumular puntos durante el evento. Así es como se ve el objeto genérico:

{
    "id": "999999.d1fa-4cca1...",
    "classId": "999999.a92b-129f...",
    "genericType": "GENERIC_TYPE_UNSPECIFIED",
    "hexBackgroundColor": "#4285f4",
    "logo": { ... },
    "cardTitle": { ... },
    "subheader": { ... },
    "header": { ... },
    "barcode": { ... },
    "heroImage": { ... },
    "textModulesData": []
}

Para insertar el objeto, la API espera un cuerpo de JWT sin firma que una los nuevos elementos:

{
    "iss": <owner-email-address>,
    "aud": "google",
    "typ": "savetowallet",
    "iat": <unix-time>,
    "origins": [],
    "payload": {
        "genericObjects": [],
        "genericClasses": [],
        ...
    }
}

Combina toda la información (con los valores que obtuviste antes cuando creaste una cuenta de entidad emisora temporal) y asigna el objeto resultante a una variable de tu clase:

private val issuerEmail = "<insert-your-issuer-email-address>"
private val issuerId = "<insert-your-issuer-id>"
private val passClass = "<insert-your-class-id>"
private val passId = UUID.randomUUID().toString()

private val newObjectJson = """
    {
      "iss": "$issuerEmail",
      "aud": "google",
      "typ": "savetowallet",
      "iat": ${Date().time / 1000L},
      "origins": [],
      "payload": {
        "genericObjects": [
          {
            "id": "$issuerId.$passId",
            "classId": "$passClass",
            "genericType": "GENERIC_TYPE_UNSPECIFIED",
            "hexBackgroundColor": "#4285f4",
            "logo": {
              "sourceUri": {
                "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg"
              }
            },
            "cardTitle": {
              "defaultValue": {
                "language": "en",
                "value": "Google I/O '22  [DEMO ONLY]"
              }
            },
            "subheader": {
              "defaultValue": {
                "language": "en",
                "value": "Attendee"
              }
            },
            "header": {
              "defaultValue": {
                "language": "en",
                "value": "Alex McJacobs"
              }
            },
            "barcode": {
              "type": "QR_CODE",
              "value": "$passId"
            },
            "heroImage": {
              "sourceUri": {
                "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/google-io-hero-demo-only.jpg"
              }
            },
            "textModulesData": [
              {
                "header": "POINTS",
                "body": "${Random.nextInt(0, 9999)}",
                "id": "points"
              },
              {
                "header": "CONTACTS",
                "body": "${Random.nextInt(1, 99)}",
                "id": "contacts"
              }
            ]
          }
        ]
      }
    }
    """

Por último, vuelve a tu método onCreate y agrega un controlador de clics a tu botón "Agregar a la Billetera de Google" para iniciar la operación con el método savePasses del cliente:

private val addToGoogleWalletRequestCode = 1000

private lateinit var layout: ActivityCheckoutBinding
private lateinit var addToGoogleWalletButton: View

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Use view binding to access the UI elements
    layout = ActivityCheckoutBinding.inflate(layoutInflater)
    setContentView(layout.root)

    addToGoogleWalletButton = layout.addToGoogleWalletButton.root
    addToGoogleWalletButton.setOnClickListener {
        walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
    }

    ...
}

De esa forma, definiste el JSON para el objeto nuevo con el ID de la entidad emisora y el ID de la clase que creaste anteriormente. Cuando el usuario hace clic en el botón "Agregar a la Billetera de Google", se llama a payClient.savePasses y se le propone agregar el nuevo objeto de pase a su Billetera de Google:

7. Controla el resultado

Ya casi terminas. Por último, controla el resultado de la operación, ya sea que tenga éxito o no. Anula el método onActivityResult para que contenga el siguiente código:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == addToGoogleWalletRequestCode) {
        when (resultCode) {
            RESULT_OK ->
                // Pass saved successfully. Consider informing the user.
            RESULT_CANCELED -> {
                // Save canceled
            }

            PayClient.SavePassesResult.SAVE_ERROR -> data?.let { intentData ->
                val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)
                // Handle error. Consider informing the user.
            }

            else -> {
                // Handle unexpected (non-API) exception
            }
        }
    }
}

Con este código, controlas que el pase se agregue con éxito, que el usuario cancele la acción y también cualquier error que pueda ocurrir. Vuelve a ejecutar la aplicación para confirmar que puedes agregar el pase y administrar el resultado como se espera.

8. Felicitaciones

Felicitaciones, integraste correctamente la API de la Billetera de Google en Android.

Más información

Observa una integración en su totalidad en la aplicación de muestra de GitHub para ver un ejemplo completo.

Regístrate para obtener una cuenta de entidad emisora

Cuando tengas todo listo para emitir tus propios pases en producción, ve a Google Pay & Wallet Console a fin de solicitar acceso a la API de la Billetera de Google y autoriza a tu aplicación para Android a emitir llamadas en esa API. Consulta la documentación para obtener más información.