A .Net Library for generating Passbook (Wallet) packages for iOS. Please get involved by forking and updating the repository.
C# JavaScript Other
Switch branches/tags
Nothing to show
Clone or download
tomasmcguinness Merge pull request #68 from rodrigograudo/master
Improving error handling on writing images to manifest.
Latest commit 7497168 Jun 18, 2018
Permalink
Failed to load latest commit information.
.nuget Added NuGet to enable package restore. Dec 12, 2012
Passbook.Generator Improving error handling on writing images to manifest. Jun 15, 2018
Passbook.Sample.Web Updated the Web project a little. Jun 5, 2018
Passbook.Web Updated the Web project a little. Jun 5, 2018
packages Updated AspNet MVC / WebApi to 5.2.3 May 28, 2015
.gitignore Added nupkg file for 0.9.8. Added .vs directory to gitignore. Mar 7, 2016
README.md Update README.md Jun 5, 2018
dotnet-passbook.0.7.7.nupkg Updated Mar 9, 2013
dotnet-passbook.0.8.0.nupkg Added new NuGet package. Jul 9, 2013
dotnet-passbook.0.9.0.nupkg Updated version and NuGet package information. Sep 28, 2013
dotnet-passbook.0.9.1.nupkg Updated NuGet package and updated Readme Oct 12, 2013
dotnet-passbook.0.9.2.nupkg New NuGet package Dec 5, 2013
dotnet-passbook.0.9.3.nupkg Created new package for Nuget with version 0.9.3 Dec 11, 2013
dotnet-passbook.0.9.4.nupkg New NuGet package May 15, 2014
dotnet-passbook.0.9.5.nupkg Updated relevantdate to full W3C time and bumped version to 0.9.5 May 25, 2014
dotnet-passbook.0.9.7.nupkg Added support for FooterImage and bumped version to 0.9.7 Dec 16, 2014
dotnet-passbook.0.9.8.nupkg Updated package. Mar 7, 2016
dotnet-passbook.1.0.0.nupkg Published version 1.0.0 to Nuget Jan 2, 2017
dotnet-passbook.1.0.1.nupkg Fixed compile issues in Providers. Created new Nuget package spec Feb 8, 2018
dotnet-passbook.1.0.2.nupkg Published version 1.0.2 May 29, 2018
dotnet-passbook.nuspec Bump version to 0.9.9 Apr 8, 2016
dotnet-passbook.sln Introduced Passbook.Web May 27, 2015
dotnet-passbook.v12.suo Moving version to 0.9.8 Jan 26, 2016

README.md

dotnet-passbook

A .Net Library for generating Passbook packages for iOS Wallet (formerly Passbook)

Why

Creating passes for Apple's Passbook is pretty simple, but requires the use of PKI for signing manifest files, which isn't so simple! During the course of building the PassVerse (no longer available), I created a library that performs all the steps in C#. I decided to open source this library to other .Net developers. It allows you to generate, sign and zip Passbook files for use with Apple's Wallet (Available in iOS, starting at version 6).

Requirements

The solution requires .Net 4.5 and Visual Studio 2012 or higher.

Certificates

Before you run the PassGenerator, you need to ensure you have all the necessary certificates installed. There are two required.

Firstly, you need to install the Apple WWDR (WorldWide Developer Relations) certificate. You can download that from here http://www.apple.com/certificateauthority/ . You must install it in the Local Machine's Intermediate Certificate store. I've hardcoded that location

Secondly, you need to installed your Passbook certificate, which you get from the Developer Portal. You must have a full iPhone developer account. There are instructions on my blog for generating a certificate if you're using a Windows Machine.

You can place this certificate in any of the stores, but it must be placed into the "personal" folder. When constructing the request for the pass, you specify the location and thumbprint for the certificate. If running this code in IIS for example, installing the certificate in the Local Machine area might make access easier. Alternatively, you could place the certificate into the AppPool's user's certification repository. When you install the certificate, be sure to note the certificate's Thumbprint.

Technical Stuff

To generate a pass, start by declaring a PassGenerator.

PassGenerator generator = new PassGenerator();

Next, create a PassGeneratorRequest. This is a raw request that gives you the full power to add all the fields necessary for the pass you wish to create. Each pass is broken down into several sections. Each section is rendered in a different way, based on the style of the pass you are trying to produce. For more information on this, please consult Apple's Passbook Programming Guide. The example below here will show how to create a very basic boarding pass.

Since each pass has a set of mandatory data, fill that in first.

PassGeneratorRequest request = new PassGeneratorRequest();
request.PassTypeIdentifier = "pass.tomsamcguinness.events";   
request.TeamIdentifier = "RW121242";
request.SerialNumber = "121212";
request.Description = "My first pass";
request.OrganizationName = "Tomas McGuinness";
request.LogoText = "My Pass";

Colours can be specified in HTML format or in RGB format.

request.BackgroundColor = "#FFFFFF";
request.LabelColor = "#000000";
request.ForegroundColor = "#000000";

request.BackgroundColor = "rgb(255,255,255)";
request.LabelColor = "rgb(0,0,0)";
request.ForegroundColor = "rgb(0,0,0)";

To select the certificate there are two options. Firstly, you can use the Windows Certificate store to hold the certificates. You choose the location of your Passbook certificate by specifying the thumbprint of the certificates. The Apple WWDRC is also loaded in this way, so you don't need to specify anything.

