Before you start
- ✓An Apple developer account with a registered pass type and its certificate
- ✓A Google Wallet issuer account and a service account key
- ✓Your current ticket QR format (it must not change)
- ✓A secure place for the certificate and key (Azure Key Vault or similar)
Deciding what goes on the pass
On a ticketing platform we built, a pass shows the event, date and time (in the venue's timezone), venue, ticket type and a short readable code. Above all, keep the QR code's contents identical to your existing tickets, so door scanners need no changes.
Apple Wallet passes
- Each ticket becomes a pass file signed with your Apple pass certificate and Apple's intermediate certificate (we use the open-source dotnet-passbook library).
- A bundle file adds a multi-ticket order in one tap.
- Front-of-pass fields don't wrap, so the ticket type goes in the main field and long names stay short. A 540 × 660 background image carries the artwork.
Google Wallet passes
These come from a save link carrying a signed token with the event and ticket inside, so nothing needs setting up with Google first. We group tickets by event and show the tier on the card. Google creates each event design once, so a change needs a new version.
Serving passes without a login
Customers open passes from emails, usually not signed in, so each is served from a public link using the ticket's unguessable id, never a sequential number.
Keeping the signing credentials safe
The Apple certificate and Google key live as secrets in Azure Key Vault and are written to temporary files at start-up. The Apple certificate was too large for an Azure DevOps pipeline variable, so deployment uses Secure Files instead.
Switching it on per organiser
A per-organiser setting (off by default) and an admin page that checks the certificates and generates a test pass mean each organiser's passes are verified before customers see them.
What usually goes wrong
From our own projects, not the manual.
Google passes showed the wrong time in summer
Reading the pass data with default settings dropped the time's offset on servers running in UTC, so passes showed GMT instead of BST. Read dates in a way that keeps the offset.
The Apple certificate wouldn't load on IIS
Loading it failed with 'the system cannot find the file specified' because the IIS app pool had no user profile. Load it into the machine's certificate store instead.
The Apple certificate was too big for a pipeline variable
Encoded as text, the certificate came to about 4,500 characters against Azure DevOps' 4,096 limit. Use the pipeline's Secure Files instead.
The Google 'add all tickets' link broke on big orders
Each ticket adds about 1.1 KB to the link, so group orders produced links of 27 to 73 KB, too long for the redirect. Offer per-ticket links (about 3 KB each) instead.
Changes to a Google event never showed up
Google creates an event design once and ignores later edits to it. Issue a new version whenever the design changes.
Pass times fell back to the wrong timezone
The data behind the pass didn't include the venue, so times used the platform default instead of the venue's timezone. Load everything the pass needs, and test with a venue in another timezone.
Do it yourself, or get help?
If you have one ticket type and a developer comfortable with signing certificates, you can ship wallet passes in a few days using Apple's and Google's documentation. If you run many organisers, need passes on existing tickets without touching scanners, or deploy to IIS or a locked-down pipeline, get help: the time goes on the gotchas, not the happy path.
Get a developer on it