In-App Payments SDK

Build on iOS

Build with In-App Payments SDK on iOS to provide a secure, managed payments client.

Swift (iOS)
iOS
Save

Prerequisites

To build with In-App Payments SDK on iOS, the following must be true:

  • You have an application ID from the Square Developer Portal
  • The deployment target for your app is iOS 10.0 or newer.

Assumptions

This guide makes the following assumptions:

  • You have read the In-App Payments SDK: What It Does. guide. This is a how-to guide and does not provide an overview of the SDK functionality.
  • You have a Square Account enabled for payment processing. If you have not enabled payment processing on your account (or you are 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.
  • You are using Xcode 9+.

Step 1: Add the In-App Payments SDK to your project

Option 1: Cocoapods

Install with CocoaPods by adding the following to your Podfile:

use_frameworks!

pod "SquareInAppPaymentsSDK"

Option 2: Carthage

Install with Carthage by adding the following to your Cartfile:

github "square/in-app-payments-ios"

Option 3: Manual Installation

  1. Download and unzip the latest SquareInAppPaymentsSDK.framework.zip artifact from the Square In-App Payments Github repository release list.
  2. Add the SquareInAppPaymentsSDK framework to your project:
    1. Open the General tab for your app target in Xcode.
    2. Drag the newly downloaded SquareInAppPaymentsSDK.framework into the Embedded Binaries section.
    3. Select Copy Items if Needed and click Finish in the dialog that appears.
  3. Add an In-App Payments SDK build phase:
    1. Open the Xcode project or workspace 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}/SquareInAppPaymentsSDK.framework/setup"

Step 2: Set your Square Application ID in your app delegate

If you do not set your Square application ID before initializing the SQIPCardEntryViewController, your app will terminate with an uncaught exception.

  1. To find your Square Application ID:
    1. Open the Square Developer Portal.
    2. Create a new Square application or select an existing application.
    3. Open the Credentials setting page for the application.
    4. Copy the Application ID field from the settings page.
  2. Set the application ID by updating REPLACE_ME in the following example code to your Square Application ID:
@import SquareInAppPaymentsSDK;

- (BOOL)application:(UIApplication *)application 
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [SQIPInAppPaymentsSDK setSquareApplicationID:@"<# REPLACE_ME #>"];
    return YES;
}
import SquareInAppPaymentsSDK

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
        [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Set your Square Application ID
        SQIPInAppPaymentsSDK.squareApplicationID = "<# REPLACE_ME #>"
        return true
    }
}

Step 3: Create and display the card entry form to collect card information

Initialize a SQIPCardEntryViewController with a SQIPTheme instance and present the view controller as a modal. You can customize the appearance of the card entry form by setting SQIPTheme properties. See the Customize the payment entry form recipe for more information.

@import SquareInAppPaymentsSDK;

@interface <#YourViewController#> () <SQIPCardEntryViewControllerDelegate>
@end

@implementation <#YourViewController#>

- (void)showCardEntryForm;
{
    SQIPTheme *theme = [[SQIPTheme alloc] init];

    // Customize the card entry form
    theme.tintColor = UIColor.greenColor;
    theme.saveButtonTitle = @"Submit";

    SQIPCardEntryViewController *cardEntryForm = [[SQIPCardEntryViewController alloc] initWithTheme:theme];
    cardEntryForm.delegate = self;
    
    // The card entry form should always be displayed in a UINavigationController.
    // The card entry form can also be pushed onto an existing navigation controller.
    UINavigationController *navigationController = 
        [[UINavigationController alloc] initWithRootViewController:cardEntryForm];

    [self presentViewController:navigationController animated:YES completion:nil];
}

#pragma mark - SQIPCardEntryViewControllerDelegate

- (void)cardEntryViewController:(nonnull SQIPCardEntryViewController *)cardEntryViewController
          didCompleteWithStatus:(SQIPCardEntryCompletionStatus)status;
{
    // Implemented in a later step.
}

- (void)cardEntryViewController:(nonnull SQIPCardEntryViewController *)cardEntryViewController
           didObtainCardDetails:(nonnull SQIPCardDetails *)cardDetails
              completionHandler:(void (^_Nonnull)(NSError *_Nullable))completionHandler;

{
    // Implemented in a later step.
}
@end
import SquareInAppPaymentsSDK

