#Srujan-PaymentRequest

1 messages · Page 1 of 1 (latest)

chrome star
#

Hi there, can you double check if you are using the test publishable key?

coarse walrus
#

I believe I am, the key starts with pk_test_ and works for the card element flow I have setup

chrome star
#

A test publishable key starts with pk_test_

coarse walrus
#

yup^^

chrome star
#

Is the complete key used in your react app

coarse walrus
#

Yes

chrome star
#

Can you share with me the code?

coarse walrus
#

I believe it's working since I am able to call other stripe functions and I integrated the CardElement and have gotten successful payments with that flow

#

Sure

#
import fetchClientSecret from '../../../utils/Payments/fetchClientSecret';

interface PaymentOptionsProps {
  totalPrice: number;
}

const PaymentOptions = ({ totalPrice }: PaymentOptionsProps) => {
  const elements = useElements();
  const stripe = useStripe();

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!stripe || !elements) {
      return;
    }

    try {
      const clientSecret = await fetchClientSecret(totalPrice);
      const cardElement = elements.getElement(CardElement);
      if (cardElement) {
        const confirmPaymentResponse = await stripe.confirmCardPayment(
          clientSecret,
          {
            payment_method: {
              card: cardElement
            }
          }
        );
        const paymentIntent = confirmPaymentResponse.paymentIntent;
        console.log(paymentIntent, 'paymentIntent');
      }
    } catch (error) {
      console.error(error); // handle stripe error
    }
  };

  // TO DO:
  // This page will be Payment Options
  // It will contain the bottom sheet that contains Google Pay button (if available) and CC input option
  // CC Input Option will move to another bottom sheet with the form that is below and a submit pay button
  return (
    <>
      <h1>Payment Options</h1>
      <form id="payment-form" onSubmit={handleSubmit}>
        <label htmlFor="card-element">Card</label>
        <CardElement id="card-element" />
        <button>Pay</button>
      </form>
    </>
  );
};

export default PaymentOptions;```
#
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe, Stripe } from '@stripe/stripe-js';
import { stripeConfig } from '../../config/stripeConfig';

interface StripeWrapperProps {
  children: React.ReactNode | React.ReactNode[];
}

const StripeWrapper = ({ children }: StripeWrapperProps) => {
  const [stripeObject, setStripeObject] = useState<Stripe | null>(null);
  const accountId = stripeConfig.accountId;
  // This function will re-run if the accountId prop changes.
  useEffect(() => {
    const fetchStripeObject = async () => {
      // If there is no accountId, do not run the loadStripe function.
      if (accountId) {
        const res = await loadStripe(stripeConfig.publicKey, {
          stripeAccount: accountId
        });
        // When we have got the Stripe object, pass it into our useState.
        setStripeObject(res);
      }
    };
    fetchStripeObject();
  }, [accountId]);

  //To do: If not loaded, implement spinner or loading status

  // Once we have the Stripe object, load everything.
  return <Elements stripe={stripeObject}>{children}</Elements>;
};

export default StripeWrapper;
#

^^I created this StripeWrapper since the app will have different stripe accounts associated with it

chrome star
#

Can you check if the stripeObject is ready when the nested component is rendered?

coarse walrus
#

Sure

#

It seems that the stripeObject is ready at the time I click the PaymentRequestButton

#

Also are you guys hiring haha? I wanna apply

chrome star
#

Where is the PaymentRequestButton ? I only see CardElement in your code.

coarse walrus
#
  const stripe = useStripe();
  const [paymentRequest, setPaymentRequest] = useState<PaymentRequest>();

  useEffect(() => {
    if (stripe) {
      const pr = stripe.paymentRequest({
        country: 'US',
        currency: 'usd',
        total: {
          label: paymentItem.label,
          amount: paymentItem.amount
        }
      });
      // Check the availability of the Payment Request API.
      pr.canMakePayment()
        .then((result) => {
          if (result) {
            setPaymentRequest(pr);
          }
        })
        .catch((err) => console.error(err));
    }
  }, [stripe, paymentItem]);

  if (stripe && paymentRequest) {
    paymentRequest.on('paymentmethod', 
#
      // Confirm the PaymentIntent without handling potential next actions (yet).
      const clientSecret = await fetchClientSecret(paymentItem.amount);
      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.
        }
      }
    });
  }
  if (paymentRequest) {
    return <PaymentRequestButtonElement options={{ paymentRequest }} />;
  }
  return <></>;
};

export default PaymentButton;```
#

