#commander-apollo-z_api

1 messages Β· Page 1 of 1 (latest)

bleak waspBOT
#

πŸ‘‹ Welcome to your new thread!

⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

πŸ”— This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1354535151161577482

πŸ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

frigid doveBOT
viscid stream
#

Hi πŸ‘‹ can we start by aligning on what you're doing, because if you're using the Payment Sheet then I'm surprised to hear you're also using an in-app browser for any part of the payment process.

wicked pagoda
#

Hi! I'm using the payment sheet, correct. With the iDEAL payment method. This opens a browser view inside the app where I can either confirm or decline the payment.

viscid stream
#

Hm, okay. And that page is being opened automatically by the Payment Sheet? Or are you directing your customers to that page yourself?

When you say you open this with Safari, is that using the buttom near the bottom of that view to open that same page in Safari?

wicked pagoda
#

The Payment Sheet is opening it automatically. And yes, it works when I authorize it that way. But when I click the Safari icon, the page opens in Safari, I can still confirm, and the payment goes through. But the returnURL is not being handled by the function anymore. The Payment Sheet still shows me that I should pay. When I do, I get the error that the paymentIntent is already being used, and the payment paid.

#

I would expect that once I return back to the app through the returnURL, that the PaymentSheet would react the same as when using the in app browser.

viscid stream
#

Hm, I'm not sure that is expected to behave the same, let me see if I can find a teammte more familiar with these iOS flows.

wicked pagoda
#

Okay thanks 😊

bleak waspBOT
lunar tusk
#

πŸ‘‹ not deeply familiar here with iOS but have a bit of experience -- our mobile dev expert isn't available right now unfortunately.

That said, when you "click the Safari" icon can you clarify exactly what you mean by that?

wicked pagoda
#

Hi! In the second image I sent, the screenshot from the in app browser, there is a small Safari icon on the bottom right corner, next to the sharing icon. When you click this icon, the page is being opened in a regular (not in app) Safari window (or whichever browser is set as the system default).

lunar tusk
#

Gotcha

#

And are you using Flow Controller here?

#

That flow specifically

wicked pagoda
lunar tusk
#

The FlowController is one variation of using PaymentSheet

#

Can you show me your relevant client-side code snippets here?

wicked pagoda
#

Here is the UI part:

struct PaymentSheetViewSimple<Content: View>: View {
    private let paymentSheet: PaymentSheet
    private let onCompletion: (PaymentSheetResult) -> Void
    private let content: Content

    @State private var showingPaymentSheet: Bool = false
    /// Initialize a `PaymentButton` with required parameters.
    public init(
        paymentSheet: PaymentSheet,
        onCompletion: @escaping (PaymentSheetResult) -> Void,
        @ViewBuilder content: () -> Content
    ) {
        self.paymentSheet = paymentSheet
        self.onCompletion = onCompletion
        self.content = content()
    }

    var body: some View {
        content
            .paymentSheet(
                isPresented: $showingPaymentSheet,
                paymentSheet: paymentSheet,
                onCompletion: onCompletion
            )
            .onAppear {
                showingPaymentSheet = true
            }
    }
}
#

The payment model:

@Observable
public class PaymentModel {
    public init() {}

    let apiPath = "/payment-sheet"
    let returnURL = "xxxx://stripe-redirect"
    public private(set) var paymentSheet: PaymentSheet?
    public private(set) var paymentResult: PaymentSheetResult?
    public var showPaymentSheet: Bool = false

    public func preparePaymentSheet(customerId: String, orderId: String) async throws {
            let requestBody = PrepareStripePaymentRequestBodySchema(
                customerId: customerId,
                amount: 10.00,
                currency: "eur"
            )
            let responseBody = try await LambdaQuery.shared.prepareStripePayment(requestBody)

            STPAPIClient.shared.publishableKey = responseBody.publishableKey

            await MainActor.run {
                var configuration = PaymentSheet.Configuration()
                configuration.returnURL = returnURL
                configuration.merchantDisplayName = "Xxxx.xx"
                configuration.billingDetailsCollectionConfiguration.address = .never
                configuration.billingDetailsCollectionConfiguration.email = .never
                configuration.billingDetailsCollectionConfiguration.name = .never
                configuration.billingDetailsCollectionConfiguration.phone = .never

                configuration.customer = PaymentSheet.CustomerConfiguration(
                    id: responseBody.customerId,
                    ephemeralKeySecret: responseBody.ephemeralKeySecret
                )
                configuration.allowsDelayedPaymentMethods = true

                self.paymentSheet = PaymentSheet(paymentIntentClientSecret: responseBody.paymentIntentClientSecret, configuration: configuration)
                self.showPaymentSheet = true
            }
    }

    public func onPaymentCompletion(result: PaymentSheetResult) {
        self.paymentResult = result
    }
}
#

And the handling of the returnUrl (which does work from within the in app browser):

    var body: some Scene {
        WindowGroup {
            AppContentView()
                .preferredColorScheme(.dark)
                .onOpenURL {
                    if StripeAPI.handleURLCallback(with: $0) {
                        Log.checkout.debug("Stripe url: \($0.debugDescription)")
                    } else {
                        Log.debug.debug("Other url: \($0.debugDescription)")
                    }
                }
        }
lunar tusk
#

Okay so doesn't look like you are using FlowController

#

So you never handle confirming the PaymentIntent yourself, correct?

wicked pagoda
#

No, I only create the intent through my backend, everything else is handled by the paymentSheet Stripe provides

bleak waspBOT
lunar tusk
#

Okay one minute

wicked pagoda
#

Okay πŸ™‚

lunar tusk
#

If you just use your custom URL scheme directly from Safari does it open your App?

wicked pagoda
#

Yes it does, also the Stripe page where I can confirm or decline a payment does open the app from Safari, and the log Log.debug.debug("Other url: \($0.debugDescription)") does log the URL

#

The URL it logs looks like this:xxxx://stripe-redirect?payment_intent=pi_xxxxxxxxxxx&payment_intent_client_secret=pi_xxxxxxxxxx_secret_xxxxxxxxx&redirect_status=succeeded

lunar tusk
#

Oh I'm sorry, I thought you weren't being redirected to your app at all in this case.

#

The deep link itself works fine, but the state of the PaymentIntent is broken?

wicked pagoda
#

Ahh no, it's basically this function that does not return true: StripeAPI.handleURLCallback(with: $0)

lunar tusk
#

Ah ah it just recognizes that it is a different URL as opposed to the Stripe redirect.

#

Okay I gotcha now

#

Curious

#

Looks to be a bug since you have no control here.

#

I'll file a ticket to get this looked at by our Eng team.

wicked pagoda
#

Okay perfect. Thanks! πŸ™‚

bleak waspBOT
#

Hello @wicked pagoda, we have sent you a direct message, please check it at https://discord.com/channels/@me/1354559486337220780

  • πŸ”—The message has instructions on how to open a direct support case with our Developer Support team, in order to help you more effectively.
lunar tusk
#

Go ahead and follow the instructions in the DM you just received and then we can follow up our email after our Eng team has had a look.

#

Let me know when you submitted that flow.

wicked pagoda
#

Sounds good! I'll let you know once I'm done with it, might be a moment though. πŸ™‚

bleak waspBOT