You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+39-22Lines changed: 39 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,49 +15,59 @@
15
15
16
16
## Overview
17
17
18
-
Wallet Kit helps you build the **JSON payloads** wallet platforms expect. It focuses on **modeling and normalization** (via Symfony Serializer): it does **not** sign Apple passes, bundle `.pkpass` files, or call Google Wallet APIs.
18
+
Wallet Kit helps you build the **JSON payloads** wallet platforms expect. It focuses on **modeling and normalization** (via Symfony Serializer): it does **not** sign Apple passes, bundle `.pkpass` files, call Google Wallet APIs, or tokenize Samsung Wallet payloads.
19
19
20
20
-**PHP** 8.3+
21
21
-**symfony/serializer** ^7.4 || ^8.0
22
22
23
23
## 🛠️ Builder
24
24
25
-
The **`Jolicode\WalletKit\Builder`** namespace provides a fluent API centered on [`WalletPass`](src/Builder/WalletPass.php). Whether you need to build passes for **Apple, Google, or both platforms simultaneously**, use [`WalletPlatformContext::both(...)`](src/Builder/WalletPlatformContext.php) andthen call `build()` to obtain a [`BuiltWalletPass`](src/Builder/BuiltWalletPass.php) (`apple()`, `google()`). You can then normalize these models using Symfony Serializer along with this package’s normalizers.
25
+
The **`Jolicode\WalletKit\Builder`** namespace provides a fluent API centered on [`WalletPass`](src/Builder/WalletPass.php). Build a [`WalletPlatformContext`](src/Builder/WalletPlatformContext.php)with `->withApple(...)`, `->withGoogle(...)`, and/or `->withSamsung(...)`, then call `build()` to obtain a [`BuiltWalletPass`](src/Builder/BuiltWalletPass.php) (`apple()`, `google()`, `samsung()`). You can then normalize these models using Symfony Serializer along with this package’s normalizers.
// Then normalize with Symfony Serializer + this library’s normalizers.
62
72
```
63
73
@@ -69,6 +79,10 @@ Apple’s model maps to a **single** tree: either use the **builder** above or b
69
79
70
80
Google’s API splits each pass type into **two** resources: a **class** (shared template) and an **object** (one per holder). The object references the class through **`classId`**. This library exposes both sides under `src/Pass/Android/` for: EventTicket, Flight, Generic, GiftCard, Loyalty, Offer, and Transit. The **builder** returns that pair from `BuiltWalletPass::google()`.
71
81
82
+
### 📱 Samsung Wallet
83
+
84
+
Samsung Wallet uses a **single unified JSON** envelope: a `Card` containing `type`, `subType`, and a `data` array of card entries with `attributes` (type-specific fields). This library models 8 Samsung card types under `src/Pass/Samsung/`: BoardingPass, EventTicket, Coupon, GiftCard, Loyalty, Generic, DigitalId, and PayAsYouGo. The **builder** maps the 7 cross-platform verticals to their Samsung equivalents and returns a `Card` from `BuiltWalletPass::samsung()`. DigitalId and PayAsYouGo are Samsung-only types — build them directly via the model classes.
-`Jolicode\WalletKit\Builder` — Fluent builders (`WalletPass`, …) for Apple, Google, Samsung, or all
83
98
-`Jolicode\WalletKit\Exception` — Builder context and `BuiltWalletPass` accessor exceptions
84
99
85
100
## API spec checks (with Castor)
86
101
87
-
When [Castor](https://github.com/jolicode/castor) is available, you can verify that tracked baselines still match the **Google Wallet discovery document** and the **Apple `pass.json` phpstan shapes** in this repo:
102
+
When [Castor](https://github.com/jolicode/castor) is available, you can verify that tracked baselines still match the **Google Wallet discovery document**, the **Apple `pass.json` phpstan shapes**, and the **Samsung Wallet model shapes** in this repo:
88
103
89
104
| Command | Purpose |
90
105
| --- | --- |
91
106
|`castor spec:check:google`| Fetches the live Wallet Objects discovery and compares its `revision` to [`tools/spec/google-wallet-baseline.json`](tools/spec/google-wallet-baseline.json). |
92
107
|`castor spec:baseline:google`| After you update Android models for a new discovery revision, refreshes that JSON baseline. |
93
108
|`castor spec:check:apple`| Regenerates a key list from `src/Pass/Apple/Model``@phpstan-type` array shapes and diffs it against [`tools/spec/apple-pass-keyset.json`](tools/spec/apple-pass-keyset.json). |
94
109
|`castor spec:baseline:apple`| Rewrites `apple-pass-keyset.json` from the current phpstan definitions (run after intentional model changes). |
110
+
|`castor spec:check:samsung`| Regenerates a key list from `src/Pass/Samsung/Model``@phpstan-type` array shapes and diffs it against [`tools/spec/samsung-wallet-keyset.json`](tools/spec/samsung-wallet-keyset.json). |
111
+
|`castor spec:baseline:samsung`| Rewrites `samsung-wallet-keyset.json` from the current phpstan definitions (run after intentional model changes). |
95
112
96
113
Scripts live under [`tools/spec/`](tools/spec/) and are also invoked by CI (`spec-check` job).
This page shows one **end-to-end example** per vertical supported by [`WalletPass`](../src/Builder/WalletPass.php). Examples below use a **dual-platform** context; you can also use [`WalletPlatformContext::appleOnly`](../src/Builder/WalletPlatformContext.php)or [`::googleOnly`](../src/Builder/WalletPlatformContext.php) when you only target one store.
17
+
This page shows one **end-to-end example** per vertical supported by [`WalletPass`](../src/Builder/WalletPass.php). Examples below use a **dual-platform** context; you can target any combination by chaining [`->withApple(...)`](../src/Builder/WalletPlatformContext.php), [`->withGoogle(...)`](../src/Builder/WalletPlatformContext.php), and/or [`->withSamsung(...)`](../src/Builder/WalletPlatformContext.php).
18
18
19
19
After `build()`, you get a [`BuiltWalletPass`](../src/Builder/BuiltWalletPass.php):
20
20
21
21
-`$built->apple()` → Apple [`Pass`](../src/Pass/Apple/Model/Pass.php) for `pass.json` (throws [`ApplePassNotAvailableException`](../src/Exception/ApplePassNotAvailableException.php) if the context had no Apple slice)
22
22
-`$built->google()->issuerClass` / `$built->google()->passObject` → Google class and object (throws [`GoogleWalletPairNotAvailableException`](../src/Exception/GoogleWalletPairNotAvailableException.php) if there was no Google slice)
23
+
-`$built->samsung()` → Samsung [`Card`](../src/Pass/Samsung/Model/Card.php) envelope (throws [`SamsungCardNotAvailableException`](../src/Exception/SamsungCardNotAvailableException.php) if there was no Samsung slice)
23
24
24
25
Serialize with **Symfony Serializer** and the normalizers from this package (see [`tests/Builder/BuilderTestSerializerFactory.php`](../tests/Builder/BuilderTestSerializerFactory.php) for a full list).
25
26
@@ -36,24 +37,27 @@ use Jolicode\WalletKit\Builder\WalletPlatformContext;
36
37
use Jolicode\WalletKit\Pass\Android\Model\Shared\ReviewStatusEnum;
37
38
use Jolicode\WalletKit\Pass\Android\Model\Shared\StateEnum;
**Google-only** (requires `issuerName`on the context for class payloads). After `build()`, use `$built->google()`; `$built->apple()` throws. You can still call `addAppleBarcode()` to supply a barcode image for the Google object.
87
+
**Google-only** (requires `issuerName`for class payloads when no Apple context provides an organization name). After `build()`, use `$built->google()`; `$built->apple()` throws. You can still call `addAppleBarcode()` to supply a barcode for the Google object.
84
88
85
89
```php
86
90
use Jolicode\WalletKit\Builder\WalletPlatformContext;
@@ -89,9 +93,9 @@ use Jolicode\WalletKit\Pass\Android\Model\Offer\RedemptionChannelEnum;
89
93
use Jolicode\WalletKit\Pass\Apple\Model\Barcode;
90
94
use Jolicode\WalletKit\Pass\Apple\Model\BarcodeFormatEnum;
**Samsung-only** (Samsung requires `appLinkLogo`, `appLinkName`, `appLinkData` on all card types). After `build()`, use `$built->samsung()`; `$built->apple()` and `$built->google()` throw.
118
+
119
+
```php
120
+
use Jolicode\WalletKit\Builder\WalletPlatformContext;
121
+
use Jolicode\WalletKit\Builder\WalletPass;
122
+
use Jolicode\WalletKit\Pass\Android\Model\Offer\RedemptionChannelEnum;
123
+
use Jolicode\WalletKit\Pass\Apple\Model\Barcode;
124
+
use Jolicode\WalletKit\Pass\Apple\Model\BarcodeFormatEnum;
125
+
126
+
$samsungContext = (new WalletPlatformContext())->withSamsung(
@@ -341,11 +413,13 @@ These methods come from [`CommonWalletBuilderTrait`](../src/Builder/CommonWallet
341
413
|`withGoogleReviewStatus` / `withGoogleObjectState`| Overrides context defaults for Google class/object lifecycle. |
342
414
|`withAppLinkData` / `withGoogleLinksModuleData`| Links and app deep links (Google; Apple where mapped). |
343
415
|`mutateApple(callable)`| Escape hatch to tweak the Apple `Pass` before `build()` returns. |
416
+
|`mutateSamsung(callable)`| Escape hatch to tweak the Samsung `Card` before `build()` returns. |
344
417
345
418
---
346
419
347
420
## Limitations
348
421
349
-
- The library does **not** sign `.pkpass` bundles or call Google Wallet REST APIs.
350
-
- Apple and Google models differ: not every field exists on both sides. Use `mutateApple` or adjust the returned Google class/object after `build()` for platform-specific details.
351
-
- A [`WalletPlatformContext`](../src/Builder/WalletPlatformContext.php) with **no** Apple and **no** Google slice throws [`InvalidWalletPlatformContextException`](../src/Exception/InvalidWalletPlatformContextException.php). Google-only contexts must include a non-empty `issuerName` (or use `::googleOnly(...)`, which enforces it).
422
+
- The library does **not** sign `.pkpass` bundles, call Google Wallet REST APIs, or tokenize Samsung Wallet payloads.
423
+
- Apple, Google, and Samsung models differ: not every field exists on all sides. Use `mutateApple`, `mutateSamsung`, or adjust the returned Google class/object after `build()` for platform-specific details.
424
+
- A [`WalletPlatformContext`](../src/Builder/WalletPlatformContext.php) with **no** platform slice will produce a `BuiltWalletPass` where all accessors throw. Google contexts without an `issuerName` must have an Apple context to fall back on (via `organizationName`).
425
+
- Samsung **Digital ID** and **Pay As You Go** card types have no Apple/Google equivalent and are not exposed through `WalletPass` factory methods. Build them directly via the Samsung model classes under `src/Pass/Samsung/Model/`.
0 commit comments