Integrating Pay by card page

Pay by card page supports paying with debit/credit cards supported by 3ds


Implementation

class CartViewModel: ObservableObject {
  @Published var isLoading = false
  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"
      return 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"]
            return continuation.resume(
              returning: PBLConfiguration(
                sessionId: sessionId as! String,
                ephemeralKey: ephemeralKey as! String,
                customerId: "[email protected]",
                environment: .sandbox,
                transactionId: transactionId as! Int,
                appleMerchantId: "merchant.payabl.isdk"  // Apple merchant id registered in developer.apple.com
              )
            )
          })
        task.resume()
      }
  }
}
extension CartViewModel: PBLPayByCardDelegate {
  func payByCardPageCompleted(result: PBLPaymentResult) {
    print(result)
  }
  
  func payByCardPageTapped(onLoadSessionCompleted: @escaping (PBLConfiguration) -> Void) {
    Task {
      guard let config = await prepareOrder() else { return }
      onLoadSessionCompleted(config)
    }
  }
}
extension CartViewModel: PBLErrorDelegate {
  func errorOccured(error: any Error) {
    print("error from sdk: ", error)
  }
}


struct ContentView: View {
    @StateObject var cartVM = CartViewModel()
    var body: some View {
        VStack {
          PBLPayByCardButton(delegate: cartVM, errorDelegate: cartVM) {
            ZStack {
              Text("Pay by card")
                .foregroundStyle(.white)
                .font(.body)
                .frame(maxWidth: .infinity, minHeight: 45)
            }
          }
    }
}

Test Scenarios (Pay by Card)

Here are the comprehensive test scenarios for Pay by Card using the provided test card numbers. Use Sandbox environment (PBLEnvironment.SANDBOX) for all tests.

Test Card Details

  • Expiry Date: Any future date (MM/YY later than current date, e.g., 12/27)
  • CVV/CVC: Any 3 digits (e.g., 123)

Success Scenarios

Card NetworkCard NumberExpected ResultNotes
Mastercard5232050000010003PBLPaymentResult.CompletedSuccessful authorization
VISA4149011500000147PBLPaymentResult.CompletedSuccessful authorization

Decline Scenarios

Card NetworkCard NumberExpected ResultError CodeError Meaning
VISA4024007119078466PBLPaymentResult.Failed.Error51Insufficient funds
VISA4532904789286871PBLPaymentResult.Failed.Error41Lost card / Do Not Honor