#reikoBooop

1 messages · Page 1 of 1 (latest)

gentle kelpBOT
river mauve
#

Hi there, can you share with me the relevant code?

quick ocean
#

Hi there its the base code that I have, I think its caused by calling discount endpoint (which created by us). When we call discount api, it will return new totalAmount and cartObject.totalAmount is the one in below code.

const [options, setOptions] = useState<StripeElementsOptions | undefined>(undefined);
const [stripeCardPromise, setStripeCardPromise] = useState<Stripe | null>(null);

useEffect(() => {
const getData = async () => {
if (process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY && cartObject) {
const stripeObject = await loadStripe(process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY); // getting stripe object for Stripe credit card element payment

    setOptions({
      mode: 'payment',
      // discounted amount should reflect to card payment
      amount: cartObject.totalAmount,
      currency: 'aud',
      payment_method_types: ['card'],
      paymentMethodCreation: 'manual',
      appearance: {
        theme: 'stripe',
        variables: {
          colorPrimary: '#0570de',
          colorBackground: '#ffffff',
          colorText: '#30313d',
          colorDanger: '#df1b41',
          fontSizeBase: '12px',
          borderRadius: '5px',
          spacingUnit: '4.25px'
        },
        rules: {
          '.Label': {
            textTransform: 'uppercase',
            fontSize: '1rem',
            marginBottom: '0.25rem',
            color: '#4a5568'
          }
        }
      }
    });

    if (stripeObject) {
      setStripeCardPromise(stripeObject);
    }
  }
};

if (process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY && cartObject) getData();

}, [cartObject?.totalAmount]);

#

// Discount
const [discountPending, setDiscountPending] = useState(false);
const [discountTotal, setDiscountTotal] = useState(0);

const handleDiscount = async () => {
setDiscountPending(true);
const { data: cartWithDiscount, error: cartWithDiscountError } = await getDiscount({
cartId: cartObject?._id,
discountCode: removeWhiteSpace(forms.discount)
});
if (cartWithDiscount) {
setCartObject({ ...cartWithDiscount, paymentIntentClientSecret: cartObject?.paymentIntentClientSecret });

  setDiscountPending(false);
  setShowDiscountModal(false);
}
if (cartWithDiscountError) {
  setValidation({ ...validation, discount: "The code you entered doesn't exist. Please check and try again." });
  setDiscountPending(false);

  console.log(cartWithDiscountError);
}

};

#

{/* manual card */}
{Object.keys(selectedPayment).length > 0 && stripeCardPromise !== null && options !== null ? null : (
<div className="w-full md:w-1/2 px-3">
<Elements stripe={stripeCardPromise} options={options}>
<CreditCardForm
setErrorMessage={setErrorMessage}
setPageIsLoading={setPageIsLoading}
checkoutData={checkoutData}
forms={forms}
handleChange={handleChange}
cartObject={cartObject}
setTransaction={setTransaction}
validation={validation}
setValidation={setValidation}
/>
</Elements>
</div>
)}

river mauve
#

It looks like loadStripe is called again when cartObject?.totalAmount changes. I don't think it's necessary to do this

quick ocean
#

okay

#

let me take the loadStripe out from the useEffect

river mauve
quick ocean
#

Sorry I had look the doc but how do I use this?? If you can let me know where I can use this

river mauve
#

I assume you'll update the amount of the PaymentIntent when the cartObject?.totalAmount changes? am I righjt?

quick ocean
#

Yes that correct

river mauve
#

OK, I guess you send a request from frontend to you backend to update the PaymentIntent, once your frontend receives the response from your backend, you can call stripe.fetchUpdateso that Elements can fetch the update from the assocaited PaymentIntent.

quick ocean
#

Ive added const { error: fetchUpdatesError } = await elements.fetchUpdates();
if (fetchUpdatesError) {
console.log('fetchUpdatesError', fetchUpdatesError);
return;
}
just before const { error, paymentMethod } = await stripe.createPaymentMethod({
elements,
params: {
billing_details: {
email: forms.email
}
}
});
But then I get below error, what am i doing wrong?

Uncaught (in promise) IntegrationError: In order to call fetchUpdates, you must pass a valid PaymentIntent or SetupIntent client secret when creating the Elements group.

e.g. stripe.elements({clientSecret: "{{CLIENT_SECRET}}"})
at t.<anonymous> (v3:1:291013)
at t.fetchUpdates (v3:1:64873)
at handleCreditCard (CreditCardForm.tsx:84:1)

river mauve
#

Did you pass a valid client_secret to stripe.elements() ?

quick ocean
#

Sorry I never passed client_secret to stripe.elements, quite frankly I dont even know how I can pass client_secret to elements

river mauve
quick ocean
#

