Skip to content

feat(targets): add Apple Wallet In-App Provisioning extensions (`wall…#188

Open
kliakhovskii-brex wants to merge 1 commit intoEvanBacon:mainfrom
kliakhovskii-brex:main
Open

feat(targets): add Apple Wallet In-App Provisioning extensions (`wall…#188
kliakhovskii-brex wants to merge 1 commit intoEvanBacon:mainfrom
kliakhovskii-brex:main

Conversation

@kliakhovskii-brex
Copy link
Copy Markdown

Motivation

Apple Wallet In-App Provisioning Extensions let users add an issuer's payment passes to Apple Wallet directly from Wallet's "+" menu (under "From Apps on Your iPhone"), without having to open the issuer app first. The feature is implemented as two app extensions working together:

  • Non-UI extension — reports which passes are available, whether authentication is needed, and supplies the signed PKAddPaymentPassRequest to Wallet.
  • UI extension — a UIViewController Wallet presents to authenticate the user when the non-UI extension reports requiresAuthentication = true.

We already implement these natively in the Brex mobile repo for the core app. With Continuous Native Generation via @bacons/apple-targets, we can scaffold and link these targets the same way we do widgets, share extensions, etc. — and once this lands here we can also push it upstream.

Reference: https://applepaydemo.apple.com/in-app-provisioning-extensions

Execution

Followed the "Adding a new target type" checklist in CLAUDE.md. All edits are derived from the central TARGET_REGISTRY so the ExtensionType union, extension-point ID map, framework list, CLI list, and e2e coverage check pick the new types up automatically.

packages/apple-targets/src/target.ts

Added two entries to TARGET_REGISTRY:

key extension point identifier frameworks app groups by default
wallet com.apple.PassKit.issuer-provisioning PassKit yes
wallet-ui com.apple.PassKit.issuer-provisioning.authorization PassKit, UIKit yes

App Groups default to mirroring the main app because Wallet extensions are documented to share state with the containing issuer app via a shared App Group container (the host — Wallet — and the containing issuer app cannot communicate directly).

Added Info.plist cases in getTargetInfoPlistForType() that wire the principal classes to:

  • $(PRODUCT_MODULE_NAME).IssuerProvisioningHandler (non-UI)
  • $(PRODUCT_MODULE_NAME).IssuerProvisioningAuthorizationViewController (UI)

packages/apple-targets/src/configuration-list.ts

Both new types fall through to createDefaultConfigurationList() — they don't need any of the special build-setting customizations (no asset catalog accent color, no watchOS SDK, etc.).

packages/create-target/templates/wallet/IssuerProvisioningHandler.swift

PKIssuerProvisioningExtensionHandler subclass with all four non-deprecated methods overridden (Apple requires this — they must not call super). Returns "no passes available" by default; issuers fill in the methods.

packages/create-target/templates/wallet-ui/IssuerProvisioningAuthorizationViewController.swift

UIViewController adopting PKIssuerProvisioningExtensionAuthorizationProviding with a completionHandler property and convenience helpers to report .authorized / .canceled.

packages/create-target/src/createAsync.ts

Added com.apple.developer.payment-pass-provisioning as the recommended entitlement for both new targets in the scaffold output. (This is a private Apple entitlement — issuers still have to email applepayentitlements@apple.com to be allow-listed; the Swift will compile without it but Wallet won't surface the extensions until Apple grants the entitlement.)

E2E + docs

  • e2e/fixture/targets/wallet/expo-target.config.json and wallet-ui/expo-target.config.json.
  • Added both rows to e2e/__tests__/build.test.ts TARGET_REGISTRY (target names wallet and walletui).
  • Added both rows to the README "Supported types" table.
  • __tests__/createAsync.test.ts snapshot list updated; new snapshots auto-generated.

Test Plan

Ran from the workspace root with bun:

cd packages/apple-targets && bunx expo-module typecheck    # passes
cd packages/apple-targets && bunx jest                     # 8/8 pass
cd packages/create-target && bunx jest                     # 38/38 pass (incl. wallet, wallet-ui)
cd packages/apple-targets && bunx expo-module build        # builds clean
cd packages/create-target && bun run build                 # builds clean

Snapshot output for the new types looks like:

// wallet
module.exports = config => ({
  type: "wallet",
  entitlements: {"com.apple.developer.payment-pass-provisioning":true},
});

// wallet-ui
module.exports = config => ({
  type: "wallet-ui",
  entitlements: {"com.apple.developer.payment-pass-provisioning":true},
});

The exhaustive never switch in getConfigurationListBuildSettingsForType() and the e2e meta-test ("registry covers all ExtensionType values") would have failed if either new type were missed — both pass.

The xcodebuild e2e suite requires macOS + Xcode, so it can't run in this Linux cloud agent. Once the branch is reviewed it can be exercised on the macOS CI runner that the repo already uses for test:e2e (the new wallet / wallet-ui cases will run automatically alongside the other 40+ targets).

Open in Web Open in Cursor 

…et`, `wallet-ui`) (#1)

* feat(targets): add Apple Wallet In-App Provisioning extensions

Adds two new target types for implementing Apple Wallet In-App
Provisioning Extensions, which let users add an issuer's payment
passes to Apple Wallet directly from Wallet's '+' menu:

- 'wallet'    — Non-UI extension (PKIssuerProvisioningExtensionHandler)
              extension point: com.apple.PassKit.issuer-provisioning
- 'wallet-ui' — Authorization UI extension
              (PKIssuerProvisioningExtensionAuthorizationProviding)
              extension point:
              com.apple.PassKit.issuer-provisioning.authorization

Both targets:
- link the PassKit framework (UI also links UIKit)
- mirror app groups from the main target by default (host app and
  extensions communicate via a shared App Group container)
- recommend the com.apple.developer.payment-pass-provisioning
  entitlement in the create-target scaffold (still requires private
  Apple allow-listing — see https://applepaydemo.apple.com/in-app-provisioning-extensions)

Includes Swift templates, e2e fixture configs, README entries, and
unit-test snapshot updates.

Co-authored-by: Konstantin Liakhovskii <kliakhovskii-brex@users.noreply.github.com>

* docs: shorten wallet target descriptions to fit table width

Co-authored-by: Konstantin Liakhovskii <kliakhovskii-brex@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Konstantin Liakhovskii <kliakhovskii-brex@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant