iOS integration

Use these guidelines to incorporate the mobile SDK into your iOS mobile app. See the iOS API for additional details about implementing each screen.

  1. Prepare for integration
  2. Add the SDK to your project
  3. Add permissions
  4. Import the SDK
  5. Add the Amount screen (optional)
  6. Add the Customer Info screen (recommended)
  7. Add the Card Entry screen (required)
  8. Add the Signature screen (optional)
  9. Trim the target architectures

You should also review the orientation guidelines.

Note: If you’re using Xamarin to build your iOS app, you must perform the steps in the Xamarin integration for iOS first.

1: Prepare for integration

Before you begin:

2: Add the SDK to your project

You must add the SDK to your project before you can start working with it. For more information, contact AffiniPay Support.

3: Add permissions

To support an AffiniPay mobile card reader, you must add an entry to the Info.plist file for for the key NSMicrophoneUsageDescription and a String value that describes why the microphone permissions on the device are needed, such as “Credit Card Reader”.

4: Import the SDK

import AffiniPaySDK

5: Add the Amount screen

The Amount screen (which is optional) enables the merchant to input the amount to be charged.

To add the Amount screen:

Obtain an AFPAmountVC object from the AffiniPaySDK and push it to an AFPNavigationController.

// Instantiate
let amountVC = AffiniPaySDK.getAmountVC({ (amountResult) in
    // Log success action
    print("Amount selected in cents: \(amountResult?.amount)")
})

// Push view controller
myNavigationController.pushViewController(amountVC!, animated: true)

6: Add the Customer Info screen

The Customer Info screen (which is recommended) enables the merchant to input information about the cardholder. Be sure to gather the appropriate cardholder details.

To add the Customer Info screen:

Obtain an AFPCustomerInfoVC object from the AffiniPaySDK, and push it to an AFPNavigationController.

// Input
let customerInformation = AFPCustomerInfo()
customerInfo.email = “name@company.com”
customerInfo.phone = “515-555-1212”
customerInfo.reference = “My Reference”

let afpCustomerInfoParams = AFPCustomerInfoParams(mandatoryFields: [AFPCustomerInfoType.name.rawValue, AFPCustomerInfoType.address1.rawValue, AFPCustomerInfoType.postalcode.rawValue], customerPrefill: customerInformation)

// Instantiate
let customerInfoVC = AffiniPaySDK.getCustomerInfoVC(afpCustomerInfoParams!, next: { (result) in
    // Log success action
    print("Name: \(result!.customerInfo!.name)")
    print("Address: \(result!.customerInfo!.address1)")
    print("Postal code: \(result!.customerInfo!.postalCode)")
})

7: Add the Card Entry screen

The Card Entry screen (which is required) enables the merchant to either swipe or insert to provide card information or manually enter the card details. This screen is required to charge with the AffiniPay Payment Gateway.

Note: When the AffiniPay card reader is used to make an EMV charge, you must submit a signature to finalize the charge. You can obtain a signature using either the mobile SDK signature screen or your own screen. See Add the Signature screen for implementation information.

To add the Card Entry screen:

Obtain an AFPCardEntryVC object from AffiniPaySDK, and push it to an AFPNavigationController.

// Input
let afpChargeInput = AFPChargeInput(publicKey: getPublicKey(), amount: getAmount(), customerInfo: getcustomerInfo())

// Instantiate
let cardEntryVC = AffiniPaySDK.getCardEntryVC(afpChargeInput!, nextWithCompletionBlock: { [weak self](chargeResult, finishCallback) in
    // Check card entry return values
    guard let amountString = chargeResult?.amount else { assert(false, "Invalid amount"); return }
    guard let tokenId = chargeResult?.oneTimeToken else { assert(false, "Invalid charge token"); return }
    print("Amount: \(amountString)")
    print("One time token: \(tokenId)")

    if let paymentDataSource = chargeResult?.paymentDataSource {
        print("Payment data source: \(paymentDataSource)")
    }
    if let posFields = chargeResult?.posFields {
        print("Pos: \(posFields)")
    }

    // Create a charge on your backend using a one token, account id, and amount
    let succeeded = createCharge()

    // Callback to signal card entry controller to finish
    finishCallback?(succeeded)
})

