iOS API

The following views are available with the AffiniPay mobile SDK:

Import

import AffiniPaySDK

Amount Selection (optional)

The AFPAmountVC view controller allows the user to enter a dollar amount.

Input

None

Output

The output will be returned as an AFPAmountResult object.

ParameterTypeDescription
amountstringThe requested charge amount given in US cents, unformatted. The AffiniPay Payment Gateway expects the charge in the same format. For example, USD $2.46 would be returned as “246”.

Interface

typedef void(^amountNextBlock_t)(AFPAmountResult* _Nullable result);

+ (AFPAmountVC* _Nullable)getAmountVC:(amountNextBlock_t _Nullable)next;

Example

// 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)

Screen highlights

  1. The unformatted amount (in cents).
  2. An error message shows when an invalid amount is entered.
  3. After the Next button is enabled and tapped, the unformatted amount (in cents) is passed to the return block of the AffiniPaySDK.getAmountVC method, as the amount field of an AFPAmountResult object.

The AFPCustomerInfoVC view controller allows the user to input specific details about a customer (such as name, address, and email) and returns those details to the caller.

Input

The input will be passed as an AFPCustomerInfoParams object with the following member:

ParameterTypeDescription
mandatoryFieldsArrayAn array of AFPCustomerInfoType raw values specifying all possible mandatory customer input fields. *

AFPCustomerInfoType is an enum specifying customer input fields with the following values:
- AFPCustomerInfoTypeEmail
- AFPCustomerInfoTypePhone
- AFPCustomerInfoTypeReference
- AFPCustomerInfoTypeName
- AFPCustomerInfoTypeAddress1
- AFPCustomerInfoTypeCity
- AFPCustomerInfoTypeState
- AFPCustomerInfoTypePostalcode
- AFPCustomerInfoTypeCountry

*The AFPCustomerInfoTypeEmail, AFPCustomerInfoTypePhone, and AFPCustomerInfoTypePostalcode fields have some validation that must be passed if any value is entered in the UI. The validation must be passed even if the field is not mandatory.
customerPrefillAFPCustomerInfoDetails about the customer that will be used pre-fill the view controller fields. Note that when you pre-fill the country, you should submit either the ISO 3166-1 alpha-2 code or the English short country name officially used by the ISO 3166 Maintenance Agency (ISO 3166/MA).

Output

The output will be returned as an AFPCustomerInfoResult object with the following members.

ParameterTypeDescription
customerInfoAFPCustomerInfoDetails about the customer.

The AFPCustomerInfo object will have the following members:

ParameterTypeDescription
namestringThe name of the customer.
emailstringThe email address of the customer.
address1stringThe street address of the customer.
address2stringApt/Unit of the customer.
citystringThe city of the customer’s billing address.
statestringThe U.S. state or Canadian province of the customer’s billing address.
countrystringThe country of the customer’s billing address.
postalCodestringThe postal code of the customer’s billing address.
phonestringThe phone number of the customer.
referencestringA number used for internal tracking, such as the customer’s account number or the transaction ID.

Interface

typedef void(^customerInfoNextBlock_t)(AFPCustomerInfoResult* _Nullable result);

+ (AFPCustomerInfoVC* _Nullable)getCustomerInfoVC:(AFPCustomerInfoInput* _Nonnull)params
                                            next:(customerInfoNextBlock_t _Nullable)next;

Example

// 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)")
})

Screen highlights

  1. Field validation indicates whether input is formatted correctly. If it's not, it's marked as invalid.
  2. Required fields are determined by the mandatoryFields parameter of AFPCustomerInfoParams and are marked with an asterisk.
  3. Optional fields are determined by the mandatoryFields parameter of AFPCustomerInfoParams.
  4. After the Next button is enabled and tapped, customer details are passed to the return block of the AffiniPaySDK.getCustomerInfoVC method, as an AFPCustomerInfoResult object. The button will not be enabled until all required fields are filled and all fields are formatted properly. A red line under a field indicates a validation failure.

Card Entry (required)

The AFPCardEntryVC view controller allows the user to input credit/debit card information manually or using the AffiniPay card reader. A token that is returned from the AffiniPay Payment Gateway can then be used to make a charge.

