#geimsdin

1 messages ยท Page 1 of 1 (latest)

wooden citrusBOT
sick nimbus
#

It looks like the second mount didn't go well

#

did you mount to a same or different HTML element?

somber wing
#

I guessed so but then the payment is processed correctly

#

I mount to the same HTML element

#

should I empty it before mounting?

sick nimbus
#

I don't think the Payment (or to be correct, the SetupIntent) is processed. The error states confirmSetup() failed

#

I would recommend against using the same HTML div. It only to create unexpected bugs

somber wing
#

Can I just empty it or should I remove from the DOM and recreate?

sick nimbus
#

Let's remove and recreate

somber wing
#

Ok, thanks, will try

somber wing
#

wcnpPaymentElement.parentNode.removeChild(wcnpPaymentElement);

        newWcnpPaymentElement = document.createElement('div');
        newWcnpPaymentElement.setAttribute("id", "wcnp-payment-element");

        wcnpPaymentForm.prepend(newWcnpPaymentElement);
#

I do this: remove and recreate from scratch but I still get the error: "Invalid value for stripe.confirmSetup(): elements should have a mounted Payment Element."

sick nimbus
#

And how are you remounting this div?

somber wing
#

wcnpPaymentForm.prepend(newWcnpPaymentElement);

#

it works, I get a new clean payment form

#

but when I submit I get no errors from stripe but that error in console

sick nimbus
#

But there should be another code block like

const options = {
  clientSecret: '{{CLIENT_SECRET}}',
  // Fully customizable with appearance API.
  appearance: {/*...*/},
};

// Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 2
const elements = stripe.elements(options);

// Create and mount the Payment Element
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
#

You probably need to recreate elements here then calling mount against your newWcnpPaymentElement

somber wing
#

let elements = stripe.elements({
clientSecret: wcNinjaPaymentData.wcNpClientSecret,
loader: 'always',
});

wcnpPayment = elements.create("payment");
wcnpPayment.mount("#wcnp-payment-element");
#

I recall the same function that created it the first time

sick nimbus
#

You sure it has been called? Put some breakpoint?

somber wing
#

I'm prett sure because the payment form appear again and there is no other code mounting it

sick nimbus
#

Hmm I see. any chances the elements passed in confirmSetup() is the old one instead of the new one?

somber wing
#

it is defined inside the function, not a global var, then every execution is created again from scratch

sick nimbus
#

Okie. It seems strange. I would try with a bit different element id

#

But overall, why don't you just refresh your customer in the page again instead of doing this thing? It will only complicated bugs and errors

somber wing
#

I'm trying to handle by ajax for better UX

sick nimbus
#

Ok let's try a different element id, probably #wcnp-payment-element-{timestamp} and somehow passing it with your function. But honestly I am not sure if it works. The DOM tree might be in a weird state after the removal :/

somber wing
#

Ok, I try

sick nimbus
#

If you can generate different element id, it might be a good idea to not remove the first element while appending the 2nd one, to see if it work without the removal logic

#

Even if you have 2 elements on the page, you have different Id and both mounted to different instance of elements

somber wing
#

It doesn't work, even with different ID, I will try to destroy all and recreate

hazy mauve
#

๐Ÿ‘‹ Taking over this thread from orakaro

#

Let me know if you have any follow up question

somber wing
#

Hi

#

I still have the same problem, even destroying completely the object

#

Is there a way to completely delete the created stripe.elements and restart from scratch in the same webpage?

hazy mauve
#

What's the error you're facing?

somber wing
#

Now this: We could not retrieve data from the specified Element.
Please make sure the Element you are attempting to use is still mounted.

#

But the one I want to fix is this: "Invalid value for stripe.confirmSetup(): elements should have a mounted Payment Element."

#

The original one

hazy mauve
#

It sounds like the element is not mounted

somber wing
#

Yes but it is

hazy mauve
#

Could you share the code?

somber wing
#

Sure, let me remove the modifications and I will share here

#

file or directly as a message? it is 208 lines

hazy mauve
#

You can send it as a file

somber wing
#

on line 85 is where I intercept the event "checkout_error" and try to reinitialize the element

hazy mauve
#

With this code, which error does it throw?
"We could not retrieve data from the specified Element. Please make sure the Element you are attempting to use is still mounted." OR
"Invalid value for stripe.confirmSetup(): elements should have a mounted Payment Element"

somber wing
#

I get this now: We could not retrieve data from the specified Element. Please make sure the Element you are attempting to use is still mounted.

hazy mauve
#

