Test and go live
Test your integration in test mode on a real iPhone. Then use the checklist to go live.
Test mode
- A test mode API key gives a test token. Payments with a test token are test payments. They show only in test mode in the MONEI Dashboard.
- In test mode, you tap a real card on the iPhone. MONEI replaces it with a Mastercard test card before the charge. Your card is never charged. See Test Tap to Pay.
- A live API key gives a live token.
- Do not use test and live tokens on the same device.
Tap to Pay on iPhone does not run in the iOS Simulator. Test on a supported iPhone: an iPhone XS or newer with iOS 18.5 or later. For the test and live API keys, see Testing.
Test these cases before you go live:
- An approved payment and a declined payment, each with its signed webhook. In test mode, an amount ending in 65 cents (for example 10.65) is declined.
- A payment that the user cancels on Apple's screen.
- An expired token: renew it and call
prepareagain. - Location access denied, and location access allowed again in Settings.
- Your pending state for
outcomeUnknown, and how your team finds the payment byorderId.
Example app
The package repository has an example app: Example/TapToPayExample.xcodeproj. It is a SwiftUI app with a token field, an amount, an order ID, a pay button, education and a result view.
- Open
Example/TapToPayExample.xcodeprojin Xcode. - Set your team and bundle ID. Your team must have the Tap to Pay on iPhone entitlement.
- Run the app on a supported iPhone.
- Paste a token from your server, or from a
curlcall with your test mode API key. See Request a token.
Versions and compatibility
The SDK uses semantic versioning (MAJOR.MINOR.PATCH):
- Patch: bug fixes. No change to the public API or to error semantics.
- Minor: an update inside the SDK, or new API that does not break your code.
- Major: a change in error semantics, or a change that breaks your code.
- 0.x versions: until 1.0.0, a minor version (for example 0.2.0) can change the public API. Read the release notes before you update.
- Prereleases (
-beta.N) are for testing only. Do not ship them to production.
| SDK version | iOS minimum | Built with | Notes |
|---|---|---|---|
0.7.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | New TapToPayError.passcodeRequired: the public calls check that the iPhone has a passcode and throw this error before the reader starts. A switch on TapToPayError with no @unknown default does not compile. |
0.6.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | New version of the payment engine. No change to the public API. |
0.5.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | New TapToPayError.setupIncomplete(fix:): the public calls check the app setup (location usage text, Tap to Pay entitlement, PRODUCT_TEAM_IDENTIFIER present and equal to the signing team) and give the exact fix. The SDK prepares the reader again by itself after the app returns from the background. A switch on TapToPayError with no @unknown default does not compile. |
0.4.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | New API for Apple's review requirements: isAccountLinked() and linkAccount() (accept Apple's terms before checkout), readerState and readerStates() (configuration progress and initializing view), and TapToPayError.osUpdateRequired. A switch on TapToPayError with no @unknown default does not compile. |
0.3.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | New TapToPayErrorCode.readerSetupFailed(reason:): a reader setup failure gives the step and an error code, not unknown. Code that matches .paymentFailed(code: .unknown) does not catch it. A switch with no @unknown default does not compile. |
0.2.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | PaymentResult has new fields: amount, currency, statusCode, statusMessage, authorizationCode, cardType and cardCountry. A declined result shows the reason without a call to MONEI. No change to existing fields. |
0.1.1 | 18.5 | Xcode 26.6 (Swift 6.3.3) | Installs without a GitHub token: public download URLs. Same SDK code as 0.1.0. |
0.1.0 | 18.5 | Xcode 26.6 (Swift 6.3.3) | First release. Signed binary. Same code as 0.1.0-beta.5. |
0.1.0-beta.5 | 18.5 | Xcode 26.6 (Swift 6.3.3) | Prerelease. Signed binary. |
0.1.0-beta.4 | 18.5 | Xcode 26.6 (Swift 6.3.3) | Prerelease. Signed binary. |
0.1.0-beta.3 | 18.5 | Xcode 27.0 (Swift 6.4) | Prerelease. Not signed. |
Use the same Xcode version as "Built with", or a newer one. From 0.1.0-beta.4, MONEI signs the MoneiTapToPay binary (team 72J3PXJJ4K).
For 0.x versions, use an exact version in Swift Package Manager. From 1.0.0, use from:. See Add the package.
Apple requirements
Before Apple gives the publishing entitlement, it reviews your app against its Tap to Pay on iPhone requirements. Apple sends the requirement checklist with the entitlement process. The table gives our summary of each item and how you meet it with the SDK. Apple's checklist is the reference. Also read Apple's Human Interface Guidelines for Tap to Pay on iPhone and the marketing guidelines.
| Item | Summary | How you meet it |
|---|---|---|
| 1.1 | Support Tap to Pay on iPhone on all supported iPhone models. | TapToPay.isSupported. Hide Tap to Pay on iPhone when it is false. |
| 1.2, 1.3 | If Tap to Pay on iPhone is your main payment method: a deployment target and device capabilities that support it. | The SDK needs iOS 18.5. Set your deployment target to iOS 18.5 or later. Set the device capabilities in your app. |
| 1.4 | Tell the user to update iOS when the iOS version does not support Tap to Pay on iPhone. | The SDK needs iOS 18.5, so your app does not run on the old iOS versions that Apple names. If Apple reports the iOS version as not supported, the calls throw osUpdateRequired (from 0.4.0). Tell the user to update iOS. |
| 1.5 | Prepare Tap to Pay on iPhone at launch and when the app comes to the foreground. | Call prepare once at launch. The SDK prepares the reader again each time the app comes back from the background. |
| 1.6 | Get the terms status from Apple. Do not store it in your app. | isAccountLinked() (from 0.4.0). |
| 1.7 to 1.9 | Face ID or Touch ID login, Apple's Human Interface Guidelines and marketing guidelines. | Your app. |
| 2.1 to 2.3 | A digital onboarding in the app that a new merchant can complete quickly on iPhone. | Your app and the MONEI account onboarding. |
| 3.1 to 3.4 | Communication about Tap to Pay on iPhone: visible, to all eligible users, and at the end of the onboarding. | Your app, with Apple's marketing assets. |
| 3.5 to 3.7 | A clear action to accept the terms, also outside checkout (for example in settings), and in checkout or before it. | linkAccount() from onboarding and settings (from 0.4.0). In checkout, acceptPayment shows the terms if they were not accepted. |
| 3.8, 3.8.1 | Only an administrator accepts the terms. Other users see a message to contact an administrator. | Your app decides who may call linkAccount(). For other users, use isAccountLinked() and your message. See Accept Apple's terms before checkout. |
| 3.8.2 | Enterprise apps: accept the terms outside the app. | Contact MONEI. |
| 3.9 | A screen that invites the merchant to try Tap to Pay on iPhone after the terms and the education. | Your app. |
| 3.9.1 | A configuration progress indicator. | readerStates(), preparing(progress:) (from 0.4.0). |
| 4.1 to 4.3 | Merchant education with Apple's content after the terms are accepted, and from settings or help. | presentEducation(from:) after linkAccount(), and from your settings or help. It shows Apple's current, localized content. |
| 4.4 to 4.8 | Education content: cards, digital wallets, PIN entry and fallback where the region needs them; Apple's toolkit outside the app. | Apple's content from presentEducation covers the in-app part. |
| 5.1 to 5.5 | A visible Tap to Pay on iPhone button in checkout, at the top, never disabled, with Apple's text and symbol. | Your app. |
| 5.6 | Apple's screen opens within one second. | Call prepare at launch. The SDK keeps the reader ready in the foreground. |
| 5.7 | An initializing view when the reader is not ready yet. | Show it while readerState is not ready (from 0.4.0). See Show the reader state. |
| 5.8 | A processing view after the card read. | Show your processing view while acceptPayment runs. Apple's screen covers it during the card read. |
| 5.9 | A clear result: approved, declined or timed out. | PaymentResult.status and TapToPayError. For outcomeUnknown, show a pending state. |
| 5.10 | A digital receipt for the customer. | Send it with the MONEI API (send payment receipt) and the paymentId, or your own receipt. |
| 5.11 | Regional requirements. | Contact MONEI. |
Review videos
Apple asks for three screen recordings with the entitlement request:
- Onboarding. A new user signs up (with identity checks, if you have them). Then show how your app introduces Tap to Pay on iPhone after the merchant account is approved.
- Enabling and education. An existing user learns that Tap to Pay on iPhone is available and accepts the terms. Show each path to the terms, for example from settings and from checkout. Show the education after the terms, where the user finds it later, and the progress indicator if the configuration is not complete.
- Checkout. Enter an amount, show the payment options and the Tap to Pay on iPhone button, the initializing view if Apple's screen takes more than a moment to open, and a successful payment. Show PIN entry and the fallback payment method where your region needs them. Record this video with a second device: a screen recording does not show Apple's Tap to Pay on iPhone screens.
Go-live checklist
- Apple gave your team the publishing Tap to Pay on iPhone entitlement.
- Your app uses a release version of the SDK, for example
0.7.0, and not a prerelease (-beta.N). - Your server uses your live API key, and the app gets live tokens only.
- Your server renews each token before it expires, and the app calls
preparewith the new token. - Each payment has a new
orderIdand acallbackUrl. - Your server verifies the signature of each webhook, and fulfils orders from the webhook only.
- Your app shows a pending state for
outcomeUnknownand never retries the payment. - Your UI uses the name "Tap to Pay on iPhone", and hides it when
TapToPay.isSupportedisfalse. - Your app meets Apple's requirements, and you recorded the review videos.
- You declared the App Store privacy details.
Common questions
Can I test in the iOS Simulator?
No. Tap to Pay on iPhone does not run in the iOS Simulator. Test on a supported iPhone.
Can I test with a real card?
Yes. In test mode, tap any real card. MONEI replaces it with a test card, and the card is never charged. A card that asks for a PIN is approved. Test mode does not use the PIN.
Can I ship a prerelease to the App Store?
No. Prereleases (-beta.N) are for testing only. Ship a release version, for example 0.7.0.
Which Xcode version do I need?
The Xcode version in the "Built with" column for your SDK version, or a newer one. For 0.7.0, use Xcode 26.6 or newer.