Terminal-2 icon

Make transactions

Add code to make transactions from your iOS POS app using the Adyen POS Mobile SDK.

Both Tap to Pay on iPhone and the iOS card reader solution use the same Adyen POS Mobile SDK for iOS.

To enable the Adyen POS Mobile SDK for iOS to handle transactions, you need to add code to your iOS POS app. This code starts a transaction with:

  • A Terminal API request.
  • The card reader as the payment interface to use.
  • The presentation mode you want to use.

After you have added this code, payments take place as follows:

  1. Your iOS POS app creates a Terminal API request that is serialized to JSON, or you receive the Terminal API request from your backend.

    Tip
    To help you create Terminal API requests, we provide a TerminalAPIKit for iOS on GitHub. Installation and usage instructions are in the repository's README.

  2. You pass the Terminal API request to the Adyen POS Mobile SDK.

  3. The SDK checks if the session is still valid, and if necessary establishes a new session.

  4. The transaction starts on your mobile device.

    The SDK shows instructions for the customer on your mobile device.
  5. The SDK passes the Terminal API response to your POS app.

Use the warm-up function

To speed up initiating transactions, you can use the warm-up function. This function checks for a session and any configuration changes, and prepares the proximity reader on the iPhone.

As a best practice, call the warm-up function:

  • When the POS app starts. In other words, as soon as the app has the active state.
  • When the POS app returns to the active state after running in the background.

To call the warm-up function:

try await paymentService.warmUp()

Handle a payment

In your iOS POS app, add code for the following steps:

  1. If you create the Terminal API payment request in your POS app, use PaymentService.installationId as the POIID in the MessageHeader of the payment request.
    Note that if you create the Terminal API payment request in the backend, this uses the installationId from the /checkout/posskd/v68/sessions response.

    For the structure of a Terminal API payment request, see Make a payment.

  2. Create an instance of Payment.Request using Payment.Request(data:), and pass the Terminal API payment request from your POS app or backend.

    let transaction = try Payment.Request(data: requestData)
  3. Get a PaymentInterface from an instance of PaymentService, using PaymentService.getPaymentInterface(with: .cardReader).

    let paymentService = PaymentService(...)
    let paymentInterface = try paymentService
                            .getPaymentInterface(with: .cardReader)
  4. Specify a TransactionPresentationMode value that matches the UI framework, SwiftUI or UIKit, of the POS app.

    Value Description
    viewModifier For use with a SwiftUI application. The UI is embedded in a View as a ViewModifier.
    presentingViewController For use with a UIKit application. The UI is presented on top of the provided UIViewController.

    Optionally use parameters to customize the user interface.

    Parameter Description
    logo A bitmap image to show on your mobile device during the transaction flow. To ensure visibility in both dark mode and light mode, the bitmap image must have a transparent background. The logo is placed in a frame with a vertical height of 40 points and scaled to aspect ratio to fit in that frame.
    successScreenTimeout Indicates how long the SDK shows the screen that indicates the transaction succeeded. If not specified, this success screen is dismissed after four seconds. You can set a time in seconds as a Double with a minimum of 0.5 seconds and a maximum of 4 seconds.

    Using viewModifier (SwiftUI)

    If you use TransactionPresentationMode with viewModifier:

    1. Set presentationMode as follows.

      let presentationMode: TransactionPresentationMode = .viewModifier
    2. Apply the presentation mode on your SwiftUI view.

      Button(...) {
        // code to start the transaction
      })
      .transactionModal(
        with: {YOUR_INSTANCE_OF_PAYMENT_SERVICE}
        logo: logo,
        parameters: .init(successScreenTimeout: 2)
      )

    Using presentingViewController (UIKit)

    If you use TransactionPresentationMode with presentingViewController(_:logo:parameters:), set presentationMode as follows.

    let presentationMode: TransactionPresentationMode = .presentingViewController(
       rootViewController,
       logo: logo,
       parameters: .init(successScreenTimeout: 2)
    )
  5. Invoke PaymentService.performTransaction(with:paymentInterface:presentationMode:) on your instance of PaymentService.

    let transactionResponse = await paymentService.performTransaction(
       with: transaction,
       paymentInterface: paymentInterface,
       presentationMode: presentationMode
    )

    The Adyen POS Mobile SDK checks for a session, starts the transaction, and shows screens on your mobile device to help the customer.

  6. Check the paymentResponse. This is the Terminal API response with the transaction result and the data you can use to generate a receipt, or with any errors.

  7. Pass the paymentResponse to your POS app.

