All Projects → alexandercerutti → Passkit Generator

alexandercerutti / Passkit Generator

Licence: mit
The easiest way to generate custom Apple Wallet passes in Node.js

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Passkit Generator

Pass Js
Apple Wallet Passes generating library for Node.JS
Stars: ✭ 230 (+46.5%)
Mutual labels:  wallet, apple
Jpasskit
jPasskit is an Java™ implementation of the Apple™ PassKit Web Service.
Stars: ✭ 184 (+17.2%)
Mutual labels:  wallet, apple
Peatiocryptoexchange
An open-source Crypto-Currency exchange. Peatio v3.0 Coming Soon !
Stars: ✭ 141 (-10.19%)
Mutual labels:  wallet
Alerttoast
Create Apple-like alerts & toasts using SwiftUI
Stars: ✭ 151 (-3.82%)
Mutual labels:  apple
Aerial
Aerial Apple TV screen saver for Windows
Stars: ✭ 1,853 (+1080.25%)
Mutual labels:  apple
Arcbit Ios
arcbit - iOS bitcoin wallet http://arcbit.io
Stars: ✭ 142 (-9.55%)
Mutual labels:  wallet
Apple Device Model List
All Apple devices model name list. 通过内部编号判断 iOS 设备型号。
Stars: ✭ 149 (-5.1%)
Mutual labels:  apple
Openhab Ios
The repository of the iOS client
Stars: ✭ 141 (-10.19%)
Mutual labels:  apple
Awesome Macos
 A curated list of awesome applications, softwares, tools and shiny things for macOS.
Stars: ✭ 12,565 (+7903.18%)
Mutual labels:  apple
Canoe
Canoe is a Nano Wallet heavily based on the MIT licensed Copay wallet from Bitpay
Stars: ✭ 146 (-7.01%)
Mutual labels:  wallet
Ruby Macho
🔩 A pure-Ruby library for parsing Mach-O files.
Stars: ✭ 153 (-2.55%)
Mutual labels:  apple
Watchpresenter
⌚️ 🤓 Controlling your Keynote using Apple Watch
Stars: ✭ 145 (-7.64%)
Mutual labels:  apple
Raw Packet
Raw-packet Project
Stars: ✭ 144 (-8.28%)
Mutual labels:  apple
Rules apple line
LINE's Apple rules for Bazel
Stars: ✭ 151 (-3.82%)
Mutual labels:  apple
Mac admin
Helpful scripts & configuration profiles for the Mac admin community
Stars: ✭ 139 (-11.46%)
Mutual labels:  apple
React Native Unified Contacts
Your best friend when working with the latest and greatest Contacts Framework in iOS 9+ in React Native.
Stars: ✭ 156 (-0.64%)
Mutual labels:  apple
San Francisco Family
All the fonts in San Francisco family font, developed by Apple. Including new SF Camera font from iOS 13!
Stars: ✭ 141 (-10.19%)
Mutual labels:  apple
Trezor Suite
🍬 Trezor Suite Monorepo
Stars: ✭ 144 (-8.28%)
Mutual labels:  wallet
Flappy Fly Bird
🐦 Flappy Bird reincarnation [Swift 5.3, GameplayKit, SpriteKit, iOS 12].
Stars: ✭ 150 (-4.46%)
Mutual labels:  apple
Covid19 mobility
COVID-19 Mobility Data Aggregator. Scraper of Google, Apple, Waze and TomTom COVID-19 Mobility Reports🚶🚘🚉
Stars: ✭ 156 (-0.64%)
Mutual labels:  apple


Node Passkit Generator logo

Simple Node.js interface to generate customized Apple Wallet Passes for iOS.


Financial Contributors on Open Collective


Architecture

This package was created with a specific architecture in mind: application and model (as preprocessed entity), to split as much as possible static objects (such as logo, background, icon, etc.) from dynamic ones (translations, barcodes, serialNumber, ...).