// Push view controller
myNavigationController.pushViewController(cardEntryVC!, animated: true)

To submit the charge:

After the AFPCardEntryVC view controller returns the AFPChargeResult object:

  1. Your mobile app must pass the AFPChargeResult (or the details it contains) to your backend server.
  2. Your backend server must POST the charge details and other required information (such as the merchant’s secret key) to the charges endpoint of the AffiniPay Payment Gateway.

Note: To ensure the security of payment details, never make a call to the AffiniPay Payment Gateway directly from your mobile app.

See AffiniPay’s sample mobile and backend apps for an example of how this can be implemented.

8: Add the Signature screen

The Signature screen (which is optional) enables the cardholder to sign and confirm the charge.

To add the Signature screen:

Obtain an AFPSignatureVC from AffiniPaySDK, and push it to an AFPNavigationController.

// Create input
let afpSignatureInput = AFPSignatureInput(transactionId: getChargeId(), amount: getAmount(), merchant: getMerchantName())

// Instantiate signature view controller
let signatureVC = AffiniPaySDK.getSignatureVC(afpSignatureInput!, nextWithCompletionBlock: { [weak self](signatureResult, finishCallback) in
    print("Signature: \(String(describing: signatureResult?.signatureString))")

    // Sign the charge on your backend using the charge id, and signature string
    let succeeded = signCharge()

    // Callback to signal signature controller to finish
    finishCallback?(succeeded)
})

// Push view controller
myNavigationController.pushViewController(signatureVC!, animated: true)

After the AFPSignatureVC view controller returns the AFPSignatureResult object:

  1. Your mobile app must pass the AFPSignatureResult object (or the details it contains) to your backend server.
  2. Your backend server must POST the signature details and other required information (such as the merchant’s secret key) to the /v1/transactions/{transactionID}/sign endpoint of the AffiniPay Payment Gateway.

Note: To ensure the security of payment details, never make a call to the AffiniPay Payment Gateway directly from your mobile app.

See AffiniPay’s sample mobile and backend apps for an example of how this can be implemented.

9: Trim the target architectures

The AffiniPay SDK includes the x86_64 and i386 architectures for ease of development on both simulators and iOS devices. You should remove these architectures before submitting your app for review. This can be done by adding a new build phase to your target in Xcode and running a script provided by the SDK:

  1. Open your project in Xcode.
  2. Navigate to the settings for the build target.
  3. Click the Build Phases tab.
  4. Add a new Run Script phase and paste the following into the script body. Adjust the FILE definition if your .framework file does not live in the same directory as your project file:

    FILE=$PROJECT_DIR/AffiniPaySDK.framework/Scripts/remove_unused_archs.sh
    source $FILE

Unused architectures will be removed from your build target as part of your build.

Orientation guidelines

The steps for configuring orientation are different depending on the navigation controller and view controllers you use.

Use AFPNavigationController with SDK-provided controllers

If you use AFPNavigationController for SDK-provided view controllers, the navigation controller will rotate the SDK-provided view controllers to their supported orientations.

Use AFPNavigationController with your own view controllers

If you push your own view controllers onto an instance of AFPNavigationController, you can choose to implement these functions to let AFPNavigationController orient your view controllers.

- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForThisController{
    // Change this code to return the desired orientations
    if (isPhone()) return UIInterfaceOrientationMaskPortrait;
    return UIInterfaceOrientationMaskAll;
}

- (BOOL)shouldAutorotateNow {
    return YES;
}

Use your own navigation controller

If you push SDK-provided view controllers onto your own navigation controller, orient them based on the following values.

View ControllerDeviceOrientations
AFPAmountVCiPhone
iPad
Portrait
All
AFPCustomerInfoVCiPhone
iPad
Portrait
All
AFPCardEntryVCiPhone
iPad
Portrait
All
AFPSignatureVCiPhone
iPad
Landscape
All