{"id":19003334,"date":"2026-08-26T08:47:23","date_gmt":"2026-08-26T08:47:23","guid":{"rendered":"https:\/\/wordpress.org\/support\/topic\/missing-validate-required-css-class-breaks-stripe-payment-method-creation\/"},"modified":"2026-08-26T08:47:23","modified_gmt":"2026-08-26T08:47:23","slug":"missing-validate-required-css-class-breaks-stripe-payment-method-creation","status":"publish","type":"topic","link":"https:\/\/wordpress.org\/support\/topic\/missing-validate-required-css-class-breaks-stripe-payment-method-creation\/","title":{"rendered":"Missing validate-required CSS class breaks Stripe payment method creation"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Custom checkout fields of type <code>radio<\/code>, <code>select<\/code>, <code>multicheckbox<\/code>, <code>multiselect<\/code> and <code>file<\/code> rendered by this plugin are missing the <code>validate-required<\/code> CSS class on their wrapper element when marked as required, even though the field is correctly flagged <code>required =&gt; true<\/code> in the PHP field definition.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The cause is in <code>lib\/view\/frontend\/class-fields-filter.php<\/code>, method <code>custom_field()<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if ( $args&#091;'required'] ) {\n    \/\/ $args&#091;'class']&#091;] = 'validate-required';\n    $required = '&amp;nbsp;&lt;abbr class=\"required\" title=\"' . esc_attr__( 'required', 'woocommerce-checkout-manager' ) . '\"&gt;*&lt;\/abbr&gt;';\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The line that adds the <code>validate-required<\/code> class to <code>$args['class']<\/code> is commented out. As a result, the field visually shows a required asterisk, but the rendered <code>&lt;p class=\"form-row ...\"&gt;<\/code> wrapper never receives <code>validate-required<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This class is the standard convention WooCommerce core (and other plugins) use client-side to detect empty required fields during checkout validation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Impact:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This went unnoticed for a long time because it only affected the visual &#8220;empty required field&#8221; highlighting for these field types. However, WooCommerce Gateway Stripe 10.9.0 (released 2026-08-17) added stricter client-side validation of required billing fields before creating\/confirming the Stripe payment intent (see their changelog: &#8220;Validate customer details against required billing fields from checkout before sending to Stripe&#8221;, &#8220;Prevent unnecessary Stripe payment method creation when shortcode checkout has empty required fields&#8221;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because of the missing <code>validate-required<\/code> class, this new Stripe logic gets confused for sites that have at least one required <code>radio<\/code>\/<code>select<\/code>\/<code>multicheckbox<\/code>\/<code>multiselect<\/code>\/<code>file<\/code> field added via this plugin. The practical symptom: <strong>checkout fails on every single order paid by Stripe (card)<\/strong>, with the WooCommerce Stripe log showing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>The information for creating and confirming the intent is missing the following data: payment_method.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">i.e. the checkout form submits to the server, but the client-side Stripe payment method (<code>pm_xxx<\/code>) was never attached before submission.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Steps to reproduce:<\/strong><\/p>\n\n\n\n<ol>\n<li>Add a required custom billing field of type &#8220;Multiple checkbox&#8221; (or radio\/select\/multiselect\/file) via WooCommerce Checkout Manager.<\/li>\n\n\n\n<li>Enable WooCommerce Gateway Stripe 10.9.0+ with the credit card (UPE) payment method.<\/li>\n\n\n\n<li>Go through checkout and pay by card.<\/li>\n\n\n\n<li>Payment fails; WooCommerce &gt; Status &gt; Logs &gt;&nbsp;<code>woocommerce-gateway-stripe<\/code>&nbsp;shows the &#8220;missing payment_method&#8221; error above.<\/li>\n\n\n\n<li>Disabling WooCommerce Checkout Manager, or removing the &#8220;required&#8221; flag from the affected field, makes checkout succeed again.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Suggested fix:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Uncomment the line in <code>class-fields-filter.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if ( $args&#091;'required'] ) {\n    $args&#091;'class']&#091;] = 'validate-required';\n    $required = '&amp;nbsp;&lt;abbr class=\"required\" title=\"' . esc_attr__( 'required', 'woocommerce-checkout-manager' ) . '\"&gt;*&lt;\/abbr&gt;';\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">so the rendered markup matches what the field definition already declares.<\/p>\n","protected":false},"template":"","class_list":["post-19003334","topic","type-topic","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19003334","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic"}],"about":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19003334\/revisions"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/media?parent=19003334"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}