Apple Pay Integration

Apple Pay Configuration


Please repeat actions below for Staging and Production environments separately.

To decrypt Apple Pay tokens, you must complete a certificate exchange:

  1. Gateway Initiates: Contact the [email protected] to generate a Certificate Signing Request (CSR) file.
  2. Merchant Signs: Upload this CSR to your Apple Developer Account under "Merchant IDs". Apple will issue a Payment Processing Certificate.
  3. Create apple merchant ID and provide it back to the [email protected] along with the newly created certificate https://developer.apple.com/account/resources/identifiers/list/merchant
  4. Make sure your xcode project is using the apple merchant id and its used to initialize our SDK
  5. You will need 2 CSR files, for sandbox and production, then you will create 2 apple merchant ids and bring the IDs to us

Integrate iOS SDK Apple Pay button

ViewModel Implementation

import SwiftUI
import PayablMerchant
import Combine
internal import PassKit

class DemoCartViewModel: ObservableObject {
    var pblApplePayLate: PBLApplePay?
    @Published var pblApplePayLateLoaded: Bool = false
    @Published var showToast: Bool = false
    @Published var toastMessage: String = ""

    var configuration: PBLConfiguration?
    
    let backendCheckoutUrl = URL(string: "backend_endpoint/payment_page")!  // In your server, this API should call mobile/init API

    func prepareOrder() async -> PBLConfiguration? {
        var request = URLRequest(url: backendCheckoutUrl)
        request.httpMethod = "POST"
        await withCheckedContinuation { [weak self] continuation in
            let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in
                guard let data = data,
                      let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
                else { return }
                let sessionId = json["sessionId"]
                let transactionId = json["transactionId"]
                let ephemeralKey = json["empheralKey"]
                
                self?.configuration = PBLConfiguration(
                    sessionId: sessionId as! String,
                    ephemeralKey: ephemeralKey as! String,
                    customerId: "",
                    environment: .sandbox,
                    transactionId: transactionId as! Int,
                    appleMerchantId: "merchant.payabl.isdk"  // Apple merchant id registered in developer.apple.com
                )
                continuation.resume()
            })
        }
        
        return configuration
        // Note: Task resume is implied in context or managed by wrapper
    }

    func prepareApplePayLate() async -> PBLConfiguration? {
        guard let pblConfig = await prepareOrder() else { return nil }
        Task { @MainActor in
            pblApplePayLateLoaded = true
        }
        return pblConfig
    }
}

extension DemoCartViewModel: PBLApplePayTapDelegate {
    func applePayTapped(onLoadSessionCompleted: @escaping (PBLConfiguration) -> Void) {
        Task {
            guard let config = await prepareApplePayLate() else { return }
            onLoadSessionCompleted(config)
        }
    }
  
    func applePayCompleted(result: PBLPaymentResult) {
        showToast = true
        switch result {
        case .completed:
            toastMessage = "Transaction Completed"
        default:
            toastMessage = "Transaction failed"
        }
        print(result)
    }
}

extension DemoCartViewModel: PBLErrorDelegate {
    func errorOccured(error: any Error) {
        print("error from sdk: ", error)
    }
}

SwiftUI View

 struct ContentView: View {
    let cartVM = DemoCartViewModel()
    var body: some View {
        VStack {
            if cartVM.pblApplePayLateLoaded {
                cartVM.pblApplePayLate?.button.frame(maxWidth: .infinity)
            }
        }
        .foregroundStyle(.white)
        .background(.black)
        .clipShape(RoundedRectangle(cornerRadius: 10))
        .padding()
        .onAppear {
            cartVM.pblApplePayLate = PBLApplePay(style: .whiteOutline, delegate: cartVM, errorDelegate: cartVM)
            cartVM.pblApplePayLateLoaded = true
        }
    }
}

Payment button styles

We support all natively supported apple pay buttons styles.

  • case white: A white button with black lettering.
  • case whiteOutline: A white button with black lettering and a black outline.
  • case black: A black button with white lettering.
  • case automatic: A button that automatically changes its appearance when the user switches between Light Mode and Dark Mode.