extension <#YourViewController#>: SQIPCardEntryViewControllerDelegate { 
    func showCardEntryForm() {
        let theme = SQIPTheme()

        // Customize the card payment form
        theme.tintColor = .green
        theme.saveButtonTitle = "Submit"
        
        let cardEntryForm = SQIPCardEntryViewController(theme: theme)
        cardEntryForm.delegate = self
        
        // The card entry form should always be displayed in a UINavigationController.
        // The card entry form can also be pushed onto an existing navigation controller.
        let navigationController = UINavigationController(rootViewController: cardEntryForm)
        present(navigationController, animated: true, completion: nil)
    }

    // MARK: - SQIPCardEntryViewControllerDelegate

    func cardEntryViewController(_ cardEntryViewController: SQIPCardEntryViewController,
                                 didCompleteWith status: SQIPCardEntryCompletionStatus) {
        // Implemented in step 6.
    }
    
    func cardEntryViewController(_ cardEntryViewController: SQIPCardEntryViewController,
                                 didObtain cardDetails: SQIPCardDetails,
                                 completionHandler: @escaping (Error?) -> Void) {
        // Implemented in step 6.
    }
}

Step 4: Implement SQIPCardEntryViewControllerDelegate methods

In this step, you are filling out the methods that you stubbed out previously.

cardEntryViewController(_:didObtainCardDetails:completionHandler:)

  • Invoked after the user has submitted their card information. Your implementation should send the provided card details to your server to perform any additional work such as charging the card. After your server has processed the card, notify the card entry view controller of the result so it can be displayed to the user.
  • If your server processed the card with no error, call the completion handler with a single nil argument. A success animation is shown to the user, and cardEntryViewController:didCompleteWithStatus: is called, at which point you should dismiss the card entry view controller.
  • If your server returned an error while processing the card, call the completion handler with the error. Its localizedDescription is shown in the card entry view controller. The user reads the error text and can edit their card information and then re-submit.

cardEntryViewController(_:didCompleteWithStatus:)

  • Invoked when the card entry form is completed. The status parameter indicates whether card entry succeeded or was cancelled.

    Use this method to dismiss the card entry view controller and update any other app state.

#pragma mark - SQIPCardEntryViewControllerDelegate

- (void)cardEntryViewController:(nonnull SQIPCardEntryViewController *)cardEntryViewController
          didCompleteWithStatus:(SQIPCardEntryCompletionStatus)status;
{
    // Note: If you pushed the card entry form onto an existing navigation controller, 
    // use [self.navigationController popViewControllerAnimated:YES] instead
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)cardEntryViewController:(nonnull SQIPCardEntryViewController *)cardEntryViewController
           didObtainCardDetails:(nonnull SQIPCardDetails *)cardDetails
              completionHandler:(void (^_Nonnull)(NSError *_Nullable))completionHandler;

{

   // Send the card nonce to your server to charge the card or store the card on file.
   // When a response is received, call the completionHandler with `nil` to indicate success,
   // or an error to indicate failure.

    /*
    [MyAPIClient.shared chargeCardWithNonce:cardDetails.nonce
                                 completion:^(id transaction, NSError *chargeError) {
        if (chargeError) {
            completionHandler(chargeError);
        } else {
            completionHandler(nil);
        }
    }];
    */

    completionHandler(nil);
}
// MARK: - SQIPCardEntryViewControllerDelegate

func cardEntryViewController(_ cardEntryViewController: SQIPCardEntryViewController,
                             didCompleteWith status: SQIPCardEntryCompletionStatus) {
    // Note: If you pushed the card entry form onto an existing navigation controller,
    // use UINavigationController.popViewController(animated:) instead
    dismiss(animated: true, completion: nil)
}

func cardEntryViewController(_ cardEntryViewController: SQIPCardEntryViewController,
                             didObtain cardDetails: SQIPCardDetails,
                             completionHandler: @escaping (Error?) -> Void) {

   // Send the card nonce to your server to charge the card or store the card on file.
   // When a response is received, call the completionHandler with `nil` to indicate success,
   // or an error to indicate failure.

    /*
    MyAPIClient.shared.chargeCard(withNonce: cardDetails.nonce) { transaction, chargeError in

        if let chargeError = chargeError {
            completionHandler(chargeError)
        }
        else {
            completionHandler(nil)
        }
    }
    */

    completionHandler(nil)
}

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