Pay Using Card Information

🚧

Ensure your card method connection is set to Server to Server in the MoneyHash dashboard.

Using your account Public API Key on the MoneyHashSDK class instance, you can access the functionality to collect card data and process payments.


Initialize MoneyHashSDK

Before starting, initialize the MoneyHash SDK with your Public API Key:

import MoneyHashSDK

let moneyHashSDK = MoneyHashSDKBuilder()
    .setPublicKey("<account_public_api_key>")
    .build()

Replace "<account_public_api_key>" with your actual Public API Key from MoneyHash.


Collect Card Data

Once the card form is set up (you can follow the steps here), you can collect card data using the collect() method from the CardForm instance:

import MoneyHashSDK
import Foundation

class CardFormViewModel: ObservableObject {
    @Published var cardForm: CardForm? // Assume this is set up as per the linked documentation

    func collectCardData() async throws -> VaultData? {
        do {
            return try await cardForm?.collect()
        } catch {
            print("Error collecting card data: \(error)")
            throw error
        }
    }
}

Note: Make sure the card form is properly set up and rendered before attempting to collect card data.


Pay

Once you've collected the card data, you can process the payment using the pay() method:

import Foundation

class CardFormViewModel: ObservableObject {
    @Published var cardForm: CardForm? // Assume this is set up as per the linked documentation

    func processPayment(intentId: String, saveCard: Bool, billingData: [String: String]?, shippingData: [String: String]?) async throws {
        do {
            guard let cardData = try await collectCardData() else { return }

            let intentDetails = try await cardForm?.pay(
                intentId: intentId,
                cardData: cardData,
                saveCard: saveCard,
                billingData: billingData,
                shippingData: shippingData
            )

            print("Payment successful: \(String(describing: intentDetails))")
        } catch {
            print("Payment failed: \(error)")
            throw error
        }
    }
}

Here, the pay() method processes the payment using the provided card data, intent ID, and optional billing/shipping data for reference look at the basics docs.

📘

Note: saveCard

Passing saveCard: true will allow MoneyHash to tokenize and save the card for future use. Make sure your intent is created with "allow_tokenize_card": true for tokenization to work.


Complete Example

Here’s a complete SwiftUI-based example that integrates the steps for collecting card data and processing payments:

import SwiftUI
import MoneyHashSDK

@available(iOS 15.0, *)
class CardFormViewModel: ObservableObject {
    @Published var cardForm: CardForm?
    
    init() {
        setupCardForm()
    }
    
    private func setupCardForm() {
        self.cardForm = CardFormBuilder()
            .setCardNumberField { [weak self] state in
                print("Card Number Field State: \(state)")
            }
            .setCVVField { [weak self] state in
                print("CVV Field State: \(state)")
            }
            .setCardHolderNameField { [weak self] state in
                print("Card Holder Name Field State: \(state)")
            }
            .setExpireMonthField { [weak self] state in
                print("Expire Month Field State: \(state)")
            }
            .setExpireYearField { [weak self] state in
                print("Expire Year Field State: \(state)")
            }
            .setCardBrandChangeHandler { [weak self] brand in
                print("Card Brand Changed: \(brand)")
            }.build()
    }
    func handlePayment(intentId: String) async {
        do {
            guard let cardData = try await collectCardData() else { return }

            let intentDetails = try await cardForm?.pay(
                intentId: intentId,
                cardData: cardData,
                saveCard: true, // Set to true to save the card (optional)
                billingData: ["address": "123 Main St", "city": "New York"], // Optional
                shippingData: ["address": "456 Elm St", "city": "Boston"]   // Optional
            )

            print("Payment Successful: \(String(describing: intentDetails))")
        } catch {
            print("Payment Error: \(error)")
        }
    }

    private func collectCardData() async throws -> VaultData? {
        return try await cardForm?.collect()
    }
}

@available(iOS 15.0, *)
struct CardFormView: View {
    @StateObject var viewModel = CardFormViewModel()

    var body: some View {
        VStack(spacing: 16) {
            SecureTextField(cardFormCollector: viewModel.cardForm!, type: .cardHolderName) {
                Text("Cardholder Name")
                    .foregroundColor(.gray)
            }
            .textFieldStyle()

            SecureTextField(cardFormCollector: viewModel.cardForm!, type: .cardNumber) {
                Text("Card Number")
                    .foregroundColor(.gray)
            }
            .textFieldStyle()

            HStack(spacing: 8) {
                SecureTextField(cardFormCollector: viewModel.cardForm!, type: .expireMonth) {
                    Text("MM")
                        .foregroundColor(.gray)
                }
                .textFieldStyle()

                SecureTextField(cardFormCollector: viewModel.cardForm!, type: .expireYear) {
                    Text("YY")
                        .foregroundColor(.gray)
                }
                .textFieldStyle()

                SecureTextField(cardFormCollector: viewModel.cardForm!, type: .cvv) {
                    Text("CVV")
                        .foregroundColor(.gray)
                }
                .textFieldStyle()
            }

            Button("Pay") {
                Task {
                    await viewModel.handlePayment(intentId: "<intent_id>")
                }
            }
        }
        .padding()
    }
}

@available(iOS 15.0, *)
extension View {
    func textFieldStyle() -> some View {
        self
            .padding()
            .background(Color(UIColor.systemGray6))
            .cornerRadius(8)
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(Color(UIColor.separator), lineWidth: 1)
            )
    }
}