Handle a refund

There are two types of refund: referenced and unreferenced. The main difference is that a referenced refund is connected to the original payment, and an unreferenced refund isn't. That makes unreferenced refunds a bit riskier. For an overview of the differences, see Refund a payment.

Refunds are usually not processed synchronously. When you send a request for a referenced or unreferenced refund, the Terminal API response only confirms we received the request. Unreferenced refunds, however, can be processed synchronously. This depends on the card scheme and the country/region where the card is used. If processed synchronously, you receive an additional field in the Terminal API response: acquirerResponseCode.

To learn the outcome of a refund, you need to set up webhooks.

Handle a referenced refund

The Terminal API request for a referenced refund is a reversal request. The SDK contains a dedicated function for this.

In your iOS POS app, add code for the following steps:

  1. If you create the Terminal API reversal request in your POS app, use PaymentService.installationId as the POIID in the MessageHeader of the reversal request.
    Note that if you create the Terminal API reversal request in the backend, this uses the installationId from the /checkout/posskd/v68/sessions response.

    For the structure of the Terminal API reversal request, see Referenced refund.

  2. Create an instance of Reversal.Request using Reversal.Request(data:), and pass the Terminal API reversal request from your POS app or backend.

    let request = try Reversal.Request(data: requestData)
  3. Invoke PaymentService.performReversal(with:) on your instance of PaymentService.

    let reversalResponse = await paymentService.performReversal(with: request)

    The Adyen POS Mobile SDK now checks for a session, and starts the transaction.

  4. Check the reversalResponse. This is the Terminal API response with the transaction result and the data you can use to generate a receipt, or with any errors.

  5. Pass the reversalResponse to your POS app.

Handle an unreferenced refund

The Terminal API request for an unreferenced refund is a payment request with an additional parameter:

  • PaymentData.PaymentType: Refund

This means you can use the same code as for handling a payment. The only difference is the structure of the Terminal API payment request that you pass as the requestData to the Payment.Request.

For the structure of the Terminal API request, see Unreferenced refund.

Testing

To test transactions, you can use the following Adyen point-of-sale test cards:

The instructions are the same for both cards; see either of the pages mentioned above.

Troubleshooting

The Adyen payments platform performs regular checks to make sure that the mobile device on which the SDK is installed is secure. Errors that occur during the security attestation process need to be resolved to make transactions, including Store and Forward payments. Below you can find the table with the most common errors and how to handle them.

Error code Description Resolve offline Required action
DEBUGGER_ENABLED Transaction canceled. -white_check_mark- Disconnect the debugger and try again.
INVALID_NYC1_FIRMWARE_VERSION Card reader firmware version is invalid. -x- Update NYC1 to the latest software version and try again.
LOCAL_TIME_TAMPERING Transaction canceled. Unable to check the security requirements. -x- In Settings > General > Date & Time toggle on Set automatically.
NON_SELF_RESOLVABLE Transaction canceled. Unable to check the security requirements. -x- Contact our Support Team to resolve the issue.
NO_TOKEN Cannot transact. -x- Must go online for SDK to check security requirements.
OFFLINE_DATA_TAMPERING An error occurred, offline data may have been lost. -x- Must go online for SDK to check security requirements.
PASSCODE_NOT_ENABLED Transaction canceled. Device passcode was removed, offline transaction data may have been lost. -white_check_mark- In Settings > Face ID & Passcode set a passcode for this device and try again.
All S&F transactions previously performed with passcode will be lost and cannot be recovered. You will not be able to continue transacting in S&F.
SCREEN_RECORDING Transaction canceled. -white_check_mark- Stop screen recording and try again.
SCREEN_CAPTURED Transaction canceled. -white_check_mark- Screen capture is not allowed. Try again.
SCREEN_TAMPERING Transaction canceled. -white_check_mark- Try again. The app must be open and in full-screen while the transaction is in progress
SCREEN_OVERLAY Transaction canceled. -white_check_mark- Keep the app open and in full-screen while the transaction is in progress.
SYSTEM_CHANGE Transaction canceled. Cannot transact due to system change. -white_check_mark- Must go online for SDK to check security requirements.
If the date/time of the device was changed, you must change it back to continue transacting. If the device was restarted, it must go online for the SDK to check security requirements.
TOKEN_EXPIRED_S&F Offline transaction window has expired. -x- Must go online for SDK to check security requirements.

Next steps