Pass creation and population doesn't fully happen in runtime. Pass template (model) can be one of a set of buffers or a folder, that will contain all the objects needed (static medias) and structure to make a pass work.

Both Pass template will be read and pushed as they are in the resulting .zip file, while dynamic objects will be patched against pass.json or generated in runtime (manifest.json, signature and translation files). All the static medias from both sources, will be read and pushed as they are in the resulting .zip file; dynamic object will be patched against pass.json, generated on runtime (manifest.json, signature) or merged if already existing (translation files).

⚠ Do not rely on branches outside "master", as might not be stable and will be removed once merged.

Install

$ npm install passkit-generator --save

API Documentation

This package comes with an API documentation, that makes available a series of methods to create and customize passes.


Looking for the previous major version?

Check the v1 branch. That branch is kept for reference only.


Coming from the previous major version?

Look at the Migration Guide.


Get Started

Model

The first thing you'll have to do, is to start creating a model. A model contains all the basic pass data that compose the Pass identity. These data can be files (icon, thumbnails, ...), or pieces of information to be written in pass.json (Pass type identifier, Team Identifier, colors, ...).

This package allows to use two kinds of models: Folder Model or Buffer Model. If starting from scratch, the preferred solution is to use the folder as model, as it will allow you to access easily all the files. Also, a buffer model is mainly designed for models that are ready to be used in your application.

Let's suppose you have a file model.zip stored somewhere: you unzip it in runtime and then get the access to its files as buffers. Those buffers should be available for the rest of your application run-time and you shouldn't be in need to read them every time you are going to create a pass.

To keep a model in memory, the method createAbstractModel has been created.


Using the .pass extension is a best practice, showing that the directory is a pass package. (Build your first pass - Apple Developer Portal).

Following to this best practice, the package is set to require each folder-model to have a .pass extension. If omitted in the configuration (as in Usage Example, at "model" key), it will be forcefully added.


$ cd yourProjectDir;
$ mkdir passModels && mkdir $_/myFirstModel.pass && cd $_;

Follow the Apple Developer documentation (Package Structure) to build a correct pass model. The icon is required in order to make the pass work. Manifest.json and signature will be automatically ignored from the model and generated in runtime.

You can also create .lproj folders (e.g. en.lproj or it.lproj) containing localized media. To include a folder or translate texts inside the pass, please refer to Localizing Passes in the API documentation.

To include a file that belongs to an .lproj folder in buffers, you'll just have to name a key like en.lproj/thumbnail.png.

Pass.json

Create a pass.json by taking example from examples folder models or the one provided by Apple for the first tutorial and fill it with the basic informations, that are teamIdentifier, passTypeIdentifier and all the other basic keys like pass type. Please refer to Top-Level Keys/Standard Keys and Top-Level Keys/Style Keys.

{
  "formatVersion": 1,
  "passTypeIdentifier": "pass.<bundle id>",
  "teamIdentifier": "<here your team identifier>",
  "organizationName": "<your organization name>",
  "description": "A localizable description of your pass. To do so, put here a placeholder.",
  "boardingPass": {}
}

Certificates

The third step is about the developer and WWDR certificates. I suggest you to create a certificate-dedicated folder inside your working directory (e.g. ./certs) to contain everything concerning the certificates.

This is a standard procedure: you would have to do it also without using this library. We'll use OpenSSL to complete our work (or to do it entirely, if only on terminal), so be sure to have it installed. You'll need the following three elements:

  • Apple WWDR (Worldwide Developer Relationship) certificate
  • Signer certificate
  • Signer key

While WWDR can be obtained from Apple PKI Portal, to get the signer key and the certificate, you'll have to get first a Certificate Signing Request (.certSigningRequest file) and upload it to Apple Developers Portal, at Pass Types Identifiers (open it, it's worth it 😜).



