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 gleich sind, z. B. Name, Datum und Uhrzeit der Veranstaltung.

Jede Karten/Tickets, die du ausgibst, 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.

Und 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 eine 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 einzelnen Karte bzw. eines eindeutigen Tickets, die an einen bestimmten Nutzer ausgestellt wird. Das Karten-/Ticketobjekt für ein Veranstaltungsticket würde beispielsweise Felder definieren, die für ein bestimmtes Ticket eindeutig sind, z. B. die Sitznummer oder ein QR-Code für dieses 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 verknüpften Karten-/Ticketklasse.

Außerdem musst du jedem Karten-/Ticketobjekt eine eindeutige ID zuweisen, mit der beim Ausstellen einer Karte bzw. eines Tickets darauf verwiesen wird.

Und 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 ein 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 bzw. ein Ticket für 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. Wenn Karten/Tickets mit der Google Wallet API ausgestellt werden, 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 bzw. ein bestimmtes Ticket zu identifizieren und dem 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.

Und so gehts

JWTs werden basierend auf der JWT-Spezifikation im JSON-Format definiert. Um ein JWT für die Ausstellung einer Karte bzw. eines Tickets mit der Google Wallet API zu definieren, gibst du die Informationen zu der Karte bzw. dem Ticket, das 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. Beim Signieren werden deine Anmeldedaten verwendet, um das JWT zu verschlüsseln, damit deine Karten/Tickets sicher bleiben und die Google Wallet API authentifizieren kann, ob die darin codierten Karten-/Ticketdetails gültig und mit deinem Ausstellerkonto verknüpft sind.

Und 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 Komplexität der Codesignatur 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, bearbeitet das SDK das JWT automatisch 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 für die Signatur 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

Nachdem du ein signiertes JWT erstellt hast, kannst du deine Karte bzw. dein Ticket für einen Google Wallet-Nutzer ausstellen. Dazu wird dem Nutzer entweder die Schaltfläche „Zu Google Wallet hinzufügen“ oder ein Link 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, damit er sie in seinem Google Wallet-Konto speichern kann.

Und so gehts

Verwende zum Erstellen einer Schaltfläche „Zu Google Wallet hinzufügen“ für eine Android-App 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, senden Sie dem Nutzer diesen Link am besten als Schaltfläche „Zu Google Wallet hinzufügen“.

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 er in seiner Google Wallet App zusammen mit allen anderen gespeicherten Karten/Tickets 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. Nachdem sie erstellt wurden, werden sie verwendet, um Karten/Tickets auszustellen, indem sie auf ihre ID verweisen.

Alternativ kannst du Karten-/Ticketklassen und Karten-/Ticketobjekte auch „Just in Time“ erstellen, indem du deren JSON direkt in das JWT einbettest, das zum Ausstellen der Karte bzw. des Tickets für einen Nutzer verwendet wird. Bei dieser Methode werden die Karten-/Ticketklassen und Karten-/Ticketobjekte von der Google Wallet API erstellt, wenn das signierte JWT über eine Schaltfläche oder einen Link „Zu Google Wallet hinzufügen“ gesendet wird.

Das folgende Beispiel zeigt ein JWT mit einer neuen Karten-/Ticketklasse und einem neuen Karten-/Ticketobjekt, das mithilfe der Attribute payload.eventTicketClasses und payload.eventTicketObjects definiert wird. Beachten Sie, dass diese Attribute Arrays sind. Sie können also eine oder mehrere Karten-/Ticketklassen oder Karten-/Ticketobjekte akzeptieren. 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": ""
        }
      }]
    }
  }