Which line does it throw from?

somber wing
#

If I don't remove the childnode but just overwrite I get this: Invalid value for stripe.confirmSetup(): elements should have a mounted Payment Element

#

line 15007 of some stripe js

#

15007 if prettyprint

#

Even if I get this errors in console the payment is passed correctly to stripe and I can find subscription and payment on my dashboard... really strange

hazy mauve
#

Not the line of StripeJS, but the line in your code that triggers the error

somber wing
#

Is not thrown by my code

#

115

#

Is where I intercept the submit

#

Do you have any idea?

#

I guess I found the problem: the first stripe.elements is still there, when I submit the second time the error is displayed 2 times, when I submit the 3rd time it is displayed 3 times

#

It is like adding instances instead of overwriting the old one

#

Then I get back to my first question: how to reinitialize stripe.elements or stripe object directly?

hazy mauve
#

Could you share why you want to re-initialise the elements?

#

What's the use case here?

somber wing
#

The user submit the payment form but doesn't fill some required billing data, woocommerce perform an ajax check and if there is an error stays in the page showing the error message.

#

If I keep the same payment form it will not work because of the setupIntent state that is already changed

#

Then I am forced to unmount the payment and reinitialize the elements with a new client secret

blazing coral
#

Hey! Taking over for my colleague. Let me catch up.

somber wing
#

Please help me

blazing coral
#

Could you please resume your last follow-up Question ?

somber wing
#

quote: "Then I get back to my first question: how to reinitialize stripe.elements or stripe object directly?"

#

if I delete the var it doesn't work, it is still stacking instances

#

Better to say: if I delete the var is better because stacks only 2 instances instead of adding at every submit a new one, but still I want to clean it

blazing coral
somber wing
#

I already shared the code here

#

I initialize stripe, then create the stripe.element... when I need to reload it I delete both stripe var and elements var

#

but still it keeps the old instance in Stripe (I guess) and that is a nonsense

#

elements.clear() in that code is just a test, you can ignore it

blazing coral
#

I initialize stripe, then create the stripe.element... when I need to reload it I delete both stripe var and elements var
I don't understand why you want to delete Stripe and element vars? You should reuse them it's like initializing a builder in your application and once you need to create a new element you juste call it

somber wing
#

Ok, please explain hoiw

#

how

#

Because before I was trying to reuse but since the SetupIntent has already been confirmed I thought that I was forced to do it

blazing coral
#

The SetupIntent is managed by your backend, and StripeJs is in your Frontend

#

So you aren't obliged to reinitialize StripeJs each time

somber wing
#

I don't reinitialize stripejs, ok, but I have to reinitialize the stripe.elements with the new clientsecret, correct?

#

I did as you suggested and now I get this error: wc-ninja-payment-public.js?ver=1.0.0:161 Uncaught (in promise)

blazing coral
#

Each time you get a new secret you should do something like this:

const appearance = {
    theme: 'stripe',
  };
  elements = stripe.elements({ appearance, clientSecret });

  const paymentElement = elements.create("payment");
  paymentElement.mount("#payment-element");

Without re-initializing stripe

somber wing
#

I did initialize only one time and I get wc-ninja-payment-public.js?ver=1.0.0:161 Uncaught (in promise)

#

if ( c === 0 ) {
//Initialize Stripe
wcnpStripe = Stripe(wcNinjaPaymentData.wcNpPubKey);
c++;
}

#

Every submit I get more errors

blazing coral
#

Could you please share all the Stacktrace in order to see what issue are you getting ?

somber wing
#

from console?

viral yew
#

Hi! I'm taking over this thread.

#

Can you clarify why you want to unmount remount the PaymentElement on your page? What are you trying to achieve?

somber wing
#

Because I need it in case the order fails for external cause and I have to resubmit the payment

versed ocean
#

makes sense I suppose. What specific problem are you having? This thread has been open for 7 hours so we can't really keep helping this way, it's clearly not working.

somber wing
#

You are the 5th trying to help me

versed ocean
somber wing
#

I really believe that something is not correct in the Stripe js object but I'm figuring out how to handle it in reverse: if checkout is succesful then submit to stripe... then I will not need a second payment to be mounted

versed ocean
#

ultimately I doubt we really support this level of dynamism in recreating the stripe.js objects, it's not at all how most sites integrate it

somber wing
#

I understand

#

I'm just trying to offer the best UX

versed ocean
#

we create various iframes and context in global scope so deleting things and such will cause problems. Really I'd just reload the full page or something and keep things simple rather than spend more time on this