Behaviour for reacting to wallet pass lifecycle events from both Apple and Google.
Configure with:
config :wallet_passes, :event_handler, MyApp.WalletEventHandlerAll callbacks are optional — implement only the ones you care about.
Callbacks run asynchronously in a supervised Task (see
WalletPasses.EventHandler.Dispatch) so they cannot extend Apple/Google
response times. Their return value is ignored. Exceptions are captured,
logged, and reported via telemetry; they do not bring down the request or
the supervisor.
Summary
Callbacks
Fires when a pass is added to a user's wallet.
Fires when an Apple device fetches the latest version of a pass. This is high-volume — iOS may fetch the pass several times per day per device. Treat as informational; do not write a row per fetch to a consumer DB without rate-limiting.
Fires when a pass is removed.
Types
@type event_meta() :: map()
@type platform() :: :apple | :google
Callbacks
@callback on_pass_added(serial_number :: String.t(), platform(), event_meta()) :: any()
Fires when a pass is added to a user's wallet.
- Apple: when a device registers for push notifications for this pass.
- Google: when a
savecallback is received from Google Wallet.
meta:
- Apple:
%{device_library_id: String.t(), push_token: String.t()} - Google:
%{object_id: String.t(), class_id: String.t(), nonce: String.t(), exp_time_millis: integer()}
@callback on_pass_fetched(serial_number :: String.t(), platform(), event_meta()) :: any()
Fires when an Apple device fetches the latest version of a pass. This is high-volume — iOS may fetch the pass several times per day per device. Treat as informational; do not write a row per fetch to a consumer DB without rate-limiting.
Google does not have an analogue (Google serves pass updates itself).
meta:
- Apple:
%{}
@callback on_pass_removed(serial_number :: String.t(), platform(), event_meta()) :: any()
Fires when a pass is removed.
- Google: unambiguous — the user removed the pass from their wallet.
- Apple: ambiguous. This event fires on any device unregister, which
includes iOS push-token rotation, app uninstall, the user disabling
notifications for the pass, or genuine pass removal. There is no
on-device signal to disambiguate. Treat the Apple variant as "this
device is no longer reachable for push," not as a definitive removal
signal. For an authoritative wallet-presence check, use
WalletPasses.wallet_presence/1(which reports both platforms separately) or rely on Google'sdel.
meta:
- Apple:
%{device_library_id: String.t()} - Google:
%{object_id: String.t(), class_id: String.t(), nonce: String.t(), exp_time_millis: integer()}