PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.8
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.8
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 / AjaxEndpoints.php

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

452 lines 18.1 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\Models\Form;
11 use FluentForm\App\Models\Submission;
12 use FluentForm\App\Models\Subscription;
13 use FluentForm\App\Models\Transaction;
14 use FluentForm\App\Modules\Form\FormFieldsParser;
15 use FluentForm\App\Modules\Payments\PaymentMethods\BaseProcessor;
16 use FluentForm\Database\Migrations\Submissions;
17 use FluentForm\Framework\Helpers\ArrayHelper;
18 use FluentForm\App\Modules\Payments\Classes\PaymentManagement;
19 use FluentForm\App\Modules\Payments\Migrations\Migration;
20 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\ConnectConfig;
21
22 class AjaxEndpoints
23 {
24 public function handleEndpoint($route)
25 {
26 $validRoutes = [
27 'enable_payment' => 'enablePaymentModule',
28 'update_global_settings' => 'updateGlobalSettings',
29 'get_payment_method_settings' => 'getPaymentMethodSettings',
30 'save_payment_method_settings' => 'savePaymentMethodSettings',
31 'get_form_settings' => 'getFormSettings',
32 'save_form_settings' => 'saveFormSettings',
33 'update_transaction' => 'updateTransaction',
34 'get_stripe_connect_config' => 'getStripeConnectConfig',
35 'disconnect_stripe_connection' => 'disconnectStripeConnect',
36 'get_pages' => 'getWpPages',
37 'cancel_subscription' => 'cancelSubscription'
38 ];
39
40 if (isset($validRoutes[$route])) {
41 $this->{$validRoutes[$route]}();
42 } else {
43 do_action('fluentform/handle_payment_ajax_endpoint', $route);
44 }
45
46 die();
47 }
48
49 public function enablePaymentModule()
50 {
51 $this->upgradeDb();
52 // Update settings
53 $settings = PaymentHelper::updatePaymentSettings([
54 'status' => 'yes'
55 ]);
56 // send response to reload the page
57
58 wp_send_json_success([
59 'message' => __('Payment Module successfully enabled!', 'fluentform'),
60 'settings' => $settings,
61 'reload' => 'yes'
62 ]);
63 }
64
65 private function upgradeDB()
66 {
67 global $wpdb;
68 $table = $wpdb->prefix . 'fluentform_transactions';
69 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder -- Checking table structure, %1s is for identifier
70 $cols = $wpdb->get_col($wpdb->prepare("DESC %1s", $table), 0);
71
72 if ($cols && in_array('subscription_id', $cols) && in_array('transaction_hash', $cols)) {
73 // We are good
74 } else {
75 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder -- Migration, dropping table to recreate, %1s is for identifier
76 $wpdb->query($wpdb->prepare("DROP TABLE IF EXISTS %1s", $table));
77 Migration::migrate();
78 // Migrate the database
79 Submissions::migrate(true); // Add payment_total
80 }
81 }
82
83 public function updateGlobalSettings()
84 {
85 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, sanitized in updatePaymentSettings()
86 $request = wpFluentForm()->request;
87 $settings = wp_unslash($request->get('settings', []));
88
89 $sanitizeMap = [
90 'status' => 'sanitize_text_field',
91 'currency' => 'sanitize_text_field',
92 ];
93 $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
94
95 // Update settings
96 $settings = PaymentHelper::updatePaymentSettings($settings);
97
98 // send response to reload the page
99 wp_send_json_success([
100 'message' => __('Settings successfully updated!', 'fluentform'),
101 'settings' => $settings,
102 'reload' => 'yes'
103 ]);
104
105 }
106
107 public function getPaymentMethodSettings()
108 {
109 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
110 $request = wpFluentForm()->request;
111 $method = sanitize_text_field($request->get('method', ''));
112
113 $paymentSettings = apply_filters_deprecated(
114 'fluentform_payment_settings_' . $method,
115 [
116 []
117 ],
118 FLUENTFORM_FRAMEWORK_UPGRADE,
119 'fluentform/payment_settings_' . $method,
120 'Use fluentform/payment_settings_' . $method . ' instead of fluentform_payment_settings_' . $method
121 );
122
123 $settings = apply_filters('fluentform/payment_settings_' . $method, $paymentSettings);
124
125 wp_send_json_success([
126 'settings' => ($settings) ? $settings : false
127 ]);
128 }
129
130 public function savePaymentMethodSettings()
131 {
132 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
133 $request = wpFluentForm()->request;
134 $method = sanitize_text_field($request->get('method', ''));
135 $settings = wp_unslash($request->get('settings', []));
136
137 $sanitizeMap = [
138 'status' => 'sanitize_text_field',
139 ];
140 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, sanitized in validation filter
141 $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
142
143
144 $settingsValidation = apply_filters_deprecated(
145 'fluentform_payment_method_settings_validation_' . $method,
146 [
147 [],
148 $settings
149 ],
150 FLUENTFORM_FRAMEWORK_UPGRADE,
151 'fluentform/payment_method_settings_validation_' . $method,
152 'Use fluentform/payment_method_settings_validation_' . $method . ' instead of fluentform_payment_method_settings_validation_' . $method
153 );
154
155 $validationErrors = apply_filters('fluentform/payment_method_settings_validation_' . $method, $settingsValidation, $settings);
156
157 if ($validationErrors) {
158 wp_send_json_error([
159 'message' => __('Failed to save settings', 'fluentform'),
160 'errors' => $validationErrors
161 ], 423);
162 }
163
164 $settings = apply_filters_deprecated(
165 'fluentform_payment_method_settings_save_' . $method,
166 [
167 $settings
168 ],
169 FLUENTFORM_FRAMEWORK_UPGRADE,
170 'fluentform/payment_method_settings_save_' . $method,
171 'Use fluentform/payment_method_settings_save_' . $method . ' instead of fluentform_payment_method_settings_save_' . $method
172 );
173
174 $settings = apply_filters('fluentform/payment_method_settings_save_' . $method, $settings);
175
176 update_option('fluentform_payment_settings_' . $method, $settings, 'yes');
177
178 wp_send_json_success([
179 'message' => __('Settings successfully updated', 'fluentform')
180 ]);
181 }
182
183 public function getFormSettings()
184 {
185 $request = wpFluentForm()->request;
186 $formId = intval($request->get('form_id', 0));
187 $settings = PaymentHelper::getFormSettings($formId, 'admin');
188 $form = Form::find($formId);
189 $addressFields = array_values(FormFieldsParser::getAddressFields($form));
190
191 $paymentSettings = [
192 'settings' => $settings,
193 'currencies' => PaymentHelper::getCurrencies(),
194 'payment_methods' => PaymentHelper::getFormPaymentMethods($formId),
195 'addressFields' => array_filter($addressFields)
196 ];
197
198 $paymentSettings = apply_filters('fluentform/form_payment_settings', $paymentSettings, $formId);
199
200 wp_send_json_success($paymentSettings, 200);
201 }
202
203 public function saveFormSettings()
204 {
205 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
206 $request = wpFluentForm()->request;
207 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, sanitized in setFormMeta()
208 $formId = intval($request->get('form_id', 0));
209 $settings = wp_unslash($request->get('settings', []));
210
211 $sanitizeMap = [
212 'enabled' => 'rest_sanitize_boolean',
213 'currency' => 'sanitize_text_field',
214 ];
215 $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
216
217 Helper::setFormMeta($formId, '_payment_settings', $settings);
218
219 wp_send_json_success([
220 'message' => __('Settings successfully saved', 'fluentform')
221 ], 200);
222 }
223
224 public function updateTransaction()
225 {
226 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Nonce verified in route registration, data sanitized below
227 $request = wpFluentForm()->request;
228 $transactionData = $request->get('transaction', []);
229 if (is_array($transactionData)) {
230 $transactionData['id'] = intval(ArrayHelper::get($transactionData, 'id'));
231 $transactionData['status'] = sanitize_text_field(ArrayHelper::get($transactionData, 'status'));
232 $transactionData['payer_name'] = sanitize_text_field(ArrayHelper::get($transactionData, 'payer_name'));
233 $transactionData['payer_email'] = sanitize_email(ArrayHelper::get($transactionData, 'payer_email'));
234 $transactionData['charge_id'] = sanitize_text_field(ArrayHelper::get($transactionData, 'charge_id'));
235 $transactionData['refund_amount'] = floatval(ArrayHelper::get($transactionData, 'refund_amount'));
236 $transactionData['refund_note'] = sanitize_text_field(ArrayHelper::get($transactionData, 'refund_note'));
237 $transactionData['should_run_actions'] = sanitize_text_field(ArrayHelper::get($transactionData, 'should_run_actions'));
238
239 // Handle billing_address and shipping_address
240 if (isset($transactionData['billing_address'])) {
241 $transactionData['billing_address'] = is_array($transactionData['billing_address'])
242 ? array_map('sanitize_text_field', $transactionData['billing_address'])
243 : sanitize_text_field($transactionData['billing_address']);
244 }
245 if (isset($transactionData['shipping_address'])) {
246 $transactionData['shipping_address'] = is_array($transactionData['shipping_address'])
247 ? array_map('sanitize_text_field', $transactionData['shipping_address'])
248 : sanitize_text_field($transactionData['shipping_address']);
249 }
250 }
251
252 // Sanitize subscription_id separately
253 $subscriptionId = intval($request->get('subscription_id', 0));
254
255 $transactionId = $transactionData['id'];
256 $oldTransaction = Transaction::find($transactionId);
257
258 $changingStatus = $oldTransaction->status != $transactionData['status'];
259
260 $updateData = ArrayHelper::only($transactionData, [
261 'payer_name',
262 'payer_email',
263 'billing_address',
264 'shipping_address',
265 'charge_id',
266 'status'
267 ]);
268
269 $updateData['updated_at'] = current_time('mysql');
270
271 Transaction::where('id', $transactionId)->update($updateData);
272
273 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
274 if ($subscriptionId) {
275 $existingSubscription = Subscription::find($subscriptionId);
276
277 $changedStatus = ArrayHelper::get($transactionData, 'status');
278
279 $isStatusChanged = $existingSubscription->status != $changedStatus;
280
281 if ($isStatusChanged) {
282 Subscription::where('id', $subscriptionId)
283 ->update([
284 'status' => $changedStatus,
285 'updated_at' => current_time('mysql')
286 ]);
287 }
288 }
289
290 $newStatus = $transactionData['status'];
291
292 // No need abstract method, only need defined method, empty implementation
293 $baseProcessor = new class extends BaseProcessor {
294 public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) {
295 }
296 };
297
298 if (
299 ($changingStatus && ($newStatus == 'refunded' || $newStatus == 'partial-refunded')) ||
300 ($newStatus == 'partial-refunded' && ArrayHelper::get($transactionData, 'refund_amount'))
301 ) {
302 $refundAmount = 0;
303 $refundNote = 'Refunded by Admin';
304
305 if ($newStatus == 'refunded') {
306 // Handle refund here
307 $refundAmount = $oldTransaction->payment_total;
308 } else if ($newStatus == 'partially-refunded') {
309 $refundAmount = ArrayHelper::get($transactionData, 'refund_amount') * 100;
310 $refundNote = ArrayHelper::get($transactionData, 'refund_note');
311 }
312
313 if ($refundAmount) {
314 $baseProcessor->setSubmissionId($oldTransaction->submission_id);
315
316 $submission = $baseProcessor->getSubmission();
317 $baseProcessor->refund($refundAmount, $oldTransaction, $submission, $oldTransaction->payment_method, 'refund_' . time(), $refundNote);
318 }
319
320 }
321
322 if ($changingStatus) {
323
324 if ($newStatus == 'paid' || $newStatus == 'pending' || $newStatus == 'processing') {
325 // Delete All Refunds
326 Transaction::bySubmission($oldTransaction->submission_id)->refunds()->delete();
327 }
328
329 $baseProcessor->setSubmissionId($oldTransaction->submission_id);
330 $baseProcessor->changeSubmissionPaymentStatus($newStatus);
331 $baseProcessor->changeTransactionStatus($transactionId, $newStatus);
332 $baseProcessor->recalculatePaidTotal();
333 }
334
335 $shouldRunActions = ArrayHelper::get($transactionData, 'should_run_actions', 'no');
336
337 if (
338 $changingStatus &&
339 $newStatus === 'paid' &&
340 $shouldRunActions === 'yes'
341 ) {
342 do_action(
343 'fluentform/run_actions_after_update_transaction_as_paid',
344 $newStatus,
345 $oldTransaction
346 );
347 }
348
349 wp_send_json_success([
350 'message' => __('Successfully updated data', 'fluentform')
351 ], 200);
352 }
353
354 public function getStripeConnectConfig()
355 {
356 wp_send_json_success(ConnectConfig::getConnectConfig());
357 }
358
359 public function disconnectStripeConnect()
360 {
361 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
362 $request = wpFluentForm()->request;
363 $attributes = $request->all();
364
365 $sanitizeMap = [
366 'mode' => 'sanitize_text_field',
367 ];
368 $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
369
370 return ConnectConfig::disconnect($attributes, true);
371 }
372
373 public function getWpPages()
374 {
375 $pages = wpFluent()->table('posts')
376 ->select(['ID', 'post_title'])
377 ->where('post_status', 'publish')
378 ->where('post_type', 'page')
379 ->orderBy('ID', 'ASC')
380 ->get();
381
382 wp_send_json_success([
383 'pages' => $pages
384 ]);
385 }
386
387 public function cancelSubscription()
388 {
389 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
390 $request = wpFluentForm()->request;
391 $attributes = $request->all();
392
393 $sanitizeMap = [
394 'subscription_id' => 'intval',
395 'transaction_id' => 'intval',
396 'submission_id' => 'intval',
397 ];
398 $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
399
400 $subscriptionId = ArrayHelper::get($attributes, 'subscription_id');
401
402 $subscription = fluentFormApi('submissions')->getSubscription($subscriptionId);
403
404 if (!$subscription) {
405 wp_send_json_error([
406 'message' => __('Subscription could not be found', 'fluentform')
407 ], 423);
408 }
409
410 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
411 $transactionId = ArrayHelper::get($attributes, 'transaction_id', 0);
412 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
413 $submissionId = ArrayHelper::get($attributes, 'submission_id', 0);
414
415 $oldTransaction = Transaction::find($transactionId);
416
417 $oldSubmission = Submission::find($submissionId);
418
419 if ($oldTransaction && $oldSubmission) {
420 $isStatusNotCancelled = $oldTransaction->status !== 'cancelled' && $oldSubmission->payment_status !== 'cancelled';
421
422 if ($isStatusNotCancelled) {
423 Transaction::where('id', $transactionId)
424 ->update([
425 'status' => 'cancelled',
426 'updated_at' => current_time('mysql')
427 ]);
428
429 Submission::where('id', $submissionId)
430 ->update([
431 'payment_status' => 'cancelled',
432 'updated_at' => current_time('mysql')
433 ]);
434 }
435 }
436
437 $response = (new PaymentManagement())->cancelSubscription($subscription);
438
439 if(is_wp_error($response)) {
440 wp_send_json_error([
441 'message' => $response->get_error_code().' - '.$response->get_error_message()
442 ], 423);
443 }
444
445 wp_send_json_success([
446 'message' => $response
447 ]);
448
449 }
450
451 }
452