Note: When the AffiniPay card reader is used to make a chip scanning (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.

Input

The input will be passed as an AFPChargeParams object with the following members:

ParameterTypeDescription
amountstringThe requested charge amount in US cents, unformatted. For example, to charge $2.46, you should submit 246.
publicKeystringThe public key for your account obtained from OAuth login and used to create a one-time token.
customerInfoAFPCustomerInfoAn AFPCustomerInfoResult object containing customer information data.

Output

The output will be returned as an AFPChargeResult object with the following members:

ParameterTypeDescription
amountstringThe requested charge amount given in US cents, unformatted. The AffiniPay Payment Gateway expects the charge in the same format. For example, USD $2.46 would be returned as “246”.
oneTimeTokenstringA temporary token given by the AffiniPay Payment Gateway that can be used to create a charge.
paymentDataSourcestringThe reason for payment failing to use EMV (Chip Scanning) and falling back to Magstripe (Swipe) instead.
posFieldsDictionaryAdditional parameters that describe the payment and verification method.

Interface

AffiniPaySDK

typedef void(^chargeNextWithCompletionBlock_t)(AFPChargeResult* _Nullable result, boolBlock_t _Nullable finishBlock);
typedef void(^chargeNextBlock_t)(AFPChargeResult* _Nullable result);

+ (AFPCardEntryVC* _Nullable)getCardEntryVC:(AFPChargeInput* _Nonnull)params
                                         next:(chargeNextBlock_t _Nullable)next;

+ (AFPCardEntryVC* _Nullable)getCardEntryVC:(AFPChargeInput* _Nonnull)params
                    nextWithCompletionBlock:(chargeNextWithCompletionBlock_t _Nullable)next;

AFPCardEntryVC

If you use getCardEntryVC:next: to instantiate your AFPCardEntryVC instance, you must call the finish function on your AFPCardEntryVC instance after your backend’s POST to the charges endpoint to notify the SDK about the success or failure of your backend’s POST.

If you use getCardEntryVC:nextWithCompletionBlock: to instantiate your AFPCardEntryVC instance, you must call the nextWithCompletionBlock reverse callback function after your backend’s POST to the charges endpoint to notify the SDK about the success or failure of your backend’s POST.

-(void)finish:(BOOL)success;

Example

// 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)

Screen highlights

  1. The card number, expiration, and CVV fields are for manual card entry.
  2. Info and error messages give information about card reader, input validation, and other errors.
  3. For manual entry, the payment token is generated and then sent to the return block of the AffiniPaySDK.getCardEntryVC method as part of an AFPChargeResult object after this button is tapped. The button is disabled if there are any input validation errors.

Signature (optional)

The AFPSignatureVC view controller allows the user to sign an AffiniPay Payment Gateway charge.

Input

The input will be passed as an AFPSignatureParams object with the following members:

ParameterTypeDescription
amountstringThe requested charge amount in US cents, unformatted. For example, to charge $2.46, you should submit 246.
accountNamestringThe name of the account that is being paid. This name will be displayed in the Signature view.

Output

The output will be returned as an AFPSignatureResult object with the following member:

ParameterTypeDescription
signaturestringThe signature of an authorized business representative. Uses default jQuery.signaturePad JSON format. Example: “[{“lx”:5,”ly”:51,”mx”:5,”my”:50}, {“lx”:5,”ly”:49,”mx”:5,”my”:51}]”

Interface

AffiniPaySDK

typedef void(^signatureNextWithCompletionBlock_t)(AFPSignatureResult* _Nullable result, boolBlock_t _Nullable doneBlock);
typedef void(^signatureNextBlock_t)(AFPSignatureResult* _Nullable result);

+ (AFPSignatureVC* _Nullable)getSignatureVC:(AFPSignatureInput* _Nonnull)params
                    nextWithCompletionBlock:(signatureNextWithCompletionBlock_t _Nullable)next;

+ (AFPSignatureVC* _Nullable)getSignatureVC:(AFPSignatureInput* _Nonnull)params
                                       next:(signatureNextBlock_t _Nullable)next;

AFPSignatureVC

If you use getSignatureVC:next: to instantiate your AFPSignatureVC instance, you must call the finish function on your AFPCardEntryVC instance after your backend’s POST to the signature endpoint to notify the SDK about the success or failure of your backend’s POST.

If you use getSignatureVC:nextWithCompletionBlock: to instantiate your AFPSignatureVC instance, you must call the nextWithCompletionBlock reverse callback function after your backend’s POST to the signature endpoint to notify the SDK about the success or failure of your backend’s POST.

-(void)finish:(BOOL)success;

Example

// 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)

Screen highlights

  1. The display name and formatted payment amount are passed in as part of the SignatureParams object.
  2. The touchable signature area.
  3. After the Done button is tapped, the raw coordinates of the signature are passed to the onSignatureReceived callback method to be saved in any format.