PHPackages                             byte5/laravel-passgenerator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. byte5/laravel-passgenerator

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

byte5/laravel-passgenerator
===========================

A Laravel package to create Apple Wallet (old Passbook) compatible tickets.

v0.4(9mo ago)8821.3k↑93.1%5[2 issues](https://github.com/byte5digital/laravel-passgenerator/issues)GPL-3.0-or-laterPHPCI passing

Since Jun 30Pushed 9mo ago3 watchersCompare

[ Source](https://github.com/byte5digital/laravel-passgenerator)[ Packagist](https://packagist.org/packages/byte5/laravel-passgenerator)[ RSS](/packages/byte5-laravel-passgenerator/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (10)Versions (8)Used By (0)

[![Laravel Passgenerator Banner](https://camo.githubusercontent.com/65ea6c551e8facf6c38b6d49dd4bfb1ddb2188be17625e5cd4126d1567dc51de/68747470733a2f2f62797465352d72656c61756e63682d73746167696e672e617a75726577656273697465732e6e65742f6d656469612f796f6e6a6c6875632f62797465352d7061636b6167652d62616e6e65722d7061737367656e657261746f722e706e67)](https://camo.githubusercontent.com/65ea6c551e8facf6c38b6d49dd4bfb1ddb2188be17625e5cd4126d1567dc51de/68747470733a2f2f62797465352d72656c61756e63682d73746167696e672e617a75726577656273697465732e6e65742f6d656469612f796f6e6a6c6875632f62797465352d7061636b6167652d62616e6e65722d7061737367656e657261746f722e706e67)

Passgenerator
=============

[](#passgenerator)

[![GitHub Actions Workflow Status](https://camo.githubusercontent.com/e386ad8ef65e85f4a7f4f558c477cdbaae93cb952b13ee697a9bfdd3bc200f39/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f62797465356469676974616c2f6c61726176656c2d7061737367656e657261746f722f63692e79616d6c)](https://camo.githubusercontent.com/e386ad8ef65e85f4a7f4f558c477cdbaae93cb952b13ee697a9bfdd3bc200f39/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f62797465356469676974616c2f6c61726176656c2d7061737367656e657261746f722f63692e79616d6c)[![Packagist Version](https://camo.githubusercontent.com/59ca8b1ff9e443f6f1ab8e3f17cab8146f26bada30f1517aeca3e18bb9f4f5ac/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f62797465352f6c61726176656c2d7061737367656e657261746f72)](https://camo.githubusercontent.com/59ca8b1ff9e443f6f1ab8e3f17cab8146f26bada30f1517aeca3e18bb9f4f5ac/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f62797465352f6c61726176656c2d7061737367656e657261746f72)[![GitHub License](https://camo.githubusercontent.com/55f7e8931ae751438e53bc5d34c214b6d6ab595fb9043a44d2685b394efbe0a5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f62797465356469676974616c2f6c61726176656c2d7061737367656e657261746f72)](https://camo.githubusercontent.com/55f7e8931ae751438e53bc5d34c214b6d6ab595fb9043a44d2685b394efbe0a5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f62797465356469676974616c2f6c61726176656c2d7061737367656e657261746f72)

Passgenerator is a Laravel package that allows you to easily create passes compatible with Apple Wallet (former Passbook).

### Documentation

[](#documentation)

You can find the full documentation [here](https://byte5digital.github.io/laravel-passgenerator).

👉 Table of Contents 👈
=====================

[](#-table-of-contents-)

- [👮 Requirements](#-requirements)
- [💾 Installation](#-installation)
- [🍎 Apple docs](#-apple-docs)
- [📝 Configuration](#-configuration)
- [🚀 Usage](#-usage)
- [❓ Troubleshooting](#-troubleshooting)
- [❓ About us](#-about-us)

👮 Requirements
--------------

[](#-requirements)

- Laravel 7 or higher

### PHP extensions

[](#php-extensions)

- ext-json
- ext-zip
- ext-openssl

💾 Installation
--------------

[](#-installation)

The best and easiest way to install the package is using the [Composer](https://getcomposer.org/) package manager. To do so, run this command in your project root:

```
composer require byte5/laravel-passgenerator
```

That's it!

🍎 Apple docs
------------

[](#-apple-docs)

From now on, some stuff is much better explained on the Apple docs, so when in doubt just check (if you haven't done so) the following documents:

- [Wallet Portal](https://developer.apple.com/wallet/)
- [Wallet Developer Guide](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/PassKit_PG/index.html#//apple_ref/doc/uid/TP40012195)
- [Crypto Signatures](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/PassKit_PG/Creating.html#//apple_ref/doc/uid/TP40012195-CH4-SW55)
- [PassKit Package Format Reference](https://developer.apple.com/library/ios/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/Introduction.html#//apple_ref/doc/uid/TP40012026)

📝 Configuration
---------------

[](#-configuration)

To start using the package some Apple files are needed, as well as some action in order to convert them to more friendly formats:

1. Go to the [Apple Developer page ➵ Identifiers ➵ Pass Type IDs](https://developer.apple.com/account/ios/identifiers/passTypeId/passTypeIdList.action).
2. Next, you need to create a pass type ID. This is similar to the bundle ID for apps. It will uniquely identify a specific kind of pass. It should be of the form of a reverse-domain name style string (i.e., pass.com.example.appname).
3. After creating the pass type ID, click on `Edit` and follow the instructions to create a new Certificate.
4. Once the process is finished, the pass certificate can be downloaded. That's not it though, the certificate is downloaded as `.cer` file, which need to be converted to `.p12` in order to work. If you are using a Mac you can import it into *Keychain Access* and export it from there. Make sure to *remember the password* you have given to the exported file since you'll have to use it later. You can also use other tools to convert the certificate but be sure it includes the private key on the exported PKCS12 file.
5. If you have made iOS development, you probably have already the *Apple Worldwide Developer Relations Intermediate Certificate* in your Mac’s keychain. If not, it can be downloaded from the [Apple Website](https://www.apple.com/certificateauthority/) (on `.cer` format). This one needs to be exported as `.pem`, you can also do so from *Keychain Access* (or whatever tool you use to manage certificates on your OS).

Once all this tedious process has been done, everything is almost ready to start using the package. The easiest now is to add to the following keys to your `.env` file:

- CERTIFICATE\_PATH ➪ The path to the `.p12` pass certificate.
- CERTIFICATE\_PASS ➪ The password set to unlock the certificate when it was exported.
- WWDR\_CERTIFICATE ➪ The path to the *Apple Worldwide Developer Relations Intermediate Certificate* on `.pem` format.
- PASSGENERATOR\_STORAGE\_DISK ➪ The name of the disk where the passes will be stored. This should match a disk defined in your `config/filesystems.php` file. By default, it is set to `local`.
- PASSGENERATOR\_STORAGE\_PATH ➪ The path where the passes will be stored. By default, it is set to `passgenerator/certs`.
- PASSGENERATOR\_CONFIG\_DISK ➪ The disk where config files and certificates are stored. If not set, fallbacks to `PASSGENERATOR_STORAGE_DISK`.

In case there is a reason the config file must be modified (conflicting env keys, dynamic certificates required...), it can be published with the following command:

```
// file will be at config/passgenerator.php
php artisan vendor:publish --provider="Byte5\PassGeneratorServiceProvider"
```

#### Below is a reasonable default for your .env file:

[](#below-is-a-reasonable-default-for-your-env-file)

```
CERTIFICATE_PATH="passgenerator/certs/certificate.p12"
CERTIFICATE_PASS="YOUR-CERTIFICATE-PASSWORD"
WWDR_CERTIFICATE="passgenerator/certs/AppleWWDRCA.pem"
PASSGENERATOR_STORAGE_DISK="private"
PASSGENERATOR_STORAGE_PATH="passgenerator/passes"
```

This will ensure the following file structure:

```
storage/
├─ app/
│  ├─ private/
│  │  ├─ passgenerator/
│  │  │  ├─ certs/
│  │  │  │  ├─ AppleWWDRCA.pem
│  │  │  │  ├─ certificate.p12
│  │  │  ├─ passes/
│  │  │  │  ├─ your_generated_pass.pkpass

```

🚀 Usage
-------

[](#-usage)

To create a pass for the first time, you have to first create the pass definition, either as a JSON file or as an array. It is *really* recommended to have already read the [Apple docs](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/PassKit_PG/YourFirst.html#//apple_ref/doc/uid/TP40012195-CH2-SW1) as well as the [PassKit Package Format Reference](https://developer.apple.com/library/ios/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/Introduction.html#//apple_ref/doc/uid/TP40012026).

```
use Byte5\PassGenerator;

//...

$pass_identifier = 'somekindofid';  // This, if set, it would allow for retrieval later on of the created Pass

$pass = new PassGenerator($pass_identifier);

$pass_definition = [
    "description"       => "description",
    "formatVersion"     => 1,
    "organizationName"  => "organization",
    "passTypeIdentifier"=> "pass.com.example.appname",
    "serialNumber"      => "123456",
    "teamIdentifier"    => "teamid",
    "foregroundColor"   => "rgb(99, 99, 99)",
    "backgroundColor"   => "rgb(212, 212, 212)",
    "barcode" => [
        "message"   => "encodedmessageonQR",
        "format"    => "PKBarcodeFormatQR",
        "altText"   => "altextfortheQR",
        "messageEncoding"=> "utf-8",
    ],
    "boardingPass" => [
        "headerFields" => [
            [
                "key" => "destinationDate",
                "label" => "Trip to: BCN-SANTS",
                "value" => "15/09/2015"
            ]
        ],
        "primaryFields" => [
            [
                "key" => "boardingTime",
                "label" => "MURCIA",
                "value" => "13:54",
                "changeMessage" => "Boarding time has changed to %@"
            ],
            [
                "key" => "destination",
                "label" => "BCN-SANTS",
                "value" => "21:09"
            ]

        ],
        "secondaryFields" => [
            [
                "key" => "passenger",
                "label" => "Passenger",
                "value" => "J.DOE"
            ],
            [
                "key" => "bookingref",
                "label" => "Booking Reference",
                "value" => "4ZK6FG"
            ]
        ],
        "auxiliaryFields" => [
            [
                "key" => "train",
                "label" => "Train TALGO",
                "value" => "00264"
            ],
            [
                "key" => "car",
                "label" => "Car",
                "value" => "009"
            ],
            [
                "key" => "seat",
                "label" => "Seat",
                "value" => "04A"
            ],
            [
                "key" => "classfront",
                "label" => "Class",
                "value" => "Tourist"
            ]
        ],
        "backFields" => [
            [
                "key" => "ticketNumber",
                "label" => "Ticket Number",
                "value" => "7612800569875"
            ], [
                "key" => "passenger-name",
                "label" => "Passenger",
                "value" => "John Doe"
            ], [
                "key" => "classback",
                "label" => "Class",
                "value" => "Tourist"
            ]
        ],
        "locations" => [
            [
                "latitude" => 37.97479,
                "longitude" => -1.131522,
                "relevantText" => "Departure station"
            ]
        ],
        "transitType" => "PKTransitTypeTrain"
    ],
];

$pass->setPassDefinition($pass_definition);

// Definitions can also be set from a JSON string
// $pass->setPassDefinition(file_get_contents('/path/to/pass.json));

// Add assets to the PKPass package
$pass->addAsset(base_path('resources/assets/wallet/background.png'));
$pass->addAsset(base_path('resources/assets/wallet/thumbnail.png'));
$pass->addAsset(base_path('resources/assets/wallet/icon.png'));
$pass->addAsset(base_path('resources/assets/wallet/logo.png'));

$pkpass = $pass->create();
```

Now, a valid ticket is already in place. Apple recommends a MIME type to serve it to its devices so something like the following should do:

```
return new Response($pkpass, 200, [
    'Content-Transfer-Encoding' => 'binary',
    'Content-Description' => 'File Transfer',
    'Content-Disposition' => 'attachment; filename="pass.pkpass"',
    'Content-length' => strlen($pkpass),
    'Content-Type' => PassGenerator::getPassMimeType(),
    'Pragma' => 'no-cache',
]);
```

Later on, if your users need to download the pass again, you don't need to create it again (wasting all those CPU cycles on crypto stuff), you can just do something like:

```
// If the pass for that ID does not exist, you can then proceed to generate it as done above.
$pkpass = PassGenerator::getPass($pass_identifier);
if (!$pkpass) {
    $pkpass = $this->createWalletPass();
}
// ...
```

It is also possible to retrieve the actual path to a pass on your filesystem. By default, *Passgenerator* will copy your default filesystem config (usually rooted on `storage_path('app')` but you can always do `getPassFilePath($pass_identifier)` and retrieve the real path (in case it exists).

### Definitions

[](#definitions)

It is also possible to programatically create/modify a pass using the definitions objects. Eg.-

```
$coupon = Byte5\Definitions\Coupon();
$coupon->setDescription('Coupon description');
$coupon->setSerialNumber('123456');

$coupon->setUserInfo([
    'email' => 'user@domain.com',
]);
$coupon->setExpirationDate(Carbon::now()->addMonths(6));

$location = new Location();
$location->setLatitude(40.4378698);
$location->setLongitude(-3.819619);
$coupon->addLocation($location);

$coupon->setMaxDistance(50);
$coupon->setRelevantDate(Carbon::now()->addDays(10));

$coupon->addAuxiliaryField(new Field('key', 'value'));

$coupon->addBackField(new Number('price', 13, [
    'currencyCode' => 'EUR',
    'numberStyle' => Number::STYLE_DECIMAL
]));

$coupon->addPrimaryField(new Date('created_at', Carbon::now(), [
    'dateStyle' => Date::STYLE_FULL,
]));

$barcode = new Barcode('7898466321', Barcode::FORMAT_CODE128);
$coupon->addBarcode($barcode);

$passgenerator->setPassDefinition($coupon);

```

❓ Troubleshooting
-----------------

[](#-troubleshooting)

### **error:0308010C:digital envelope routines::unsupported**

[](#error0308010cdigital-envelope-routinesunsupported)

If you run into this error, you are probably using OpenSSL 3.0 and trying to work with a legacy certificate. While some people recommend to enable the legacy option for OpenSSL 3.0, this doesn't solve the core problem.

Instead, you should convert your certificate to a more modern format. You can do this by running the following commands:

```
#unpack the key:
openssl pkcs12 -in PassType.p12 -nodes -out key_decrypted.tmp

#pack the key using a more moden algorithm:
openssl pkcs12 -export -in key_decrypted.tmp -out new.p12 -certpbe AES-256-CBC -keypbe AES-256-CBC
```

❓ About Us
----------

[](#-about-us)

[![byte5 Logo](https://raw.githubusercontent.com/byte5digital/.github/main/profile/assets/byte5.svg)](https://raw.githubusercontent.com/byte5digital/.github/main/profile/assets/byte5.svg)

We’re a development company based in Frankfurt, Germany — **remote-friendly, open-minded, and tech-driven**. Our team brings deep expertise in Laravel, Umbraco, and decentralized tech like IOTA. We collaborate with clients who care about clean code, scalable solutions, and long-term maintainability.

We contribute to open source, run [Laravel DACH Meetups](https://www.meetup.com/laravel-meetup-germany/), and support developer communities across the DACH region.

If you love building smart solutions with real impact — we should talk.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance57

Moderate activity, may be stable

Popularity43

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity31

Early-stage or recently created project

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~10 days

Total

6

Last Release

273d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/41282cdb98ee1dbc33dd57e79146e6ada49c414f8d0ebc0e94a4dccd571e6585?d=identicon)[byte5](/maintainers/byte5)

---

Top Contributors

[![goela268](https://avatars.githubusercontent.com/u/67412191?v=4)](https://github.com/goela268 "goela268 (43 commits)")[![jfoulquie-tnw](https://avatars.githubusercontent.com/u/159464174?v=4)](https://github.com/jfoulquie-tnw "jfoulquie-tnw (21 commits)")[![j3j5](https://avatars.githubusercontent.com/u/1239921?v=4)](https://github.com/j3j5 "j3j5 (19 commits)")[![rumeau](https://avatars.githubusercontent.com/u/2340790?v=4)](https://github.com/rumeau "rumeau (4 commits)")[![pabloroman](https://avatars.githubusercontent.com/u/450173?v=4)](https://github.com/pabloroman "pabloroman (2 commits)")[![tectiv3](https://avatars.githubusercontent.com/u/1974189?v=4)](https://github.com/tectiv3 "tectiv3 (2 commits)")[![christophstockinger](https://avatars.githubusercontent.com/u/24808473?v=4)](https://github.com/christophstockinger "christophstockinger (2 commits)")[![marctnw](https://avatars.githubusercontent.com/u/160036534?v=4)](https://github.com/marctnw "marctnw (1 commits)")[![mikerodham](https://avatars.githubusercontent.com/u/7014362?v=4)](https://github.com/mikerodham "mikerodham (1 commits)")[![thijsw](https://avatars.githubusercontent.com/u/28638?v=4)](https://github.com/thijsw "thijsw (1 commits)")[![DriverCat](https://avatars.githubusercontent.com/u/69649036?v=4)](https://github.com/DriverCat "DriverCat (1 commits)")[![eonghk](https://avatars.githubusercontent.com/u/139964?v=4)](https://github.com/eonghk "eonghk (1 commits)")[![graphicmist](https://avatars.githubusercontent.com/u/36309?v=4)](https://github.com/graphicmist "graphicmist (1 commits)")[![jordyvanderhaegen](https://avatars.githubusercontent.com/u/24370626?v=4)](https://github.com/jordyvanderhaegen "jordyvanderhaegen (1 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (1 commits)")[![marckyes](https://avatars.githubusercontent.com/u/417513?v=4)](https://github.com/marckyes "marckyes (1 commits)")

---

Tags

phplaravelapplepassbook

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/byte5-laravel-passgenerator/health.svg)

```
[![Health](https://phpackages.com/badges/byte5-laravel-passgenerator/health.svg)](https://phpackages.com/packages/byte5-laravel-passgenerator)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[thenextweb/passgenerator

A Laravel package to create Apple Wallet (old Passbook) compatible tickets.

297435.6k](/packages/thenextweb-passgenerator)[yajra/laravel-datatables-oracle

jQuery DataTables API for Laravel

4.9k33.8M339](/packages/yajra-laravel-datatables-oracle)[monicahq/laravel-cloudflare

Add Cloudflare ip addresses to trusted proxies for Laravel.

3372.7M4](/packages/monicahq-laravel-cloudflare)[kra8/laravel-snowflake

Snowflake for Laravel and Lumen.

188402.3k6](/packages/kra8-laravel-snowflake)[bezhansalleh/filament-google-analytics

Google Analytics integration for FilamentPHP

205144.8k5](/packages/bezhansalleh-filament-google-analytics)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
