Add to Apple Wallet from Your .NET Application: A Step-by-Step Guide

Created on November 12, 2023 at 11:19 am

The iOS Wallet app allows users to manage payment cards, boarding passes, tickets, gift cards, and other passes. Let’s learn how to set up, build, and distribute Apple ORG

Wallet PRODUCT passes from a .NET application.

I recently worked on the ‘Add to Apple ORG Wallet’ functionality at work, allowing the addition of Event tickets to Apple Wallet ORG .

The iOS Wallet app allows users to manage payment cards, boarding passes, tickets, gift cards, and other passes.

The Wallet Pass FAC is time and location enabled, so passes can be configured to display on the user’s device at the appropriate moment. Passes can also be updated with push notifications making it easy to notify users if details change.

In this blog post, let’s learn how you can set up, build, and distribute Apple ORG

Wallet PRODUCT passes using .NET application.

I will use an AWS Lambda Function to host the API ORG endpoint for distributing the pass files. However, you can use your existing application hosting mechanism for this.

This article is sponsored by AWS ORG and is part of my AWS Series.

Apple Wallet Passes

PRODUCT Apple Wallet Passes are created as a package/bundle, containing a pass.json file that defines the pass, and image assets such as the logo and the icon.

The pass.json file contains the information that identifies the pass, the text information, and details shown on the pass in the Wallet ORG app.

The below image shows the files inside a sample pass file. It has the pass.json , logo and icon images, the manifest file, and also the signature file to avoid tampering with the pass file once it’s generated.

Imaging showing the files inside a pass file. It contains the pass.json file, along with the icon and logo images, the manifest file and the signature file for the pass contents.

Generating Wallet Passes Using .NET

To generate Apple Wallet Pass PRODUCT files from .NET applications, you can use the dotnet-passbook NuGet PRODUCT package.

The NuGet PRODUCT package makes it very easy and straightforward to create Wallet Pass PRODUCT files. The NuGet ORG package provides a PassGenerator ORG class that takes in one CARDINAL or more instances of PassGeneratorRequest .

The PassGenerator ORG converts these requests into a byte array, which represents the pass bundle that contains one CARDINAL or more pass files.

public async Task<APIGatewayHttpApiV2ProxyResponse> GetAppleWalletPasses() { var eventId = Guid.NewGuid(); var eventName = " YouTube Demo Event WORK_OF_ART "; var venueName = " YouTube Online WORK_OF_ART "; var eventDate = DateTime.Now.AddDays(55); var icon = await _appleWalletConfiguration.GetIcon(); var logo = await _appleWalletConfiguration. GetLogo ORG (); var request = GeneratePassRequest(Guid.NewGuid().ToString(), eventId, icon, logo, eventName, eventDate, venueName, "Subscriber"); var generator = new PassGenerator PERSON (); var requests = new List<PassGeneratorRequest>() { request }; var pass = generator.Generate(requests); }

The PassGeneratorRequest identifies one CARDINAL pass that will be added to the Apple ORG Wallet. If you have multiple passes to be added in the same bundle, create multiple PassGeneratorRequest .

The below code shows a sample PassGeneratorRequest that adds a pass with a EventTicket FAC style. It sets the relevant properties to be shown on the Apple Wallet Pass ORG .

var request = new PassGeneratorRequest { Style = PassStyle.EventTicket, PassTypeIdentifier = _appleWalletConfiguration.PassTypeIdentifier, SerialNumber = serialNumber, GroupingIdentifier ORG = eventId. ToString PERSON (), BackgroundColor ORG = "#823EB7", LabelColor = "#000000", ForegroundColor = "#ffffff", Images = { { PassbookImage ORG .Icon, icon}, { PassbookImage ORG .Icon2X, icon}, { PassbookImage ORG .Icon3X, icon}, { PassbookImage ORG .Logo, logo}, { PassbookImage ORG . Logo2X ORG , logo}, { PassbookImage ORG . Logo3X PRODUCT , logo}, }, Description = eventName, OrganizationName = "Rahul", RelevantDate = eventDate, ExpirationDate WORK_OF_ART = eventDate.AddDays(1), AppleWWDRCACertificate ORG = _appleWalletConfiguration.AppleWWDRCACertificate(), PassbookCertificate PRODUCT = _appleWalletConfiguration.PassbookCertificate() }; request. AddHeaderField(new StandardField("time" PERSON , eventDate.ToShortTimeString(), eventDate.ToShortDateString())); request. AddPrimaryField(new PERSON StandardField("name", null, eventName)); request. AddSecondaryField(new PERSON StandardField("venue", " Venue WORK_OF_ART ", venueName)); request. AddAuxiliaryField(new StandardField("ticketType PERSON ", "Ticket Type", ticketType)); request.AddBackField(new StandardField("ticketHolderName-back", "Ticket holder", "Rahul Nath")); request. AddBackField(new StandardField("ticketType-back PERSON ", "Ticket Type", ticketType));

