PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.3
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.3
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 3.6.65 All 196 releases
fluentform / app / Modules / Payments / PaymentHandler.php

PaymentHandler.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.3, at app/Modules/Payments/PaymentHandler.php

735 lines 29.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Modules\Payments;
4
5 if (!defined('ABSPATH')) {
6 exit; // Exit if accessed directly.
7 }
8
9 use FluentForm\App\Helpers\Helper;
10 use FluentForm\App\Modules\Acl\Acl;
11 use FluentForm\App\Modules\Form\FormFieldsParser;
12 use FluentForm\App\Modules\Payments\Orders\OrderData;
13 use FluentForm\App\Services\FormBuilder\ShortCodeParser;
14 use FluentForm\Framework\Helpers\ArrayHelper;
15 use FluentForm\App\Modules\Payments\Classes\PaymentAction;
16 use FluentForm\App\Modules\Payments\Classes\PaymentEntries;
17 use FluentForm\App\Modules\Payments\Classes\PaymentReceipt;
18 use FluentForm\App\Modules\Payments\Components\CustomPaymentComponent;
19 use FluentForm\App\Modules\Payments\Components\ItemQuantity;
20 use FluentForm\App\Modules\Payments\Components\MultiPaymentComponent;
21 use FluentForm\App\Modules\Payments\Components\PaymentMethods;
22 use FluentForm\App\Modules\Payments\Components\PaymentSummaryComponent;
23 use FluentForm\App\Modules\Payments\Components\Subscription;
24 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\Components\StripeInline;
25 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\ConnectConfig;
26 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\StripeHandler;
27 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\StripeSettings;
28
29 class PaymentHandler
30 {
31 public function init()
32 {
33
34 add_filter('fluentform/global_settings_components', [$this, 'pushGlobalSettings'], 1, 1);
35
36 add_filter('fluentform/global_settings_component_settings_data', [$this, 'getGlobalSettingsPaymentVars']);
37
38 add_action('wp_ajax_fluentform_handle_payment_ajax_endpoint', [$this, 'handleAjaxEndpoints']);
39
40 if (!$this->isEnabled()) {
41 return;
42 }
43
44 add_filter('fluentform/show_payment_entries', '__return_true');
45
46 add_filter('fluentform/form_settings_menu', array($this, 'maybeAddPaymentSettings'), 10, 2);
47 // Let's load Payment Methods here
48 (new StripeHandler())->init();
49
50 // Let's load the payment method component here
51 new MultiPaymentComponent();
52 new Subscription();
53 new CustomPaymentComponent();
54 new ItemQuantity();
55 new PaymentMethods();
56 new PaymentSummaryComponent();
57
58 add_filter('fluentform/editor_components', function ($components) {
59 if (!Helper::hasPro()) {
60 $components['payments'][] = [
61 'index' => 6,
62 'element' => 'payment_coupon',
63 'attributes' => [],
64 'settings' => [],
65 'editor_options' => [
66 'title' => __('Coupon', 'fluentform'),
67 'icon_class' => 'el-icon-postcard',
68 'template' => 'inputText',
69 ],
70 ];
71 }
72 return $components;
73 }, 11);
74
75 new StripeInline();
76
77 add_action('fluentform/before_insert_payment_form', array($this, 'maybeHandlePayment'), 10, 3);
78
79 add_filter('fluentform/submission_order_data', function ($data, $submission) {
80 return OrderData::getSummary($submission, $submission->form);
81 }, 10, 2);
82
83 add_filter('fluentform/entries_vars', function ($vars, $form) {
84 if ($form->has_payment) {
85 $vars['has_payment'] = $form->has_payment;
86 $vars['currency_config'] = PaymentHelper::getCurrencyConfig($form->id);
87 $vars['currency_symbols'] = PaymentHelper::getCurrencySymbols();
88 $vars['payment_statuses'] = PaymentHelper::getPaymentStatuses();
89 }
90 return $vars;
91 }, 10, 2);
92
93 add_filter(
94 'fluentform/submission_labels',
95 [$this, 'modifySingleEntryLabels'],
96 10,
97 3
98 );
99
100
101 add_filter('fluentform/all_entry_labels_with_payment', array($this, 'modifySingleEntryLabels'), 10, 3);
102
103 add_action('fluentform/rendering_payment_form', function ($form) {
104 if (Helper::isElementorEditor()) {
105 return;
106 }
107
108 $src = fluentFormMix('js/payment_handler.js');
109 $version = FLUENTFORM_VERSION;
110
111 // If pro is installed and script is compatible, load script from pro
112 if (Helper::isProPaymentScriptCompatible()) {
113 $src = FLUENTFORMPRO_DIR_URL . 'public/js/payment_handler_pro.js';
114 $version = FLUENTFORMPRO_VERSION;
115 }
116
117 wp_enqueue_script('fluentform-payment-handler',
118 $src,
119 array('jquery'),
120 $version,
121 true
122 );
123
124 wp_enqueue_style(
125 'fluentform-payment-skin',
126 fluentFormMix('css/payment_skin.css'),
127 array(),
128 FLUENTFORM_VERSION
129 );
130
131 wp_localize_script('fluentform-payment-handler', 'fluentform_payment_config', [
132 'i18n' => [
133 'item' => __('Item', 'fluentform'),
134 'price' => __('Price', 'fluentform'),
135 'qty' => __('Qty', 'fluentform'),
136 'line_total' => __('Line Total', 'fluentform'),
137 'total' => __('Total', 'fluentform'),
138 'not_found' => __('No payment item selected yet', 'fluentform'),
139 'discount:' => __('Discount:', 'fluentform'),
140 'processing_text' => __('Processing payment. Please wait...', 'fluentform'),
141 'confirming_text' => __('Confirming payment. Please wait...', 'fluentform'),
142 /* translators: %s is the item name */
143 'Signup Fee for %s' => __('Signup Fee for %s', 'fluentform'),
144 /* translators: 1: item name, 2: plan name */
145 'Signup Fee for %1$s - %2$s' => __('Signup Fee for %1$s - %2$s', 'fluentform'),
146 ]
147 ]);
148
149 $secretKey = apply_filters_deprecated(
150 'fluentform-payment_stripe_publishable_key',
151 [
152 StripeSettings::getPublishableKey($form->id),
153 $form->id
154 ],
155 FLUENTFORM_FRAMEWORK_UPGRADE,
156 'fluentform/payment_stripe_publishable_key',
157 'Use fluentform/payment_stripe_publishable_key instead of fluentform-payment_stripe_publishable_key.'
158 );
159
160 $publishableKey = apply_filters('fluentform/payment_stripe_publishable_key', $secretKey, $form->id);
161
162 $stripeCustomCss = [
163 'styles' => [
164 'base' => [
165 'backgroundColor' => 'white',
166 'color' => '#32325d',
167 'fontFamily' => "-apple-system, \"system-ui\", \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif",
168 'fontSize' => '14px',
169 'fontSmoothing' => 'antialiased',
170 'iconColor' => '#32325d',
171 'textDecoration' => 'none',
172 '::placeholder' => [
173 'color'=> "#aab7c4"
174 ],
175 ":focus" => [
176 'backgroundColor' => 'white',
177 'color' => '#32325d',
178 'fontFamily' => "-apple-system, \"system-ui\", \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif",
179 'fontSize' => '14px',
180 'fontSmoothing' => 'antialiased',
181 'iconColor' => '#32325d',
182 'textDecoration' => 'none',
183 ],
184 ],
185 'invalid' => [
186 'color' => "#fa755a",
187 'iconColor' => "#fa755a"
188 ]
189 ]
190 ];
191
192 $paymentConfig = [
193 'currency_settings' => PaymentHelper::getCurrencyConfig($form->id),
194 'stripe' => [
195 'publishable_key' => $publishableKey,
196 'inlineConfig' => PaymentHelper::getStripeInlineConfig($form->id),
197 'custom_style' => apply_filters(
198 'fluentform/stripe_inline_custom_css',
199 $stripeCustomCss,
200 $form->id
201 ),
202 'locale' => 'en'
203 ],
204 'stripe_app_info' => [
205 'name' => 'Fluent Forms',
206 'version' => FLUENTFORM_VERSION,
207 'url' => site_url(),
208 'partner_id' => 'pp_partner_FN62GfRLM2Kx5d'
209 ],
210 ];
211 $paymentConfig = apply_filters('fluentform/payment_config', $paymentConfig, $form->id);
212
213 wp_localize_script('fluentform-payment-handler', 'fluentform_payment_config_' . $form->id, $paymentConfig);
214
215 }, 11, 1);
216
217 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Public payment callback from gateway, nonce not applicable, verified by transaction_hash in validateFrameLessPage()
218 if (isset($_GET['fluentform_payment']) && isset($_GET['payment_method'])) {
219 add_action('wp', function () {
220 $data = $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Data sanitized below and verified by validateFrameLessPage()
221
222 $type = isset($_GET['fluentform_payment']) ? sanitize_text_field(wp_unslash($_GET['fluentform_payment'])) : '';
223
224 if ($type == 'view' && $route = ArrayHelper::get($data, 'route')) {
225 do_action_deprecated(
226 'fluent_payment_view_' . $route,
227 [
228 $data
229 ],
230 FLUENTFORM_FRAMEWORK_UPGRADE,
231 'fluentform/payment_view_' . $route,
232 'Use fluentform/payment_view_' . $route . ' instead of fluent_payment_view_' . $route
233 );
234 do_action('fluentform/payment_view_' . $route, $data);
235 }
236
237 $this->validateFrameLessPage($data);
238 $paymentMethod = isset($_GET['payment_method']) ? sanitize_text_field(wp_unslash($_GET['payment_method'])) : '';
239 do_action_deprecated(
240 'fluent_payment_frameless_' . $paymentMethod,
241 [
242 $data
243 ],
244 FLUENTFORM_FRAMEWORK_UPGRADE,
245 'fluentform/payment_frameless_' . $paymentMethod,
246 'Use fluentform/payment_frameless_' . $paymentMethod . ' instead of fluent_payment_frameless_' . $paymentMethod
247 );
248 do_action('fluentform/payment_frameless_' . $paymentMethod, $data);
249 });
250 }
251 // phpcs:enable WordPress.Security.NonceVerification.Recommended -- End of payment callback processing
252
253 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- IPN callback from payment gateway, verified by gateway signature
254 if (isset($_REQUEST['fluentform_payment_api_notify'])) {
255 add_action('wp', function () {
256 $paymentMethod = isset($_REQUEST['payment_method']) ? sanitize_text_field(wp_unslash($_REQUEST['payment_method'])) : '';
257 do_action_deprecated(
258 'fluentform_ipn_endpoint_' . $paymentMethod,
259 [
260 ],
261 FLUENTFORM_FRAMEWORK_UPGRADE,
262 'fluentform/ipn_endpoint_' . $paymentMethod,
263 'Use fluentform/ipn_endpoint_' . $paymentMethod . ' instead of fluentform_ipn_endpoint_' . $paymentMethod
264 );
265 do_action('fluentform/ipn_endpoint_' . $paymentMethod);
266 });
267 }
268 // phpcs:enable WordPress.Security.NonceVerification.Recommended -- End of IPN webhook processing
269
270 add_filter('fluentform/editor_vars', function ($vars) {
271 $settings = PaymentHelper::getCurrencyConfig($vars['form_id']);
272 $vars['payment_settings'] = $settings;
273 $vars['has_payment_features'] = !!$settings;
274 return $vars;
275 });
276
277 add_filter('fluentform/admin_i18n', array($this, 'paymentTranslations'), 10, 1);
278
279 add_filter('fluentform/payment_smartcode', array($this, 'paymentReceiptView'), 10, 3);
280
281 add_action('user_register', array($this, 'maybeAssignTransactions'), 99, 1);
282
283 (new PaymentEntries())->init();
284
285 /*
286 * Transactions and subscriptions Shortcode
287 */
288 (new TransactionShortcodes())->init();
289
290 add_filter(
291 'fluentform/validate_input_item_subscription_payment_component',
292 [$this, 'validateSubscriptionInputs'],
293 10,
294 3
295 );
296
297 add_filter(
298 'fluentform/validate_input_item_multi_payment_component',
299 [$this, 'validatePaymentInputs'],
300 10,
301 3
302 );
303
304 add_filter(
305 'fluentform/validate_input_item_payment_method',
306 [$this, 'validatePaymentMethod'],
307 10,
308 5
309 );
310 }
311
312 public function pushGlobalSettings($components)
313 {
314 $subMenuItems = [
315 [
316 'title' => 'Settings',
317 'hash' => 'payments/general_settings',
318 ],
319 [
320 'title' => 'Payment Methods',
321 'hash' => 'payments/payment_methods',
322 ]
323 ];
324 $subMenuItems = apply_filters('fluentform/global_settings_payment_sub_menu_items', $subMenuItems);
325
326 $components['payment_settings'] = [
327 'title' => __('Payment Settings', 'fluentform'),
328 'sub_menu'=> $subMenuItems
329 ];
330 return $components;
331 }
332
333 public function getGlobalSettingsPaymentVars($globalSettingVars)
334 {
335 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Admin page, nonce verified by WordPress admin
336 if (isset($_GET['ff_stripe_connect'])) {
337 $data = ArrayHelper::only($_GET, ['ff_stripe_connect', 'mode', 'state', 'code']);
338 ConnectConfig::verifyAuthorizeSuccess($data);
339 }
340
341 $paymentSettings = PaymentHelper::getPaymentSettings();
342 $isSettingsAvailable = PaymentHelper::hasPaymentSettings();
343
344 $nav = 'general';
345
346 if (isset($_REQUEST['nav'])) {
347 $nav = sanitize_text_field(wp_unslash($_REQUEST['nav']));
348 }
349 // phpcs:enable WordPress.Security.NonceVerification.Recommended -- End of admin page GET parameter processing
350
351 $paymentMethods = apply_filters_deprecated(
352 'fluentformpro_available_payment_methods',
353 [
354 []
355 ],
356 FLUENTFORM_FRAMEWORK_UPGRADE,
357 'fluentform/available_payment_methods',
358 'Use fluentform/available_payment_methods instead of fluentformpro_available_payment_methods.'
359 );
360
361 $globalSettings = apply_filters_deprecated(
362 'fluentformpro_payment_methods_global_settings',
363 [
364 []
365 ],
366 FLUENTFORM_FRAMEWORK_UPGRADE,
367 'fluentform/payment_methods_global_settings',
368 'Use fluentform/payment_methods_global_settings instead of fluentformpro_payment_methods_global_settings.'
369 );
370
371 $paymentVars = [
372 'is_setup' => $isSettingsAvailable,
373 'general' => $paymentSettings,
374 'payment_methods' => apply_filters('fluentform/available_payment_methods', $paymentMethods),
375 'available_payment_methods' => apply_filters('fluentform/payment_methods_global_settings', $globalSettings),
376 'currencies' => PaymentHelper::getCurrencies(),
377 'active_nav' => $nav,
378 'stripe_webhook_url' => add_query_arg([
379 'fluentform_payment_api_notify' => '1',
380 'payment_method' => 'stripe'
381 ], site_url('index.php')),
382 'paypal_webhook_url' => add_query_arg([
383 'fluentform_payment_api_notify' => '1',
384 'payment_method' => 'paypal'
385 ], site_url('index.php'))
386 ];
387
388 // Enqueue payment global settings css
389 wp_enqueue_style('ff-payment-settings', fluentFormMix('css/payment_settings.css'), [], FLUENTFORM_VERSION);
390
391 $globalSettingVars['payment_vars'] = apply_filters('fluentform/global_settings_component_payment_vars', $paymentVars);
392 return $globalSettingVars;
393 }
394
395 public function handleAjaxEndpoints()
396 {
397 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify()
398 $route = isset($_REQUEST['route']) ? sanitize_text_field(wp_unslash($_REQUEST['route'])) : '';
399 $formScopedRoutes = [
400 'get_form_settings',
401 'save_form_settings',
402 'update_transaction',
403 'cancel_subscription'
404 ];
405
406 if (in_array($route, $formScopedRoutes, true)) {
407 Acl::verify('fluentform_forms_manager', $this->resolveRouteFormId($route));
408 } else {
409 Acl::verify('fluentform_settings_manager');
410 }
411 // phpcs:enable WordPress.Security.NonceVerification.Recommended -- End of AJAX endpoint nonce verification by Acl::verify()
412
413 (new AjaxEndpoints())->handleEndpoint($route);
414 }
415
416 private function resolveRouteFormId($route)
417 {
418 switch ($route) {
419 case 'get_form_settings':
420 case 'save_form_settings':
421 return Acl::verifyFormId(wpFluentForm()->request->get('form_id'));
422 case 'update_transaction':
423 return $this->resolveTransactionFormId();
424 case 'cancel_subscription':
425 return $this->resolveSubscriptionFormId();
426 default:
427 return null;
428 }
429 }
430
431 private function resolveTransactionFormId()
432 {
433 $transactionData = wpFluentForm()->request->get('transaction', []);
434 $transactionId = absint(ArrayHelper::get($transactionData, 'id'));
435
436 if (!$transactionId) {
437 return -1;
438 }
439
440 $transaction = \FluentForm\App\Models\Transaction::select('form_id')->find($transactionId);
441
442 return $transaction ? (int) $transaction->form_id : -1;
443 }
444
445 private function resolveSubscriptionFormId()
446 {
447 $subscriptionId = absint(wpFluentForm()->request->get('subscription_id'));
448
449 if (!$subscriptionId) {
450 return -1;
451 }
452
453 $subscription = \FluentForm\App\Models\Subscription::select('form_id')->find($subscriptionId);
454
455 return $subscription ? (int) $subscription->form_id : -1;
456 }
457
458 public function maybeHandlePayment($insertData, $data, $form)
459 {
460 // Let's get selected Payment Method
461 if (!FormFieldsParser::hasPaymentFields($form)) {
462 return;
463 }
464
465 $paymentAction = new PaymentAction($form, $insertData, $data);
466
467 if (!$paymentAction->getSubscriptionItems() && !$paymentAction->getCalculatedAmount()) {
468 return;
469 }
470
471 /*
472 * We have to check if
473 * 1. has payment method
474 * 2. if user selected payment method
475 * 3. or maybe has a conditional logic on it
476 */
477 if ($paymentAction->isConditionPass()) {
478 if (FormFieldsParser::hasElement($form, 'payment_method') &&
479 !$paymentAction->selectedPaymentMethod
480 ) {
481 wp_send_json([
482 'errors' => [__('Sorry! No selected payment method found. Please select a valid payment method', 'fluentform')]
483 ], 423);
484 }
485 }
486
487 /*
488 * Some Payment Gateway like Razorpay, Square not supported $subscriptionItems.
489 * So we are providing filter hook to validate payment fields.
490 */
491 $errors = apply_filters(
492 'fluentform/validate_payment_items_' . $paymentAction->selectedPaymentMethod,
493 [],
494 $paymentAction->getOrderItems(),
495 $paymentAction->getSubscriptionItems(),
496 $form
497 );
498
499 if ($errors) {
500 wp_send_json([
501 'errors' => $errors
502 ], 423);
503 }
504
505 $paymentAction->draftFormEntry();
506 }
507
508 public function isEnabled()
509 {
510 $paymentSettings = PaymentHelper::getPaymentSettings();
511 return $paymentSettings['status'] == 'yes';
512 }
513
514 public function modifySingleEntryLabels($labels, $submission, $form)
515 {
516 $formFields = FormFieldsParser::getPaymentFields($form);
517 if ($formFields && is_array($formFields)) {
518 $labels = ArrayHelper::except($labels, array_keys($formFields));
519 }
520 return $labels;
521 }
522
523 public function maybeAddPaymentSettings($menus, $formId)
524 {
525 $form = \FluentForm\App\Models\Form::find($formId);
526 if ($form->has_payment) {
527 $menus = array_merge(array_slice($menus, 0, 1), array(
528 'payment_settings' => [
529 'title' => __('Payment Settings', 'fluentform'),
530 'slug' => 'form_settings',
531 'hash' => 'payment_settings',
532 'route' => '/payment-settings',
533 ]
534 ), array_slice($menus, 1));
535 }
536 return $menus;
537 }
538
539
540 /**
541 * @param $html string
542 * @param $property string
543 * @param $instance ShortCodeParser
544 * @return false|string
545 */
546 public function paymentReceiptView($html, $property, $instance)
547 {
548 $entry = $instance::getEntry();
549 $receiptClass = new PaymentReceipt($entry);
550 return $receiptClass->getItem($property);
551 }
552
553 private function validateFrameLessPage($data)
554 {
555 // We should verify the transaction hash from the URL
556 $transactionHash = sanitize_text_field(ArrayHelper::get($data, 'transaction_hash'));
557 $submissionId = intval(ArrayHelper::get($data, 'fluentform_payment'));
558 if (!$submissionId) {
559 die('Validation Failed');
560 }
561
562 if ($transactionHash) {
563 $transaction = \FluentForm\App\Models\Transaction::bySubmission($submissionId)
564 ->where('transaction_hash', $transactionHash)
565 ->first();
566 if ($transaction) {
567 return true;
568 }
569
570 die('Transaction hash is invalid');
571 }
572
573 $uid = sanitize_text_field(ArrayHelper::get($data, 'entry_uid'));
574 if (!$uid) {
575 die('Validation Failed');
576 }
577
578 $originalUid = Helper::getSubmissionMeta($submissionId, '_entry_uid_hash');
579
580 if ($originalUid != $uid) {
581 die(esc_html__('Transaction UID is invalid', 'fluentform'));
582 }
583
584 return true;
585 }
586
587 public function maybeAssignTransactions($userId)
588 {
589 $user = get_user_by('ID', $userId);
590 if (!$user) {
591 return false;
592 }
593 $userEmail = $user->user_email;
594
595 $transactions = \FluentForm\App\Models\Transaction::where('payer_email', $userEmail)
596 ->where(function ($query) {
597 $query->whereNull('user_id')
598 ->orWhere('user_id', '');
599 })
600 ->get();
601
602 if (count($transactions) === 0) {
603 return false;
604 }
605
606 $submissionIds = [];
607 $transactionIds = [];
608 foreach ($transactions as $transaction) {
609 $submissionIds[] = $transaction->submission_id;
610 $transactionIds[] = $transaction->id;
611 }
612
613 $submissionIds = array_unique($submissionIds);
614 $transactionIds = array_unique($transactionIds);
615
616 \FluentForm\App\Models\Submission::whereIn('id', $submissionIds)
617 ->update([
618 'user_id' => $userId,
619 'updated_at' => current_time('mysql')
620 ]);
621
622 \FluentForm\App\Models\Transaction::whereIn('id', $transactionIds)
623 ->update([
624 'user_id' => $userId,
625 'updated_at' => current_time('mysql')
626 ]);
627
628 return true;
629 }
630
631 public function paymentTranslations($i18n)
632 {
633 $paymentI18n = array(
634 'Order Details' => __('Order Details', 'fluentform'),
635 'Product' => __('Product', 'fluentform'),
636 'Qty' => __('Qty', 'fluentform'),
637 'Unit Price' => __('Unit Price', 'fluentform'),
638 'Total' => __('Total', 'fluentform'),
639 'Sub-Total' => __('Sub-Total', 'fluentform'),
640 'Discount' => __('Discount', 'fluentform'),
641 'Price' => __('Price', 'fluentform'),
642 'Payment Details' => __('Payment Details', 'fluentform'),
643 'From Subscriptions' => __('From Subscriptions', 'fluentform'),
644 'Card Last 4' => __('Card Last 4', 'fluentform'),
645 'Payment Total' => __('Payment Total', 'fluentform'),
646 'Payment Status' => __('Payment Status', 'fluentform'),
647 'Transaction ID' => __('Transaction ID', 'fluentform'),
648 'Payment Method' => __('Payment Method', 'fluentform'),
649 'Transaction' => __('Transaction', 'fluentform'),
650 'Refunds' => __('Refunds', 'fluentform'),
651 'Refund' => __('Refund', 'fluentform'),
652 'at' => __('at', 'fluentform'),
653 'View' => __('View', 'fluentform'),
654 'has been refunded via' => __('has been refunded via', 'fluentform'),
655 'Note' => __('Note', 'fluentform'),
656 'Edit Transaction' => __('Edit Transaction', 'fluentform'),
657 'Billing Name' => __('Billing Name', 'fluentform'),
658 'Billing Email' => __('Billing Email', 'fluentform'),
659 'Billing Address' => __('Billing Address', 'fluentform'),
660 'Shipping Address' => __('Shipping Address', 'fluentform'),
661 'Reference ID' => __('Reference ID', 'fluentform'),
662 'refunds-to-be-handled-from-provider-text' => __('Please note that, Actual Refund needs to be handled in your Payment Service Provider.', 'fluentform'),
663 'Please Provide new refund amount only.' => __('Please Provide new refund amount only.', 'fluentform'),
664 'Refund Note' => __('Refund Note', 'fluentform'),
665 'Cancel' => __('Cancel', 'fluentform'),
666 'Confirm' => __('Confirm', 'fluentform'),
667 );
668 return array_merge($i18n,$paymentI18n);
669 }
670
671 public function validateSubscriptionInputs($error, $field, $formData)
672 {
673 if (isset($formData[$field['name']])) {
674 $subscriptionOptions = ArrayHelper::get($field, 'raw.settings.subscription_options', []);
675 $selectedPlanIndex = $formData[$field['name']];
676 $acceptedSubscriptionPlan = is_numeric($selectedPlanIndex) && in_array($selectedPlanIndex, array_keys($subscriptionOptions));
677 if (!$acceptedSubscriptionPlan) {
678 $error = __('This subscription plan is invalid', 'fluentform');
679 }
680 $selectedPlan = ArrayHelper::get($subscriptionOptions, $selectedPlanIndex, []);
681 if ('yes' === ArrayHelper::get($selectedPlan, 'user_input')) {
682 $userGivenValue = ArrayHelper::get($formData, "{$field['name']}_custom_$selectedPlanIndex");
683 $userGivenValue = $userGivenValue ?: 0;
684 $planMinValue = ArrayHelper::get($selectedPlan, 'user_input_min_value');
685 if (!is_numeric($userGivenValue) || ($planMinValue && $userGivenValue < $planMinValue)) {
686 $error = __('This subscription plan value is invalid', 'fluentform');
687 }
688 }
689 }
690
691 return $error;
692 }
693
694 public function validatePaymentInputs($error, $field, $formData)
695 {
696 if (ArrayHelper::get($formData, $field['name'])) {
697 $fieldType = ArrayHelper::get($field, 'raw.attributes.type');
698
699 if (in_array($fieldType, ['radio', 'select', 'checkbox'])) {
700 $pricingOptions = array_column(
701 ArrayHelper::get($field, 'raw.settings.pricing_options', []),
702 'label'
703 );
704
705 $pricingOptions = array_map('sanitize_text_field', $pricingOptions);
706
707 if (in_array($fieldType, ['radio', 'select'])) {
708 $acceptedPaymentPlan = in_array($formData[$field['name']], $pricingOptions);
709 } else {
710 $acceptedPaymentPlan = array_diff($formData[$field['name']], $pricingOptions);
711
712 $acceptedPaymentPlan = empty($acceptedPaymentPlan);
713 }
714
715 if (!$acceptedPaymentPlan) {
716 $error = __('This payment item is invalid', 'fluentform');
717 }
718 }
719 }
720
721 return $error;
722 }
723
724 public function validatePaymentMethod($error, $field, $formData, $fields, $form)
725 {
726 if ($selectedMethod = ArrayHelper::get($formData, $field['name'])) {
727 $activeMethods = array_keys(PaymentHelper::getFormPaymentMethods($form->id));
728 if (!in_array($selectedMethod, $activeMethods)) {
729 $error = __('This payment method is invalid', 'fluentform');
730 }
731 }
732 return $error;
733 }
734 }
735