#rahlok-react-useeffect

1 messages ยท Page 1 of 1 (latest)

calm saffronBOT
tough lichen
#

At what point are you getting the PaymentIntent must include a PaymentMethod error?

visual trench
#

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

visual trench
#

I think it's happening at the point of payment intent

tough lichen
#

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

visual trench
#

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

visual trench
#

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

tough lichen
#

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.

visual trench
#

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

tough lichen
#

Yeah can you share your code

visual trench
#

Absolutely

#

That's my React component

#

it's derived from a Stripe sample on Github

#

I really appreciate your help

tough lichen
#

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?

visual trench
#

I understand, I believe step 5 is the issue as the payment appears as incomplete in my Dashboard

tough lichen
#

Ok. Can you also link the sample you're referencing from Github?

paper hill
#

Hello ๐Ÿ‘‹
I can take a look
Can you also link the PaymentIntent ID from your example?
The ID starting with pi_xxx

visual trench
#

Thank you!

#

"pi_3MWIrTKANfnETzod0IPkR0uY"

paper hill
#

One of the things jumping out here is that your account is on a very old API version

#

2016-03-07

visual trench
#

oh!

#

thanks for spotting!

paper hill
#

If your existing apps are not using this API version, then I'd recommend upgrading to latest and see if that makes a difference.

visual trench
#

Cool, how do I upgrade?

paper hill
visual trench
#

Done, thank you

paper hill
#

Cool, try creating a new PaymentIntent and run your tests again

visual trench
#

Issue still occurs

#

pi_3MWLzHKANfnETzod1kFs4AvB

paper hill
#

do you see any errors in your console?

visual trench
#

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)

paper hill
#

looks like your API isn't responding with type of response your code expects

#

You'd want to look into that

visual trench
#

Ok thanks, how would I look into that?

paper hill
#

Looking into your backend server logs to see if anything failed.

visual trench
#

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

paper hill
#

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

visual trench
#

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();
    });

paper hill
#

where are you accessing the client_secret?

visual trench
#
const { error, paymentIntent } = await stripe.confirmCardPayment(
        response.paymentIntent.client_secret
      );
#

Would you like the see the full component?

paper hill
#

no, you can print the response here and check if there's anything missing

visual trench
#

in the line after the above code block?

#

would it be console.log(client_secret)?

paper hill
#

console.log(response)

visual trench
#

thank you

paper hill
visual trench
#

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

paper hill
visual trench
#

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

paper hill
#

what do you see when you print console.log(response)

visual trench
#

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

paper hill
#

๐Ÿ‘

visual trench
#

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"
paper hill
#

You would need to figure out what code is running after the abvoe succeeds ๐Ÿ™‚ and take it from there

visual trench
#

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?

paper hill
visual trench
#

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?

paper hill
#

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

visual trench
#

In here?

const Checkout = (props) => {
  const stripe = useStripe();
  const [paymentRequest, setPaymentRequest] = useState(null);
  const price = props.price;
  const dollar_price = price * 100;

paper hill
#

sure

visual trench
#

where exactly am I pasting the block in to?

paper hill
#

where have you tried? ๐Ÿ˜„

#

Don't be afraid to write/test your code.

visual trench
#

I've tried it in various places but VSCode just throws errors

paper hill
#

what kind of error?

visual trench
#

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

half star
#

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

visual trench
#

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?

visual trench
#

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?

#

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

inner wraith
#

๐Ÿ‘‹ stepping in

#

Catching up

visual trench
#

thank you

inner wraith
#

That code block just goes within your Checkout component but outside of UseEffect

visual trench
#

ok

#

I have two useEffects, should it go before or after them?

inner wraith
#

Outside of both. This is an event listener so you don't want it involved with a render

visual trench
#

ok, should I make a new useEffect for it?

inner wraith
#

Nope. Are you familiar with how useEffect works?

visual trench
#

kind of

inner wraith
#

It is important to understand what useEffect will do or you can run into lots of issues with how your code renders

visual trench
#

Thank you. Does it not make sense in my code that I have two then?

inner wraith
#

Yeah you don't need the second one at all

visual trench
#

ok thank you

inner wraith
#

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

visual trench
#

ok greart

#

the second useEffect had my endpoint on it, do I not need to use my endpoint?

inner wraith
#

Ah I missed that. Yes you want that in the initial useEffect

visual trench
#

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]);
inner wraith
#

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?

visual trench
#

no

#

I just want that button

inner wraith
#

Oh okay in that case I wouldn't create the PaymentIntent on page load (in useEffect)

visual trench
#

ok