For information on the different fields, the pass styles available, and what each property represents check out the Wallet Guidelines WORK_OF_ART and the documentation.

Setting Up Apple Certificates

To generate Apple Wallet Passes PRODUCT , you need to register with the Apple Developer Portal ORG and have the appropriate certificates ready to sign the Wallet passes.

You need two CARDINAL certificates

Your application/company Passbook certificate along with its password

Apple WWDR ORG ( WorldWide Developer Relations ORG ) certificate

You can find the full instructions to generate the certificates in the dotnet-passbook NuGet PRODUCT package documentation here.

You can store these certificates and other related configurations for generating the Wallet as part of the application configuration – appsettings.json file.

I chose to store the certificate files as base64 encoded string which can be converted to a X509Certificate2 DATE in .NET code as shown below.

public class AppleWalletConfiguration { public string WWDRCertificateBase64 { get; set; } public string PassTypeIdentifier { get; set; } public string PassbookCertificateBase64 { get; set; } public string PassbookPassword { get; set; } public string IconUrl { get; set; } public string LogoUrl PRODUCT { get; set; } public X509Certificate2 DATE AppleWWDRCACertificate() => new(Convert. FromBase64String(WWDRCertificateBase64 GPE )); public X509Certificate2 PassbookCertificate WORK_OF_ART () => new(Convert.FromBase64String(PassbookCertificateBase64), PassbookPassword); public async Task<byte[]> GetLogo() => await LogoUrl PRODUCT .GetBytesAsync(); public async Task<byte[]> GetIcon() => await IconUrl.GetBytesAsync(); }

Distributing Wallet Pass Files Using .NET

To distribute the Wallet Pass Files FAC generated, you can host this in an API ORG endpoint and share the link via email, a button on a web page, or an app.

You can host this along with your other application code on the Cloud or your own servers.

For this post, I’ll host this AWS Lambda PRODUCT , as it’s a quick and easy way to host such kind of API endpoints. Using the latest Lambda Annotations Framework WORK_OF_ART makes it even easier to create and host API endpoints.

All we need to do is add the Lambda Annotation Framework NuGet LAW package and wrap our Pass Generation function with the LambdaFunction FAC attribute. Since this is going to be exposed as an API ORG will also add the HttpApi ORG attribute and specify the route and the method Get .

[LambdaFunction(Policies = "AWSLambdaBasicExecutionRole")] [HttpApi(LambdaHttpMethod.Get, "/apple-wallet")] public async Task<APIGatewayHttpApiV2ProxyResponse> GetAppleWalletPasses() { var eventId = Guid.NewGuid(); var eventName = " YouTube Demo Event WORK_OF_ART "; … var generator = new PassGenerator PERSON (); var requests = new List<PassGeneratorRequest>() { request }; var pass = generator.Generate(requests); return new APIGatewayHttpApiV2ProxyResponse() { Body = Convert. ToBase64String(pass ORG ), IsBase64Encoded = true, StatusCode ORG = 200 CARDINAL , Headers = new Dictionary<string, string> { { " Content-Type WORK_OF_ART ", "application/vnd.apple.pkpasses" }, { " Content-Disposition WORK_OF_ART ", "attachment; filename=tickets.pkpasses.zip; filename*=UTF-8”tickets.pkpasses.zip GPE " } } }; }

The HttpApi ORG attribute allows us to expose the Lambda Function ORG over a Lambda Function URL or an HTTP API Gateway endpoint.

Both of these mechanisms expect binary content to be encoded as base64 string, with the appropriate HTTP headers set. To achieve this we can use the APIGatewayHttpApiV2ProxyResponse object as shown above.

Once deployed, you can navigate the API Gateway PRODUCT URL endpoint or expose a Lambda Function PRODUCT URL, and navigate to the URL from an iPhone Safari PERSON browser, to add it to Apple Wallet ORG .

Below is the screenshot of the pass generated using the above code, with the appropriate information we passed to create the pass.

Apple Wallet Passes ORG added to phone showing the front and the back details of the pass.

For debugging pass files you can use the PKPassValidator service, where you can upload a pass file and it will show any issues with the file generated.

The Apple ORG Wallet pass generated above is static and does not update itself.

However most of the time you would need to deliver live updates to these passes in case any information changes for example date changes, venue changes, status updates, etc. For this, we can configure the WebServiceUrl , on the pass that it will poll for pass updates

We will learn how to configure and set up the CallbackUrl ORG in a future blog post. Until then, happy coding! 👋

Connecting to blog.lzomedia.com... Connected... Page load complete