#squidonomics - ios payment intent

1 messages · Page 1 of 1 (latest)

dull hedgeBOT
signal belfry
#

Hi 👋

#

Can you share the relevant code snippets? Formatted between three `?

#

To be clear, I'm not a Swift programmer but I can reach out to my colleagues and double check any syntax or process issues.

vernal aurora
#

Hello

#

Here's the two snippets from the tutorial video I followed that work when emulating but not on an actual device

#
            if let paymentIntent = model.paymentIntentParams {
                Button(action: {payAvail = true; paymentIntent.paymentMethodParams = paymentMethodParams}) {
                Text("Pay")
            }
            .paymentConfirmationSheet(isConfirmingPayment: $payAvail, paymentIntentParams: paymentIntent, onCompletion: model.onCompletion)
            .disabled(payAvail)
            } else {
                Text("Loading...")
            }
            
            if let paymentStatus = model.paymentStatus {
                HStack {
                    switch paymentStatus {
                    case .succeeded:
                        Image(systemName: "checkmark.circle.fill").foregroundColor(.green)
                        Text("Payment complete!")
                    case .failed:
                        Image(systemName: "xmark.octagon.fill").foregroundColor(.red)
                        Text("Payment failed! \(model.lastPaymentError ?? NSError())")
                    case .canceled:
                        Image(systemName: "xmark.octagon.fill").foregroundColor(.orange)
                        Text("Payment canceled.")
                    @unknown default:
                        Text("Unknown status")
                    }
                }
            }
        }.onAppear{ model.preparePaymentIntent(paymentMethodType: "card", currency: "usd")}    }
            
           
        }
} ```
#
    @Published var paymentStatus: STPPaymentHandlerActionStatus?
    @Published var paymentIntentParams: STPPaymentIntentParams?
    @Published var lastPaymentError: NSError?
    var custmamnt = ""
    var paymentMethodType: String?
    var currency: String?
    let feesandtaxes : Double = UserDefaults.standard.double(forKey: "Cost") * 0.03 + 0.30

    func preparePaymentIntent(paymentMethodType: String, currency: String){
        self.paymentMethodType = paymentMethodType
        self.currency = currency
        custmamnt = "\(UserDefaults.standard.string(forKey: "Cost") ?? "")"
        let url = URL(string: backendUrl + "create-payment-intent")!
        let json: [String: Any] = ["items": ["amount": feesandtaxes + 3.00 + UserDefaults.standard.double(forKey: "Cost")]]
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: json)
        let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self]
            (data, response, error) in
            guard let response = response as? HTTPURLResponse,
                  response.statusCode == 200,
                  let data = data,
                  let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                  let clientSecret = json["clientSecret"] as? String else {
                print("uh oh")
                return
            }
            print(request.httpBody)
            DispatchQueue.main.asyncAfter(deadline: DispatchTime(uptimeNanoseconds: 3000000)) {
                self?.paymentIntentParams = STPPaymentIntentParams(clientSecret: clientSecret)
            }
        })
        task.resume()
    } ```
#
            self.paymentStatus = status
            self.lastPaymentError = error

        }
}```
#

this last function is in the backend model the message was just too long to send together

#

thank you

signal belfry
#

What iOS device are you running on? When you say it sends the PI twice are they separate PIs? Or the same being sent twice?

vernal aurora
#

I am running it on a real iphone 11 and an emulated iphone 11

#

It sends a PI that creates a payment intent and then sends the confirm payment intent with no card information immediately after without accepting my card details on the real iphone

signal belfry
#

Okay that is different that what I was reading your question as.

#

Have you tried decoupling your logic with the onAppear hook?

#

It seems you can address this by wrapping the onAppear callback in a conditional to check for this:

.onAppear{
               if firstTime{
                   firstTime = false
                   self.perform()
               }
           }
vernal aurora
#

but I havent tried wrapping it

#

I will put this in right now

signal belfry
#

squidonomics - ios payment intent

vernal aurora
#

Unfortunately I am still seeing two packets go out

signal belfry
#

And these two are requests the Create and Confirm requests for the same PI?

vernal aurora
#

currently looking at my logs right now and the second one isn't even hitting stripe servers. I get a response which contains the client secret

