Entwicklungsablauf für Google Wallet-Karten/Tickets

Die Google Wallet API bietet vordefinierte Karten-/Tickettypen, die für bestimmte Anwendungsfälle optimiert sind, z. B. Geschenkkarten, Bordkarten und Veranstaltungstickets. Es gibt auch einen generischen Karten-/Tickettyp, der für Anwendungsfälle vorgesehen ist, in denen ein bestimmter Karten-/Tickettyp nicht verfügbar ist.

Dieser Artikel soll dich mit den grundlegenden Schritten vertraut machen, die zum Erstellen und Ausstellen von Karten/Tickets mit der Google Wallet API erforderlich sind. Es gibt mehrere Möglichkeiten, einige der unten beschriebenen Schritte auszuführen. Grundsätzlich werden aber alle Karten-/Tickettypen anhand desselben grundlegenden Entwicklungsablaufs erstellt.

Eine ausführliche Anleitung zum Erstellen von Karten/Tickets findest du in den Leitfäden für Web, E-Mail und SMS bzw. Android-Apps.

Zweck

Eine Karten-/Ticketklasse definiert eine Reihe von Eigenschaften, die für mehrere Karten/Tickets gelten, ähnlich wie bei einer Vorlage. Wenn Sie beispielsweise Tickets für eine Veranstaltung ausstellen, definiert die Karten-/Ticketklasse Felder, die für alle Tickets identisch sind, z. B. Name, Datum und Uhrzeit der Veranstaltung.

Jede von dir ausgegebene Karte bzw. jedes von dir ausgegebene Ticket muss auf eine Karten-/Ticketklasse verweisen. Außerdem musst du jeder Karten-/Ticketklasse, die du erstellst, eine eindeutige ID zuweisen, die beim Erstellen von Karten/Tickets verwendet wird, um darauf zu verweisen.

So gehts

Eine Karten-/Ticketklasse ist im JSON-Format definiert und kann mit der Google Wallet REST API, dem Android SDK oder in der Google Wallet Business Console erstellt werden.

Beispiel für die Karten-/Ticketklasse anzeigen

{
  "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"
      }
    }
  }
}
    

Zweck

Ein Karten-/Ticketobjekt definiert die Eigenschaften einer eindeutigen Karte, die einem bestimmten Nutzer ausgestellt wird. Das Karten-/Ticketobjekt für ein Veranstaltungsticket definiert beispielsweise eindeutige Felder für ein bestimmtes Ticket, z. B. die Sitznummer oder einen QR-Code für das Ticket.

Wenn ein Karten-/Ticketobjekt erstellt wird, speichert die Google Wallet API eine neue Karte bzw. ein neues Ticket und verknüpft sie mit deinem Ausstellerkonto. Diese gespeicherte Karte bzw. das gespeicherte Ticket ist eine Kombination aus den eindeutigen Eigenschaften des Karten-/Ticketobjekts und den Vorlageneigenschaften der zugehörigen Karten-/Ticketklasse.

Außerdem musst du jedem Karten-/Ticketobjekt eine eindeutige ID zuweisen, die beim Ausstellen einer Karte bzw. eines Tickets verwendet wird, um darauf zu verweisen.

So gehts

Ein Karten-/Ticketobjekt ist im JSON-Format definiert und kann mit der Google Wallet REST API oder dem Android SDK erstellt werden.

Beispiel für das Karten-/Ticketobjekt einblenden

{
  "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": ""
  }
}
    

Zweck

Um eine Karte / ein Ticket an einen Nutzer auszustellen, müssen eine Karten-/Ticketklasse und ein Karten-/Ticketobjekt in einem JSON-Webtoken (JWT) codiert sein. Das JWT-Format ist ein gängiger und offener Standard für die Darstellung von Ansprüchen zwischen zwei Parteien. Beim Ausstellen von Karten/Tickets mit der Google Wallet API werden JWTs verwendet, um einen Anspruch zu senden, demzufolge ein Nutzer berechtigt ist, auf eine bestimmte Karte bzw. ein bestimmtes Ticket zuzugreifen, das mit deinem Ausstellerkonto verknüpft ist.

Wenn ein JWT an die Google Wallet API gesendet wird, werden die codierten Daten verwendet, um eine bestimmte Karte / ein bestimmtes Ticket zu identifizieren und an den Nutzer auszustellen. Wenn die Karte bzw. das Ticket bereits ausgestellt wurde, kann die Google Wallet API anhand dieser Daten auch erkennen, dass die Karte bzw. das Ticket ein Duplikat ist, sodass sie dem Google Wallet des Nutzers nur einmal hinzugefügt wird.

So gehts

JWTs werden basierend auf der JWT-Spezifikation im JSON-Format definiert. Um ein JWT für das Ausstellen einer Karte bzw. eines Tickets mit der Google Wallet API zu definieren, gibst du die Informationen zu der Karte bzw. dem Ticket, die du ausstellen möchtest, im Attribut payload des JWT an.

