spatie/laravel-mobile-pass
Generate Apple Wallet and Google Wallet passes in Laravel (tickets, boarding passes, coupons, membership cards). Create and sign pass files, serve them to users, and push updates to installed passes to keep details current across devices.
Installation:
composer require spatie/laravel-mobile-pass
php artisan vendor:publish --provider="Spatie\MobilePass\MobilePassServiceProvider"
php artisan migrate
Configure Environment:
MOBILE_PASS_APPLE_WEBSERVICE_HOST (HTTPS required) and MOBILE_PASS_APPLE_CERTIFICATE_PATH in .env.MOBILE_PASS_GOOGLE_ISSUER_ID and MOBILE_PASS_GOOGLE_PRIVATE_KEY_PATH.First Pass:
use Spatie\MobilePass\PassBuilders\Apple\BoardingPassBuilder;
$pass = (new BoardingPassBuilder)
->setPassSerialNumber('USER123')
->setPassTypeIdentifier('pass.com.yourcompany.boarding')
->setTeamIdentifier('YOUR_TEAM_ID')
->setOrganizationName('Your Company')
->setHeaderFields(['primary': 'Flight 123'])
->setStoreCardFields(['primary': 'Boarding Pass'])
->setBarcode('123456789', 'QR')
->setForegroundColor('#FF0000')
->setBackgroundColor('#FFFFFF')
->setLogoText('YOUR_COMPANY')
->setDescription('Boarding pass for flight 123')
->setWebServiceURL('https://your-app.com/mobile-pass/apple/webservice');
$pass->save();
Download Link:
return redirect()->away($pass->addToWalletUrl());
Generate a boarding pass for a flight and push it to Apple Wallet. Use the addToWalletUrl() method to trigger the download and installation flow.
Builder Pattern:
Use platform-specific builders (BoardingPassBuilder, EventTicketBuilder, etc.) for Apple/Google passes.
$boardingPass = (new BoardingPassBuilder)
->setPassSerialNumber($userId)
->setBarcode($ticketNumber, 'QR')
->setExpirationDate(now()->addDays(7))
->setHeaderFields(['primary': 'Flight ' . $flightNumber])
->build();
Dynamic Content: Fetch real-time data (e.g., flight status) and update passes via:
$boardingPass->update([
'headerFields' => ['primary' => 'Flight ' . $updatedFlightNumber],
'barcode' => $newTicketNumber,
]);
Platform-Specific Logic:
.pkpass bundles with pass.json manifest.$eventTicket = (new EventTicketBuilder)
->setPassSerialNumber($userId)
->setClassId('YOUR_CLASS_ID')
->setObjectId('TICKET_' . $eventId)
->setEventName('Concert 2024')
->setStartDate(now())
->setEndDate(now()->addHours(3))
->setLocation('Venue X')
->build();
Queue Updates:
Enable async updates via MOBILE_PASS_QUEUE_CONNECTION in .env:
$boardingPass->update([...]); // Triggers PushPassUpdateJob
User-Specific Passes:
Tie passes to users via pass_serial_number (e.g., user_id@email.com).
$pass->setPassSerialNumber($user->email);
Webhooks for Google:
Handle GoogleMobilePassSaved/GoogleMobilePassRemoved events:
event(new GoogleMobilePassSaved($pass));
Remote Images:
Use Image::fromUrl() for dynamic assets:
$boardingPass->setLogoImage(Image::fromUrl('https://example.com/logo.png'));
NFC Support (Apple): Add NFC fields for contactless interactions:
$boardingPass->setNFCFields([
'message' => 'Tap to board',
'messageEncoding' => 'utf-8',
]);
Localization:
Set language in builders for multilingual passes:
$boardingPass->setLanguage('fr');
HTTPS Requirement for Apple:
mobile-pass.apple.webservice.host must be HTTPS. Non-HTTPS URLs will fail silently during pass generation.Pass Serial Number Uniqueness:
pass_serial_number to be unique per user. Reuse can cause conflicts.user_id or email + timestamp (e.g., user123@2024-05-20).Google Callback Verification:
MOBILE_PASS_GOOGLE_CALLBACK_SECRET is set and matches the Google Wallet API expectations.storage/logs/laravel.log for GoogleCallbackVerificationFailed errors.Image Hosting:
Image::fromUrl()) must be publicly accessible. Private URLs will break pass rendering.Apple Certificate Cache:
.pkpass files. Clear cache if updates aren’t reflecting:
php artisan mobile-pass:clear-cache
Time Zones:
$boardingPass->setExpirationDate(now()->setTimezone('UTC')->addDays(7));
Apple Webservice Lookup:
curl -X GET https://your-app.com/mobile-pass/apple/webservice/lookup?passSerialNumber=USER123
pass data.Google Wallet Debugging:
GoogleMobilePassSaved events for installation status.Pass Validation:
Custom Pass Types:
Extend Spatie\MobilePass\PassBuilders\PassBuilder to create custom pass types:
class CustomPassBuilder extends PassBuilder {
public function setCustomField(string $value): self {
$this->customField = $value;
return $this;
}
}
Override MobilePass Model: Publish the model and migrate:
php artisan vendor:publish --tag=mobile-pass-models
Then extend Spatie\MobilePass\Models\MobilePass:
class CustomMobilePass extends MobilePass {
protected $table = 'custom_mobile_passes';
}
Update .env:
MOBILE_PASS_MODEL=App\Models\CustomMobilePass
Custom Webservice Logic: Override the webservice handler:
// app/Providers/AppServiceProvider.php
public function boot() {
MobilePass::boot(function ($pass) {
// Custom logic before pushing updates
});
}
Queue Job Customization:
Extend PushPassUpdateJob to add pre/post-update logic:
class CustomPushPassUpdateJob extends PushPassUpdateJob {
protected function handleUpdate(MobilePass $pass) {
// Custom update logic
parent::handleUpdate($pass);
}
}
Bind it in AppServiceProvider:
$this->app->bind(PushPassUpdateJob::class, CustomPushPassUpdateJob::class);
Apple Team Identifier: Must match your Apple Developer account’s Team ID. Find it in Apple Developer Account.
Google Issuer ID:
Must be a valid Google Wallet Merchant ID (e.g., issuer123456789). Apply for one here.
Pass Type Identifiers:
Apple requires passTypeIdentifier to follow the format:
pass.com.yourcompany.[type]
Example: pass.com.yourcompany.boarding.
Barcode Types:
Supported types: PKBarcodeFormatQR, `PKBarcodeFormatPDF417
How can I help you explore Laravel packages today?