The ForageSDK is a Swift library for securely processing EBT payments. You can use the library to add all of the following EBT checkout operations to your iOS app:
- Store tokenized EBT card numbers for future use
- Check the balance of an EBT card
- Capture an EBT payment
- ForageSDK
You can use CocoaPods or Swift Package Manager (SPM) to install forage-ios-sdk
.
The Forage iOS SDK requires Xcode 14.1 or later and is compatible with apps targeting iOS 13 or above. Earlier Xcode versions do not support Swift packages with resources.
-
If you haven’t already, install the latest version of CocoaPods.
-
If you don’t have an existing Podfile, run the following command to create one:
pod init
- Add the following line to your
Podfile
:
pod 'ForageSDK', '~> 4.4.3'
- Run the following command
pod install
- To update to the latest version of the SDK, run:
pod repo update
pod update ForageSDK
See the step-by-step Xcode installation instructions
To use Swift Package Manager, in Xcode add the https://github.com/teamforage/forage-ios-sdk dependency and choose the Dependency Rule
as Branch and the branch enter main
.
Click on the Add Package
button. On the next screen, select the package ForageSDK
, and finish by clicking on Add Package
.
Follow the official Apple SPM guide instructions for more details.
import ForageSDK
// your code here
Initialize the ForageSDK by calling ForageSDK.setup
and passing in a ForageSDK.Config
object with a valid merchantID
and sessionToken
.
ℹ️ Note: ForageSDK.setup
must be called before initializing the Forage UI Elements.
ForageSDK.setup(
ForageSDK.Config(
merchantID: "1234567",
sessionToken: "sandbox_eyJ0eXAiOiJKV1Qi..."
)
)
ForageSDK provides two UI Elements to securely communicate with the Forage API.
A ForageElement
that securely collects the customer's EBT PAN. This field validates the PAN based on the Issuer Identification Number (IIN).
private let foragePanTextField: ForagePANTextField = {
let tf = ForagePANTextField()
tf.borderColor = .black
tf.borderWidth = 3
tf.clearButtonMode = .whileEditing
tf.cornerRadius = 4
tf.font = .systemFont(ofSize: 22)
tf.placeholder = "EBT Card Number"
return tf
}()
Forage validates an EBT Element’s input as a customer types. To notify customers of input validation errors, you'll need to conform to the ForageElementDelegate
protocol.
The focusDidChange
method is triggered when a ForageElement
gains or loses focus.
foragePanTextField.delegate = self
// signature
public protocol ForageElementDelegate: AnyObject {
func focusDidChange(_ state: ObservableState)
func textFieldDidChange(_ state: ObservableState)
}
// usage
extension ForagePanView: ForageElementDelegate {
func focusDidChange(_ state: ObservableState) {
if state.isFirstResponder { ... } // element gained focus
else { ... } // element lost focus (blurred)
}
func textFieldDidChange(_ state: ObservableState) {
// show an error message on blur if the input is invalid
if !state.isValid && !state.isFirstResponder { ... }
}
}
The ObservableState
protocol defines properties reflecting the state of a ForageElement
.
public protocol ObservableState {
/// Indicates whether the input is focused.
var isFirstResponder: Bool { get }
/// Indicates whether the input is empty.
var isEmpty: Bool { get }
/// Indicates whether all validation checks pass, excluding the the minimum length validator.
var isValid: Bool { get }
/// Indicates whether all validation checks pass and the ForageElement is ready for submission.
var isComplete: Bool { get }
}
The DerivedCardInfoProtocol
protocol defines inferred information about the ForagePANTextField
.
public protocol DerivedCardInfoProtocol {
/// The US state that issued the EBT card, derived from the Issuer Identification Number (IIN),
/// also known as BIN (Bank Identification Number).
/// The IIN is the first 6 digits of the PAN.
var usState: USState? { get }
}
This field can be accessed through the derivedCardInfo
property.
foragePanTextField.derivedCardInfo.usState
Call foragePanTextField.becomeFirstResponder()
to programmatically set focus on the ForagePANTextField
:
func becomeFirstResponder() -> Bool
Call ForageSDK.shared.tokenizeEBTCard
to tokenize a customer’s EBT card number and create a Forage PaymentMethod
.
// Signature
func tokenizeEBTCard(
foragePanTextField: ForagePANTextField,
customerID: String,
reusable: Bool?,
completion: @escaping (Result<PaymentMethodModel, Error>) -> Void
)
// Usage
ForageSDK.shared.tokenizeEBTCard(
foragePanTextField: foragePanTextField,
// NOTE: The following line is for testing purposes only and should not be used in production.
// Please replace this line with a real hashed customer ID value.
customerID: UUID.init().uuidString,
reusable: true
) { result in
// Handle result and error here
switch result {
case .success(let paymentMethod):
// Handle the PaymentMethod here (balance, card, reusable, etc.)
case .failure(let error):
if let forageError = error as? ForageError {
// handle forageError.code, forageError.httpStatusCode and forageError.message
}
}
}
A ForageElement
that securely collects the customer's EBT card PIN to perform a balance check or capture an EBT payment.
private let foragePinTextField: ForagePINTextField = {
let tf = ForagePINTextField()
tf.borderRadius = 10
tf.backgroundColor = .systemGray6
return tf
}()
Use the ForageElementDelegate
to subscribe to input validation and element focus state changes for ForagePINTextField
.
foragePinTextField.delegate = self
extension ForagePinView: ForageElementDelegate {
func focusDidChange(_ state: ObservableState) {
if state.isFirstResponder { ... }
}
func textFieldDidChange(_ state: ObservableState) {
if state.isComplete { ... }
}
}
FNS requirements for balance inquiries
FNS prohibits balance inquiries on sites and apps that offer guest checkout. Skip this section if your customers can opt for guest checkout.
If guest checkout is not an option, then it's up to you whether or not to add a balance inquiry feature. No FNS regulations apply.
Call ForageSDK.shared.checkBalance
to retrieve the balance of a customer’s EBT card.
// Signature
func checkBalance(
foragePinTextField: ForagePINTextField,
paymentMethodReference: String,
completion: @escaping (Result<BalanceModel, Error>) -> Void
)
// Usage
ForageSDK.shared.checkBalance(
foragePinTextField: foragePinTextField,
paymentMethodReference: paymentMethodReference
) { result in
// Handle result and error here
}
// Signature
func capturePayment(
foragePinTextField: ForagePINTextField,
paymentReference: String,
completion: @escaping (Result<PaymentModel, Error>) -> Void
)
// Usage
ForageSDK.shared.capturePayment(
foragePinTextField: foragePinTextField,
paymentReference: paymentReference
) { result in
// Handle result and error here
}
Call ForageSDK.shared.deferPaymentCapture
to collect a customer's EBT Card PIN before capturing a Payment
server-side.
// Signature
func deferPaymentCapture(
foragePinTextField: ForagePINTextField,
paymentReference: String,
)
foragePinTextField
: A reference to aForagePINTextField
component.paymentReference
: A unique string identifier for a previously created ForagePayment
object.
// Usage
ForageSDK.shared.deferPaymentCapture(
foragePinTextField: foragePinTextField,
paymentReference: paymentReference
) { result in
// Handle result and error here
}
The Forage iOS SDK sample application can be found here.
To get the application running:
- Clone this repo and open the
SampleForageSDK.xcodeproj
project in theSample/
directory. - Ensure that you have a valid Merchant ID for the Forage API, which can be found on the dashboard (sandbox | prod).
- Create an authentication token with
pinpad_only
scope. - Create a session token.
- Run the Sample app and provide your Merchant ID and session token on the first screen.
- Forage SDKs include built-in EBT card number validation in both sandbox and production. Use the Test EBT cards for developing against successful transactions and invalid EBT test card numbers for triggering exceptions.
- Xcode 14.1 or above
- iOS 13 or above
- Swift 5.5
- 3rd party libraries: