Starting a Tap to Pay Transaction

📘

Currently Tap to Pay is in Beta Release. If you would like to participate, please reach out to your Account Manager.


Call the startTransaction() to initiate a transaction. This can be used to start a Sale, Refund or Account Verification transaction. The request accepts various parameters, including amount, transaction type, unique reference, whether to enable/disable gratuity and currency.

When the startTransaction() method is successful, asynchronous updates are provided in the following callbacks; transactionUpdate, userNotification, applicationSelection, signatureVerification, and transactionFinished.

For additional information, you can refer to the SDK README.

Using Tap To Pay on iPhone

Use Tap to Pay on iPhone to accept contactless payments directly on supported iPhone devices without any additional hardware.

Requirements

⚠️

Passcode required

Your iPhone must use a passcode. This is a security requirement for Tap to Pay to work. An error message will appear similar to a connection error if no passcode is active.

How it works

Tap to Pay uses the same TransactionRequest model as a mobile reader for payments, but uses the iPhone's built-in NFC reader to accept contactless cards and digital wallets.

Connect to Tap to Pay

Before taking a Tap to Pay transaction, you must first connect to the Tap to Pay reader on the iPhone using connectToTap. Once the connection is successful, you can proceed to take a payment.

if #available(iOS 17.4, *) {
    omni.connectToTap(completion: {
        print("Connected to Tap to Pay!")

        // Now take a payment
        let amount = Amount(cents: 1050) // $10.50
        let request = TransactionRequest(amount: amount)

        omni.takeTapTransaction(with: request) { transaction in
            print("Tap payment successful!")
            print("Transaction ID: \(transaction.id)")
            print("Amount: \(transaction.total)")
        } error: { error in
            print("Tap payment failed: \(error)")
        }

    }, error: { error in
        print("Failed to connect to Tap to Pay: \(String(describing: error))")
    })
} else {
    print("Tap to Pay requires iOS 17.4 or later")
}

Taking a Tap to Pay Transaction

// Create an Amount
let amount = Amount(cents: 1050) // $10.50

// Create the TransactionRequest
let request = TransactionRequest(amount: amount)

// Take a Tap to Pay transaction
if #available(iOS 17.4, *) {
    omni.takeTapTransaction(with: request) { transaction in
        print("Tap payment successful!")
        print("Transaction ID: \(transaction.id)")
        print("Amount: \(transaction.total)")
        
        // Handle successful payment
        // Update your UI, print receipt, etc.
    } error: { error in
        print("Tap payment failed: \(error)")
        
        // Handle error
        // Show error message to user
    }
} else {
    print("Tap to Pay requires iOS 17.4 or later")
}


Complete Example

import Fattmerchant

class PaymentViewController: UIViewController {
    var omni: Omni?
    
    @IBAction func processTapPayment(_ sender: UIButton) {
        guard #available(iOS 17.4, *) else {
            showAlert(title: "Not Supported", message: "Tap to Pay requires iOS 17.4 or later")
            return
        }
        
        // Create amount for $25.00
        let amount = Amount(cents: 2500)
        
        // Create transaction request
        let request = TransactionRequest(amount: amount)
        
        // Optional: Add metadata
        request.meta = ["order_id": "12345", "customer_name": "John Doe"]
        
        // Show processing UI
        showProcessingUI()
        
        // Process the payment
        omni?.takeTapTransaction(with: request, completion: { [weak self] transaction in
            guard let self = self else { return }
            
            self.hideProcessingUI()
            
            // Payment succeeded
            self.showSuccessUI(transaction: transaction)
            
            print("✅ Payment successful!")
            print("Transaction ID: \(transaction.id)")
            print("Amount: \(transaction.total)")
            print("Last 4: \(transaction.lastFour ?? "N/A")")
            
        }, error: { [weak self] error in
            guard let self = self else { return }
            
            self.hideProcessingUI()
            
            // Payment failed
            self.showErrorUI(error: error)
            
            print("❌ Payment failed: \(error.localizedDescription)")
        })
    }
    
    private func showProcessingUI() {
        // Show loading indicator and "Hold card near iPhone" message
    }
    
    private func hideProcessingUI() {
        // Hide loading indicator
    }
    
    private func showSuccessUI(transaction: StaxTransaction) {
        // Show success checkmark, amount, etc.
    }
    
    private func showErrorUI(error: OmniException) {
        // Show error message
    }
    
    private func showAlert(title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}


Refund a Payment

You can use the [Stax API]({{ site.api_ref_url }}#reference/0/transactions){:target="_blank" rel="noreferrer"} to refund a payment. Once you receive the transaction, call the refundMobileReaderTransaction method to attempt the refund.

// Attain a transaction
var transaction = Transaction()

// Perform refund
omni.refundMobileReaderTransaction(transaction: transaction, completion: { (refundedTransaction) in
  // Refund successful!
}, error: { error in
  // Error
})




Did this page help you?