1

I am trying to implement Stripe on SwiftUI. After the user registers, I would like them to add a payment method to their account without making an actual payment. I have successfully created the STPPaymentCardTextField using a UIViewRepresentable. However, I'm having trouble with the STPAuthenticationContext. I'm not too sure how to go about this as the examples on the Stripe documentation are all for UIKit. Here is what I have so far:

struct StripePaymentCardTextField: UIViewRepresentable {

@Binding var cardParams: STPPaymentMethodCardParams
@Binding var isValid: Bool

func makeUIView(context: Context) -> STPPaymentCardTextField {
    let input = STPPaymentCardTextField()
    input.borderWidth = 0
    input.backgroundColor = UIColor(ColorManager.brandGray)
    input.cornerRadius = 10
    input.becomeFirstResponder()
    input.delegate = context.coordinator
    
    return input
}

func makeCoordinator() -> StripePaymentCardTextField.Coordinator { Coordinator(self) }

func updateUIView(_ view: STPPaymentCardTextField, context: Context) { }

class Coordinator: NSObject, STPPaymentCardTextFieldDelegate, STPAuthenticationContext {
    
    func authenticationPresentingViewController() -> UIViewController {
        return self
    }
    
    var parent: StripePaymentCardTextField
    
    init(_ textField: StripePaymentCardTextField) {
        parent = textField
    }
    
    func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {
        parent.cardParams = textField.cardParams
        parent.isValid = textField.isValid
    }
    
    func createPaymentMethod(setupIntentClientSecret: String) {
        let paymentMethodParams = STPPaymentMethodParams(card: parent.cardParams, billingDetails: nil, metadata: nil)
        let setupIntentParams = STPSetupIntentConfirmParams(clientSecret: setupIntentClientSecret)
        
        setupIntentParams.paymentMethodParams = paymentMethodParams
        
        let paymentHandler = STPPaymentHandler.shared()
        paymentHandler.confirmSetupIntent(setupIntentParams, with: self) { (status, setupIntent, error) in
            switch (status) {
            case .failed:
                // Setup failed
                break
            case .canceled:
                // Setup canceled
                break
            case .succeeded:
                // Setup succeeded
                break
            @unknown default:
                fatalError()
                break
            }
        }
    }
}

}

On the following lines of code, I am receiving the error "Cannot convert return expression of type 'StripePaymentCardTextField.Coordinator' to return type 'UIViewController'"

func authenticationPresentingViewController() -> UIViewController {
    return self
}

Any help would be very much appreciated! :)

devOP1
  • 295
  • 3
  • 13
  • Stripe has a detailed documentation page showing how to collect card details without taking a payment upfront: https://stripe.com/docs/payments/save-and-reuse?platform=ios – koopajah May 15 '21 at 00:21
  • @koopajah thats exactly what i followed. Im working with swiftui and came across a problem. Please read the question again. – devOP1 May 15 '21 at 00:25
  • Sorry I did misread your code and I see you are already following that doc. The main example I know of for SwiftUI is accepting a payment: https://github.com/stripe-samples/accept-a-payment/tree/main/custom-payment-flow/client/ios-swiftui/AcceptAPayment but maybe you'll find what you need in that one? – koopajah May 15 '21 at 00:41
  • 1
    I think you want to move away from `UIViewRepresentable` specifically and move to this flow instead: https://github.com/stripe-samples/accept-a-payment/blob/main/custom-payment-flow/client/ios-swiftui/AcceptAPayment/Views/Card.swift#L22 – koopajah May 15 '21 at 00:48

0 Answers0