inner wraith
#

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.
}
}
});```

visual trench
#

thank you, where abouts in my code can I paste that?

#

at the top of the component?

inner wraith
#

Anywhere within your Checkout component but outside of useEffect

visual trench
#

I pasted it just below my variables but now I get "'paymentMethod' is not defined"

inner wraith
#

Where?

#

Can you show me the updated code?

visual trench
#

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.
      }
    }
  });
inner wraith
#

Ah yeah okay so remove paymentMethodId: paymentMethod.id, from your axios request

#

Cause you don't have the PaymentMethod yet

visual trench
#

done

inner wraith
#

Okay test again

visual trench
#

now I get a black screen when I load the component

#

/blank

inner wraith
#

How are you testing this?

#

Are you on HTTPS?

#

And do you have a card saved in your wallet?

visual trench
#

yeah on https

#

yep, saved to my wallet

inner wraith
#

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

visual trench
inner wraith
#

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

visual trench
#

thank you, added to the code, now pushing

inner wraith
#

Don't think they are... they look related to mp3s

visual trench
#

pushed to remote

#

btw I really appreciate your help

inner wraith
#

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")

inner wraith
visual trench
#

thank you, I moved the code block and git pushed

inner wraith
#

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

visual trench
#

no worries!

inner wraith
#

Just move the paymentRequest.on into your if (paymentRequest) { return <PaymentRequestButtonElement options={{ paymentRequest }} />; }

visual trench
#
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?

inner wraith
#

Yep that looks good

visual trench
#

ok pushed

inner wraith
#

I see the button

#

Is this in test mode?

#

(I assume so but wary of testing on your site without knowing 100%)

visual trench
#

yeah using test keys

inner wraith
#

I'll let you test it out actually

#

Let me know what happens now!

visual trench
#

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

inner wraith
#

Hmm I have a feeling the issue is with the confirmCardPayment and the client secret

#

Let's add a log for the response.json()

visual trench
#

ok cool

inner wraith
#

Oh wait

#

Are you seeing a PaymentMethod created in your account?

#

In your Stripe Dashboard logs?

visual trench
inner wraith
#

Yep cool

#

Okay so yeah add a log right before const { clientSecret } = response.json(); to log out response.json()

visual trench
#

console.log(response)?

inner wraith
#

console.log("response: ", response.json())

#

Recommend always prefixing your logs with a string that indicates what you are logging

#

Helps make your logs clear

visual trench
#

thank you

#

pushed

inner wraith
#

K test again and let me know what it logs

visual trench
#

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)
inner wraith
#

What is at line 113

#

Forgot I have your github.

visual trench
#

my print statement

inner wraith
#

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());

visual trench
#

lol computers are weird

inner wraith
#

(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

visual trench
#

thanks, shall I remove the original print we made?

inner wraith
#

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

visual trench
#

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?

inner wraith
#

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?

visual trench
#

it seemed to time out

#

don't think there was a body property

inner wraith
#

You can remove the log for the second result object now btw since we see the button successfully with GPay: true

#

Try to just log response.data instead

visual trench
#

ok

#

I thought the log we made was the second one?

inner wraith
#

Sorry mean the one on line 35

visual trench
#

cool

inner wraith
#

That is working fine so no need to log that anymore

visual trench
#

great

#

so basically, I'm being a pain by using axios? Shall I switch the fetch?

inner wraith
#

No it is just preference

#

Both work fine

visual trench
#

cool

inner wraith
#

I just never really use axios

visual trench
#

do I need to un-jsonify then?

inner wraith
#

Yeah

visual trench
#

here const { clientSecret } = response.json();?

#

remove .json?

inner wraith
#

Yep

#

That should likely be response.data

#

Instead

#

But we will know once we log out the response.data

visual trench
#

const { clientSecret } = response.data();

inner wraith
#

Don't need a function

#

Just response.data

visual trench
#
      console.log(clientSecret);```
inner wraith
#

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)

visual trench
#

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)

#

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

inner wraith
#

(One sec)

visual trench
#

๐Ÿ‘

inner wraith
#

Okay had to step away for a quick sec

visual trench
#

no problem!

inner wraith
#

Let's see....

visual trench
#

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

inner wraith
#

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);

visual trench
#

ah sorry

inner wraith
#

No worries ๐Ÿ™‚

visual trench
#

response data:
Object
client_secret
:
"pi_3MWOnIKANfnETzod1jaUkD9w_secret_Xtez4NmAGqDAYpceOdWDehrBB"
id
:
"pi_3MWOnIKANfnETzod1jaUkD9w"
[[Prototype]]
:
Object

inner wraith
#

Okay nice

#

So you want to set const clientSecret = response.data.client_secret

visual trench
#

ok cool, I'll do that

#

no curly brackets?

#

does it replace 116?

inner wraith
#

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

visual trench
#

thank you

inner wraith
#

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

visual trench
#

right

inner wraith
#

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

visual trench
#

great, done, I can push?

inner wraith
#

Yep

visual trench
#

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

inner wraith
#

Is there a successful payment in your Dashboard?

visual trench
#

and the payment succeeded in the dashboard

inner wraith
#

๐ŸŽ‰

visual trench
#

amazing, I just need a success message on the UI now

inner wraith
#

Yep exactly

visual trench
#

I really appreciate you for this

inner wraith
#

Happy to help!

visual trench
#

feels close now

inner wraith
#

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 ๐Ÿ™‚

visual trench
#

does it look like those blocks are running?

inner wraith
#

Yep

#

ev.complete('success') is what triggers the modal to close

visual trench
#

wow

#

so I can just put some JSX in there?

inner wraith
#

You can also always add logs into those blocks

#

To see them get hit

visual trench
#

ok, I'm gonna try the logs now to start with

inner wraith
#

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!

visual trench
#

thank you very very very much!

#

is there anything I can do to express my gratitude to Stripe?

inner wraith
#

I'll relay it along :).

#

Good luck with the rest of your project!

visual trench
#

thank you!

#

you're awesome