#

however, if let paymentIntent = model.paymentIntentParams

#

does not enable the button and gets passed onto the else condition

#

when I emulate an iphone the button does get enabled which is where I am stuck

signal belfry
#

Yeah that part is confusing me too. I haven't seen an issue where the emulator and devices diverge this much.

#

If you strip out the Stripe specific code can you replicate this behavior?

vernal aurora
#

no, it only seems to happen with the stripe elements.

#

I can send and receive requests normally everywhere else

signal belfry
#

Okay can you tell me what the two requests are? What URLs are they to?

vernal aurora
#

If you need a video of it happening I can take one of both interactions

signal belfry
#

Okay, that URL ins't a Stripe URL. When does it reach out to Stripe?

vernal aurora
#

sorry

#

"/v1/charges?payment_intent=pi_3LnljSAwKsZ0hizW0DWRITjM"

#

this is the url on the logs

signal belfry
#

But we don't accept URL params in those requests so that seems odd. All parameters are URL form encoded

vernal aurora
#

Response body{ "id": "pi_3LnljSAwKsZ0hizW0DWRITjM", "object": "payment_intent", "amount": 1099, "amount_capturable": 0, "amount_details": { "tip": { } }, "amount_received": 0, "application": null, "application_fee_amount": null, "automatic_payment_methods": { "enabled": true }, "canceled_at": null, "cancellation_reason": null, "capture_method": "automatic", "charges": { "object": "list", "data": [ ], "has_more": false, "total_count": 0, "url": "/v1/charges?payment_intent=pi_3LnljSAwKsZ0hizW0DWRITjM" }, "client_secret": "pi_3LnljSAwKsZ0hizW0DWRITjM_secret_hOyTZD8pfXbG3W6TEhMzYAvZr", "confirmation_method": "automatic", "created": 1664553994, "currency": "usd", "customer": null, "description": null, "invoice": null, "last_payment_error": null, "livemode": false, "metadata": { }, "next_action": null, "on_behalf_of": null, "payment_method": null, "payment_method_options": { "card": { "installments": null, "mandate_options": null, "network": null, "request_three_d_secure": "automatic" } }, "payment_method_types": [ "card" ], "processing": null, "receipt_email": null, "review": null, "setup_future_usage": null, "shipping": null, "source": null, "statement_descriptor": null, "statement_descriptor_suffix": null, "status": "requires_payment_method", "transfer_data": null, "transfer_group": null}

#

that was response log

signal belfry
#

Okay and that URL is getting hit twice?

#

Or are you calling the /v1/pamyment_intents/:id/confirm?

vernal aurora
#

on the emualted device the payment intent is created, the client secret returned and then I can fill out the Stripe form to send card details and it gets confirmed.

#

with the real ios device I open the same page and the client secret is returned once but network activity shows two packeted being sent. Then if let paymentIntent = model.paymentIntentParams fails

#

should I call confirm?

signal belfry
#

but network activity shows two packeted being sent
To what URL?

#

This difference in behavior is really weird.

vernal aurora
#

they're both to my local server it's just that I only return one client secret and it keeps my button disabled

#

so I know it goes through

vernal aurora
#

Upon checking my server does not respond with the customer id or ephemeral key

#

could that be the issue with a live device?

#

I'm not sure if emulated devices are allowed special permission like postman on stripe servers

signal belfry
#

It would be an issue. The emulated device should not have any different permissions as far as Stripe is concerned. It may be something to do with the iOS device permissions though.

#

Can you include a logging statement in the preparePaymentIntent function to confirm that function is being called twice?

vernal aurora
#

I will go do that now

signal belfry
#

Okay great. And how does the Payment Sheet example app run?

vernal aurora
#

I have it to where I'm not sending two requests anymore

#

the example payment app is doing the same thing right now though

hardy gyro
#

👋

#

Stepping in as Snufkin needs to step away

#

You noted above that this is not happening anymore except on the example

#

Were you able to figure out how to resolve this?

vernal aurora
#

I was able to resolve the double request issue. I am going to get the ephermeral keys and try to see if that allows me to make requests again.

hardy gyro
#

Cool