Should I put the event listener in the parent component?

chrome star
#

Is the <PaymentButton> wrapped inside <Elements> ?

coarse walrus
#

Yeah

#

It's far down the list but the StripeWrapper wraps the whole App, we have routes to /checkout which renders the Checkout page which renders PaymentOptions and PaymentButton posted above

#

The odd thing is though that I can get a successful payment and a paymentIntent obj returned from calling stripe.confirmCardPayment on the CardElement flow, but none of my console logs from within the event listener get triggered when I hit the pay button from the google pay sheet

#

I'm also running the app locally and porting through ngrok so I can serve https and ssl since stripe requires that

chrome star
#

Can you share with me your merchant ID? you can find it from the Stripe Dashboard -> Settings ->Account Details

coarse walrus
#

is that the same as accountID? I don't have access to stripe dashboard currently, but I can get access tomorrow

#

Would it start with acct_?

chrome star
#

Yes

coarse walrus
#

'acct_1LG9DeR8BkSiL135'

chrome star
#

Thanks, give me a sec to check your account

coarse walrus
#

Appreciate it Jack!

chrome star
#

Hmm, this is custom account. and I don't see you are making any destination charges.

coarse walrus
#

one sec, lemme try with the CC input see if anything shows up

chrome star
#

I mean you are making direct charges on custom account, which is not recommended.

coarse walrus
#

Hmm, so what is recommended?

#

We have a backend team that set this account up so I'm trying to understand what the heck they did

chrome star
#

You should use destination charge or separate charges and transfers

coarse walrus
#

Could you send me a link to some docs?

chrome star
#

Stripe recommends using destination charges for Express or Custom accounts.

coarse walrus
#

Thank you

#

But I guess the question remains, is the error because these accounts aren't properly configured? It seems only related to google pay as far as I can tell

chrome star
#

It's not related, but i just want to let you know the best practices of using Stripe Connect.

#

Is there a public URL where I can visit and reproduce the issue?

coarse walrus
#

Yes, in order to reproduce you'll need to run chrome to see google pay. If you want to test out the card element input you'd either have to run chrome with cors disabled somehow or with safari cors disabled. This is local testing...in production we won't have cors error since the endpoint for the client secret fetch will have the same origin

#

Any way I can share this link with you privately?

chrome star
#

Sure, you can DM me

#

I've opened the link and the Google Pay button works for me

coarse walrus
#

You don't get an error after clicking Pay?

chrome star
#

No error

coarse walrus
#

Are you running on chrome?

#

With any specific configurations?

chrome star
#

Yes, and I just have an active card in my Google Pay account

coarse walrus
#

So you're using a real card or test card? You're not using the test card suite ?

chrome star
#

Real card

coarse walrus
#

That's probably the issue then for me...I was using the test card suite

#

Hmm...I'm still getting the same error with a real card

chrome star
#

Test again in incognito mode?

coarse walrus
#

I just keep getting unexpected developer error for some reason

chrome star
#

Can you share with me a screenshot?

coarse walrus
#

Gets hung on that processing page

chrome star
#

Any errors in the console?

#

Ah, I shouldn't advise the incognito mode, your Google account is not logged in.

coarse walrus
#

Timed out waiting for a PaymentResponse.complete() call. No other error showing this time

#

Ah I see

chrome star
#

Can you try another Google account?

coarse walrus
#

I mean I signed in fine and saw my saved cards

chrome star
#

Did you save the card in Google Pay account or in Chrome browser? because they are different

coarse walrus
#

Google pay

#

I'll try it with a different google account and try setting up another card I guess