# TruePay — Native Apple Pay iOS demo A minimal SwiftUI + PassKit app that takes a **native in-app Apple Pay** payment and sends the **encrypted** payment token to TruePay's `POST /api/v1/transactions/wallet-pay`. TruePay decrypts the token server-side with the merchant's **Payment Processing certificate** (uploaded in the Merchant Portal → Apple Pay) and charges the card. The app never sees the card number and never holds any certificate — it only produces the encrypted Apple Pay token and forwards it to TruePay. ## How it maps to TruePay 1. Merchant creates an **Apple Merchant ID** + **Apple Pay Payment Processing certificate** in their Apple Developer account. 2. Merchant uploads that `.p12` (+ Apple merchant identifier) in **Merchant Portal → Apple Pay**. 3. This app runs Apple Pay with the **same Apple merchant identifier** and POSTs the token to `/api/v1/transactions/wallet-pay`: ```json { "amount": 7.250, "currency": "OMR", "reference_number": "demo-123", "wallet": { "type": "APPLE_PAY", "payment_token": { "paymentData": { … }, "paymentMethod": { … }, "transactionIdentifier": "…" } } } ``` with headers `OMPAY-API-Key` / `OMPAY-API-Secret`. 4. TruePay decrypts and returns `{ "success": true, "data": { "status": "SUCCESSFUL", … } }`. ## Prerequisites - **Xcode 15+**, a real **iPhone** (Apple Pay does not work in the Simulator for real payments), signed into an Apple ID with a card in Wallet. - An **Apple Merchant ID** with an **Apple Pay Payment Processing certificate**, and the app's bundle signed by a team that owns it. - For OMPAY testing you can use the identifier **`merchant.com.ompay.tp`** (team `9C48KB4AR3`) — its PSP certificate is already uploadable to a test merchant in TruePay. - A TruePay **API key/secret** for a merchant that has `wallet_apple_pay` enabled and has uploaded the matching PSP certificate. ## Create the Xcode project **Fastest (with [XcodeGen](https://github.com/yonaskolb/XcodeGen)):** a `project.yml` is included, so `brew install xcodegen && xcodegen generate` produces `TruePayApplePayDemo.xcodeproj` ready to open/build. Then edit `Config.swift` and run. **Or manually (2 minutes):** 1. **File → New → Project → iOS → App.** Product name `TruePayApplePayDemo`, Interface **SwiftUI**, Language **Swift**. Set the **Team** to the one that owns the Apple Merchant ID. 2. Delete the generated `ContentView.swift` / `…App.swift` and **drag in** the four Swift files from `Sources/` here, plus add `TruePayApplePayDemo.entitlements`. 3. **Signing & Capabilities → + Capability → Apple Pay**, then add the merchant identifier `merchant.com.ompay.tp` (this writes `com.apple.developer.in-app-payments` — the same as the provided `.entitlements`). 4. Edit **`Config.swift`**: set `baseURL` to your TruePay Core URL (`https://api.uat.truepay.ompay.om`), `apiKey`/`apiSecret` to your merchant credentials, and `merchantIdentifier` to your Apple merchant id. 5. Run on a **real device** with a card already in Wallet, and tap **Pay with Apple Pay**. > **"Could not present Apple Pay"** means Apple Pay refused the request on the device — nothing > was sent to TruePay, so no certificate, merchant record or setting there can cause it or fix it. > The app now names the reason. Three things must carry the SAME identifier, and the entitlement > is the one people miss: > 1. `Config.merchantIdentifier`, > 2. `com.apple.developer.in-app-payments` in `TruePayApplePayDemo.entitlements`, > 3. the App ID's **Apple Pay** capability — and the provisioning profile must be re-downloaded > after the merchant id is added there, or the build is still signed without it. > > After that: the device must have a card in Wallet for one of `supportedNetworks` (the Simulator > usually has none), and the amount must be greater than zero. > Apple Pay in-app does **not** require a verified web domain (that's only for Apple Pay on the > web). The app's Apple Merchant ID + entitlement is what authorizes it. ## Files - `Sources/Config.swift` — TruePay base URL, API key/secret, Apple merchant id, amount. - `Sources/TruePayApplePayDemoApp.swift` — SwiftUI `@main` entry point. - `Sources/ContentView.swift` — amount + Apple Pay button + result. - `Sources/PaymentHandler.swift` — builds the `PKPaymentRequest`, presents Apple Pay, and POSTs the token to TruePay `/wallet-pay`. - `TruePayApplePayDemo.entitlements` — the Apple Pay in-app-payments entitlement.