PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | stripe/controllers/FrmStrpLiteActionsController.php +76 -19 6.30 → trunk View file →
@@ -123,13 +123,13 @@
123 123 return $response;
124 124 }
125 125
126 126 if ( ! self::stripe_is_configured() ) {
127 - $response['error'] = __( 'There was a problem communicating with Stripe. Please try again.', 'formidable' );
127 + $response['error'] = __( 'Stripe still needs to be configured.', 'formidable' );
128 128 return $response;
129 129 }
130 130
131 - $customer = self::set_customer_with_token( $atts );
131 + $customer = self::set_customer_with_token( $atts, self::get_customer_id_from_posted_setup_intents( $form->id ) );
132 132
133 133 if ( ! is_object( $customer ) ) {
134 134 $response['error'] = $customer;
135 135 return $response;
@@ -155,15 +155,56 @@
155 155 return FrmStrpLiteAppHelper::call_stripe_helper_class( 'initialize_api' );
156 156 }
157 157
158 158 /**
159 + * Get the customer id from a setup intent that was created for this submission.
160 + * A Stripe Link subscription builds its subscription from the setup intent's customer,
161 + * so reusing that customer here avoids creating a duplicate customer for guests.
162 + *
163 + * @since 6.35
164 + *
165 + * @param int|string $form_id
166 + *
167 + * @return false|string The Stripe customer id, or false if it can't be found.
168 + */
169 + public static function get_customer_id_from_posted_setup_intents( $form_id ) {
170 + $posted_intents = FrmStrpLiteAuth::get_payment_intents( 'frmintent' . $form_id );
171 +
172 + if ( ! is_array( $posted_intents ) || ! $posted_intents ) {
173 + return false;
174 + }
175 +
176 + $setup_intent_ids = array_filter(
177 + $posted_intents,
178 + function ( $intent_id ) {
179 + return str_starts_with( $intent_id, 'seti_' );
180 + }
181 + );
182 +
183 + if ( ! $setup_intent_ids ) {
184 + return false;
185 + }
186 +
187 + $first_setup_intent_id = reset( $setup_intent_ids );
188 + $first_setup_intent_id = explode( '_secret_', $first_setup_intent_id )[0];
189 + $setup_intent = FrmStrpLiteAppHelper::call_stripe_helper_class( 'get_setup_intent', $first_setup_intent_id );
190 +
191 + if ( ! is_object( $setup_intent ) || empty( $setup_intent->customer ) ) {
192 + return false;
193 + }
194 +
195 + return $setup_intent->customer;
196 + }
197 +
198 + /**
159 199 * Set a customer object to $_POST['customer'] to use later.
160 200 *
161 - * @param array $atts
201 + * @param array $atts The action, entry, and form for the payment.
202 + * @param false|string $customer_id The Stripe customer id when it is already known.
162 203 *
163 204 * @return object|string
164 205 */
165 - private static function set_customer_with_token( $atts ) {
206 + private static function set_customer_with_token( $atts, $customer_id = false ) {
166 207 if ( isset( self::$customer ) ) {
167 208 // It's an object if this isn't the first Stripe action running.
168 209 return self::$customer;
169 210 }
@@ -171,8 +212,12 @@
171 212 $payment_info = array(
172 213 'user_id' => FrmTransLiteAppHelper::get_user_id_for_current_payment(),
173 214 );
174 215
216 + if ( $customer_id ) {
217 + $payment_info['customer_id'] = $customer_id;
218 + }
219 +
175 220 if ( ! empty( $atts['action']->post_content['email'] ) ) {
176 221 $payment_info['email'] = apply_filters( 'frm_content', $atts['action']->post_content['email'], $atts['form'], $atts['entry'] );
177 222 $payment_info['email'] = self::replace_email_shortcode( $payment_info['email'] );
178 223 }
@@ -285,11 +330,17 @@
285 330 *
286 331 * @return array
287 332 */
288 333 public static function add_action_defaults( $defaults ) {
334 + // Stripe action options.
289 335 $defaults['plan_id'] = '';
290 336 $defaults['capture'] = '';
291 337 $defaults['stripe_link'] = '';
338 +
339 + // PayPal action options.
340 + $defaults['product_name'] = '';
341 + $defaults['pay_later'] = '';
342 +
292 343 return $defaults;
293 344 }
294 345
295 346 /**
@@ -316,9 +367,9 @@
316 367 public static function before_save_settings( $settings, $action ) {
317 368 $settings['currency'] = strtolower( $settings['currency'] );
318 369
319 370 // Gateway is a radio button but it should always be an array in the database for
320 - // compatibility with the payments submodule where it is a checkbox.
371 + // compatibility with the payments submodule where it is a checkbox (when Authorize.Net is active).
321 372 $settings['gateway'] = ! empty( $settings['gateway'] ) ? (array) $settings['gateway'] : array( 'stripe' );
322 373
323 374 $is_stripe = in_array( 'stripe', $settings['gateway'], true );
324 375
@@ -364,9 +415,21 @@
364 415 * @return string
365 416 */
366 417 public static function create_plan_id( $settings ) {
367 418 $amount = self::prepare_amount( $settings['amount'], $settings );
368 - return sanitize_title_with_dashes( $settings['description'] ) . '_' . $amount . '_' . $settings['interval_count'] . $settings['interval'] . '_' . $settings['currency'];
419 + $parts = array(
420 + sanitize_title_with_dashes( $settings['description'] ),
421 + $amount,
422 + $settings['interval_count'] . $settings['interval'],
423 + $settings['currency'],
424 + );
425 +
426 + if ( isset( $settings['trial_interval_count'] ) && '' !== $settings['trial_interval_count'] ) {
427 + // Include the trial so two actions that differ only by trial length don't share a plan.
428 + $parts[] = $settings['trial_interval_count'];
429 + }
430 +
431 + return implode( '_', $parts );
369 432 }
370 433
371 434 /**
372 435 * If this form submits with ajax, load the scripts on the first page.
@@ -461,16 +524,20 @@
461 524
462 525 $action_settings = self::prepare_settings_for_js( $form_id );
463 526 $found_gateway = false;
464 527
465 - foreach ( $action_settings as $action ) {
528 + foreach ( $action_settings as &$action ) {
466 529 $gateways = $action['gateways'];
467 530
468 531 if ( ! $gateways || in_array( 'stripe', (array) $gateways, true ) ) {
469 532 $found_gateway = true;
470 - break;
471 533 }
534 +
535 + if ( ! empty( $action['layout'] ) && ! in_array( $action['layout'], array( 'accordion', 'tabs' ), true ) ) {
536 + $action['layout'] = '';
537 + }
472 538 }
539 + unset( $action );
473 540
474 541 if ( ! $found_gateway ) {
475 542 return;
476 543 }
@@ -657,17 +724,7 @@
657 724 if ( ! $has_processed ) {
658 725 return $errors;
659 726 }
660 727
661 - $field_id = $field->temp_id ?? $field->id;
662 -
663 - if ( isset( $errors[ 'field' . $field_id . '-cc' ] ) ) {
664 - unset( $errors[ 'field' . $field_id . '-cc' ] );
665 - }
666 -
667 - if ( isset( $errors[ 'field' . $field_id ] ) ) {
668 - unset( $errors[ 'field' . $field_id ] );
669 - }
670 -
671 - return $errors;
728 + return FrmTransLiteActionsController::remove_cc_errors( $errors, $field );
672 729 }
673 730 }