| @@ -610,8 +610,26 @@ | ||
| 610 | 610 | |
| 611 | 611 | return apply_filters('fluentform/available_payment_statuses', $paymentStatuses); |
| 612 | 612 | } |
| 613 | 613 | |
| 614 | + public static function reversedPaymentStatuses() | |
| 615 | + { | |
| 616 | + return apply_filters('fluentform/reversed_payment_statuses', [ | |
| 617 | + 'refunded', 'partially-refunded', 'cancelled', | |
| 618 | + ]); | |
| 619 | + } | |
| 620 | + | |
| 621 | + public static function isReversedPaymentStatus($status) | |
| 622 | + { | |
| 623 | + $status = is_null($status) ? '' : (string) $status; | |
| 624 | + | |
| 625 | + if ('' === $status) { | |
| 626 | + return false; | |
| 627 | + } | |
| 628 | + | |
| 629 | + return in_array($status, static::reversedPaymentStatuses(), true); | |
| 630 | + } | |
| 631 | + | |
| 614 | 632 | public static function getFormPaymentMethods($formId) |
| 615 | 633 | { |
| 616 | 634 | $inputs = FormFieldsParser::getInputs($formId, ['element', 'settings']); |
| 617 | 635 | foreach ($inputs as $field) { |
| @@ -799,23 +817,47 @@ | ||
| 799 | 817 | |
| 800 | 818 | $stripe = ArrayHelper::get($methods, 'stripe'); |
| 801 | 819 | $stripeInlineStyles = ArrayHelper::get(Helper::getFormMeta($formId, '_ff_form_styles', []), 'stripe_inline_element_style', false); |
| 802 | 820 | if ($stripe) { |
| 803 | - return apply_filters( | |
| 804 | - 'fluentform/stripe_inline_config', | |
| 805 | - [ | |
| 806 | - 'is_inline' => ArrayHelper::get($stripe, 'settings.embedded_checkout.value') == 'yes', | |
| 807 | - 'inline_styles' => $stripeInlineStyles, | |
| 808 | - 'verifyZip' => ArrayHelper::get($methods['stripe'], 'settings.verify_zip_code.value') === 'yes', | |
| 809 | - 'disable_link' => false | |
| 810 | - ], | |
| 811 | - $formId | |
| 812 | - ); | |
| 821 | + $config = [ | |
| 822 | + 'is_inline' => ArrayHelper::get($stripe, 'settings.embedded_checkout.value') == 'yes', | |
| 823 | + 'inline_styles' => $stripeInlineStyles, | |
| 824 | + 'verifyZip' => ArrayHelper::get($methods['stripe'], 'settings.verify_zip_code.value') === 'yes', | |
| 825 | + 'disable_link' => false, | |
| 826 | + 'enable_payment_element' => static::isStripePaymentElement($stripe), | |
| 827 | + 'is_zero_decimal' => static::isZeroDecimal(static::getFormCurrency($formId)), | |
| 828 | + ]; | |
| 829 | + | |
| 830 | + // Classic and conversational forms both create the Payment Element with these options | |
| 831 | + if ($config['enable_payment_element']) { | |
| 832 | + $config['payment_element_options'] = apply_filters( | |
| 833 | + 'fluentform/stripe_payment_element_options', | |
| 834 | + [ | |
| 835 | + 'layout' => 'tabs', | |
| 836 | + 'wallets' => ['applePay' => 'auto', 'googlePay' => 'auto', 'link' => 'never'], | |
| 837 | + 'fields' => ['billingDetails' => ['address' => $config['verifyZip'] ? 'auto' : 'if_required']], | |
| 838 | + 'appearance' => [], | |
| 839 | + ], | |
| 840 | + $formId | |
| 841 | + ); | |
| 842 | + } | |
| 843 | + | |
| 844 | + return apply_filters('fluentform/stripe_inline_config', $config, $formId); | |
| 813 | 845 | } |
| 814 | 846 | |
| 815 | 847 | return []; |
| 816 | 848 | } |
| 817 | 849 | |
| 850 | + /** | |
| 851 | + * Stripe's Payment Element (card plus Apple Pay / Google Pay) replaces the Card Element on the embedded field, | |
| 852 | + * so it only applies with Embedded Checkout on. | |
| 853 | + */ | |
| 854 | + public static function isStripePaymentElement($stripeMethod) | |
| 855 | + { | |
| 856 | + return ArrayHelper::get($stripeMethod, 'settings.embedded_checkout.value') === 'yes' | |
| 857 | + && ArrayHelper::get($stripeMethod, 'settings.enable_payment_element.value') === 'yes'; | |
| 858 | + } | |
| 859 | + | |
| 818 | 860 | public static function log($data, $submission = false, $forceInsert = false) |
| 819 | 861 | { |
| 820 | 862 | if (!$forceInsert) { |
| 821 | 863 | static $paymentSettings; |
| @@ -855,8 +897,12 @@ | ||
| 855 | 897 | } |
| 856 | 898 | |
| 857 | 899 | $form = \FluentForm\App\Models\Form::find($submission->form_id); |
| 858 | 900 | |
| 901 | + if (!apply_filters('fluentform/should_process_submission_actions', true, $submission, $form)) { | |
| 902 | + return false; | |
| 903 | + } | |
| 904 | + | |
| 859 | 905 | $formData = $submission->response; |
| 860 | 906 | if (!is_array($formData)) { |
| 861 | 907 | $formData = json_decode($formData, true); |
| 862 | 908 | } |
| @@ -1005,15 +1051,18 @@ | ||
| 1005 | 1051 | ); |
| 1006 | 1052 | |
| 1007 | 1053 | $billingInterval = $plan['billing_interval']; |
| 1008 | 1054 | $billingInterval = ArrayHelper::get(self::getBillingIntervals(), $billingInterval, $billingInterval); |
| 1055 | + $billingInterval = esc_html($billingInterval); | |
| 1056 | + $trialDays = esc_html(ArrayHelper::get($plan, 'trial_days')); | |
| 1057 | + $billTimes = esc_html(ArrayHelper::get($plan, 'bill_times')); | |
| 1009 | 1058 | $replaces = array( |
| 1010 | 1059 | '{signup_fee}' => '<span class="ff_bs ffbs_signup_fee">' . $signupFee . '</span>', |
| 1011 | 1060 | '{first_interval_total}' => '<span class="ff_bs ffbs_first_interval_total">' . $firstIntervalTotal . '</span>', |
| 1012 | 1061 | '{subscription_amount}' => '<span class="ff_bs ffbs_subscription_amount">' . $subscriptionAmount . '</span>', |
| 1013 | 1062 | '{billing_interval}' => '<span class="ff_bs ffbs_billing_interval">' . $billingInterval . '</span>', |
| 1014 | - '{trial_days}' => '<span class="ff_bs ffbs_trial_days">' . $plan['trial_days'] . '</span>', | |
| 1015 | - '{bill_times}' => '<span class="ff_bs ffbs_bill_times">' . ArrayHelper::get($plan, 'bill_times') . '</span>' | |
| 1063 | + '{trial_days}' => '<span class="ff_bs ffbs_trial_days">' . $trialDays . '</span>', | |
| 1064 | + '{bill_times}' => '<span class="ff_bs ffbs_bill_times">' . $billTimes . '</span>', | |
| 1016 | 1065 | ); |
| 1017 | 1066 | |
| 1018 | 1067 | if (ArrayHelper::get($plan, 'user_input') == 'yes') { |
| 1019 | 1068 | $cases['{subscription_amount}'] = '<span class="ff_dynamic_input_amount">' . $subscriptionAmount . '</span>'; |
| @@ -1044,9 +1093,9 @@ | ||
| 1044 | 1093 | $customText .= $cases['bill_times']; |
| 1045 | 1094 | } |
| 1046 | 1095 | if($withMarkup) { |
| 1047 | 1096 | $class = $plan['is_default'] === 'yes' ? '' : 'hidden_field'; |
| 1048 | - return '<div class="ff_summary_container ff_summary_container_' . $plan['index'] . ' ' . $class . '">' . $customText . '</div>'; | |
| 1097 | + return '<div class="ff_summary_container ff_summary_container_' . esc_attr($plan['index']) . ' ' . $class . '">' . $customText . '</div>'; | |
| 1049 | 1098 | } |
| 1050 | 1099 | return $customText; |
| 1051 | 1100 | } |
| 1052 | 1101 | |