Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] ApplePayContextDelegate completions aren't sendable #4324

Open
blsage opened this issue Dec 3, 2024 · 5 comments
Open

[BUG] ApplePayContextDelegate completions aren't sendable #4324

blsage opened this issue Dec 3, 2024 · 5 comments
Labels
kind:bug triaged Issue has been reviewed by Stripe and is being tracked internally

Comments

@blsage
Copy link

blsage commented Dec 3, 2024

Summary

When you try to await your client secret within your applePayContext delegate function, you receive an error regarding Sendable:

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure; this is an error in the Swift 6 language model
Closure captures 'completion' which is accessible to code in the current task

Code to reproduce

    func applePayContext(
        _ context: STPApplePayContext,
        didCreatePaymentMethod paymentMethod: StripeAPI.PaymentMethod,
        paymentInformation: PKPayment,
        completion: @escaping STPIntentClientSecretCompletionBlock
    ) {
        let contribution = self.contribution
        Task {
            do {
                let clientSecret = try await contribution.clientSecret
                completion(clientSecret, nil) // <- Here
            } catch {
                completion(nil, error)
            }
        }
    }

iOS version

18.1.1

Installation method

SPM

SDK version

Stripe 24.1.0

@blsage blsage added the kind:bug label Dec 3, 2024
@tjclawson-stripe
Copy link

Hi @blsage thanks for reporting, we'll look into this

@tjclawson-stripe tjclawson-stripe added the triaged Issue has been reviewed by Stripe and is being tracked internally label Dec 6, 2024
@porter-stripe
Copy link
Collaborator

HI @blsage, can you try to call the completion handler on the MainActor? Maybe something like this

func applePayContext(
    _ context: STPApplePayContext,
    didCreatePaymentMethod paymentMethod: StripeAPI.PaymentMethod,
    paymentInformation: PKPayment,
    completion: @escaping STPIntentClientSecretCompletionBlock
) {
    let contribution = self.contribution
    Task {
        do {
            let clientSecret = try await contribution.clientSecret
            
            // Switch explicitly to the main actor
            await MainActor.run {
                completion(clientSecret, nil)
            }
        } catch {
            // Switch to the main actor for completion as well
            await MainActor.run {
                completion(nil, error)
            }
        }
    }
}

@blsage
Copy link
Author

blsage commented Dec 17, 2024

Tried all variations of that. The fundamental problem is that you need to make the completion be sendable or you can't send it to the main actor.

@blsage
Copy link
Author

blsage commented Dec 17, 2024

But maybe it's best to triage this issue until you migrate the whole API to async/await and swift 6? Seems a bit like trying to fit a square peg into a round hole.

@blsage
Copy link
Author

blsage commented Dec 17, 2024

My ultimate solution was to create a sendable wrapper class and initialize it with the completion as a let parameter. Very hacky but removed the warnings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug triaged Issue has been reviewed by Stripe and is being tracked internally
Projects
None yet
Development

No branches or pull requests

3 participants