iOS: Swift: MobilePaymentsSDK: Payments screen would not get presented for card reader swipe

Common Reasons for Payment Screen Not Appearing

  1. SDK Initialization First, verify the SDK is properly initialized. Add this before calling makeSquareTransaction:
// Add at app startup or before payments
func initializeSDK() {
    do {
        try MobilePaymentsSDK.shared.initialize(applicationLaunchOptions: nil)
        print("Square SDK initialized successfully")
    } catch {
        print("Failed to initialize Square SDK: \(error)")
    }
}
  1. Delegate Implementation Ensure your view controller properly implements PaymentManagerDelegate:
class YourViewController: UIViewController, PaymentManagerDelegate {
    // Required delegate methods
    func paymentManager(_ paymentManager: PaymentManager, didCompletePayment result: PaymentResult) {
        // Handle successful payment
    }
    
    func paymentManager(_ paymentManager: PaymentManager, didFailPayment error: Error) {
        // Handle payment failure
    }
    
    func paymentManagerDidCancel(_ paymentManager: PaymentManager) {
        // Handle payment cancellation
    }
}
  1. Modified Payment Parameters Here’s the complete makePaymentParameters function with all required fields:
func makePaymentParameters(amountMoney: Money) -> PaymentParameters {
    return PaymentParameters(
        idempotencyKey: UUID().uuidString,
        amountMoney: amountMoney,
        // Add these required parameters
        autocomplete: false,
        locationId: "YOUR_LOCATION_ID",
        customerId: nil,  // Optional
        notes: notes,     // Optional
        statementDescription: nil,  // Optional
        metadata: nil     // Optional
    )
}
  1. Updated Transaction Method Here’s the corrected makeSquareTransaction method with error handling:
func makeSquareTransaction(
    centsAmount: Int,
    notes: String,
    from viewController: UIViewController
) {
    // Verify SDK initialization
    guard MobilePaymentsSDK.shared.isInitialized else {
        print("Square SDK not initialized")
        return
    }
    
    // Verify delegate
    guard let vc = viewController as? PaymentManagerDelegate else {
        print("PaymentManagerDelegate is required")
        return
    }
    
    // Create payment parameters
    let amountMoney = Money(amount: UInt(centsAmount), currency: .USD)
    let paymentParams = makePaymentParameters(amountMoney: amountMoney)
    
    // Create prompt parameters
    let paymentPromptParameters = PromptParameters(
        mode: .default,
        additionalMethods: .all
    )
    
    // Start payment with completion handler
    DispatchQueue.main.async {
        MobilePaymentsSDK.shared.paymentManager.startPayment(
            paymentParams,
            promptParameters: paymentPromptParameters,
            from: viewController,
            delegate: vc
        ) { result in
            switch result {
            case .success:
                print("Payment screen presented successfully")
            case .failure(let error):
                print("Failed to present payment screen: \(error)")
            }
        }
    }
}

Implementation Checklist

  1. Verify Info.plist Settings
<key>NSCameraUsageDescription</key>
<string>Required for card scanning</string>
<key>NSMicrophoneUsageDescription</key>
<string>Required for tap to pay</string>
<key>NSNFCReaderUsageDescription</key>
<string>Required for tap to pay</string>
  1. Add Required Capabilities In Xcode:
  • Enable “Near Field Communication Tag Reading” capability
  • Enable “Payment Processing” capability
  1. Usage Example
class YourViewController: UIViewController, PaymentManagerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        initializeSDK()
    }
    
    @IBAction func onPayButtonTapped(_ sender: Any) {
        makeSquareTransaction(
            centsAmount: 1000, // $10.00
            notes: "Test payment",
            from: self
        )
    }
    
    // Delegate methods implementation
    func paymentManager(_ paymentManager: PaymentManager, didCompletePayment result: PaymentResult) {
        print("Payment completed: \(result)")
    }
    
    func paymentManager(_ paymentManager: PaymentManager, didFailPayment error: Error) {
        print("Payment failed: \(error)")
    }
    
    func paymentManagerDidCancel(_ paymentManager: PaymentManager) {
        print("Payment cancelled")
    }
}

Debugging Steps

  1. Add logging to track the flow:
print("SDK Initialized: \(MobilePaymentsSDK.shared.isInitialized)")
print("Payment Parameters: \(paymentParams)")
print("View Controller: \(viewController)")
  1. Check for any console errors or warnings
  2. Verify you’re calling this on the main thread