request.CertThumbprint = "22C5FADDFBF935E26E2DDB8656010C7D4103E02E";
request.CertLocation = System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser;

An alternative way to pass the certificates into the PassGenerator is to load them as byte[] and add them to the request.

request.Certificate = certData; // Loaded from a database or other mechanism for example.
request.CertificatePassword = "abc123"; // The password for the certificate's private key.
string appleCertPath = (HttpContext.Current.Server.MapPath("~/Certificates
AppleWWDRCA.cer");
request.AppleWWDRCACertificate = File.ReadAllBytes(appleCertPath);

Next, define the images you with to use. You must always include both standard and retina sized images. Images are supplied as byte[].

// override icon and icon retina
request.Images.Add(PassbookImage.Icon, System.IO.File.ReadAllBytes(Server.MapPath("~/Icons/icon.png")));
request.Images.Add(PassbookImage.IconRetina, System.IO.File.ReadAllBytes(Server.MapPath("~/Icons/icon@2x.png")));

You can now provide more pass specific information. The Style must be set and then all information is then added to fields to the required sections. For a baording pass, the fields are add to three sections; primary, secondary and auxiliary.

request.Style = PassStyle.BoardingPass;

request.AddPrimaryField(new StandardField("origin", "San Francisco", "SFO"));
request.AddPrimaryField(new StandardField("destination", "London", "LDN"));

request.AddSecondaryField(new StandardField("boarding-gate", "Gate", "A55"));

request.AddAuxiliaryField(new StandardField("seat", "Seat", "G5" ));
request.AddAuxiliaryField(new StandardField("passenger-name", "Passenger", "Thomas Anderson"));

request.TransitType = TransitType.PKTransitTypeAir;

You can add a BarCode.

request.AddBarCode(BarcodeType.PKBarcodeFormatPDF417, "01927847623423234234", "ISO-8859-1", "01927847623423234234");

Starting with iOS 9, multiple barcodes are now supported. This helper method supports this new feature. If you wanted to support iOS 8 and earlier, you can use the method SetBarcode().

To link the pass to an existing app, you can add the app's Apple ID to the AssociatedStoreIdentifiers array.

   request.AssociatedStoreIdentifiers.Add(551768478);

Finally, generate the pass by passing the request into the instance of the Generator. This will create the signed manifest and package all the the image files into zip.

	byte[] generatedPass = generator.Generate(request);

If you are using ASP.NET MVC for example, you can return this byte[] as a Passbook package

return new FileContentResult(generatedPass, "application/vnd.apple.pkpass");

IIS Security

If you're running the signing code within an IIS application, you might run into some issues accessing the private key of your certificates. To resolve this open MMC => Add Certificates (Local computer) snap-in => Certificates (Local Computer) => Personal => Certificates => Right click the certificate of interest => All tasks => Manage private key => Add IIS AppPool\AppPoolName and grant it Full control. Replace "AppPoolName" with the name of the application pool that your app is running under. (sometimes IIS_IUSRS)

Updating passes

To be able to update your pass, you must provide it with a callback. When generating your request, you must provide it with an AuthenticationToken and a WebServiceUrl.

request.AuthenticationToken = "vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzFdc";
request.WebServiceUrl = "http://192.168.1.59:82/api";

There are several methods that the Pass will invoke when it's installed and updated. To see a reference implementation of this, look at the PassRegistrationController class in the Passbook.Sample.Web project.

The method that is of most interest in the beginning is the Post method as this actually captures the PushToken for the passes. The UpdateController has a very simple mechanism for sending an update. At present, the device ID is hard-coded, but this should provide a working reference.

Sample Web Application

Included as part of the solution, the Passbook.Sample.Web project allows you to create some sample passes. You can run this and access the pages from your iPhone to see how the passes are installed and to see the registration and update mechanism in operation.

The project also includes some dummy requests, so illustrate how you can create wrappers around the basic PassGenerationRequest. The above BoardPass can be generated using the BoardingPassGeneratorRequest. Instead of adding the fields explicitly, this encapsulates this logic, so you can call

request.Origin = "San Francisco";
request.OriginCode = "SFO";

request.Destination = "London";
request.DestinationCode = "LDN";

request.Seat = "7A";
request.BoardingGate = "F12";
request.PassengerName = "John Appleseed";

request.TransitType = TransitType.PKTransitTypeAir;

/Home/Index will open a simple HTML page where you can choose the card type.
/Pass/EventTicket will generate an event based Pass (not fully functional).
/Pass/BoardingPass will generate simple baording card.

These passes are functional and can be saved in iOS Passbook.

NuGet

Dotnet-passbook is also available to download from NuGet.

Install-Package dotnet-passbook

=======

iOS 10

This library covers almost all of the fields in Passbook, but the NFC fields are omitted. These are for use in Apple Pay and require special certificates, which I don't have.

Contribute

All pull requests are welcomed! If you come across an issue you cannot fix, please raise an issue or drop me an email at tomas@tomasmcguinness.com or follow me on twitter @tomasmcguinness

.Net Core

I've had several people ask whether this library will support .Net Core. If I get the time, I'll try and make this a .Net Standard library, but I'm dependant on Crypto libs etc., so I'll need to evaluate them to ensure they will work .Net Core also.

License

Dotnet-passbook is distributed under the MIT license: http://tomasmcguinness.mit-license.org/