solspace / craft-freeform

Freeform for Craft: The most reliable form builder that's ready for wherever your project takes you.
https://docs.solspace.com/craft/freeform/v5/
Other
48 stars 61 forks source link

Stripe could not load payment element error #1537

Closed icreatestuff closed 1 month ago

icreatestuff commented 2 months ago

What happened?

We have a form with a Stripe field set to allow dynamic payments via an 'amount' field.

Using the form Rules we have the Stripe field set to only display if a checkbox is ticked.

The checkbox appears before the amount field in the order of fields within the form.

We've noticed that if the checkbox is ticked, there is an AJAX request sent to initialise the Stripe Element which fails because there is so far no 'Amount' set - that makes sense. However when an amount is then set within the field, that AJAX request isn't being re-run meaning the Stripe element is then never initialised.

I believe this has only started to be the case since Freeform v5.6.3. Beforehand it seemed as though any change or keyup for the amount field would re-trigger the Javascript.

Errors and Stack Trace (if available)

No response

How can we reproduce this?

  1. Create a form that uses a Stripe field set to have a dynamic amount based on a number input field
  2. Have the Stripe field hidden until a checkbox is ticked
  3. Tick the checkbox and notice the Stripe field appear but is not rendered
  4. Enter an amount in the number field and notice the Stripe field remains uninitialised

Freeform Edition

Pro

Freeform Version

5.6.3

Craft Version

4.12.5

When did this issue start?

No response

Previous Freeform Version

5.6.2

kjmartens commented 1 month ago

Hi @icreatestuff,

Just to confirm, you're saying that you have an "Amount" field that has no value... and when you attempt to load the Stripe field (by checking the checkbox field), the Stripe field doesn't show (and likely errors on the Amount field?). Then when you add a value to the Amount field, nothing updates in the form and the Stripe field still doesn't show?

If so, this is expected behavior in Freeform 5, as the implementation of Stripe we're using expects that the payment is ready to go by the time the Stripe Payments field is loaded. If you wish to work around this, there are two options:

  1. It's highly recommended that the Stripe Payments field be located on "page 2" (or last page of form). If you absolutely don't want to do this, and keep it a single page form... here's the workaround
  2. Ensure that the Amount field contains a value of 1 or more upon page load (so set the default to 1 or greater.

Please let me know if I am understanding this correctly. 🙂

icreatestuff commented 1 month ago

Hi @kjmartens,

That's an accurate description. I guess my main point was that I'm fairly certain the behaviour has changed between 5.6.2 and 5.6.3 as described. Before, any change to the amount re-triggered the javascript to check for and initialise the Stripe Payment Element. Now, it only attempts to initialise it once, which if it fails causes a broken a form.

As a way to try and work around the change in 5.6.3 I've setup 2 rules for displaying the Stripe field. Show the field if:

  1. The checkbox field is ticked AND
  2. The amount field is greater than 0

This works to render the Stripe Payment Element but now I get a Javascript error in the console when submitting the form, and the submission never completes.

Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmPayment(): the 'elements' provided was created by a different Stripe instance. Please use the same Stripe instance to create the 'elements' and call stripe.confirmPayment().

freeform.js?v=1727415928:2
kjmartens commented 1 month ago

Sorry for the delay @icreatestuff,

In my testing, the refresh still seems to happen accurately when everything is configured correctly. When you say that you have a conditional rule to show the Stripe field if the amount field is greater than 0, this won't solve the issue either. The Stripe payment element field needs to be fed a value greater than 0 immediately at the form's load, not somewhere along the way. The approach you describe is flawed in that regard.