- Issue created by @wheelercreek
- πΊπΈUnited States wheelercreek
Looks like if I create the payment gateway as a card element rather than payment element, that works. So I think that will do for me.
I'm getting the same error. Payment Element is the preferred method with Stripe
- πΊπ¦Ukraine marchuk.vitaliy Rivne, UA
@wheelercreek @jeffgtr
This sounds like a cache issue. Can you try clearing the cache and check again?
And you should definitely use the Stripe Payment Element plugin because the Stripe Card Element uses a deprecated API. - π«π·France nicolas bouteille
Hi,
We have Payment Element enabled for 3 days now in production.
A lot of payments have successfully passed.
I just saw this same error pass right now for a customer
IntegrationError: Invalid value for stripe.confirmPayment(): elements should have a mounted Payment Element or Express Checkout Element.
At review step.
This error came along with another error
The "stripe_payment_element" plugin did not specify a "offsite-payment" form class
Coming from
commerce/modules/payment/src/Plugin/Commerce/InlineForm/PaymentGatewayForm.php(103): Drupal\Core\Plugin\PluginFormFactory->createInstance()
commerce/modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentProcess.php(218)$pane_form['offsite_payment'] = $inline_form->buildInlineForm($pane_form['offsite_payment'], $form_state);
seems to be the line that triggers the error
I have no clue what the customer did or faced to generate this error.
I am surprised the customer could access the "payment process" step since the PaymentIntent was never confirmed...
Did he try to hack the checkout flow and submit the pane manually in js? - π«π·France nicolas bouteille
Hi,
I discovered a use case when this can happen. A client sent me an screenshot of the review step on her iPad. PaymentElement did not load correctly so it was missing. (could not reproduce bug on 2 iPads btw)
There was only two checkboxes of CGVs that we enforce users to check before they can submit, and the "Pay and complete purchase" button.
Because an error had occured while mounting PaymentElement, the JS code that is supposed to override the form submit (prevent default etc) never got executed.
So when she submitted the form, she went the regular Commerce way of submitting the Review step and then going to the PaymentProcess step. Leading to this specific error.In order to prevent this from happening in the future :
1/ we disable the submit button in case error happen that prevent our code from overriding submit in JS
hereif (!drupalSettings.commerceStripePaymentElement || !drupalSettings.commerceStripePaymentElement.publishableKey) { myCustomLogErrorCode() // custom code to log the error and send us an alert mail Drupal.commerceStripe.displayError(drupalSettings.utils.CUSTOM_ERROR_MESSAGE); $("form.my-custom-checkout-flow-form .form-actions input.form-submit").prop("disabled", true); return; }
and here we actually added a try catch :
try { // Create an instance of Stripe Elements. var elements = stripe.elements(settings.createElementsOptions); var paymentElement = elements.create('payment', settings.paymentElementOptions); paymentElement.mount('#' + settings.elementId); } catch (e) { myCustomLogErrorCode() // custom code to log the error and send us an alert mail Drupal.commerceStripe.displayError(drupalSettings.utils.CUSTOM_ERROR_MESSAGE); $("form.my-custom-checkout-flow-form .form-actions input.form-submit").prop("disabled", true); return; }
What we also did, because in our case even when confirming payment with an existing payment method we always use the return_url and never submit the form in JS, we also added a custom check in validateForm of our CheckoutFlow plugin that prevents the review step from ever being submitted. The only way to pass this step in our case is throught the return_url passed to stripe.confirmPayment()
public function validateForm(array &$form, FormStateInterface $form_state) { parent::validateForm($form, $form_state); if ($form['#step_id'] === 'review') { myCustomLogErrorCode() // custom code to log the error and send us an alert mail $form_state->setError($form, CustomUtils::CUSTOM_ERROR_MESSAGE); } }
- π¬π§United Kingdom gillarf
I'm seeing the same error consistently on our site.
Did anyone get to the bottom of this?
- π«π·France nicolas bouteille
Yes it happens when PaymentElement JS does not load correctly and customers can submit the Review step form without actually paying. Read above for more details. I have not been able to understand how / when this happens though.
- π«π·France nicolas bouteille
I have two new information about this:
First, Stripe Payment Element not loading/displaying can be because of js.stripe.com/v3 being blocked.
In our case OneTrust cookie consent tool was blocking Stripe JS until we set this cookie as Strictly Necessary.Second, when we face the error
The "stripe_payment_element" plugin did not specify a "offsite-payment" form class
we can conclude that we've reached the line
$pane_form['offsite_payment'] = $inline_form->buildInlineForm($pane_form['offsite_payment'], $form_state);
in PaymentProcess.php
However, we are not supposed to reach this line with PaymentElement as a Payment Gateway inside PaymentProcess.php
we are supposed to enter the preceding if statement:if ($payment_gateway_plugin instanceof SupportsStoredPaymentMethodsInterface && !$this->order->get('payment_method')->isEmpty()) { $payment->payment_method = $this->order->get('payment_method')->entity; $payment_gateway_plugin->createPayment($payment, $this->configuration['capture']); $this->checkoutFlow->redirectToStep($next_step_id); }
Which directly redirects to the next step, so the rest of the code should not be executed...
So chances are we did not enter it because $this->order->get('payment_method')->isEmpty()
So you can start digging why the order does not have a payment_method at that moment... which is not supposed to happenBTW, I have noticed in StripePaymentElement->onReturn()
there is no$order->save()
after$this->createPaymentMethod($payment_method, $payment_details); $order->set('payment_method', $payment_method);
if nothing goes wrong the order eventually gets saved later on with the payment_method associated, but in our case it seems something went wrong (it seems to user got logged out...), so the payment method was actually created but never associated with the order, so we were facing the error
The "stripe_payment_element" plugin did not specify a "offsite-payment" form class
because the order did not have any payment_method attached when reaching "payment" step.I had to manually unlock the order + set the payment_method ID in the payment_method column of the order directly in the database and delete the order entry in cache_entity to unblock the situation...
- First commit to issue fork.
- Merge request !99Issue #3416076 by TomTech, Nicolas Bouteille, wheelercreek, jeffgtr, vmarchuk,... β (Merged) created by TomTech
-
TomTech β
committed dbdf4a18 on 8.x-1.x
Issue #3416076 by TomTech, Nicolas Bouteille, wheelercreek, jeffgtr,...
-
TomTech β
committed dbdf4a18 on 8.x-1.x
- Assigned to TomTech
- Status changed to Fixed
5 months ago 12:45am 18 June 2024 - πΊπΈUnited States TomTech
The code was originally written in a way that did not expect to get to this particular code path. We can see that it is possible.
As @nicolas-bouteille noted, if the js does not load properly, the form can be submitted, causing this error.
We've added two protections around this:
1. The form is now loaded with the submit button disabled, until the js properly loads. We're NOT disabling it during initial js load, because it is possible that the js might never load (e.g. if a 3rd party script error causes js to fail), or even if it does, there is a race condition that the button is enabled until the js executes. (This does mean that a user can encounter a scenario where the button is NOT enabled, since the script did not load/execute, but this is at least a better experience than a WSOD.)2. If a user is still somehow able to submit the form (much less likely now), we have implemented the offsite form, though we simply redirect them back to the review page. Hopefully, any js loading issues will be resolved on the return trip.
The other scenario mentioned involves an error occurring during the onReturn() callback. If there is a reproducible case there, go ahead and open up a new issue so that situation can be handled appropriately.
Automatically closed - issue fixed for 2 weeks with no activity.
- πΊπ¦Ukraine gilmord πΊπ¦Ukraine
I updated commerce_stripe module, and now payment button is disabled, I assume this is due to this issue
No special steps - add to cart, go to checkout, enter billing information, on payment step fill card details - unable to submit, button is disabled - πΊπ¦Ukraine gilmord πΊπ¦Ukraine
Js file was update, but library version not updated
So button disabled with php code in stripe review payn, and js stays cached by cloudflare, varnish etcThis needs to be fixed.
- π«π·France nicolas bouteille
This morning again I got a case where the payment_method had not been correctly associated to the order, leading later on to the error "The "stripe_payment_element" plugin did not specify a "offsite-payment" form class"...
The payment_method had been created, but the payment_method column was null for the order.
You did not tell me what you think about adding
$order->save()
after$this->createPaymentMethod($payment_method, $payment_details); $order->set('payment_method', $payment_method);
in StripePaymentElement->onReturn()
any reason it is not done? - π¬π§United Kingdom brenm
I've got this exact same issue.
New Drupal 10 install - 10.3.6
Drupal Commerce 2.40
Drupal Commerce Stripe 1.1I get to the review stage on checkout but the Stripe payment details don't appear.
I click the "Pay and Complete Purchase" button
I get the errorDrupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "stripe_payment_element" plugin did not specify a "offsite-payment" form class in Drupal\Core\Plugin\PluginFormFactory->createInstance() (line 41 of /app/web/core/lib/Drupal/Core/Plugin/PluginFormFactory.php).
I press the back button and then I refresh the page. The stripe payment form appears.
This is happening in both TEST and LIVE modes. I've double and triple checked my public and private keys. I'm using "Stripe Payment Element"
How do I resolve this? It's driving me nuts!