iOS integration {Deprecated}
The SDK integration described on this page is no longer available. To integrate AffiniPay payments into your iOS mobile app, see Deep linking from your iOS mobile app.
Use these guidelines to incorporate the mobile SDK into your iOS mobile app. See the iOS API for additional details about implementing each screen.
- Prepare for integration
- Add the SDK to your project
- Add permissions
- Import the SDK
- Add the Amount screen (optional)
- Add the Card Entry screen (required)
- Add the Customer Info screen (recommended)
- Trim the target architectures
You should also review the orientation guidelines.
1: Prepare for integration
Before you begin:
- Obtain an AffiniPay merchant account from AffiniPay Support. You can use the test-mode secret key to test your integration.
- Ensure you are using:
- Xcode version 10 or higher.
- iOS version 9.3 or higher.
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”.
In addition, for the Bluetooth card reader, you must add entries to the Info.plist file for:
- The key
NSBluetoothAlwaysUsageDescription
and a String value - The key
NSBluetoothPeripheralUsageDescription
and a String value
4: Import the SDK
import AffiniPaySDK
5: Add the Amount screen
How the amount to be paid is determined is application specific. Your app might allow the user to input a dollar amount or possibly sum the contents of a shopping cart. Once the amount is known, then your app can invoke our card-entry process to begin the payment process.
6: Add the Card Entry screen
You must include the Card Entry screen that enables the merchant to either swipe to provide card information or manually enter the card details. This screen is required to charge with the AffiniPay Payment Gateway.
To add the Card Entry screen:
- Create
InitParams
.let afpTokenInitParams = AFPTokenizationInitParams(publicKey: getPublicKey(), amount: "100", // cents accountName: accountName, // name of account to deposit trustAccount: true, // or false requireCvv: true, // or false requireSwipeCvv: true, // or false disableCardReader: false, // or false autoShowHideNavigationBar: true)
- Create
AFPCardEntryVC
andClientDetailsController
and passInitParams
in thegetCardEntryVC
method.public class MainViewController: UIViewController { var clientVC: ClientDetailsController? private var afpCardEntryVC: AFPCardEntryVC? public override func viewDidLoad() { super.viewDidLoad() } func showCardEntry() { // Instantiate card entry view controller self.afpCardEntryVC = AffiniPaySDK.getCardEntryVC(afpTokenInitParams, onReturnSwiperData: { (swiperData) in // swiperData print("swiperData: \(swiperData)") }, onReturnCardData: { (data) in // data print("data: \(data)") // show client details page // ... the client details screen is going to be created by the partners self.clientVC = self.storyboard.instantiateViewController(withIdentifier: "ClientDetailsController") as? ClientDetailsController self.clientVC!.delegate = self // this is needed to get callback from the client details self.afpCardEntryVC?.navigationController?.pushViewController(self.clientVC!, animated: true) }, onReturnPaymentToken: { (result) in self.clientVC?.stopLoading() // stop loading at client details page if (result!.error) != nil { // error } else { print("Amount: \(amountString)") print("One time token: \(tokenId)" // step: Create a charge on the backend using one token, account id, and amount // ... The network layer code to create charge // step: Show Signature screen on successful charge // ... the signature screen is going to be created by the partners // ... the flow ends here }, onReset: { // callback on reset print("Block Called => onReset") }, onDismiss: { // callback on dismis print("Block Called => onDismiss") }, onCancelCvvAlert: { // callback on dismiss print("Block Called => onCancelCvvAlert") self.afpCardEntryVC!.dismiss() }) } }
To submit the charge:
After the AFPCardEntryVC
view controller returns the AFPChargeResult
object:
- Your mobile app must pass the
amountString
andtokenID
to your backend server. - 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.
7: Add the Customer Info screen
Prior to completing a transaction, additional customer information can be passed along with the transaction. Some customer information fields are required, and collecting them may also be application specific. For example, your application may already have all required customer information in its database. In which case it just needs to pass it along during the tokenization process. Other applications will need to provide a user interface for collecting this information. Be sure to gather the appropriate cardholder details.
To add a Customer Info screen:
- Create
ClientDetailsController.swift
and handle the Callback.import UIKit import AffiniPaySDK.AFPCustomerInfo protocol ClientDetailsControllerDelegate { func onSubmitClientInfo(customerInfo: AFPCustomerInfo) } class ClientDetailsController: UIViewController { var delegate: ClientDetailsControllerDelegate! static let sharedInstance = ClientDetailsController() @IBOutlet weak var loadingActivityIndicator: UIActivityIndicatorView! static func clientDetailsVC() -> ClientDetailsController { let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main) let clientDetailsVC = storyboard.instantiateViewController(withIdentifier: "ClientDetailsController") as! ClientDetailsController return clientDetailsVC } @IBAction func onClientDetailsSubmit(_ sender: UIButton) { let customerInfo = self.getCustomerInfoInput() self.delegate.onSubmitClientInfo(customerInfo: customerInfo!) } @IBAction func onBackAction(_ sender: UIButton) { self.navigationController?.popViewController(animated: true) } func getCustomerInfoInput() -> AFPCustomerInfo? { let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate var inputValues: AFPCustomerInfo? = appDelegate?.getPrefillTestInput() if inputValues == nil { inputValues = AFPCustomerInfo() inputValues?.email = "iossdk@affinipay.com" inputValues?.phone = "512-555-1212" inputValues?.reference = "iOS SDK sample app" inputValues?.city = "Austin" inputValues?.state = "Texas" inputValues?.country = "US" inputValues?.name = "Max Payne" inputValues?.address1 = "12" inputValues?.address2 = "xyz" inputValues?.postalCode = "12123" } return inputValues } func startLoading() { loadingActivityIndicator.startAnimating() } func stopLoading() { loadingActivityIndicator.stopAnimating() } } Implement ClientDetailsControllerDelegate where CardEntry instance was created. public class MainViewController: UIViewController, ClientDetailsControllerDelegate { // ...
// MARK: - ClientDetailsControllerDelegate func onSubmitClientInfo(customerInfo: AFPCustomerInfo) { self.clientVC?.startLoading() let afpTokenizationCompleteParams = AFPTokenizationCompleteParams(customerInfo: customerInfo) self.afpCardEntryVC?.startTokenization(afpTokenizationCompleteParams!) } }
8: 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:
- Open your project in Xcode.
- Navigate to the settings for the build target.
- Click the Build Phases tab.
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.
Device | Orientations |
---|---|
iPhone | Portrait |
iPad | All |