mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 18:25:24 +00:00
Updated Readme to newer version
This commit is contained in:
143
README.md
143
README.md
@@ -4,7 +4,7 @@
|
||||
<img width="600" src="https://github.com/alexandercerutti/passkit-generator/raw/master/assets/logo.svg?sanitize=true" alt="Node Passkit Generator logo">
|
||||
<br>
|
||||
<br>
|
||||
<p align="center">Simple Node.js interface to generate customized <a href="https://developer.apple.com/wallet/">Apple Wallet Passes</a> for iOS.</p>
|
||||
<p align="center">Simple Node.js interface to generate customized <a href="https://developer.apple.com/wallet/">Apple Wallet Passes</a> for iOS and WatchOS.</p>
|
||||
|
||||

|
||||

|
||||
@@ -16,14 +16,11 @@
|
||||
|
||||
### 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, ...).
|
||||
This library 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, ...), while keeping an eye on the different possible execution contexts.
|
||||
|
||||
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.
|
||||
Pass creation and population might not fully happen in runtime. This library allows to create a pass from scratch, specify a folder model (template) or specify a set of buffers. In the last two cases, both should 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.
|
||||
Whenever adding files, through scratch, template or buffer, these will be read and pushed as they are in the resulting .zip file, while dynamic data will be patched (`pass.json` with props) or generated in runtime (`manifest.json`, `signature` and translation files).
|
||||
|
||||
### Install
|
||||
|
||||
@@ -41,30 +38,28 @@ This package comes with an [API documentation](./API.md), that makes available a
|
||||
|
||||
### Looking for the previous major version?
|
||||
|
||||
Check the [v1 branch](https://github.com/alexandercerutti/passkit-generator/tree/v1.6.8). That branch is kept for reference only.
|
||||
Check the [v2 tag](https://github.com/alexandercerutti/passkit-generator/tree/v2.0.8). That tag is kept for reference only.
|
||||
|
||||
---
|
||||
|
||||
### Coming from the previous major version?
|
||||
|
||||
Look at the [Migration Guide](https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2).
|
||||
Look at the [Migration Guide](https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v2-to-v3).
|
||||
|
||||
---
|
||||
|
||||
## Get Started
|
||||
## Gettin 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, ...).
|
||||
Assuming that you don't have a model yet, the first thing you'll have to do, is creating one. 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, ...) and whatever you know that likely won't be customized on runtime.
|
||||
|
||||
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.
|
||||
When starting from zero, the best suggested solution is to use a Template (folder) to start with, as it will allow an easier access to all the files and data. Nothing will prevent you using a buffer model or creating a pass from scratch, but they are meant for an advanced usage or different contexts (e.g. running a cloud function might require a scratch model for faster startup, without storing the model in a "data bucket").
|
||||
|
||||
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`](https://github.com/alexandercerutti/passkit-generator/blob/master/API.md#create-an-abstract-model) has been created.
|
||||
|
||||
---
|
||||
**To maintain a pass model available during the run-time, a PKPass instance can be created from whatever source, and then used as a template through `PKPass.from`**.
|
||||
|
||||
> Using the .pass extension is a best practice, showing that the directory is a pass package.
|
||||
> ([Build your first pass - Apple Developer Portal](https://apple.co/2LYXWo3)).
|
||||
@@ -75,16 +70,11 @@ If omitted in the configuration (as in [Usage Example](#usage_example), at "mode
|
||||
---
|
||||
|
||||
Model creation can be performed both manually or with the auxiliary of a web tool I developed, [Passkit Visual Designer](https://pkvd.app), which will let you design your model through a neat user interface.
|
||||
It will output a .zip file that you can decompress and use it as both file model and buffer model.
|
||||
It will output a .zip file that you can decompress and use as source.
|
||||
|
||||
Since `.pass` extension is required, **it will be up to you to unzip the generated model in a .pass folder**.
|
||||
---
|
||||
|
||||
```bash
|
||||
$ cd yourProjectDir;
|
||||
$ mkdir passModels && mkdir $_/myFirstModel.pass && cd $_;
|
||||
```
|
||||
|
||||
Follow the [Apple Developer documentation](https://apple.co/2wuJLC1) (_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 follow the [Apple Developer documentation](https://apple.co/2wuJLC1) (_Package Structure_) to build a correct pass model. The **icon is required** in order to make the pass work. Omitting an icon resolution, might make a pass work on a device (e.g. Mac) but not on another (e.g. iPhone). _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](./API.md#method_localize) in the API documentation.
|
||||
|
||||
@@ -98,7 +88,7 @@ Create a `pass.json` by taking example from examples folder models or the one pr
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"passTypeIdentifier": "pass.<bundle id>",
|
||||
"teamIdentifier": "<here your team identifier>",
|
||||
"teamIdentifier": "<your team identifier>",
|
||||
"organizationName": "<your organization name>",
|
||||
"description": "A localizable description of your pass. To do so, put here a placeholder.",
|
||||
"boardingPass": {}
|
||||
@@ -118,7 +108,7 @@ You'll need the following three elements:
|
||||
- Signer certificate
|
||||
- Signer key
|
||||
|
||||
While WWDR can be obtained from [Apple PKI Portal](https://www.apple.com/certificateauthority/), 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](https://developer.apple.com/account/ios/identifier/passTypeId) (open it, it's worth it 😜).
|
||||
While WWDR can be obtained from [Apple PKI Portal](https://www.apple.com/certificateauthority/), to get the `signer key` and the `certificate`, [you'll have to issue first a `Certificate Signing Request` (`.certSigningRequest` file)](https://help.apple.com/developer-account/#/devbfa00fef7) and upload it to Apple Developers Portal when [creating a new certificate](https://developer.apple.com/account/resources/certificates/add) (open it, it's worth it 😜). Follow the procedure here below.
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
@@ -127,11 +117,11 @@ While WWDR can be obtained from [Apple PKI Portal](https://www.apple.com/certifi
|
||||
|
||||
<hr>
|
||||
|
||||
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.
|
||||
1. Create a new pass type identifier ([direct link](https://developer.apple.com/account/resources/identifiers/passTypeId/add/)) and provide it with a description and a reverse-domain identifier (starting with "pass."). You will have to 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`).
|
||||
3. [In the list of your passTypeIds](https://developer.apple.com/account/resources/identifiers/list/passTypeId) (filter), click on your new pass id to edit it.
|
||||
4. Click "Create Certificate" button and follow the instructions (like providing the Certificate Signing Request, we talked about earlier) until you won't download a certificate like `pass.cer`.
|
||||
5. Open the downloaded certificate in macOS Keychain Access. Go in "Certificates" on left 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.
|
||||
|
||||
```sh
|
||||
@@ -154,37 +144,37 @@ While WWDR can be obtained from [Apple PKI Portal](https://www.apple.com/certifi
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Use `const { createPass } = require("passkit-generator");`
|
||||
* for usage in pure Node.js. Please note that `Pass` is only exported
|
||||
* as Typescript type.
|
||||
* Use `const { PKPass } = require("passkit-generator");`
|
||||
* for usage in pure Node.js
|
||||
*/
|
||||
import { createPass, Pass } from "passkit-generator";
|
||||
import { PKPass } from "passkit-generator";
|
||||
|
||||
try {
|
||||
const examplePass = await createPass({
|
||||
const pass = PKPass.from({
|
||||
model: "./passModels/myFirstModel",
|
||||
certificates: {
|
||||
wwdr: "./certs/wwdr.pem",
|
||||
signerCert: "./certs/signercert.pem",
|
||||
signerKey: {
|
||||
keyFile: "./certs/signerkey.pem",
|
||||
passphrase: "123456"
|
||||
}
|
||||
signerKey: "./certs/signerkey.pem",
|
||||
signerKeyPassphrase: "123456"
|
||||
},
|
||||
overrides: {
|
||||
// keys to be added or overridden
|
||||
serialNumber: "AAGH44625236dddaffbda"
|
||||
}
|
||||
}, {
|
||||
// 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
|
||||
pass.localize("en", { ... });
|
||||
pass.setBarcodes("36478105430"); // Random value
|
||||
|
||||
// Generate the stream .pkpass file stream
|
||||
const stream: Stream = examplePass.generate();
|
||||
|
||||
const stream = pass.getAsStream();
|
||||
doSomethingWithTheStream(stream);
|
||||
|
||||
// or
|
||||
|
||||
const buffer = pass.getAsBuffer();
|
||||
doSomethingWithTheBuffer(buffer);
|
||||
} catch (err) {
|
||||
doSomethingWithTheError(err);
|
||||
}
|
||||
@@ -194,42 +184,41 @@ try {
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Use `const { createPass } = require("passkit-generator");`
|
||||
* for usage in pure Node.js. Please note that `Pass` is only exported
|
||||
* as Typescript type.
|
||||
* Use `const { PKPass } = require("passkit-generator");`
|
||||
* for usage in pure Node.js
|
||||
*/
|
||||
import { createPass, Pass } from "passkit-generator";
|
||||
import { PKPass } 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([ ... ])
|
||||
},
|
||||
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"
|
||||
}
|
||||
const examplePass = new PKPass({
|
||||
"thumbnail": Buffer.from([ ... ]),
|
||||
"icon": Buffer.from([ ... ]),
|
||||
"pass.json": Buffer.from([ ... ]),
|
||||
"it.lproj/pass.strings": Buffer.from([ ... ])
|
||||
},
|
||||
{
|
||||
wwdr: "./certs/wwdr.pem",
|
||||
signerCert: "./certs/signercert.pem",
|
||||
signerKey: "./certs/signerkey.pem",
|
||||
signerKeyPassphrase: "123456",
|
||||
},
|
||||
{
|
||||
// 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
|
||||
pass.localize("en", { ... });
|
||||
pass.setBarcodes("36478105430"); // Random value
|
||||
|
||||
// Generate the stream .pkpass file stream
|
||||
const stream: Stream = examplePass.generate();
|
||||
|
||||
const stream = pass.getAsStream();
|
||||
doSomethingWithTheStream(stream);
|
||||
|
||||
// or
|
||||
|
||||
const buffer = pass.getAsBuffer();
|
||||
doSomethingWithTheBuffer(buffer);
|
||||
} catch (err) {
|
||||
doSomethingWithTheError(err);
|
||||
}
|
||||
@@ -242,7 +231,7 @@ For more complex usage examples, please refer to [examples](https://github.com/a
|
||||
|
||||
## 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.
|
||||
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 and keep learning 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.
|
||||
|
||||
@@ -255,8 +244,8 @@ 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!
|
||||
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, which help me maintain the development of this package ❤️!
|
||||
|
||||
### Code Contributors
|
||||
|
||||
|
||||
Reference in New Issue
Block a user