Delivering passes to users | laravel-mobile-pass | Spatie

 SPATIE

  Laravel Mobile Pass
======================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-mobile-pass](https://spatie.be/docs/laravel-mobile-pass/v1)  Basic-usage  Delivering passes to users

 Version   v1

 Other versions for crawler [v1](https://spatie.be/docs/laravel-mobile-pass/v1)

  Delivering passes to users
- [ Introduction ](https://spatie.be/docs/laravel-mobile-pass/v1/introduction)
- [ Support us ](https://spatie.be/docs/laravel-mobile-pass/v1/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-mobile-pass/v1/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-mobile-pass/v1/installation-setup)
- [ Getting credentials from Apple ](https://spatie.be/docs/laravel-mobile-pass/v1/getting-credentials-from-apple)
- [ Getting credentials from Google ](https://spatie.be/docs/laravel-mobile-pass/v1/getting-credentials-from-google)
- [ Questions and issues ](https://spatie.be/docs/laravel-mobile-pass/v1/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-mobile-pass/v1/changelog)
- [ About us ](https://spatie.be/docs/laravel-mobile-pass/v1/about-us)

Basic usage
-----------

- [ Generating your first pass ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/generating-your-first-pass)
- [ Delivering passes to users ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/handing-out-passes)
- [ Adding images ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/adding-images)
- [ Adding barcodes ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/adding-barcodes)
- [ Updating a pass ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/updating-a-pass)
- [ Retrieving mobile passes ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/retrieving-mobile-passes)
- [ Expiring passes ](https://spatie.be/docs/laravel-mobile-pass/v1/basic-usage/expiring-passes)

Available pass types
--------------------

- [ Introduction ](https://spatie.be/docs/laravel-mobile-pass/v1/available-pass-types/introduction)
- [ Boarding pass ](https://spatie.be/docs/laravel-mobile-pass/v1/available-pass-types/boarding-pass)
- [ Event ticket ](https://spatie.be/docs/laravel-mobile-pass/v1/available-pass-types/event-ticket)
- [ Coupon ](https://spatie.be/docs/laravel-mobile-pass/v1/available-pass-types/coupon)
- [ Loyalty card ](https://spatie.be/docs/laravel-mobile-pass/v1/available-pass-types/loyalty)
- [ Generic ](https://spatie.be/docs/laravel-mobile-pass/v1/available-pass-types/generic)

Apple Wallet
------------

- [ Field zones ](https://spatie.be/docs/laravel-mobile-pass/v1/apple-wallet/field-zones)
- [ Apple-specific methods ](https://spatie.be/docs/laravel-mobile-pass/v1/apple-wallet/apple-specific-methods)
- [ Pass relevance ](https://spatie.be/docs/laravel-mobile-pass/v1/apple-wallet/pass-relevance)
- [ NFC passes ](https://spatie.be/docs/laravel-mobile-pass/v1/apple-wallet/nfc)
- [ Attaching Wi-Fi credentials ](https://spatie.be/docs/laravel-mobile-pass/v1/apple-wallet/attaching-wifi-credentials)
- [ Storing mobile passes ](https://spatie.be/docs/laravel-mobile-pass/v1/apple-wallet/storing-mobile-passes)

Google Wallet
-------------

- [ Pass classes ](https://spatie.be/docs/laravel-mobile-pass/v1/google-wallet/pass-classes)
- [ Object methods ](https://spatie.be/docs/laravel-mobile-pass/v1/google-wallet/object-methods)
- [ Hosting pass images ](https://spatie.be/docs/laravel-mobile-pass/v1/google-wallet/hosting-images)

Advanced usage
--------------

- [ Handling errors ](https://spatie.be/docs/laravel-mobile-pass/v1/advanced-usage/handling-errors)
- [ Customizing actions ](https://spatie.be/docs/laravel-mobile-pass/v1/advanced-usage/customizing-actions)
- [ Customizing models ](https://spatie.be/docs/laravel-mobile-pass/v1/advanced-usage/customizing-models)
- [ Reading stored passes ](https://spatie.be/docs/laravel-mobile-pass/v1/advanced-usage/reading-stored-passes)
- [ Events ](https://spatie.be/docs/laravel-mobile-pass/v1/advanced-usage/events)
- [ Testing your passes ](https://spatie.be/docs/laravel-mobile-pass/v1/advanced-usage/testing-your-passes)

 Delivering passes to users
==========================

###  On this page

1. [ Generating a URL ](#content-generating-a-url)
2. [ Returning the model from a controller ](#content-returning-the-model-from-a-controller)
3. [ As a QR code ](#content-as-a-qr-code)
4. [ As an email attachment ](#content-as-an-email-attachment)
5. [ Giving the Apple URL an expiration ](#content-giving-the-apple-url-an-expiration)

Once a `MobilePass` exists, you've got a handful of ways to get it in front of the user. The sections below cover the common delivery surfaces: controllers, buttons, and QR codes on printed confirmations. Whatever surface you pick, the mechanics are the same for Apple and Google, since the package figures out the right link for you.

Generating a URL
--------------------------------------------------------------------------------------------------------

Call `addToWalletUrl()` on the `MobilePass` model to get a shareable link. The model knows its platform and returns the right one.

```
$url = $mobilePass->addToWalletUrl();
```

For Apple, that's a signed download URL serving the `.pkpass` file. For Google, it's a `pay.google.com` save link that Google itself presents to the user.

The URL works behind any anchor or form. This sits nicely on a post-checkout confirmation page:

```

    Add to Wallet

```

Returning the model from a controller
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

The `MobilePass` model implements `Responsable`, so the simplest way to deliver a pass is to return the model itself from a controller. Laravel takes it from there, serving the signed `.pkpass` for Apple passes and redirecting to the Google Wallet save URL for Google passes. One controller, both platforms.

```
use Spatie\LaravelMobilePass\Models\MobilePass;

class AddToWalletController
{
    public function __invoke(MobilePass $mobilePass)
    {
        return $mobilePass;
    }
}
```

If you need the URL itself (for a button, a QR code, or somewhere else entirely), call `$mobilePass->addToWalletUrl()` and embed the string wherever you like.

As a QR code
--------------------------------------------------------------------------------------------

If you're printing confirmations or showing them on another screen, wrap the URL in a QR code. Any QR library works.

```
use SimpleSoftwareIO\QrCode\Facades\QrCode;

QrCode::size(240)->generate($mobilePass->addToWalletUrl());
```

As an email attachment
--------------------------------------------------------------------------------------------------------------------------

For Apple passes, you can attach the `.pkpass` file directly to a mailable. The `MobilePass` model implements Laravel's `Attachable` contract, so attaching it is a one-liner. Google passes aren't files (Google hosts them for you), so this route is Apple-only.

Here's the full Mailable:

```
use App\Models\User;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Spatie\LaravelMobilePass\Models\MobilePass;

class TicketPurchased extends Mailable
{
    public function __construct(
        public User $user,
        public MobilePass $mobilePass,
    ) {}

    public function envelope(): Envelope
    {
        return new Envelope(subject: 'Your ticket');
    }

    public function content(): Content
    {
        return new Content(markdown: 'mail.ticket-purchased');
    }

    /** @return array */
    public function attachments(): array
    {
        return [$this->mobilePass];
    }
}
```

The attachment lands in the inbox as a `.pkpass` file named after the pass's download name. iPhones recognise the MIME type (`application/vnd.apple.pkpass`) and offer to add it to Wallet straight from Mail.

Giving the Apple URL an expiration
--------------------------------------------------------------------------------------------------------------------------------------------------------------

By default the Apple link is a `signedRoute`, not a `temporarySignedRoute`, so it doesn't expire. That matches how wallet download links are usually used in practice (people open them days later on a new device), but you can change it by swapping in a custom `MobilePass` model and overriding `addToAppleWalletUrl()`:

```
namespace App\Models;

use Illuminate\Support\Facades\URL;
use Spatie\LaravelMobilePass\Models\MobilePass as BaseMobilePass;

class MobilePass extends BaseMobilePass
{
    protected function addToAppleWalletUrl(): string
    {
        return URL::temporarySignedRoute(
            'mobile-pass.apple.download',
            now()->addHour(),
            ['mobilePass' => $this->id],
        );
    }
}
```

Then register it in `config/mobile-pass.php` under `models.mobile_pass`. See [Customizing models](advanced-usage/customizing-models) for the full walkthrough.

 A good
match?
-------------

### What we do best

- All things Laravel
- Custom frontend components
- Building APIs
- AI-powered features
- Simplifying things
- Clean solutions
- Integrating services

### Not our cup of tea

- WordPress themes
- Cutting corners
- Free mockups to win a job
- "Just execute the briefing"

 In short: we'd like to be a **substantial part** of your project.

 [ Get in touch via email ](mailto:info@spatie.be?subject=A%20good%20match%21&body=Tell%20us%20as%20much%20as%20you%20can%20about%0A-%20your%20online%20project%0A-%20your%20planning%0A-%20your%20budget%0A-%20%E2%80%A6%0A%0AAnything%20that%20helps%20us%20to%20start%20straightforward%21)
