PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.15
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.15
6.2.15 6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 All 197 releases
← All changes | app/Modules/Payments/PaymentHandler.php +55 -7 6.2.11 → 6.2.15 View file →
@@ -27,8 +27,30 @@
27 27 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\StripeSettings;
28 28
29 29 class PaymentHandler
30 30 {
31 + /**
32 + * A reversed order (refund/partial-refund/cancel) must not fire the deferred
33 + * submission action pipeline (notifications, integrations, user registration)
34 + * when it is later reached via a double-opt-in / admin-approval confirmation or a
35 + * subscription webhook. The normal paid flow is unaffected (latch already set),
36 + * as are non-payment forms and unsettled-but-not-reversed states (pending/failed).
37 + */
38 + public function skipActionsForReversedPayment($shouldProcess, $submission, $form)
39 + {
40 + if (!$shouldProcess || empty($form->has_payment)) {
41 + return $shouldProcess;
42 + }
43 +
44 + $paymentStatus = isset($submission->payment_status) ? $submission->payment_status : null;
45 +
46 + if (PaymentHelper::isReversedPaymentStatus($paymentStatus)) {
47 + return false;
48 + }
49 +
50 + return $shouldProcess;
51 + }
52 +
31 53 public function init()
32 54 {
33 55
34 56 add_filter('fluentform/global_settings_components', [$this, 'pushGlobalSettings'], 1, 1);
@@ -35,9 +57,11 @@
35 57
36 58 add_filter('fluentform/global_settings_component_settings_data', [$this, 'getGlobalSettingsPaymentVars']);
37 59
38 60 add_action('wp_ajax_fluentform_handle_payment_ajax_endpoint', [$this, 'handleAjaxEndpoints']);
39 -
61 +
62 + add_filter('fluentform/should_process_submission_actions', [$this, 'skipActionsForReversedPayment'], 10, 3);
63 +
40 64 if (!$this->isEnabled()) {
41 65 return;
42 66 }
43 67
@@ -299,9 +323,12 @@
299 323 [$this, 'validatePaymentInputs'],
300 324 10,
301 325 3
302 326 );
303 -
327 +
328 + add_filter('fluentform/validate_input_item_custom_payment_component', [$this, 'validatePaymentNumber'], 10, 3);
329 + add_filter('fluentform/validate_input_item_item_quantity_component', [$this, 'validatePaymentNumber'], 10, 3);
330 +
304 331 add_filter(
305 332 'fluentform/validate_input_item_payment_method',
306 333 [$this, 'validatePaymentMethod'],
307 334 10,
@@ -466,10 +493,11 @@
466 493 return;
467 494 }
468 495
469 496 $paymentAction = new PaymentAction($form, $insertData, $data);
470 -
497 +
471 498 if (!$paymentAction->getSubscriptionItems() && !$paymentAction->getCalculatedAmount()) {
499 + $paymentAction->flagZeroTotalOrder();
472 500 return;
473 501 }
474 502
475 503 /*
@@ -616,9 +644,14 @@
616 644
617 645 $submissionIds = array_unique($submissionIds);
618 646 $transactionIds = array_unique($transactionIds);
619 647
648 + // Claim only unowned submissions; payer_email is unverified and may match a registered owner.
620 649 \FluentForm\App\Models\Submission::whereIn('id', $submissionIds)
650 + ->where(function ($query) {
651 + $query->whereNull('user_id')
652 + ->orWhere('user_id', '');
653 + })
621 654 ->update([
622 655 'user_id' => $userId,
623 656 'updated_at' => current_time('mysql')
624 657 ]);
@@ -685,9 +718,9 @@
685 718 if ('yes' === ArrayHelper::get($selectedPlan, 'user_input')) {
686 719 $userGivenValue = ArrayHelper::get($formData, "{$field['name']}_custom_$selectedPlanIndex");
687 720 $userGivenValue = $userGivenValue ?: 0;
688 721 $planMinValue = ArrayHelper::get($selectedPlan, 'user_input_min_value');
689 - if (!is_numeric($userGivenValue) || ($planMinValue && $userGivenValue < $planMinValue)) {
722 + if (!is_numeric($userGivenValue) || $userGivenValue < 0 || ($planMinValue && $userGivenValue < $planMinValue)) {
690 723 $error = __('This subscription plan value is invalid', 'fluentform');
691 724 }
692 725 }
693 726 }
@@ -696,9 +729,10 @@
696 729 }
697 730
698 731 public function validatePaymentInputs($error, $field, $formData)
699 732 {
700 - if (ArrayHelper::get($formData, $field['name'])) {
733 + // A submitted "0" is still a value and must match an offered option.
734 + if (!in_array(ArrayHelper::get($formData, $field['name']), [null, '', []], true)) {
701 735 $fieldType = ArrayHelper::get($field, 'raw.attributes.type');
702 736
703 737 if (in_array($fieldType, ['radio', 'select', 'checkbox'])) {
704 738 $pricingOptions = array_column(
@@ -710,9 +744,9 @@
710 744
711 745 if (in_array($fieldType, ['radio', 'select'])) {
712 746 $acceptedPaymentPlan = in_array($formData[$field['name']], $pricingOptions);
713 747 } else {
714 - $acceptedPaymentPlan = array_diff($formData[$field['name']], $pricingOptions);
748 + $acceptedPaymentPlan = array_diff((array) $formData[$field['name']], $pricingOptions);
715 749
716 750 $acceptedPaymentPlan = empty($acceptedPaymentPlan);
717 751 }
718 752
@@ -723,9 +757,23 @@
723 757 }
724 758
725 759 return $error;
726 760 }
727 -
761 +
762 + // The order builder silently drops an amount or quantity it cannot price, zeroing the order.
763 + public function validatePaymentNumber($error, $field, $formData)
764 + {
765 + $value = ArrayHelper::get($formData, $field['name']);
766 + if ($error || in_array($value, [null, ''], true) || (is_numeric($value) && $value > 0)) {
767 + return $error;
768 + }
769 +
770 + $isOptionalZero = is_numeric($value) && 0 == $value
771 + && !ArrayHelper::get($field, 'raw.settings.validation_rules.required.value');
772 +
773 + return $isOptionalZero ? $error : __('This payment item is invalid', 'fluentform');
774 + }
775 +
728 776 public function validatePaymentMethod($error, $field, $formData, $fields, $form)
729 777 {
730 778 if ($selectedMethod = ArrayHelper::get($formData, $field['name'])) {
731 779 $activeMethods = array_keys(PaymentHelper::getFormPaymentMethods($form->id));