#phiredrop-ios-payment-sheet

1 messages · Page 1 of 1 (latest)

brazen joltBOT
sterile radish
#

If you make a request to that endpoint from something other than your phone app, do you get the expected data back?

mighty solar
#

Yes, earlier in the init of my app, I receive my publishable key.

sterile radish
#

Gotcha, trying to think of what might be happening on the client that is messing up here

regal oak
#

👋 stepping in

#

That's strange

#

Can you add some logs in Glitch to ensure it is hitting that endpoint correctly?

mighty solar
#

I'm very new to server side stuff, so I'm not sure how I'd accomplish that

regal oak
#

Just add a few console.log("test") within the app.post endpoint

#

Glitch should provide you a Console at the bottom to see those logs

mighty solar
#

kk

regal oak
#

Okay can you log out the publishable key that you are passing to the client

#

And make sure it is the correct one

#

Ah actually hold on

#

I think I know the issue

mighty solar
#

Yes in the init, it gets logged and is correct

#

At least it was yesterday... let me validate now

#

Ok yes - during init I print the fetched pk and it's valid

regal oak
#

Try changing the request.setValue to request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")

#

On your client

#

And add a line below that for request.httpBody = parameters.data(using: .utf8)

mighty solar
regal oak
#

AH wait ignore that sorry

#

You aren't sending anything to the server here right?

#

Oh you are

#

Change parameters to json

#

Actually that should be fine how it is

#

Just remove that line

#

Ahhhh

#

Sorry I'm all over the place

#

I actually see the problem

#

On your client you are handling JSON

mighty solar
#

it's ok! I really appreciate the extra set of eyes

regal oak
#

But you aren't sending JSON from your server

#

So in Glitch change from res.send to res.json

#

And ignore what I said to change above

mighty solar
#

kk, testing!

#

Hmm, seems to be the same. Here's the change and the output

regal oak
#

Hmmm can you print data ?

mighty solar
#

it returns 207 bytes

regal oak
#

Your code isn't actually catching this error, no?

#

Like you don't have an else statement

#

It is just going to hit that print message no matter what?

#

Try something like ``` 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 {
let message = error?.localizedDescription ?? "Failed to decode response from server."
self?.displayAlert(title: "Error loading page", message: message)
return
}

        print("Created PaymentIntent")
        self?.paymentIntentClientSecret = clientSecret
mighty solar
#

the else is in the clientSecret let

regal oak
#

Ah I missed that

#

I'm also not the most familiar with Swift

mighty solar
#

like it's not finding the client Secret on the Glitch?

#

No worries

#

I have it saved in the .env on the Glitch server though, like the instructions say

regal oak
#

Is it possible to print data and json after they are initialized?

#

I can't remember if you can print them within that guard

mighty solar
regal oak
#

Huh doesn't seem to like that. Can you print that stuff within the else statement?

mighty solar
#

Yeah that's where it was working

#

if you see my screenshot from 10:08 above

#

If I'm understanding you correctly

regal oak
#

Okay sorry let me grab a colleague more familiar with Swift

mighty solar
#

I just printed json and it returned

["currency": "usd", "paymentMethodType": "card"]

#

so there isn't a clientSecret that it's returning and assigning to a local constant

regal oak
#

That is what you are passing from your client

#

So that is indeed odd

mighty solar
#

Ok dumb question incoming: where does it get the clientSecret from? Because that's not stored in the Xcode project

#

at least it's not explicitly defined I don't think. I don't see it defined in the example project either

regal oak
#

The clientsecret comes from your Server.

mighty solar
#

So in this case, Glitch

regal oak
#

So you create the PaymentIntent on your Server, that creates the paymentIntent.client_secret then you pass that to your client to be able to securely complete the payment.

mighty solar
#

gotcha

regal oak
#

So earlier you had said you had already logged out the publishable key and the client secret, correct?

#

On your client?

#

And you were seeing the publishable key?

#

But did you never actually see the client secret?

mighty solar
#

that's' correct

regal oak
#

Did you set your secret key in Glitch?

mighty solar
#

Yes they're both there in the .env fields

regal oak
#

Okay so can you log out the client secret on your server right before res.json?

#

So console.log(paymentIntent.client_secret)

mighty solar
#

kk

#

Seems to be getting the PI

regal oak
#

Okay so yeah it really does have to be something client side with Swift

#

Which I'm pretty stumped as everything you have there looks fine

#

Let me grab my colleague

mighty solar
#

kk!

long sleet
#

hello! reading here one sec

rigid sleet
#

you need to use let paymentIntentClientSecret = json["paymentIntent"] as? String, because you return paymentIntent in your backend code

#

i.e. because you do

    publishableKey: process.env.publishable_key, // https://stripe.com/docs/keys#obtain-api-keys
    ---> paymentIntent <---: paymentIntent.client_secret, 
    customer: customer.id,
    ephemeralKey: ephemeralKey.secret
  });
});

it is json["paymentIntent"] to get that value in the frontend

mighty solar
#

Hey! That got us a step closer! It printed Created PaymentIntent!

#

Thank you very much!

The Apple Pay Button is still showing Loading... though from this code:

                    if backendModel.paymentIntentParams != nil {
                        PaymentButton() {
                            applePayModel.pay(clientSecret: backendModel.paymentIntentParams?.clientSecret)
                        }
                        .padding()
                    } else {
                        Text("Loading...")
                    }```
