Swift Library
Last updated: 2026-05-19
Swift Library
The Swift EPAS Client Library is a native Apple wrapper for ECR applications that communicate directly with Westpay payment terminals over TCP and EPAS XML. The public API is intentionally aligned with the .NET and Java libraries, while adapting to Swift naming conventions, async or await, and Swift error handling.
Requirements
| Item | Value |
|---|---|
| Distribution | Swift Package Manager |
| Product | EpasClient |
| Main client | EpasClient |
| Supported platforms | macOS and iPadOS |
| Callback protocol | EpasClientDelegate |
Package Setup
Add the package to Xcode and import EpasClient where needed.
swiftimport EpasClient
Minimal Setup
swiftimport EpasClient @MainActor final class EcrApplication: EpasClientDelegate { lazy var epas = EpasClient(delegate: self) func display(text: String) { print(text) } func printReceipt(receipt: ReceiptData) { print(receipt.generateSimpleReceipt(width: 32)) } func printReport(report: String) { print(report) } func verifySignature(displayText: String) async -> BooleanCallbackResult? { display(text: displayText) return BooleanCallbackResult(handled: true, value: true) } func log(level: LogLevel, text: String) { print("[\(level)] \(text)") } }
Implement the remaining delegate methods that your ECR needs for voice referral, payment code, VAT, loyalty, DCC, parameter download, and terminal status handling.
Create the Client
Use one EpasClient instance per terminal connection.
swiftlet clientApp = EcrApplication() let client = EpasClient(delegate: clientApp)
Connect and Login
swiftlet connection = TerminalNetworkConnection( terminalConnectionDetails: IPEndPoint("192.168.10.25", 6001), useKeepAlive: true ) try await client.connect(connection) let environment = TerminalEnvironment( terminalId: "80000082", storeId: "store_1", workstationId: "pos_1", configurationServer: IPEndPoint("185.27.171.42", 55133), authorisationServer: IPEndPoint("185.27.171.42", 55144), operatorId: "cashier_1", iso639_1_LanguageCode: TerminalEnvironment.langSwedish ) let login = try await client.login(environment) guard login.loggedIn else { throw EpasClientError.invalidState("Terminal login was rejected.") }
connect(_:) and operational methods throw when communication or validation fails. TransactionResponse, LoginResponse, and other response models still carry the business outcome from the terminal.
Supported API Surface
The current Swift library supports the main EPAS workflows:
connect(_:)disconnect()login(_:)logout()purchase(_ request: PurchaseRequest)purchase(_ transactionAmounts: PurchaseTransactionAmounts)purchase(_ purchaseAmount: Decimal)purchaseBeforeAmount()sendPurchaseAmounts(_:)refund(_ request: RefundRequest)refund(_ amount: Decimal)reverseLastTransaction(_:transactionTerminalId:)cashAdvance(_:)getLastTransaction(_:)enableCardReaders(_:_:)requestAdministrativeOperation(_:)sendRawXml(_:)abort()status()
Purchase Examples
Simple Purchase
swiftlet response = try await client.purchase(100.00)
Purchase with Cashback
swiftlet response = try await client.purchase( PurchaseTransactionAmounts(100.00, cashbackAmount: 20.00) )
Purchase with Full Request
swiftlet request = PurchaseRequest( amount: 100.00, cashbackAmount: 0.00, paymentMethod: "Swish", terminalId: nil, merchantCategoryCode: 5411 ) let response = try await client.purchase(request)
Pre-Amount Purchase
swiftTask { let response = try await client.purchaseBeforeAmount() handleTransactionResponse(response) } let sendResult = try await client.sendPurchaseAmounts( PurchaseTransactionAmounts(100.00, cashbackAmount: 0.00) )
Other Transaction Flows
swiftlet refund = try await client.refund(45.00) let reversal = try await client.reverseLastTransaction("1234567890") let cashAdvance = try await client.cashAdvance(200.00) let last = try await client.getLastTransaction("80000082")
Administrative and Diagnostic APIs
swiftlet readers = try await client.enableCardReaders( true, EnableCardReaderOptions( notifyOnCancel: true, transactionType: .payment ) ) let admin = try await client.requestAdministrativeOperation(.printConfiguration) let xmlResult = try await client.sendRawXml(""" <?xml version="1.0" encoding="utf-8"?> <SaleToPOIRequest> ... </SaleToPOIRequest> """)
Delegate Callbacks
The Swift SDK routes terminal activity through EpasClientDelegate.
Display, receipt, report, and log
swiftfunc display(text: String) func printReceipt(receipt: ReceiptData) func printReport(report: String) func log(level: LogLevel, text: String)
Cashier decision callbacks
swiftfunc verifySignature(displayText: String) async -> BooleanCallbackResult? func forceFallback(displayText: String) async -> BooleanCallbackResult? func handleVoiceReferral(displayText: String) async -> TextCallbackResult? func paymentCodeRequired(displayText: String) async -> TextCallbackResult? func vatAmountRequired(displayText: String) async -> DecimalCallbackResult? func loyaltyCardPresented(cardNumber: String) async -> BooleanCallbackResult? func checkDccOnOriginalTransaction(displayText: String) async -> BooleanCallbackResult? func parameterDownloadAvailable(displayText: String) async -> Bool
Status and diagnostics
swiftfunc linkStatusChanged(isConnected: Bool) func busyStatusChanged(isBusy: Bool) func cardStatusChanged(isInserted: Bool) func epasMessageReceived(message: String)
Receipt Handling
ReceiptData is structured and can be stored, reformatted, printed, or rendered electronically. The sample ECR groups receipts by transaction and lets the operator switch between merchant and cardholder copies.
swiftfunc printReceipt(receipt: ReceiptData) { receiptStore.append(receipt) printer.print(receipt.generateSimpleReceipt(width: 32)) }
Status Handling
The Swift client maintains a ClientStatus model that can be polled when needed.
swiftlet status = await client.status() if status.isConnected && status.isLoggedIn { ui.showReady() }
ClientStatus exposes:
isConnectedisLoggedInisBusyisCardInsertedterminalId
Error Model
Swift uses throws for transport, validation, and internal-state failures. ApiResult is still used as a semantic compatibility layer for methods such as disconnect(), sendPurchaseAmounts(_:), and sendRawXml(_:).
Common API result values include:
okerrorInvalidParametererrorConnectionFailureerrorNotConnectederrorCommunicationsFailureerrorLibraryFailureerrorParseFailure
Sample ECR
The repository contains a macOS sample ECR application that exercises the Swift SDK and exposes:
- connection and login forms
- transaction actions
- XML trace
- terminal display mirroring
- receipt history
- callback dialogs
Use the sample as the fastest parity and regression test tool while integrating new SDK functionality.