Wallet Passes for NativePHP Mobile#
Put tickets, memberships, loyalty cards and boarding passes into Apple Wallet and Google Wallet from inside your NativePHP app.
use Firsthand\Wallet\Facades\Wallet; Wallet::add($ticket->mobilePass); // a spatie/laravel-mobile-pass pass
- iOS: Apple's own Add-to-Wallet sheet, showing the real pass. A NativePHP page can't do this by itself, because the web view doesn't hand a
.pkpassto Wallet. - Android: the Google Wallet save sheet, straight from your app.
- Made to pair with spatie/laravel-mobile-pass, which creates, signs and updates the passes on your server. This plugin is the missing phone half: getting the pass into Wallet. It also takes any pass link or
.pkpassfile. - Know what happened. On iOS the
PassAddFinishedevent tells you whether the pass was added, the sheet was closed, or the pass couldn't be read.
Tested on real devices: an iPad (Apple's sheet from both
Wallet::add()and the native button) and an Android phone (Google Wallet save sheet, pass added). Videos: iPad · Android.
Requirements#
- NativePHP Mobile 4.x, Laravel 11–13, PHP 8.3+
- iOS 18+. Adding a pass needs no entitlement or capability. Passes must be signed with a Pass Type ID certificate from your Apple Developer account, which Spatie's package handles.
- Android 10+, and a Google Pay & Wallet Console issuer account for Google passes.
Installation#
composer require firsthand/nativephp-walletphp artisan native:plugin:register firsthand/nativephp-wallet
Adding a pass#
Wallet::add($mobilePass); // spatie/laravel-mobile-passWallet::add('https://example.com/tickets/42.pkpass'); // any link that serves the passWallet::add($url, ['Authorization' => 'Bearer '.$token]); // a link that needs headersWallet::add(storage_path('passes/ticket.pkpass')); // a file in the appWallet::add($pkpassBytes); // the .pkpass contents
add() shows the sheet and returns straight away. The outcome arrives afterwards (iOS):
use Firsthand\Wallet\Events\PassAddFinished;use Native\Mobile\Attributes\On; // native screens (NativePHP 4) #[On(PassAddFinished::class)] // #[OnNative(...)] in a Livewire web-view pagepublic function walletDone(string $status, ?string $serial_number = null): void{ // $status: "added", "closed", "invalid" (Wallet couldn't read the pass), "failed"}
On Android, pass a Google Wallet save link (https://pay.google.com/gp/v/save/…). That's what Spatie's addToWalletUrl() gives for a Google pass. An Apple .pkpass can't be added on Android, and the plugin says so rather than failing silently.
Wallet::status(); // ['platform' => 'ios', 'can_add' => true, 'wallet' => true]
On an iPad, the sheet works the same way, but Wallet keeps the pass for the person's iPhone and Apple Watch rather than showing it on the iPad. Apple's sheet says so itself.
Apple's "Add to Apple Wallet" button#
On a native screen (NativePHP 4's default), drop in Apple's own button. It's the real PKAddPassButton, which is the only "Add to Apple Wallet" button Apple allows in an app:
<native:wallet-add-button :pass="$ticket->mobilePass" /><native:wallet-add-button pass="https://example.com/tickets/42.pkpass" button-style="outline" />
pass takes anything Wallet::add() does. A tap opens Apple's sheet straight from native code, and the outcome arrives as the same PassAddFinished event. A pass the plugin can't make sense of fails when the screen renders, not when someone taps the button.
The button is iOS only; on Android the tag draws nothing, so one screen can serve both. On Android, and in web-view pages, use your own button with your own words, such as "Save ticket", and call Wallet::add(). Don't draw an imitation of Apple's badge: Apple reserves it for the native control.
JavaScript (Vue / React)#
import { add, onPassAddFinished } from '@firsthand/nativephp-wallet'; onPassAddFinished(({ status }) => { if (status === 'added') showThanks(); });await add('https://example.com/tickets/42.pkpass');
Troubleshooting#
| What you see | Why |
|---|---|
invalid |
The pass isn't signed with a valid Pass Type ID certificate, its passTypeIdentifier/teamIdentifier don't match the certificate, or the link served an error page instead of the pass |
failed with "HTTP 401/403" |
The link needs a login: pass headers, or use a signed URL (Spatie's are) |
| Android: "not a Google Wallet save link" | Android needs a Google pass; .pkpass is Apple-only |
License#
One purchase covers unlimited apps. See the LICENSE file in the package.