#rahlok-react-useeffect
1 messages ยท Page 1 of 1 (latest)
Hi there. I recommend following this guide closely: https://stripe.com/docs/stripe-js/elements/payment-request-button?client=react#react-create-payment
At what point are you getting the PaymentIntent must include a PaymentMethod error?
Hi there, thanks for your swift response. I've been through it a few times but feel pretty lost at this point.
I can share the logs with you if you think that would help
Just want to know this
Oh
I thought you meant there was an error with that message
This behavior is expectd
It will say that until you go through the checkout process
How do I do that? I'm testing it with Google Pay
In my app, there is no cart, they just by a single item at a time using Apple / Google Pay
/buy
Do you think that it's step 5 that's missing?
I'm not entirely sure how to factor the code from step 5 into mine
If you don't have step 5, you'll need it
I recommend just implementing it in the same way that guide does. That will be easiest for you if you're struggling.
but it doesn't tell me where in my component to put it
does it go in a useEffect Hook?
I'd be happy to show you the code
Yeah can you share your code
Absolutely
That's my React component
it's derived from a Stripe sample on Github
I really appreciate your help
Can you link the sample you're looking at?
Also it's difficult to read through a ton of code on here while juggling other threads, so is there a specific place you're stuck on? Just step 5 is the issue?
I understand, I believe step 5 is the issue as the payment appears as incomplete in my Dashboard
Ok. Can you also link the sample you're referencing from Github?
Hello ๐
I can take a look
Can you also link the PaymentIntent ID from your example?
The ID starting with pi_xxx
One of the things jumping out here is that your account is on a very old API version
2016-03-07
If your existing apps are not using this API version, then I'd recommend upgrading to latest and see if that makes a difference.
Cool, how do I upgrade?
You can go to this page here
https://dashboard.stripe.com/developers
and there should be an API version section at the bottom
Done, thank you
Cool, try creating a new PaymentIntent and run your tests again
do you see any errors in your console?
Unable to download payment manifest "https://pay.google.com/gp/p/payment_method_manifest.json".
CheckoutForm.js:73 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'client_secret')
at CheckoutForm.js:73:32
at c (regeneratorRuntime.js:44:17)
at Generator.<anonymous> (regeneratorRuntime.js:125:22)
at Generator.next (regeneratorRuntime.js:69:21)
at m (asyncToGenerator.js:3:20)
at o (asyncToGenerator.js:22:9)
looks like your API isn't responding with type of response your code expects
You'd want to look into that
Ok thanks, how would I look into that?
Looking into your backend server logs to see if anything failed.
Ok, I'll look at the logs now
2023-01-31T15:43:10.716583+00:00 heroku[router]: at=info method=OPTIONS path="/create-payment-intent/" host=warm-gorge-84676.herokuapp.com request_id=5fedf382-bf81-4704-a55e-4d30becfb613 fwd="80.42.40.151" dyno=web.1 connect=0ms service=4ms status=200 bytes=595 protocol=https
2023-01-31T15:43:10.716901+00:00 app[web.1]: 10.1.41.211 - - [31/Jan/2023:15:43:10 +0000] "OPTIONS /create-payment-intent/ HTTP/1.1" 200 0 "https://real-stripe.vercel.app/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
2023-01-31T15:43:11.459460+00:00 heroku[router]: at=info method=POST path="/create-payment-intent/" host=warm-gorge-84676.herokuapp.com request_id=8efc8703-0233-406e-bf41-a1f18036760a fwd="80.42.40.151" dyno=web.1 connect=0ms service=655ms status=200 bytes=501 protocol=https
2023-01-31T15:43:11.459841+00:00 app[web.1]: 10.1.41.211 - - [31/Jan/2023:15:43:11 +0000] "POST /create-payment-intent/ HTTP/1.1" 200 115 "https://real-stripe.vercel.app/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
2023-01-31T15:45:58.081689+00:00 app[web.1]: 10.1.80.213 - - [31/Jan/2023:15:45:58 +0000] "OPTIONS /create-payment-intent/ HTTP/1.1" 200 0 "https://real-stripe.vercel.app/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
2023-01-31T15:45:58.082510+00:00 heroku[router]: at=info method=OPTIONS path="/create-payment-intent/" host=warm-gorge-84676.herokuapp.com request_id=94746e26-d582-4a2a-875f-0c56ee932f1a fwd="80.42.40.151" dyno=web.1 connect=0ms service=14ms status=200 bytes=595 protocol=https
2023-01-31T15:45:58.763218+00:00 app[web.1]: 10.1.80.213 - - [31/Jan/2023:15:45:58 +0000] "POST /create-payment-intent/ HTTP/1.1" 200 115 "https://real-stripe.vercel.app/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
that's the log as appears in Heroku
That's not helpful at all ๐
Did you print the response you received from your API?
If not, add a print statement in your react app that prints the response before you access client_secret from it
oh, sorry
would I add the print statement just after the following code:
const response = await fetch('https://warm-gorge-84676.herokuapp.com/create-payment-intent/', {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// cartDetails,
paymentDetails,
amount: price,
currency: 'usd',
payment_method: 'card'
// automatic_payment_methods: true,
}),
}).then((res) => {
return res.json();
});
where are you accessing the client_secret?
const { error, paymentIntent } = await stripe.confirmCardPayment(
response.paymentIntent.client_secret
);
Would you like the see the full component?
no, you can print the response here and check if there's anything missing
console.log(response)
thank you
Also as my colleague mentioned, you should really be using this guide for your integration
https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements
It goes over every step in detail. The example you're looking at is for a serverless react app (which isn't the same thing you're building)
Ok, thanks for that. I've read through that, but I'm looking for just the Google / Apple Pay button, not any of the other features
also, the console didn't print anything just now
It would be similar implementation for PaymentRequest Button
https://stripe.com/docs/stripe-js/elements/payment-request-button
That's what I originally went through, but still had issues.
ah, that reminds me
in an app where I used that tutorial, I get the following error in the console:
An error occurred: IntegrationError: Missing value for stripe.confirmCardPayment intent secret: value should be a client_secret string.
at $ (v3:1:78388)
at ee (v3:1:78460)
at l (v3:1:125945)
at v3:1:367685
at v3:1:59259
at t.<anonymous> (v3:1:405645)
at t.confirmCardPayment (v3:1:152956)
at Checkout.js:56:35
at d (regeneratorRuntime.js:44:17)
at Generator.<anonymous> (regeneratorRuntime.js:125:22)
I'm using the same end point for this app
what do you see when you print console.log(response)
it doesn't print
I'm getting this now in my console:
Object
error
:
code
:
"resource_missing"
doc_url
:
"https://stripe.com/docs/error-codes/resource-missing"
message
:
"No such payment_intent: 'pi_3MWMOXKANfnETzod0HpxMaDf'; a similar object exists in test mode, but a live mode key was used to make this request."
param
:
"intent"
request_log_url
:
"https://dashboard.stripe.com/logs/req_Rh5LPHDSYUwyFR?t=1675181358"
type
:
"invalid_request_error"
[[Prototype]]
:
Object
[[Prototype]]
:
Object
i'll check the key
๐
Ok, so apparently the payment succeeds, but it doesn't appear in the browser:
from the console:
Object
paymentIntent
:
amount
:
200
amount_details
:
{tip: {โฆ}}
automatic_payment_methods
:
null
canceled_at
:
null
cancellation_reason
:
null
capture_method
:
"automatic"
client_secret
:
"pi_3MWMRkKANfnETzod0d1PIl6V_secret_tP2VZ9IvPm8ZfHfYQf728BN9o"
confirmation_method
:
"automatic"
created
:
1675181556
currency
:
"usd"
description
:
null
id
:
"pi_3MWMRkKANfnETzod0d1PIl6V"
last_payment_error
:
null
livemode
:
false
next_action
:
null
object
:
"payment_intent"
payment_method
:
"pm_1MWMRkKANfnETzod9H9ZbmFy"
payment_method_types
:
['card']
processing
:
null
receipt_email
:
null
setup_future_usage
:
null
shipping
:
null
source
:
null
status
:
"succeeded"
You would need to figure out what code is running after the abvoe succeeds ๐ and take it from there
I also get the following:
DEVELOPER_ERROR in loadPaymentData: An error occurred in call back, please try to avoid this by setting structured error in callback response
H @ pay.js:149
controller-2a60bf966deafec3d204696aa075b888.js:1 Timed out waiting for a call to complete(). Once you have processed the payment in the "paymentmethod" handler, you must call event.complete within 30 seconds.
warn @ controller-2a60bf966deafec3d204696aa075b888.js:1
I'm getting 200s on this one: "pi_3MWMRkKANfnETzod0d1PIl6V"
and the payment is showing as successful in my Payments tab
The code just doesn't seem to be listening
can I share with you the code I'm trying to get to listen for the complete payment?
Look at the example here and compare your code, try and identify what's missing ๐
https://stripe.com/docs/stripe-js/elements/payment-request-button?client=react#react-complete-payment
it's step 5 that I need to get right, right?
but I don't know how to factor the code block it provides into my React code, can you advise on that?
that block is an event listener
you don't necessarily need to add it into useEffect hook
You just need to make sure you add in the scope where paymentRequest variable exists
In here?
const Checkout = (props) => {
const stripe = useStripe();
const [paymentRequest, setPaymentRequest] = useState(null);
const price = props.price;
const dollar_price = price * 100;
sure
where exactly am I pasting the block in to?
I've tried it in various places but VSCode just throws errors
what kind of error?
I have an existing useEffect Hook:
useEffect(() => {
if (paymentRequest) {
paymentRequest.on('paymentmethod', async event => {
const paymentMethod = event.paymentMethod;
try {
const response = await axios.post(
'https://warm-gorge-84676.herokuapp.com/create-payment-intent/',
{
paymentMethodId: paymentMethod.id,
amount: dollar_price,
automatic_payment_methods: {
'enabled': true,
},
currency: 'usd',
}
);
const pi = await stripe.confirmCardPayment(response.data.client_secret, {
payment_method: paymentMethod.id
});
should it go in there?
that's actually the second useEffect hook in my component
rahlok-react-useeffect
@visual trench Taking over though I don't really follow your question. Right now you're just asking where your code goes but that's really up to you.
The PaymentIntent should have been created way earlier on page load though
interesting
const Checkout = (props) => {
const stripe = useStripe();
const [paymentRequest, setPaymentRequest] = useState(null);
const price = props.price;
const dollar_price = price * 100;
useEffect(() => {
if (stripe) {
const pr = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Purchase',
amount: dollar_price,
},
requestPayerName: true,
requestPayerEmail: true,
applePay: true,
googlePay: true,
});
pr.canMakePayment().then(result => {
if (result) {
setPaymentRequest(pr);
}
});
}
}, [stripe]);
useEffect(() => {
if (paymentRequest) {
paymentRequest.on('paymentmethod', async event => {
const paymentMethod = event.paymentMethod;
try {
const response = await axios.post(
'https://warm-gorge-84676.herokuapp.com/create-payment-intent/',
{
paymentMethodId: paymentMethod.id,
amount: dollar_price,
automatic_payment_methods: {
'enabled': true,
},
currency: 'usd',
}
);
const pi = await stripe.confirmCardPayment(response.data.client_secret, {
payment_method: paymentMethod.id
});
if (paymentRequest) {
return <PaymentRequestButtonElement options={{ paymentRequest }} />;
}
return <div>
<PayButton />
</div>;
};
export default Checkout;
I'm just trying to figure out where to put the event listener
do you have a sample that I can simply use my own keys and endpoint in? One that just renders the PaymentRequestButton in?
I know about this indeed
thank you
but I have followed that and am missing a step
the issue I am having is when it provides the following code:
paymentRequest.on('paymentmethod', async (ev) => {
// Confirm the PaymentIntent without handling potential next actions (yet).
const {paymentIntent, error: confirmError} = await stripe.confirmCardPayment(
clientSecret,
{payment_method: ev.paymentMethod.id},
{handleActions: false}
);
if (confirmError) {
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
ev.complete('fail');
} else {
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
ev.complete('success');
// Check if the PaymentIntent requires any actions and if so let Stripe.js
// handle the flow. If using an API version older than "2019-02-11"
// instead check for: `paymentIntent.status === "requires_source_action"`.
if (paymentIntent.status === "requires_action") {
// Let Stripe.js handle the rest of the payment flow.
const {error} = await stripe.confirmCardPayment(clientSecret);
if (error) {
// The payment failed -- ask your customer for a new payment method.
} else {
// The payment has succeeded.
}
} else {
// The payment has succeeded.
}
}
});
I don't know where to put that
how do I use that in my React component?
here is my code on Github: https://github.com/carvalhochris/songcards-chakra/blob/main/src/Stripe/Checkout.js
I just need to know where I can add the event listen so that the user knows the payment is successful
I simply don't know what to do with the code block that Stripe provides in step 5 of the Payment Request Button tutorial
thank you
That code block just goes within your Checkout component but outside of UseEffect
Outside of both. This is an event listener so you don't want it involved with a render
ok, should I make a new useEffect for it?
Nope. Are you familiar with how useEffect works?
kind of
Gotcha. In that case I would pause and read thoroughly through https://reactjs.org/docs/hooks-effect.html
And https://beta.reactjs.org/reference/react/useEffect specifically
It is important to understand what useEffect will do or you can run into lots of issues with how your code renders
Thank you. Does it not make sense in my code that I have two then?
Yeah you don't need the second one at all
ok thank you
It is fine to use the first one to create your paymentRequest and check canMakePayment
Since you want that to happen on page-load (on render)
But then, you want to wait for the customer to take action (click on the PaymentRequstButton and authenticate either Apple Pay or Google Pay) before you confirm the Payment
Since that doesn't happen on page-load, you don't want your event listener inside the useEffect hook
ok greart
the second useEffect had my endpoint on it, do I not need to use my endpoint?
Ah I missed that. Yes you want that in the initial useEffect
ok, how do I add it to the first one:
useEffect(() => {
if (stripe) {
const pr = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Purchase',
amount: dollar_price,
},
requestPayerName: true,
requestPayerEmail: true,
applePay: true,
googlePay: true,
});
pr.canMakePayment().then(result => {
if (result) {
setPaymentRequest(pr);
}
});
}
}, [stripe]);
You just put const response = await axios.post( 'https://warm-gorge-84676.herokuapp.com/create-payment-intent/', { paymentMethodId: paymentMethod.id, amount: dollar_price, automatic_payment_methods: { 'enabled': true, }, currency: 'usd', } ); inside that useEffect callback
Hmm actually let's pause for a sec
Are you offering other ways to pay than via Payment Request Button?
Oh okay in that case I wouldn't create the PaymentIntent on page load (in useEffect)
ok
I would actually call it in your paymentRequest.on('paymentmethod' callback
So then you aren't just unnecessarily creating PaymentIntents
So it would look like: ```paymentRequest.on('paymentmethod', async (ev) => {
const response = await axios.post(
'https://warm-gorge-84676.herokuapp.com/create-payment-intent/',
{
paymentMethodId: paymentMethod.id,
amount: dollar_price,
automatic_payment_methods: {
'enabled': true,
},
currency: 'usd',
}
);
const {clientSecret} = response.json()
// Confirm the PaymentIntent without handling potential next actions (yet).
const {paymentIntent, error: confirmError} = await stripe.confirmCardPayment(
clientSecret,
{payment_method: ev.paymentMethod.id},
{handleActions: false}
);
if (confirmError) {
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
ev.complete('fail');
} else {
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
ev.complete('success');
// Check if the PaymentIntent requires any actions and if so let Stripe.js
// handle the flow. If using an API version older than "2019-02-11"
// instead check for: paymentIntent.status === "requires_source_action".
if (paymentIntent.status === "requires_action") {
// Let Stripe.js handle the rest of the payment flow.
const {error} = await stripe.confirmCardPayment(clientSecret);
if (error) {
// The payment failed -- ask your customer for a new payment method.
} else {
// The payment has succeeded.
}
} else {
// The payment has succeeded.
}
}
});```
Anywhere within your Checkout component but outside of useEffect
I pasted it just below my variables but now I get "'paymentMethod' is not defined"
sure
const Checkout = props => {
const stripe = useStripe();
const [paymentRequest, setPaymentRequest] = useState(null);
const price = props.price;
const dollar_price = price * 100;
paymentRequest.on('paymentmethod', async ev => {
const response = await axios.post(
'https://warm-gorge-84676.herokuapp.com/create-payment-intent/',
{
paymentMethodId: paymentMethod.id,
amount: dollar_price,
automatic_payment_methods: {
enabled: true,
},
currency: 'usd',
}
);
const { clientSecret } = response.json();
// Confirm the PaymentIntent without handling potential next actions (yet).
const { paymentIntent, error: confirmError } =
await stripe.confirmCardPayment(
clientSecret,
{ payment_method: ev.paymentMethod.id },
{ handleActions: false }
);
if (confirmError) {
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
ev.complete('fail');
} else {
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
ev.complete('success');
// Check if the PaymentIntent requires any actions and if so let Stripe.js
// handle the flow. If using an API version older than "2019-02-11"
// instead check for: `paymentIntent.status === "requires_source_action"`.
if (paymentIntent.status === 'requires_action') {
// Let Stripe.js handle the rest of the payment flow.
const { error } = await stripe.confirmCardPayment(clientSecret);
if (error) {
// The payment failed -- ask your customer for a new payment method.
} else {
// The payment has succeeded.
}
} else {
// The payment has succeeded.
}
}
});
Ah yeah okay so remove paymentMethodId: paymentMethod.id, from your axios request
Cause you don't have the PaymentMethod yet
done
Okay test again
How are you testing this?
Are you on HTTPS?
And do you have a card saved in your wallet?
Okay is there somewhere I can visit to test from my end?
It is also time to start adding logs to your code to see at what point it is not working
Okay let's start by adding a log within pr.canMakePayment().then(result => { if (result) { setPaymentRequest(pr); } });
So add console.log("result: ", result)
if (result) {
console.log("result: ", result)
setPaymentRequest(pr);
}
});```
I'm also seeing some CORS errors on your page
Not sure if those are coming into play yet
thank you, added to the code, now pushing
Don't think they are... they look related to mp3s
Can you also move your paymentRequest.on('paymentmethod', block below your useEffect? I know I specified "anywhere outside" but really the top of your Component's code should be the useEffect code.
I should have specified that before (I mostly meant anywhere below.. shouldn't have used term "outside")
Happy to help
thank you, I moved the code block and git pushed
Hmm okay now we can see the line of the error and it indeed doesn't like that we don't have paymentRequest yet
Let's just throw the paymentRequest.on in an if (paymentRequest) {} block
Doh
You already have that when you are surfacing your button
Okay my bad I missed that
no worries!
Just move the paymentRequest.on into your if (paymentRequest) { return <PaymentRequestButtonElement options={{ paymentRequest }} />; }
if (paymentRequest) {
paymentRequest.on('paymentmethod', async ev => {
const response = await axios.post(
'https://warm-gorge-84676.herokuapp.com/create-payment-intent/',
{
// paymentMethodId: paymentMethod.id,
amount: dollar_price,
automatic_payment_methods: {
enabled: true,
},
currency: 'usd',
}
);
const { clientSecret } = response.json();
// Confirm the PaymentIntent without handling potential next actions (yet).
const { paymentIntent, error: confirmError } =
await stripe.confirmCardPayment(
clientSecret,
{ payment_method: ev.paymentMethod.id },
{ handleActions: false }
);
if (confirmError) {
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
ev.complete('fail');
} else {
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
ev.complete('success');
// Check if the PaymentIntent requires any actions and if so let Stripe.js
// handle the flow. If using an API version older than "2019-02-11"
// instead check for: `paymentIntent.status === "requires_source_action"`.
if (paymentIntent.status === 'requires_action') {
// Let Stripe.js handle the rest of the payment flow.
const { error } = await stripe.confirmCardPayment(clientSecret);
if (error) {
// The payment failed -- ask your customer for a new payment method.
} else {
// The payment has succeeded.
}
} else {
// The payment has succeeded.
}
}
});
return <PaymentRequestButtonElement options={{ paymentRequest }} />;
}
like this?
Yep that looks good
ok pushed
I see the button
Is this in test mode?
(I assume so but wary of testing on your site without knowing 100%)
yeah using test keys
times out, here is what the console says:
controller-2a60bf966deafec3d204696aa075b888.js:1 Unrecognized paymentRequest() parameter: googlePay is not a recognized parameter. This may cause issues with your integration in the future.
warn @ controller-2a60bf966deafec3d204696aa075b888.js:1
cheri:1 Unable to download payment manifest "https://pay.google.com/about/".
Checkout.js:35 result: ObjectapplePay: falsegooglePay: truelink: false[[Prototype]]: Object
result: ObjectapplePay: falsegooglePay: truelink: false[[Prototype]]: Object
payment is showing as incomplete in my Stripe dashboard
Hmm I have a feeling the issue is with the confirmCardPayment and the client secret
Let's add a log for the response.json()
ok cool
Oh wait
Are you seeing a PaymentMethod created in your account?
In your Stripe Dashboard logs?
yes?
Yep cool
Okay so yeah add a log right before const { clientSecret } = response.json(); to log out response.json()
console.log(response)?
console.log("response: ", response.json())
Recommend always prefixing your logs with a string that indicates what you are logging
Helps make your logs clear
K test again and let me know what it logs
looks like it didn't print
this came up though:
Uncaught (in promise) TypeError: r.json is not a function
at Checkout.js:113:42
at d (regeneratorRuntime.js:44:17)
at Generator.<anonymous> (regeneratorRuntime.js:125:22)
at Generator.next (regeneratorRuntime.js:69:21)
at ot (asyncToGenerator.js:3:20)
at a (asyncToGenerator.js:22:9)
my print statement
Hmm weird error
Why is it saying r.son in the error....
You aren't actually in a typescript file... that said you don't have a ; after the log
Is it really complaining about that??
Try console.log("response: ", response.json());
lol computers are weird
(Add the semicolon)
Ohhhh
We aren't awaiting
Oops
Should be await response.json()
Since this is an async process to jsonify it
const { clientSecret } = await response.json();
So above that do let result = await response.json(); console.log(result);
But yeah that is the main issue here... forgetting the await
thanks, shall I remove the original print we made?
Yep
Since you can't await within a print
That is why you need to just set a different variable like result and then print that variable after it is initialized
nice, thanks for sharing. I'm learning with you ๐
result: ObjectapplePay: falsegooglePay: truelink: false[[Prototype]]: Objectconstructor: ฦ Object()hasOwnProperty: ฦ hasOwnProperty()isPrototypeOf: ฦ isPrototypeOf()propertyIsEnumerable: ฦ propertyIsEnumerable()toLocaleString: ฦ toLocaleString()toString: ฦ toString()valueOf: ฦ valueOf()__defineGetter__: ฦ __defineGetter__()__defineSetter__: ฦ __defineSetter__()__lookupGetter__: ฦ __lookupGetter__()__lookupSetter__: ฦ __lookupSetter__()__proto__: (...)get __proto__: ฦ __proto__()set __proto__: ฦ __proto__()
would you prefer a screenshot?
No one sec. I usually use fetch so not really familiar with axios. But that seems like you aren't getting the body of the response back.
Is there a body property there in the log?
Also what happened afterwards?
Did it work or you hit an error?
You can remove the log for the second result object now btw since we see the button successfully with GPay: true
Okay so sounds like we may not need to jsonify the response at all according to https://masteringjs.io/tutorials/axios/response-body
Try to just log response.data instead
Sorry mean the one on line 35
cool
That is working fine so no need to log that anymore
cool
I just never really use axios
do I need to un-jsonify then?
Yeah
Yep
That should likely be response.data
Instead
But we will know once we log out the response.data
const { clientSecret } = response.data();
console.log(clientSecret);```
The doc above indicates that axios attempts to parse the body for you and returns it as a property of data
I'd log console.log("response data: " response.data)
ah yes of course
testing...
Uncaught (in promise) TypeError: r.json is not a function
at Checkout.js:113:35
at d (regeneratorRuntime.js:44:17)
at Generator.<anonymous> (regeneratorRuntime.js:125:22)
at Generator.next (regeneratorRuntime.js:69:21)
at ot (asyncToGenerator.js:3:20)
at a (asyncToGenerator.js:22:9)
Unable to download payment manifest "https://pay.google.com/gp/p/payment_method_manifest.json".
Timed out waiting for a call to complete(). Once you have processed the payment in the "paymentmethod" handler, you must call event.complete within 30 seconds.
incomplete payment
(One sec)
๐
Okay had to step away for a quick sec
no problem!
Let's see....
Not sure if this one is relevent:
Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received
Okay still looks like you have let result = await response.json(); in your code
So swap that with line 117
(Delete that line and place the code in 117 there instead)
You can also remove the console.log(result);
ah sorry
No worries ๐
response data:
Object
client_secret
:
"pi_3MWOnIKANfnETzod1jaUkD9w_secret_Xtez4NmAGqDAYpceOdWDehrBB"
id
:
"pi_3MWOnIKANfnETzod1jaUkD9w"
[[Prototype]]
:
Object
Hmm actually now that I think of it... it should be fine how it was
Oh wait
I see the issue with how it was
You may want to take a look at https://stackoverflow.com/questions/25187903/what-do-curly-braces-around-javascript-variable-name-mean to understand the destructuring expression (the curly brackets)
thank you
So right now you have your variable as clientSecret but in the response.data object it is client_secret
So those need to match in order for it to destructure correctly
Otherwise you just don't use the destructuring expression
right
So yeah, the simplest thing here is to just remove the brackets
And yes this replaces line 116
Specifically it should be const clientSecret = response.data.client_secret on line 116
great, done, I can push?
Yep
ok, slightly different behaviour
it doesn't time out anymore
the gpay sheet just disappears like it finished
response data:
Object
client_secret
:
"pi_3MWOxFKANfnETzod0dhNr1tD_secret_CMY6nzv3fVLVnYJWuu7FmklVj"
id
:
"pi_3MWOxFKANfnETzod0dhNr1tD"
[[Prototype]]
:
Object
Is there a successful payment in your Dashboard?
and the payment succeeded in the dashboard
๐
amazing, I just need a success message on the UI now
Yep exactly
I really appreciate you for this
Happy to help!
feels close now
Yeah you just want a success message in your ev.complete('success'); block
And also probably a failure message in the confirmError block
But I'm going to leave those parts to you as the Stripe part here is concluded ๐
does it look like those blocks are running?
ok, I'm gonna try the logs now to start with
Yep you can put JSX in there
You can also set State in those blocks
That is likely what you want to do to update your UI
But yeah, various ways to go there.
I need to step away. I'll archive this thread but feel free to reach back out in the main channel if we can help further with Stripe-specific stuff in the future!