This reference assumes you have completed the Integration Guide. Testing runs on a physical iPhone (XS or later, iOS 18.1 or later) against the Finix Sandbox, with the Sandbox Apple Account signed in as the iPhone's primary account (see Create an Apple Sandbox Account and the sign-in step covered in the Integration Guide).
With the Sandbox Apple Account signed in as the device's primary account, the Terms and Conditions flow and card reads run against Apple's Sandbox. You can tap physical Finix sandbox test cards or Apple Pay Sandbox test cards (Visa, Mastercard, American Express, Discover) added to Wallet on a second Sandbox-signed-in device.
Settings → App Store → Sandbox Account only affects In-App Purchase testing. It has no effect on Tap to Pay on iPhone or Wallet. The Sandbox tester must be the account the whole device is signed in to.
Tap to Pay on iPhone does not work on beta releases of iOS. Test on release iOS versions.
The Finix Tap to Pay on iPhone demo app is a working SwiftUI reference integration you can run against your Sandbox credentials. See the Demo App Walkthrough for setup.
Your app-level logic (receipts, persistence, UI state) can be tested without a device. The result type's memberwise initializer is internal; use the public mock factory to construct results in your test target:
import XCTest
import FinixTapToPaySDK
@testable import YourApp
final class ReceiptRendererTests: XCTestCase {
func testRendersApprovedReceipt() {
let result = TapToPayTransactionResult.mock(
amount: 1250,
currency: "USD",
cardBrand: "VISA",
last4: "4242",
transferId: "TRxxxxxxxxxxxxx",
transferState: "SUCCEEDED"
)
let receipt = ReceiptRenderer().render(result)
XCTAssertTrue(receipt.contains("$12.50"))
XCTAssertTrue(receipt.contains("VISA •••• 4242"))
}
}mock(amount:currency:...) provides default values for the card fields and nil for the transfer fields. Override the fields your test asserts on.
Run through these on a physical iPhone before requesting the distribution entitlement:
- First link: fresh install, sign-in,
linkAccount()presents Apple's Terms and Conditions. - Re-link: call
linkAccount()again; confirm your app treats.accountAlreadyLinkedas success. - Cold and warm prepare: first
prepareReader()after install (slow) and after foregrounding (fast); your indeterminate progress UI shows during user-visible preparation. - Sale, authorization, and refund: one of each; verify each Transfer in the Sandbox Finix Dashboard.
- Cancel mid-read: dismiss the tap sheet and cancel from your UI; both paths surface
.transactionCancelledand return to checkout cleanly. - Backgrounding: background the app mid-flow; confirm you re-prepare on foreground and no reader call runs from the background.
- Un-activated Device: point at a Device that was never activated; confirm your recovery path (re-provision) works.
- Unsupported device: on the simulator or an old iPhone, confirm Tap to Pay on iPhone entry points are hidden by your
isSupported()gate.
After a test transaction, confirm end-to-end that the transaction reached Finix and recorded as a contactless, Tap-to-Pay payment.
- In the Finix Dashboard, enter the Merchant's ID and hit Enter.
- Open a transactions view (for example, Payments and authorizations).
- Select the transaction from the list.

- In the drawer that opens, confirm under Payment Details:
- Created Via is
Card Present iOS Tap To Pay SDK(or similar). - Entry Type is
Contactless.

Next: Privacy and data collection.