Overview
Collecting payments in your iOS app consists of creating an object for collecting card information in your app, tokenizing card information and payment details, and submitting the payment to Paysafe for processing.
Using the demo app
In order to test the Cards integration using the Demo app, you have to modify some constants representing the API key and the account id associated with the Card payment method.
- Open Example/LotteryTicket/LotteryTicket/Managers/PaymentManager.swift file.
- Modify apiKey string to contain your API key.
- Modify cardAccountId string to contain the account id associated with the Venmo payment method.
Set up the SDK
Configure the SDK with your Paysafe API key and environment so that it can make requests to the Payments API, such as in your SceneDelegate or AppDelegate.
import PaysafeCardPayments
// theme example
let theme = PSTheme(
backgroundColor: UIColor(red: 44/255, green: 30/255, blue: 70/255, alpha: 1.0),
borderColor: UIColor(red: 201/255, green: 201/255, blue: 201/255, alpha: 1.0),
focusedBorderColor: UIColor(red: 133/255, green: 81/255, blue: 161/255, alpha: 1.0),
textInputColor: UIColor(red: 214/255, green: 195/255, blue: 229/255, alpha: 1.0),
placeholderColor: UIColor(red: 111/255, green: 77/255, blue: 155/255, alpha: 1.0),
hintColor: UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
)
PaysafeSDK.shared.setup(
apiKey: apiKey,
environment: .test,
theme: theme
) { result in
switch result {
case .success:
print("[Paysafe SDK] initialized successfully")
case let .failure(error):
print("[Paysafe SDK] initialize failure \(error.displayMessage)")
}
}
The setup function creates and initializes the Paysafe iOS SDK. Pass the following parameters during its initialization from the application:
- The Base64-encoded version of the single-use token API key is used to authenticate with the Payment Hub REST API.
- Environment (TEST/ PRODUCTION).
- Theme (Optional, defaults to basic theme).
Create checkout page
Securely collect card information on the client with PSCardForm, a pre-defined cards component provided by the SDK that collects the card number, expiration date and CVC.
Here is an example of a checkout screen written in SwiftUI.
struct CheckoutView: View {
/// PSCardNumberInputSwiftUIView
private var cardNumberView: PSCardNumberInputSwiftUIView
/// PSCardholderNameInputSwiftUIView
private var cardholderNameView: PSCardholderNameInputSwiftUIView
/// PSCardExpiryInputSwiftUIView
private var cardExpiryView: PSCardExpiryInputSwiftUIView
/// PSCardCVVInputSwiftUIView
private var cardCVVView: PSCardCVVInputSwiftUIView
init {
cardNumberView = PSCardNumberInputSwiftUIView()
cardholderNameView = PSCardholderNameInputSwiftUIView()
cardExpiryView = PSCardExpiryInputSwiftUIView()
cardCVVView = PSCardCVVInputSwiftUIView()
}
var body: some View {
VStack(spacing: 16) {
Group {
cardNumberView
cardholderNameView
cardExpiryView
cardCVVView
}
.frame(height: 80)
}.onAppear {
// Initialize the PSCardForm object
}
}
}
Initialize the PSCardForm
.onAppear {
PSCardForm.initialize(
currencyCode: "USD",
accountId: "<accountId>",
cardNumberSwiftUIView: cardNumberView,
cardholderNameSwiftUIView: cardholderNameView,
cardExpirySwiftUIView: cardExpiryView,
cardCVVSwiftUIView: cardCVVView
) { [weak self] result in
DispatchQueue.main.async { [weak self] in
guard let self else { return }
isInitializing = false
switch result {
case let .success(cardForm):
self.cardForm = cardForm
case let .failure(error):
print("Error", "\(error.displayMessage)")
}
}
}
}
Tokenize
Configure tokenize options
/// Payment amount in minor units
let amount = totalPrice * 100
let options = PSCardTokenizeOptions(
amount: amount,
currencyCode: "USD",
transactionType: .payment,
merchantRefNum: "<merchant-ref-num>",
billingDetails: BillingDetails(
country: US,
zip: "32256",
state: "FL",
city: "Jacksonville",
street: "5335 Gate Pkwy",
nickName: "Jax Billing Address"
),
accountId: "<accountId>",
threeDS: ThreeDS(merchantUrl: "https://<merchantUrl>/path")
)
Call tokenize method
let completion: PSTokenizeBlock = { [weak self] tokenizeResult in
DispatchQueue.main.async { [weak self] in
guard let self else { return }
isloading = false
switch tokenizeResult {
case let .success(paymentHandleToken):
print(paymentHandleToken)
case let .failure(error):
print("Error", "\(error.displayMessage)")
}
}
}
cardForm.tokenize(
using: options,
completion: completion
)
Complete payment with PaymentHandleToken
Send the payment handle token received from PSCardForm.tokenize() to your merchant server, where the standard Payments API payment endpoint can be used to make payment.
curl -location -request POST 'https://api.test.paysafe.com/paymenthub/v1/payments' \
- u apiKeyId:apiKeyPassword
}'
- header 'Content-Type: application/json' \
- data-raw '{
"merchantRefNum": "payment-token-demo-1",
"amount": 5000,
"currencyCode": "USD",
"settleWithAuth": true,
"paymentHandleToken": "CARDS PAYMENT TOKEN RECEIVED FROM CLIENT BROWSER"
}'
Test the integration
By this point you should have a basic card integration that collects card details and makes a payment.
There are several test cards you can use in test mode to make sure this integration is ready. Use them with any CVC, postal code, and future expiration date.
Card number | Description |
---|---|
4835641100110000 | Succeeds and immediately processes the payment. |
5100400000000000 | Requires authentication. Paysafe will trigger a modal asking for the customer to authenticate. |
5573560100022200 | Always fails with a decline code of insufficient funds. |
For the full list of test cards see our guide on testing.