Reader SDK

Build on iOS

Build with Reader SDK on iOS to process in-person payments with Square hardware.

Prerequisites

To build with Reader SDK, the following must be true:

  • You are using Xcode 9.1+
  • You are using an iOS Base SDK of 11.1 or newer.
  • The deployment target for your app is iOS 11.0 or newer.

Assumptions

This guide makes the following assumptions:

  • You have read the Reader SDK Overview. This is a how-to guide and does not provide an overview of the SDK's functionality.
  • Your version of Reader SDK adheres to Square's update policy. To limit risk to developers and their users, Square enforces an update policy for Reader SDK requiring developers keep their version of Reader SDK current.
  • You are building with Swift. Swift is used because it is considered a friendly language for newer iOS developers. We recommend reading Swift for Beginners at Udacity if this is your first time working in Swift.
  • You have a Square Account enabled for payment processing. If you have not enabled payment processing on your account (or you're not sure), visit squareup.com/activate.
  • You are generally familiar with developing apps on iOS. If you are new to iOS development, we recommend reading the The Basics at Swift.org.

Device Permissions

To work with Square Readers, apps must have the device permissions noted below. If the required device permissions are not granted when the checkout flow initiates, Reader SDK returns an error message.

iOS device permission Purpose
Location To confirm payments are occurring in a supported country.
Microphone To connect Magstripe Readers.

Step 1: Request Reader SDK credentials

  1. Open the Square Application Dashboard. You will be prompted to login or create a new account.
  2. Create a new Square application.
  3. Click on the new application to bring up the Square application settings pages.
  4. Open the Reader SDK page and click "Request Credentials" to generate your Reader SDK repository password.

You will need the Repository password and the Application ID and from the Reader SDK page to configure Reader SDK in the next steps:

Readersdk settings page

Step 2: Install Reader SDK

  1. Download and configure the latest version of SquareReaderSDK.framework in your project root. The framework is installed in the current directory:
ruby <(curl https://connect.squareup.com/readersdk-installer) install \
--app-id SQUARE_READER_SDK_APPLICATION_ID                             \
--repo-password SQUARE_READER_SDK_REPOSITORY_PASSWORD
  1. Add Reader SDK to your project:
    1. Open the General tab for your app target in Xcode.
    2. Drag the newly downloaded SquareReaderSDK.framework into the Embedded Binaries section and click "Finish" in the modal that appears.

Step 3: Configure your iOS project for Reader SDK

Add a Reader SDK build phase

  1. Open the Xcode workspace or project for your application.
  2. In the Build Phases tab for your application target, click the + button (at the top of the pane).
  3. Select New Run Script Phase.
  4. Paste the following into the editor panel of the new run script:
FRAMEWORKS="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"
"${FRAMEWORKS}/SquareReaderSDK.framework/setup"

Disable Bitcode

Reader SDK does not currently support bitcode. To disable Bitcode:

  1. Open the Build Settings tab for your application target.
  2. In the top right search field, search for 'bitcode'.
  3. Change the value of Enable Bitcode to NO.

Add support for required interface orientations

In Xcode, open the General tab for your app target and make sure the Landscape Left and Landscape Right device orientations are supported:

Ios device orientation

If your application runs on iPhone, it must support portrait and landscape interface orientations so that Reader SDK can display the signature screen during checkout.

If you want specific screens in your app to only support the portrait orientation, you can override the supportedInterfaceOrientations method in your UIViewController subclasses.

Update your Info.plist

Add or update the following key/value pairs in the Info tab for your application target to explain why your application requires these device permissions. Xcode may display human-readable labels (e.g., "Privacy - Microphone Usage Description") rather than the raw keys.

Key Value
NSLocationWhenInUseUsageDescription This app integrates with Square for card processing. To protect buyers and sellers, Square requires your location to process payments.
NSMicrophoneUsageDescription This app integrates with Square for card processing. To swipe magnetic cards via the headphone jack, Square requires access to the microphone.
NSBluetoothPeripheralUsageDescription This app integrates with Square for card processing. Square uses Bluetooth to connect your device to compatible hardware.
NSCameraUsageDescription This app integrates with Square for card processing. Upload your account logo, feature photo and product images with the photos stored on your mobile device.
NSPhotoLibraryUsageDescription This app integrates with Square for card processing. Upload your account logo, feature photo and product images with the photos stored on your mobile device.

Step 4: Add code to request device permissions

Request location permission

Add code to ensure your app has permission to use location services before starting a checkout flow. The location permission is managed by Apple's CLLocationManager class:

import CoreLocation

class YourViewController: UIViewController {

    private lazy var locationManager = CLLocationManager()

    func requestLocationPermission() {
        switch CLLocationManager.authorizationStatus() {
        case .notDetermined:
            self.locationManager.requestWhenInUseAuthorization()
        case .restricted, .denied:
            print("Show UI directing the user to the iOS Settings app")
        case .authorizedAlways, .authorizedWhenInUse:
            print("Location services have already been authorized.")
        }
    }
}

Request microphone permission

Add code to ensure your app has permission to access the microphone before starting checkout. The microphone permission is managed by Apple's AVAudioSession class. You must have the record permission from AVAudioSession in order to use Square's magstripe readers.

import AVFoundation

extension <#YourViewController#> {

    func requestMicrophonePermission() {
        // Note: The microphone permission prompt will not be displayed
        // when running on the simulator
        AVAudioSession.sharedInstance().requestRecordPermission { authorized in
            if !authorized {
                print("Show UI directing the user to the iOS Settings app")
            }
        }
    }
}

Step 5: Add code to initialize Reader SDK

Update the application:didFinishLaunchingWithOptions: method in your app delegate to initialize Reader SDK:

import SquareReaderSDK

func application(
  _ application: UIApplication,
  didFinishLaunchingWithOptions launchOptions:
  [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

  SQRDReaderSDK.initialize(applicationLaunchOptions: launchOptions)

  return true
}

Step 6: Add code to request a mobile authorization code

Reader SDK requires a mobile authorization code from the Mobile Authorization API. Mobile authorization codes allow custom mobile apps to process payments on Square hardware on behalf of a specific Square account for a given location.

Mobile authorization codes are short lived and should be used immediately to authorize Reader SDK. Authorization is valid until it is explicitly revoked by calling deauthorize or your application fails to take a payment within 90 days. Mobile authorization codes do not need to be manually refreshed under normal operations.

Create a function, retrieveAuthorizationCode, to handle the work of calling your authorization service and handling the result:

import SquareReaderSDK

func retrieveAuthorizationCode() -> String {
    // TODO: Add code to retrieve a mobile authorization code.
    return "<#Mobile Authorization Code#>"
}

Step 7: Add code to authorize Reader SDK

Use the retrieveAuthorizationCode function from Step 6 to authorize Reader SDK.

import SquareReaderSDK

func authorizeReaderSDKIfNeeded() {

    if SQRDReaderSDK.shared.isAuthorized {
        print("Already authorized.")
    }
    else {
        let authCode = retrieveAuthorizationCode()
        SQRDReaderSDK.shared.authorize(withCode: authCode) { location, error in  

            if let authError = error {
                // Handle the error
                print(authError)
            }
            else {
                // Proceed to the main application interface.
            }
        }
    }
}

Step 8: Implement CheckoutControllerDelegate methods

Your view controller must conform to the SQRDCheckoutControllerDelegate protocol to handle results and errors from the checkout flow:

import SquareReaderSDK

extension <#YourViewController#>: SQRDCheckoutControllerDelegate {    
    func checkoutControllerDidCancel(
      _ checkoutController: SQRDCheckoutController) {
        print("Checkout cancelled.")
    }

    func checkoutController(
      _ checkoutController: SQRDCheckoutController, didFailWith error: Error) {
        // TODO: Handle checkout errors
    }

    func checkoutController(
      _ checkoutController: SQRDCheckoutController,
      didFinishCheckoutWith result: SQRDCheckoutResult) {
        // TODO: Handle checkout success
    }
}

Step 9: Add code to start the checkout flow

Create a SQRDCheckoutParameters object. At a minimum, you need to set the amount of money to be charged. Then, start the checkout flow by instantiating a Square Checkout controller (SQRDCheckoutController) and presenting it:

import SquareReaderSDK

extension <#YourViewController#> {    
  func startCheckout() {
    // Create an amount of money in the currency of the authorized Square account
    let amountMoney = SQRDMoney(amount: 100)

    // Create parameters to customize the behavior of the checkout flow.
    let params = SQRDCheckoutParameters(amountMoney: amountMoney)
    params.additionalPaymentTypes = [.cash, .manualCardEntry]

    // Create a checkout controller and call present to start checkout flow.
    let checkoutController = SQRDCheckoutController(
      parameters: params,
      delegate: self)
    checkoutController.present(from: self)
  }
}

Step 10: Add code to handle the checkout result

  1. Implement the success delegate method. For now we will print the checkout result to the Xcode console:
func checkoutController(
  _ checkoutController: SQRDCheckoutController,
  didFinishCheckoutWith result: SQRDCheckoutResult) {
  // result contains details about the completed checkout
  print("Checkout completed: \(result.description).")
}
  1. Implement the failure delegate method. Reader SDK provides error types for all failable operations. For example, errors that occur while presenting the checkout flow will always be of type SQRDCheckoutControllerError.
func checkoutController(
  _ checkoutController: SQRDCheckoutController, didFailWith error: Error) {
    // Checkout controller errors are always of type SQRDCheckoutControllerError
    let checkoutControllerError = error as! SQRDCheckoutControllerError

    switch checkoutControllerError.code {
        case .sdkNotAuthorized:
            // Checkout failed because the SDK is not authorized
            // with a Square merchant account.
            print("Reader SDK is not authorized.")
        case .usageError:
            // Checkout failed due to a usage error. Inspect the userInfo
            // dictionary for additional information.
            if let debugMessage = checkoutControllerError.userInfo[SQRDErrorDebugMessageKey],
                let debugCode = checkoutControllerError.userInfo[SQRDErrorDebugCodeKey] {
                print(debugCode, debugMessage)
            }
    }
}

