Getting Started

Getting Started with VGS Collect iOS SDK

Before you start, you can check the VGSCollectSDK GitHub Page, download the Demo Application, or browse the SDK Reference.

How to Integrate the SDK

Quickstart from Dashboard

Ensure your organization is registered at VGS Dashboard. A Sandbox Vault will be pre-created for you. Use your VGS Dashboard to start collecting data. If you haven't registered an organization yet, check the Quick Integration guides. Then, follow the VGSCollectSDK integration guide below.

Integrate VGSCollectSDK into Your iOS Project

Step 1: Install the SDK

VGSCollectSDK is distributed through Swift Package Manager and CocoaPods. Additionally, an XCFramework (distributed as VGSCollectSDK.xcframework.zip) is available via GitHub releases.

Integrate with Swift Package Manager

To use Swift Package Manager, add the dependency https://github.com/verygoodsecurity/vgs-collect-ios.git in Xcode and choose the exact version. Then, select VGSCollectSDK and, optionally, other packages provided with VGSCollectSDK. Follow the official Apple SPM guide instructions for more details.

Integrate with CocoaPods

Install the latest version of CocoaPods. Open Terminal and run the command:

sudo gem install cocoapods

If you don't have an existing Podfile in your project, navigate to your project folder and run the following command to create one:

pod init

Then, open the file in Xcode for editing:

open -a Xcode Podfile

Add the VGSCollectSDK pod to your Podfile inside your project folder:

target 'MyApp' do
  use_frameworks!

  # Add VGSCollectSDK pod here
  pod 'VGSCollectSDK'

end

Return to your Terminal window and run the following command to install VGSCollectSDK:

pod install

From now on, open your project in Xcode using the <your-app>.xcworkspace file instead of the .xcodeproj file.

Update Pods (Optional)

If you previously installed VGSCollectSDK, you might need to update the SDK to the latest version. To do so, run the following command in Terminal:

pod update

Integrate with XCFramework

XCFramework integration is a separate integration method. An XCFramework is attached to each GitHub release as VGSCollectSDK.xcframework.zip. Only the Core SDK module is supported in the XCFramework distribution. To validate the XCFramework checksum, run in Terminal shasum -a 256 VGSCollectSDK.xcframework.zip and compare it with the value provided in the VGSCollectSDK-checksum.txt file in the repository.

Next

Follow the integration guide to see an example of how to create a simple form for collecting credit card data and sending it to your Vault.

Step 2: Configure Your App

Import the VGSCollectSDK framework and initialize a VGSCollect instance in your app. When initializing VGSCollect, set your Vault id and Environment type:

import UIKit
import VGSCollectSDK

class ViewController: UIViewController {

  /// Initialize VGSCollect instance
  var vgsCollect = VGSCollect(id: "<VAULT_ID>", environment: <ENVIRONMENT>)

  // ...
}
  • You can have multiple VGSCollect instances; each will work independently with its own configured fields. - All VGSCollect instances can be configured differently.\

The integration process consists of two steps: configuring VGS Collect UI components and sending data to VGS.

Configure UI Components

Create UI Form

Add VGS Collect UI components to your view and set up the layout. More information about VGS Collect UI components is described here.

import UIKit
import VGSCollectSDK

class ViewController: UIViewController {

    /// Initialize VGSCollect instance
    var vgsCollect = VGSCollect(id: "<VAULT_ID>", environment: <ENVIRONMENT>)

    /// VGS UI components
    var cardNumberField = VGSCardTextField()
    var cardHolderNameField = VGSTextField()
    var expCardDateField = VGSTextField()
    var cvcField = VGSTextField()

    /// Native UI components
    lazy var sendButton: UIButton = {
      let button = UIButton()
      button.layer.cornerRadius = 4
      button.backgroundColor = .systemBlue
      button.setTitle("Send", for: .normal)
      button.addTarget(self, action: #selector(sendData), for: .touchDown)
      return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupLayout()
        setupFieldsConfiguration()
    }

    /// Create a UI form for collecting credit card data
    func setupLayout() {
        let stackView = UIStackView(arrangedSubviews: [cardHolderNameField, cardNumberField, expCardDateField, cvcField, sendButton])
        stackView.axis = .vertical
        stackView.spacing = 8
        stackView.distribution = .fillEqually
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        NSLayoutConstraint.activate([
            stackView.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: 2),
            view.rightAnchor.constraint(equalToSystemSpacingAfter: stackView.rightAnchor, multiplier: 2),
            stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 120),
            stackView.heightAnchor.constraint(equalToConstant: 250)
        ])
    }

    func setupFieldsConfiguration() {}

    @objc
    func sendData() {}
}