If you don't have access to macOS (or you are a terminal enthusiast), follow these steps instead.


  1. Create a new pass type identifier and provide it with a Name and a reverse-domain bundle id (starting with "pass."). You will put this identifier as value for passTypeIdentifier in pass.json file.

  2. Confirm and register the new identifier.

  3. Go back to the pass type identifiers, click on your new pass id and edit it.

  4. Click "Create Certificate" button and follow the instructions until you won't download a certificate like pass.cer. (here you'll generate the .certSigningRequest file to be uploaded).

  5. Open the downloaded certificate. Go in "Certificates" on left in macOS Keychain access and right-click > Export "\<certname\>". Choose a password (and write it down) and you will get a PKCS#12 file (.p12).

  6. Open terminal, place where you want to save the files and insert the following OpenSSL commands changing the contents between angular brackets. You'll have to choose a secret passphrase (and write it down) that you'll use also in the application.

    # Creating and changing dir
    $ mkdir "certs" && cd $_
    # Extracting key and cert from pkcs12
    $ openssl pkcs12 -in <cert-name>.p12 -clcerts -nokeys -out signerCert.pem -passin pass:<your-password>
    $ openssl pkcs12 -in <cert-name>.p12 -nocerts -out signerKey.pem -passin pass:<your-password> -passout pass:<secret-passphrase>
    
  7. Execute step 5 also for the WWDR certificate (.cer) you downloaded from Apple PKI portal (default name: AppleWWDRCA.cer) but instead exporting it as PKCS#12 (.p12 - you'll also be unable to do that), export it as PEM (.pem) file.


Usage Example

Folder Model

/**
 * Use `const { createPass } = require("passkit-generator");`
 * for usage in pure Node.js. Please note that `Pass` is only exported
 * as Typescript type.
 */
import { createPass, Pass } from "passkit-generator";

try {
	const examplePass = await createPass({
		model: "./passModels/myFirstModel",
		certificates: {
			wwdr: "./certs/wwdr.pem",
			signerCert: "./certs/signercert.pem",
			signerKey: {
				keyFile: "./certs/signerkey.pem",
				passphrase: "123456"
			}
		},
		overrides: {
			// keys to be added or overridden
			serialNumber: "AAGH44625236dddaffbda"
		}
	});

	// Adding some settings to be written inside pass.json
	examplePass.localize("en", { ... });
	examplePass.barcode("36478105430"); // Random value

	// Generate the stream, which gets returned through a Promise
	const stream: Stream = examplePass.generate();

	doSomethingWithTheStream(stream);
} catch (err) {
	doSomethingWithTheError(err);
}

Buffer Model

import { createPass, Pass } from "passkit-generator";

try {
	const examplePass = await createPass({
		model: {
			"thumbnail": Buffer.from([ ... ]),
			"icon": Buffer.from([ ... ]),
			"pass.json": Buffer.from([ ... ]),
			"it.lproj/pass.strings": Buffer.from([ ... ])
		},

		// The rest will be the same as above 
		...	
	});

} catch (err) {
	doSomethingWithTheError(err);
}

For more complex usage examples, please refer to examples folder.


Other

If you used this package in any of your projects, feel free to open a topic in issues to tell me and include a project description or link (for companies). 😊 You'll make me feel like my time hasn't been wasted, even if it had not anyway because I learnt a lot of things by creating this.

The idea to develop this package, was born during the Apple Developer Academy 17/18, in Naples, Italy, driven by the need to create an iOS app component regarding passes generation for events.

A big thanks to all the people and friends in the Apple Developer Academy (and not) that pushed me and helped me into realizing something like this and a big thanks to the ones that helped me to make technical choices and to all the contributors.

Any contribution, is welcome. Made with ❤️ in Italy.


Contributors

A big thanks to all the people that contributed to improve this package. Any contribution is welcome. Do you have an idea to make this improve or something to say? Open a topic in the issues and we'll discuss together! Thank you ❤ Also a big big big big thank you to all the financial contributors!

Code Contributors

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].