Error objects always contain user displayable details (error code and description) and debugging information (debug code and debug message).

Optional: Connect a Contactless Reader

If you are using a Magstripe Reader, you do not need to write explicit code to connect the Reader. If you are using a Contactless + Chip Reader, you must add code to handle pairing.

To pair a Contactless + Chip Card reader, conform to the SQRDReaderSettingsControllerDelegate protocol and present the Reader Settings flow:

import SquareReaderSDK

extension <#YourViewController#>: SQRDReaderSettingsControllerDelegate {

    func pairCardReaders() {
        let readerSettingsController = SQRDReaderSettingsController(
          delegate: self
        )
        readerSettingsController.present(from: self)
    }

    // MARK: - SQRDReaderSettingsControllerDelegate

    func readerSettingsControllerDidPresent(
      _ readerSettingsController: SQRDReaderSettingsController) {
        print("Reader settings flow presented.")
    }

    func readerSettingsController(
      _ readerSettingsController: SQRDReaderSettingsController,
      didFailToPresentWith error: Error) {
        // Handle the error - this example prints the error to the console
        print(error)
    }
}

Optional: Deauthorize Reader SDK

To switch Square locations or to deauthorize the current location, you will need to add code that deauthorizes Reader SDK:

import SquareReaderSDK

func deauthorizeReaderSDKIfPossible() {

    if SQRDReaderSDK.shared.canDeauthorize {
        SQRDReaderSDK.shared.deauthorize { error in  

            if let deauthError = error {
                // Handle error
                print(deauthError)
            }
            else {
                // Deauthorization succeeded
            }
        }
    } else {
       print("Cannot deauthorize.")
    }
}

Optional: Configure Reader SDK for Square Stand

Reader SDK on iOS also supports swipe payments using Square Stand and a Reader connected via USB. Stand support is limited to accepting payments. Reader SDK cannot talk to peripherals connected through Square Stand such as printers, cash drawers, or barcode scanners.

To use Square Stand with your app, add the following key/value pairs to your Info.plist. Reader SDK will automatically detect if a Square Stand is connected and use it to accept swiped credit card payments.

Key Values
UISupportedExternalAccessoryProtocols com.squareup.s020
com.squareup.s025
com.squareup.s089

Testing Reader SDK on iOS

Reader SDK provides a Testing module that contains additional initializers that are not exposed in the Reader SDK framework. You can use these initializers to construct mock objects in your tests. For example, you might initialize a SQRDCard object in a unit test and use it to verify the behavior of your application.

import SquareReaderSDK.Testing // import the Testing module

func test_updateWithCard() {
    let card = SQRDCard(brand: .visa, lastFour: "1111")
    self.cardView.updateWithCard(card)

    XCTAssertEqualObjects(self.cardView.lastFourLabel.text, "1111")
    XCTAssertEqualObjects(self.cardView.brandLabel.text, "Visa")
}
Prev
< Reader SDK Overview
Next
Reader SDK Technical Reference (iOS) >

Contact Developer Support, join our Slack channel, or ask for help on Stack Overflow