Similar but I believe it was different doc I was following...
I tried to pass the clientSecret but somehow I get type error Type 'string' is not assignable to type 'undefined'.ts(2322) but its not undefined i am passing client secret starting with pi_ and has secret in the middle
useEffect(() => {
const getData = async () => {
if (cartObject && cartObject?.paymentIntentClientSecret) {
setOptions({
mode: 'payment',
clientSecret: cartObject.paymentIntentClientSecret,

      // discounted amount should reflect to card payment
      amount: cartObject.totalAmount,
      currency: 'aud',
      payment_method_types: ['card'],
      paymentMethodCreation: 'manual',
      appearance: {
        theme: 'stripe',
        variables: {
          colorPrimary: '#0570de',
          colorBackground: '#ffffff',
          colorText: '#30313d',
          colorDanger: '#df1b41',
          fontSizeBase: '12px',
          borderRadius: '5px',
          spacingUnit: '4.25px'
        },
        rules: {
          '.Label': {
            textTransform: 'uppercase',
            fontSize: '1rem',
            marginBottom: '0.25rem',
            color: '#4a5568'
          }
        }
      }
    });
  }
};

if (cartObject?.paymentIntentClientSecret) getData();

}, [cartObject]);

#

Sorry I was passing wrong client secret, once sec

river mauve
#

I'd also suggest you do a conditional rendering that only renders Elements if client_seret is available

quick ocean
#

The documentation you sent across is bit different from what I followed...the documation that I used I could get paymentMethod id from stripe.cretatePaymentMethod() then I can pass the paymentMethod.id to get paymentIntent.

river mauve
#

What document are you following? send me the link

quick ocean
river mauve
#

OK. It's still the same, you need to create a PaymentIntent upfront in order to render the PaymentElement

quick ocean
#

but with the document I sent through, I only get integration error if I have different totalAmount so I can technically use the initial doc right?

#

I just confused why changing totalAmount cause the integration error to start with?

river mauve
#

Did you see the PaymentElement rendered successfully before changing the amount?

quick ocean
#

yes it does render perfectly, in fact there is no error if I dont change the amount and payment goes through fine

river mauve
#

When you change the amount, do you also change anything related to Stripe?

quick ocean
#

only the option property as I am passing amount to Elements from the options
setOptions({
mode: 'payment',

      // discounted amount should reflect to card payment
      amount: cartObject.totalAmount,
      currency: 'aud',
      payment_method_types: ['card'],
      paymentMethodCreation: 'manual',
      appearance: {
        theme: 'stripe',
        variables: {
          colorPrimary: '#0570de',
          colorBackground: '#ffffff',
          colorText: '#30313d',
          colorDanger: '#df1b41',
          fontSizeBase: '12px',
          borderRadius: '5px',
          spacingUnit: '4.25px'
        },
        rules: {
          '.Label': {
            textTransform: 'uppercase',
            fontSize: '1rem',
            marginBottom: '0.25rem',
            color: '#4a5568'
          }
        }
      }
    });
  }
};
river mauve
quick ocean
#

Yes it is, the weird thing is that I get integration error only when I have change totalAmount and type in phone number (which is stored in completely separate state)
so not necessary changing the totalAmount is causing this integration error
following is the summary of when I encounter the error. I initially thought that phone number is triggering this error but seems more like combination of both. On top of that, we actually did not have this error previously, we just encounter this error from this week

with phone number + different totalAmount -> error
without phone number + different totalAmount -> success
with phone number + same totalAmount -> success
without phone number + same totalAmount -> success

river mauve
#

Are you using AddressElement to collect the phone number?

quick ocean
#

no im using separate input field to collect phone number

river mauve
#

OK, so you build your own input field to collect phone? hmm, how can your input field affect stripe elements?

quick ocean
#

not entirely sure how.... im also using separate input field for email address but that doesn't seem to have any affect on stripe elements

river mauve
#

Can you remove the phone field temporarily and see if it works?

quick ocean
#

Yes if I remove phone field it does work with same amount & different amount

#

I initially thought Stripe element have same field of phone so I change name to phoneNumber but didnt change anything
<input
className={shadow-input appearance-none border ${ validation.phoneNumber ? 'border-warning' : null } rounded-md w-full py-3 px-2 text-xs text-gray-700 leading-tight focus:outline-none focus:shadow-outline}
type="text"
placeholder="04123 456 789"
name="phoneNumber" // used to be phone
value={forms.phoneNumber}
onChange={handleChange}
onBlur={checkPhone}
/>

river mauve
#

how do you put this input and stripe elements together?

quick ocean
#

like below, its not even in the same component.. PaymentElement tag is inside of CreditCardForm
<input
className={shadow-input appearance-none border ${ validation.phoneNumber ? 'border-warning' : null } rounded-md w-full py-3 px-2 text-xs text-gray-700 leading-tight focus:outline-none focus:shadow-outline}
type="text"
placeholder="04123 456 789"
name="phoneNumber"
value={forms.phoneNumber}
onChange={handleChange}
onBlur={checkPhone}
/>
{/* manual card */}
{Object.keys(selectedPayment).length > 0 && stripeCardPromise !== null && options !== null ? null : (
<div className="w-full md:w-1/2 px-3">
<Elements stripe={stripeCardPromise} options={options}>
<CreditCardForm
setErrorMessage={setErrorMessage}
setPageIsLoading={setPageIsLoading}
checkoutData={checkoutData}
forms={forms}
handleChange={handleChange}
cartObject={cartObject}
setTransaction={setTransaction}
validation={validation}
setValidation={setValidation}
/>
</Elements>
</div>
)}

river mauve
#

Hmm, that's really strange

quick ocean
#

I know its quite odd one

quick ocean
#

does stripe offer input field for phone number?