So it seems like the `paymentIntentParams` isn't properly updated in the screenshot
#

Although that could be because of my variable change, looking thru it all now

rigid sleet
#

hard to say much with just screenshots of small snippets of parts of the code unfortunately

mighty solar
#

Happy to host a zoom 🙂

rigid sleet
#

doesn't work that way, but you can share the full text of the ViewController with an issue and point out specific parts that you're having trouble with!

mighty solar
#

Sure thing. I'll prepare that

rigid sleet
mighty solar
#

Yes, I've adapted that into my project

#

It's been very helpful, and really is just the connection between the client and server that's different that I'm working on ironing out

#

I have little experience setting up backends, so I'm using the Glitch test server just to get the flow working, then will migrate to something more permanent

#

Here's the Apple Pay Button code, again pretty much taken from that example:

#

Here's the Backend Model that we just got it to successfully get the clientSecret:

#

Right after print("Created PaymentIntent") it should be setting the paymentIntentParams

#

However the button is showing "Loading" instead of the Apple Pay Button, as if backendModel.paymentIntentParams == nil

rigid sleet
#

unfortunately I've never used SwiftUI so I don't really understand how the async model here(the view updating when the backend model has been updated after the network request) so I'll defer to @long sleet . I don't see anything immediately odd though, the code you posted does look like what we have in the example app

mighty solar
#

Thank you all so much for the assistance so far!

#

Even if I remove that check and just show the ApplePay Button, then tap the Apple Pay Button, it crashes the app, so it's definitely more than just an issue updating the view

rigid sleet
#

