Reputation: 5374
I'm trying to implement Stripe in my SwiftUI app using the STPApplePayContextDelegate
.
I have created a class that conforms to this delegate according to this documentation but no luck. I get this error: // Type of expression is ambiguous without more context
in this line let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: self)
What am I doing wrong here?
struct PaymentButtonController : UIViewControllerRepresentable {
class Coordinator : NSObject, STPApplePayContextDelegate {
var vc : UIViewController?
@objc func buttonPressed() {
let merchantIdentifier = "merchant.com.your_app_name"
let paymentRequest = StripeAPI.paymentRequest(withMerchantIdentifier: merchantIdentifier, country: "US", currency: "USD")
// Configure the line items on the payment request
paymentRequest.paymentSummaryItems = [
// The final line should represent your company;
// it'll be prepended with the word "Pay" (i.e. "Pay iHats, Inc $50")
PKPaymentSummaryItem(label: "iHats, Inc", amount: 50.00),
]
// Initialize an STPApplePayContext instance
if let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: self) {
// Present Apple Pay payment sheet
if let vc = vc {
applePayContext.presentApplePay(on: vc)
}
} else {
// There is a problem with your Apple Pay configuration
}
}
func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
let clientSecret = "..."
print("ENDLICH")
// Retrieve the PaymentIntent client secret from your backend (see Server-side step above)
// Call the completion block with the client secret or an error
completion(clientSecret, nil);
}
func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
print("ENDLICH")
switch status {
case .success:
// Payment succeeded, show a receipt view
break
case .error:
// Payment failed, show the error
break
case .userCancellation:
// User cancelled the payment
break
@unknown default:
fatalError()
}
}
}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
func makeUIViewController(context: Context) -> UIViewController {
let button = PKPaymentButton(paymentButtonType: .plain, paymentButtonStyle: .automatic)
button.addTarget(context.coordinator, action: #selector(context.coordinator.buttonPressed), for: .touchUpInside)
let vc = UIViewController()
context.coordinator.vc = vc
vc.view.addSubview(button)
return vc
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
Upvotes: 1
Views: 1579
Reputation: 52565
The function you're calling (presentApplePay
) expects a UIViewController
as its input, but you're passing self
, which is your ApplePayContext
, defined above as NSObject, ObservableObject, STPApplePayContextDelegate
.
The challenge that you're going to face is getting a UIViewController
context to pass to it, as you won't have any references to a UIViewController
in pure SwiftUI.
You have a few possible solutions:
presentApplePay
UIViewControllerRepresentable
to get a UIViewController you can embed into your SwiftUI view and past as the argument (https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable)Update: In response your request for code, here's something to start with. Note that not everything is hooked up yet -- you'll need to connect the buttonPressed method, add layout constraints to the button, etc, but it gives you a way to figure out how to get a reference to a UIViewController
struct PaymentButtonController : UIViewControllerRepresentable {
class Coordinator : NSObject {
var vc : UIViewController?
@objc func buttonPressed() {
print("Button with VC: \(vc)")
}
}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
func makeUIViewController(context: Context) -> UIViewController {
let button = PKPaymentButton()
button.addTarget(context.coordinator, action: #selector(context.coordinator.buttonPressed), for: .touchUpInside)
let vc = UIViewController()
context.coordinator.vc = vc
vc.view.addSubview(button)
return vc
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
Embed in your view by using this in your SwiftUI code:
PaymentButtonController()
Upvotes: 2