Beispiel-JWT anzeigen

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

Zweck

Alle JWTs, die zum Ausstellen einer Karte bzw. eines Tickets an die Google Wallet API gesendet werden, müssen mit Anmeldedaten signiert werden, die du zuvor in der Google Wallet Business Console angegeben hast. Bei der Signatur werden deine Anmeldedaten verwendet, um das JWT zu verschlüsseln, damit deine Karten/Tickets sicher bleiben und die Google Wallet API authentifiziert werden kann, um zu authentifizieren, dass die darin codierten Karten-/Ticketdetails gültig sind und mit deinem Ausstellerkonto verknüpft sind.

So gehts

Die Google Wallet-Clientbibliotheken und das Android SDK bieten praktische Methoden zum Signieren deiner JWTs. Es gibt auch zahlreiche Open-Source-Bibliotheken, die die komplexe Codesignierung bewältigen.

Für Nutzer, die die Google Wallet REST API zum Ausstellen von Karten/Tickets verwenden, wird das JWT mit einem Google Cloud-Dienstkontoschlüssel signiert. Wenn du das Google Wallet Android SDK verwendest, signiert das SDK automatisch das JWT mit dem SHA-1-Fingerabdruck deines App-Signaturzertifikats.

Zum Schutz deiner Anmeldedaten sollten JWTs nur auf deinem Server oder mit dem Google Wallet Android SDK in deiner App signiert werden.

Beispielcode-Signierung anzeigen

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')
        

Zweck

Sobald du ein signiertes JWT erstellt hast, kannst du deine Karte bzw. dein Ticket an einen Google Wallet-Nutzer ausstellen. Dazu wird entweder die Schaltfläche „Zu Google Wallet hinzufügen“ oder der Link „Zu Google Wallet hinzufügen“ eingeblendet. Wenn ein Nutzer auf die Schaltfläche oder den Hyperlink klickt, wird das signierte JWT an die Google Wallet API gesendet, die es dann anhand deiner gespeicherten Anmeldedaten entschlüsselt. Nach der Authentifizierung der JWT-Signatur wird die Karte bzw. das Ticket an den Nutzer ausgestellt und in Google Wallet gespeichert.

So gehts

Wenn du eine Schaltfläche „Zu Google Wallet hinzufügen“ für eine Android-App erstellen möchtest, verwende das Google Wallet Android SDK, das Methoden zum Generieren der Schaltfläche bietet. Erstellen Sie für alle anderen Plattformen, einschließlich Web, E-Mails und SMS, einen Hyperlink im Format https://pay.google.com/gp/v/save/<signed_jwt>. Wenn möglich, solltest du dem Nutzer diesen Link als Schaltfläche „Zu Google Wallet hinzufügen“ senden.

Weitere Informationen zur Verwendung der Schaltfläche „Zu Google Wallet hinzufügen“ finden Sie in den Markenrichtlinien für die Google Wallet API.

Beispielcode anzeigen

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

Android SDK

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

Sobald der Nutzer die ausgestellte Karte bzw. das ausgestellte Ticket gespeichert hat, wird sie zusammen mit allen anderen gespeicherten Karten/Tickets in seiner Google Wallet App angezeigt.

Karten-/Ticketobjekte und Karten-/Ticketklassen im JWT erstellen

Karten-/Ticketklassen und Karten-/Ticketobjekte können mit der Google Wallet REST API oder dem Android SDK im Voraus erstellt werden. Nach der Erstellung werden sie dann verwendet, um Karten/Tickets auszustellen, indem auf ihre ID verwiesen wird.

Alternativ kannst du Karten-/Ticketklassen und Karten-/Ticketobjekte auch „Just in Time“ erstellen, indem du ihre JSON-Datei direkt in das JWT einbettest, mit dem die Karte bzw. das Ticket an einen Nutzer ausgestellt wird. Bei dieser Methode werden die Karten-/Ticketklassen und Karten-/Ticketobjekte von der Google Wallet API erstellt, wenn das signierte JWT über die Schaltfläche oder den Link „Zu Google Wallet hinzufügen“ gesendet wird.

Das folgende Beispiel zeigt ein JWT mit einer neuen Karten-/Ticketklasse und einem Karten-/Ticketobjekt, das über die Attribute payload.eventTicketClasses und payload.eventTicketObjects definiert ist. Diese Eigenschaften sind Arrays und können daher eine oder mehrere Karten-/Ticketklassen oder Karten-/Ticketobjekte annehmen. Du kannst auch nur ein neues Karten-/Ticketobjekt im JWT angeben, das anhand seiner ID auf eine vorhandene Karten-/Ticketklasse verweist.

Beispiel-JWT anzeigen

  {
    "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": ""
        }
      }]
    }
  }