if it crashes you should have an error message in the XCode console (shift-cmd-c to open that in the Debug Area if it's not open), but overall I'd also be adding print statements throughout the app to see what the values of things are

mighty solar
#

So that's odd. It indeed is nil even though we're getting the clientSecret

#

Printing clientSecret does return the pi_xxxxxx

tidal imp
#

Just checking in. Are there any outstanding questions here?

mighty solar
#

Hello! Yes the issue of the clientSecret being passed into the paymentIntentParams being nil

long sleet
#

hello! I can try and look

mighty solar
#

Hey awesome!

long sleet
#

ah so log out self there, is that nil ? cause you're doing an optional chaining there

#

(inside the dispatch to main queue)

#

not sure what self is instantiated as here, assume it is a View Controller or similar (I've done vanilla iOS, not SwiftUI much)

mighty solar
#

I did log that out in the screeny above right? Or are you looking for a different bit?

long sleet
#

where

#

you didn't log out print(self?) above right?

mighty solar
#

oh, I did print(self?.paymentIntentParams) with some extra text in it

long sleet
#

yes I see that

#

my point is something else

mighty solar
#

ah, kk

long sleet
#

just print(self) is fine or rather, breakpoint on the print(clientSecret) line and inspect in the watch window (or the console) what self is then

mighty solar
#

ah, kk

#

print(self) returns nil

long sleet
#

yep so that's the issue here

#

you're getting a PaymentIntent client_secret from your server just fine

#

your app's screen (or view / equivalent) that you're referencing as self is nil here

#

so you need to look into that

#

I don't know off hand since it can be a bunch of different reasons

#

so really, once you identify that, you'll be able to set self.paymentIntentParams = "thing" just fine

#

in optional chaining, self?.property resolves to nil if self is nil

mighty solar
#

Hmm. Even creating an AppStorage var of clientSecretKey and setting it to clientSecret returns nil

#

even though clientSecret is printing with a value. so strange

long sleet
#

where are you doing the AppStorage part??

#

don't see it in the snippet

#

the snippet seems the same as before

#

the main issue is just the self?,thing part and that being nil

#

the clientSecret part is irrelevant for now, since that String is set just fine

#

you could even replace that with any String like "blah" just for testing, since the actual issue is on the optional part

mighty solar
#

Just defined it at the top, basically confirming that I'm unable to assign that value to a string. Even doing

self?.paymentIntentParams.clientSecret = clientSecret
returns nil.

#

So yeah, something with self? that isn't being set properly

sterile radish
#

Have you checked it self itself resolves to anything? It is sounding like self isn't being initiated

mighty solar
#

Hmm, well printing self like above, even after receiving the clientSecret, still returns nil for some reason

sterile radish
#

Do you see where in your code that object is supposed to be initiated? Maybe that isn't being called before the client secret is getting to your app?

mighty solar
#

Do you mean self?

#

Or something else? Sorry

sterile radish
#

Yes, self but like I am assuming there is some broader context where that object is initiated right?

#

Like in the view's own code it is self but somewhere the view needs to be initialized in other code

mighty solar
sterile radish
#

Lost track, what file are you in here?

mighty solar
#

BackendModel.swift

#

In the example project, it's in Models folder

#

We're stuck getting self?.paymentIntentParams = STPPaymentIntentParams(clientSecret: clientSecret) to actually update with the clientSecret value, even though we are returned a value and it prints fine. For some reason, that paymentIntentParams isn't updating with the value

tidal imp
#

Hi there 👋 taking over, as my colleague needs to step away

Give me a few minutes to find someone more versed in Mobile development. If there isn't anyone, we may need to have you get ahold of support to start an asynchronous thread

#

phiredrop-ios-payment-sheet

mighty solar
#

Ok thank you much! 🙂

long sleet
#

don't have a clear one-shot answer cause I'm not the most well versed in SwiftUI (more on vanilla Swift) but that is my read

#

so my read is, somewhere along the lines, either the Card view is not getting retained, or model is not getting retained

#

the first thing to try is - clone the same "as is" and try it there and breakpoint on self?.paymentIntentParams and log that out

#

if that works, then the issue is in how you've adapted the sample into yoru code

#

that will allow you to identify where the issue lies and approach it

#

does that help?

mighty solar
#

Hmm.. So I'm using ApplePay.swift, not Card.swift. Not sure if that makes a difference

#

although the paymentMethodType being returned says card. hmm

#

I guess not... they still specify card in the ApplePay.swift

long sleet
#

we're talking about diff things

#

let's start here

#

cloning the sample

#

and checking the same flow and what happens there

mighty solar
#

Do you know how to get the podfiles setup? I've only ever used SPM

long sleet
#

did you install the Stripe SDK??

#

as a podfile?

mighty solar
#

I installed it using SPM in my project. That screenshot is the example project

long sleet
#

see the readme instructions

mighty solar
#

I could just use my same glitch server as the example server though yeah?

long sleet
#

you might have to change some endpoints or keys in your JSON, if you modified them, but otherwise if you modeled after that, mostly should work the same

mighty solar
#

kk, got cocoapods installed, running pod install

long sleet
#

nice!

mighty solar
#

Ok, compiled and tested a successful Apple Pay payment on the sample app using my backend Glitch server

#

Printing the paymentIntentParams?.clientSecret in sample also works

long sleet
#

ah good

#

so that means the sample does work fine, wanted to figure out if there was something wrong in the sample code

#

now

#

what you'd need to do is compare the sample's code to your code and see why your View or Model are getting deallocated/losing reference to where by the time you run something on main thread, self becomes nil

#

another way to do this would be to replace the sample's code with your code bit by bit until you can get it running fully. Or you hit the error but then you know which change caused the error and troubleshoot there

#

recommend doing that since there's an issue with your code, just hard to pinpoint what. It isn't related to Stripe specifically either, just a general Swift/iOS code issue where something that is being referenced has become nil by the time it is being referenced

mighty solar
#

Yes this will help with pinpointing it hopefully. Thanks so much

shut copper
#

Glad you were able to narrow it down with @long sleet! We're going to archive this thread since you're up and running and the issue was more related to your code/environment. If you end up having a specific question about our API/iOS SDK though, feel free to ask again in #dev-help !