Setup VGS Collect Fields

Each VGSTextField should be configured with VGSConfiguration. For more details on field configuration, see here.

//...

func setupFieldsConfiguration() {

    /// Create card number field configuration
    let cardConfiguration = VGSConfiguration(collector: vgsCollect, fieldName: "card_number")
    cardConfiguration.type = .cardNumber
    cardConfiguration.isRequiredValidOnly = true

    /// Set up configuration for the card number field
    cardNumberField.configuration = cardConfiguration
    cardNumberField.placeholder = "Card Number"

    /// Configure card holder name field
    let nameConfiguration = VGSConfiguration(collector: vgsCollect, fieldName: "card_cardHolderName")
    nameConfiguration.type = .cardHolderName
    cardHolderNameField.configuration = nameConfiguration
    cardHolderNameField.placeholder = "CardHolder Name"

    /// Configure card expiration date field
    let expDateConfiguration = VGSConfiguration(collector: vgsCollect, fieldName: "card_expirationDate")
    expDateConfiguration.type = .expDate
    expCardDateField.configuration = expDateConfiguration
    expCardDateField.placeholder = "Exp Date"

    /// Configure card CVC field
    let cvcConfiguration = VGSConfiguration(collector: vgsCollect, fieldName: "card_cvc")
    cvcConfiguration.type = .cvc
    cvcField.configuration = cvcConfiguration
    cvcField.placeholder = "CVC"
    cvcField.isSecureTextEntry = true

    vgsCollect.textFields.forEach { textField in
      textField.font = UIFont.systemFont(ofSize: 22)
      textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
      textField.textColor = .darkGray
      textField.textAlignment = .natural
      textField.tintColor = .lightGray
    }
}

// ...

Observe VGSTextField States

You can observe the state of VGSTextField during user interactions. Read more about observing states here.

//...
override func viewDidLoad() {
    super.viewDidLoad()

    setupLayout()
    setupFieldsConfiguration()

    /// Observing text fields
    vgsCollect.observeStates = { textFields in
        textFields.forEach { textField in
            print(textField.state.description)

            /// VGSCardState - extended state for VGSCardTextField
            if let cardState = textField.state as? VGSCardState {
                print(cardState.cardBrand.stringValue)
            }
        }
    }
}
//...

Securely Collecting and Sending Information

Use vgsCollect.sendData(_:) to collect data from VGS Collect UI components and securely send it to your Vault. More details on sending data to your Vault can be found here.

// ...
@objc
func sendData() {

    /// Check if text fields are valid
    vgsCollect.textFields.forEach { textField in
        textField.borderColor = textField.state.isValid ? .lightGray : .red
    }

    /// Additional information will be sent along with all sensitive data from VGSCollect fields
    var extraData = [String: Any]()
    extraData["customKey"] = "Custom Value"

    vgsCollect.sendData(path: "/post", extraData: extraData) { response in
        switch response {
          case .success(_, let data, _):
            if let data = data, let jsonData = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
              print(String(data: try! JSONSerialization.data(withJSONObject: jsonData["json"]!, options: .prettyPrinted), encoding: .utf8)!)
            }
            return
          case .failure(let code, _, _, let error):
            switch code {
            case 400..<499:
               // Wrong request. This can also happen when your routes are not set up yet or your <VAULT_ID> is incorrect
               print("Wrong Request Error: \(code)")
            case VGSErrorType.inputDataIsNotValid.rawValue:
              if let error = error as? VGSError {
                print("Input data is not valid. Details:\n \(error)")
              }
            default:
              print("Something went wrong. Code: \(code)")
            }
          return
        }
    }
}

Next Steps

Last updated