File "PaymentHandler.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/fluentform/app/Modules/Payments/PaymentHandler.php
File size: 26.84 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace FluentForm\App\Modules\Payments;
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}
use FluentForm\App\Helpers\Helper;
use FluentForm\App\Modules\Acl\Acl;
use FluentForm\App\Modules\Form\FormFieldsParser;
use FluentForm\App\Modules\Payments\Orders\OrderData;
use FluentForm\App\Services\FormBuilder\ShortCodeParser;
use FluentForm\Framework\Helpers\ArrayHelper;
use FluentForm\App\Modules\Payments\Classes\PaymentAction;
use FluentForm\App\Modules\Payments\Classes\PaymentEntries;
use FluentForm\App\Modules\Payments\Classes\PaymentReceipt;
use FluentForm\App\Modules\Payments\Components\CustomPaymentComponent;
use FluentForm\App\Modules\Payments\Components\ItemQuantity;
use FluentForm\App\Modules\Payments\Components\MultiPaymentComponent;
use FluentForm\App\Modules\Payments\Components\PaymentMethods;
use FluentForm\App\Modules\Payments\Components\PaymentSummaryComponent;
use FluentForm\App\Modules\Payments\Components\Subscription;
use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\Components\StripeInline;
use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\ConnectConfig;
use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\StripeHandler;
use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\StripeSettings;
class PaymentHandler
{
public function init()
{
add_filter('fluentform/global_settings_components', [$this, 'pushGlobalSettings'], 1, 1);
add_filter('fluentform/global_settings_component_settings_data', [$this, 'getGlobalSettingsPaymentVars']);
add_action('wp_ajax_fluentform_handle_payment_ajax_endpoint', [$this, 'handleAjaxEndpoints']);
if (!$this->isEnabled()) {
return;
}
add_filter('fluentform/show_payment_entries', '__return_true');
add_filter('fluentform/form_settings_menu', array($this, 'maybeAddPaymentSettings'), 10, 2);
// Let's load Payment Methods here
(new StripeHandler())->init();
// Let's load the payment method component here
new MultiPaymentComponent();
new Subscription();
new CustomPaymentComponent();
new ItemQuantity();
new PaymentMethods();
new PaymentSummaryComponent();
add_filter('fluentform/editor_components', function ($components) {
if (!Helper::hasPro()) {
$components['payments'][] = [
'index' => 6,
'element' => 'payment_coupon',
'attributes' => [],
'settings' => [],
'editor_options' => [
'title' => __('Coupon', 'fluentform'),
'icon_class' => 'el-icon-postcard',
'template' => 'inputText',
],
];
}
return $components;
}, 11);
new StripeInline();
add_action('fluentform/before_insert_payment_form', array($this, 'maybeHandlePayment'), 10, 3);
add_filter('fluentform/submission_order_data', function ($data, $submission) {
return OrderData::getSummary($submission, $submission->form);
}, 10, 2);
add_filter('fluentform/entries_vars', function ($vars, $form) {
if ($form->has_payment) {
$vars['has_payment'] = $form->has_payment;
$vars['currency_config'] = PaymentHelper::getCurrencyConfig($form->id);
$vars['currency_symbols'] = PaymentHelper::getCurrencySymbols();
$vars['payment_statuses'] = PaymentHelper::getPaymentStatuses();
}
return $vars;
}, 10, 2);
add_filter(
'fluentform/submission_labels',
[$this, 'modifySingleEntryLabels'],
10,
3
);
add_filter('fluentform/all_entry_labels_with_payment', array($this, 'modifySingleEntryLabels'), 10, 3);
add_action('fluentform/rendering_payment_form', function ($form) {
$src = fluentformMix('js/payment_handler.js');
$version = FLUENTFORM_VERSION;
// If pro is installed and script is compatible, load script from pro
if (Helper::isProPaymentScriptCompatible()) {
$src = FLUENTFORMPRO_DIR_URL . 'public/js/payment_handler_pro.js';
$version = FLUENTFORMPRO_VERSION;
}
wp_enqueue_script('fluentform-payment-handler',
$src,
array('jquery'),
$version,
true
);
wp_enqueue_style(
'fluentform-payment-skin',
fluentFormMix('css/payment_skin.css'),
array(),
FLUENTFORM_VERSION
);
wp_localize_script('fluentform-payment-handler', 'fluentform_payment_config', [
'i18n' => [
'item' => __('Item', 'fluentform'),
'price' => __('Price', 'fluentform'),
'qty' => __('Qty', 'fluentform'),
'line_total' => __('Line Total', 'fluentform'),
'total' => __('Total', 'fluentform'),
'not_found' => __('No payment item selected yet', 'fluentform'),
'discount:' => __('Discount:', 'fluentform'),
'processing_text' => __('Processing payment. Please wait...', 'fluentform'),
'confirming_text' => __('Confirming payment. Please wait...', 'fluentform'),
'Signup Fee for' => __('Signup Fee for', 'fluentform')
]
]);
$secretKey = apply_filters_deprecated(
'fluentform-payment_stripe_publishable_key',
[
StripeSettings::getPublishableKey($form->id),
$form->id
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/payment_stripe_publishable_key',
'Use fluentform/payment_stripe_publishable_key instead of fluentform-payment_stripe_publishable_key.'
);
$publishableKey = apply_filters('fluentform/payment_stripe_publishable_key', $secretKey, $form->id);
$stripeCustomCss = [
'styles' => [
'base' => [
'backgroundColor' => 'white',
'color' => '#32325d',
'fontFamily' => "-apple-system, \"system-ui\", \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif",
'fontSize' => '14px',
'fontSmoothing' => 'antialiased',
'iconColor' => '#32325d',
'textDecoration' => 'none',
'::placeholder' => [
'color'=> "#aab7c4"
],
":focus" => [
'backgroundColor' => 'white',
'color' => '#32325d',
'fontFamily' => "-apple-system, \"system-ui\", \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif",
'fontSize' => '14px',
'fontSmoothing' => 'antialiased',
'iconColor' => '#32325d',
'textDecoration' => 'none',
],
],
'invalid' => [
'color' => "#fa755a",
'iconColor' => "#fa755a"
]
]
];
$paymentConfig = [
'currency_settings' => PaymentHelper::getCurrencyConfig($form->id),
'stripe' => [
'publishable_key' => $publishableKey,
'inlineConfig' => PaymentHelper::getStripeInlineConfig($form->id),
'custom_style' => apply_filters(
'fluentform/stripe_inline_custom_css',
$stripeCustomCss,
$form->id
),
'locale' => 'en'
],
'stripe_app_info' => [
'name' => 'Fluent Forms',
'version' => FLUENTFORM_VERSION,
'url' => site_url(),
'partner_id' => 'pp_partner_FN62GfRLM2Kx5d'
],
];
$paymentConfig = apply_filters('fluentform/payment_config', $paymentConfig, $form->id);
wp_localize_script('fluentform-payment-handler', 'fluentform_payment_config_' . $form->id, $paymentConfig);
}, 11, 1);
if (isset($_GET['fluentform_payment']) && isset($_GET['payment_method'])) {
add_action('wp', function () {
$data = $_GET;
$type = sanitize_text_field($_GET['fluentform_payment']);
if ($type == 'view' && $route = ArrayHelper::get($data, 'route')) {
do_action_deprecated(
'fluent_payment_view_' . $route,
[
$data
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/payment_view_' . $route,
'Use fluentform/payment_view_' . $route . ' instead of fluent_payment_view_' . $route
);
do_action('fluentform/payment_view_' . $route, $data);
}
$this->validateFrameLessPage($data);
$paymentMethod = sanitize_text_field($_GET['payment_method']);
do_action_deprecated(
'fluent_payment_frameless_' . $paymentMethod,
[
$data
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/payment_frameless_' . $paymentMethod,
'Use fluentform/payment_frameless_' . $paymentMethod . ' instead of fluent_payment_frameless_' . $paymentMethod
);
do_action('fluentform/payment_frameless_' . $paymentMethod, $data);
});
}
if (isset($_REQUEST['fluentform_payment_api_notify'])) {
add_action('wp', function () {
$paymentMethod = sanitize_text_field($_REQUEST['payment_method']);
do_action_deprecated(
'fluentform_ipn_endpoint_' . $paymentMethod,
[
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/ipn_endpoint_' . $paymentMethod,
'Use fluentform/ipn_endpoint_' . $paymentMethod . ' instead of fluentform_ipn_endpoint_' . $paymentMethod
);
do_action('fluentform/ipn_endpoint_' . $paymentMethod);
});
}
add_filter('fluentform/editor_vars', function ($vars) {
$settings = PaymentHelper::getCurrencyConfig($vars['form_id']);
$vars['payment_settings'] = $settings;
$vars['has_payment_features'] = !!$settings;
return $vars;
});
add_filter('fluentform/admin_i18n', array($this, 'paymentTranslations'), 10, 1);
add_filter('fluentform/payment_smartcode', array($this, 'paymentReceiptView'), 10, 3);
add_action('user_register', array($this, 'maybeAssignTransactions'), 99, 1);
(new PaymentEntries())->init();
/*
* Transactions and subscriptions Shortcode
*/
(new TransactionShortcodes())->init();
add_filter(
'fluentform/validate_input_item_subscription_payment_component',
[$this, 'validateSubscriptionInputs'],
10,
3
);
add_filter(
'fluentform/validate_input_item_multi_payment_component',
[$this, 'validatePaymentInputs'],
10,
3
);
add_filter(
'fluentform/validate_input_item_payment_method',
[$this, 'validatePaymentMethod'],
10,
5
);
}
public function pushGlobalSettings($components)
{
$subMenuItems = [
[
'title' => 'Settings',
'hash' => 'payments/general_settings',
],
[
'title' => 'Payment Methods',
'hash' => 'payments/payment_methods',
]
];
$subMenuItems = apply_filters('fluentform/global_settings_payment_sub_menu_items', $subMenuItems);
$components['payment_settings'] = [
'title' => __('Payment Settings', 'fluentform'),
'sub_menu'=> $subMenuItems
];
return $components;
}
public function getGlobalSettingsPaymentVars($globalSettingVars)
{
if (isset($_GET['ff_stripe_connect'])) {
$data = ArrayHelper::only($_GET, ['ff_stripe_connect', 'mode', 'state', 'code']);
ConnectConfig::verifyAuthorizeSuccess($data);
}
$paymentSettings = PaymentHelper::getPaymentSettings();
$isSettingsAvailable = PaymentHelper::hasPaymentSettings();
$nav = 'general';
if (isset($_REQUEST['nav'])) {
$nav = sanitize_text_field($_REQUEST['nav']);
}
$paymentMethods = apply_filters_deprecated(
'fluentformpro_available_payment_methods',
[
[]
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/available_payment_methods',
'Use fluentform/available_payment_methods instead of fluentformpro_available_payment_methods.'
);
$globalSettings = apply_filters_deprecated(
'fluentformpro_payment_methods_global_settings',
[
[]
],
FLUENTFORM_FRAMEWORK_UPGRADE,
'fluentform/payment_methods_global_settings',
'Use fluentform/payment_methods_global_settings instead of fluentformpro_payment_methods_global_settings.'
);
$paymentVars = [
'is_setup' => $isSettingsAvailable,
'general' => $paymentSettings,
'payment_methods' => apply_filters('fluentform/available_payment_methods', $paymentMethods),
'available_payment_methods' => apply_filters('fluentform/payment_methods_global_settings', $globalSettings),
'currencies' => PaymentHelper::getCurrencies(),
'active_nav' => $nav,
'stripe_webhook_url' => add_query_arg([
'fluentform_payment_api_notify' => '1',
'payment_method' => 'stripe'
], site_url('index.php')),
'paypal_webhook_url' => add_query_arg([
'fluentform_payment_api_notify' => '1',
'payment_method' => 'paypal'
], site_url('index.php'))
];
// Enqueue payment global settings css
wp_enqueue_style('ff-payment-settings', fluentFormMix('css/payment_settings.css'), [], FLUENTFORM_VERSION);
$globalSettingVars['payment_vars'] = apply_filters('fluentform/global_settings_component_payment_vars', $paymentVars);
return $globalSettingVars;
}
public function handleAjaxEndpoints()
{
if (isset($_REQUEST['form_id'])) {
Acl::verify('fluentform_forms_manager');
} else {
Acl::verify('fluentform_settings_manager');
}
$route = sanitize_text_field($_REQUEST['route']);
(new AjaxEndpoints())->handleEndpoint($route);
}
public function maybeHandlePayment($insertData, $data, $form)
{
// Let's get selected Payment Method
if (!FormFieldsParser::hasPaymentFields($form)) {
return;
}
$paymentAction = new PaymentAction($form, $insertData, $data);
if (!$paymentAction->getSubscriptionItems() && !$paymentAction->getCalculatedAmount()) {
return;
}
/*
* We have to check if
* 1. has payment method
* 2. if user selected payment method
* 3. or maybe has a conditional logic on it
*/
if ($paymentAction->isConditionPass()) {
if (FormFieldsParser::hasElement($form, 'payment_method') &&
!$paymentAction->selectedPaymentMethod
) {
wp_send_json([
'errors' => [__('Sorry! No selected payment method found. Please select a valid payment method', 'fluentform')]
], 423);
}
}
/*
* Some Payment Gateway like Razorpay, Square not supported $subscriptionItems.
* So we are providing filter hook to validate payment fields.
*/
$errors = apply_filters(
'fluentform/validate_payment_items_' . $paymentAction->selectedPaymentMethod,
[],
$paymentAction->getOrderItems(),
$paymentAction->getSubscriptionItems(),
$form
);
if ($errors) {
wp_send_json([
'errors' => $errors
], 423);
}
$paymentAction->draftFormEntry();
}
public function isEnabled()
{
$paymentSettings = PaymentHelper::getPaymentSettings();
return $paymentSettings['status'] == 'yes';
}
public function modifySingleEntryLabels($labels, $submission, $form)
{
$formFields = FormFieldsParser::getPaymentFields($form);
if ($formFields && is_array($formFields)) {
$labels = ArrayHelper::except($labels, array_keys($formFields));
}
return $labels;
}
public function maybeAddPaymentSettings($menus, $formId)
{
$form = wpFluent()->table('fluentform_forms')->find($formId);
if ($form->has_payment) {
$menus = array_merge(array_slice($menus, 0, 1), array(
'payment_settings' => [
'title' => __('Payment Settings', 'fluentform'),
'slug' => 'form_settings',
'hash' => 'payment_settings',
'route' => '/payment-settings',
]
), array_slice($menus, 1));
}
return $menus;
}
/**
* @param $html string
* @param $property string
* @param $instance ShortCodeParser
* @return false|string
*/
public function paymentReceiptView($html, $property, $instance)
{
$entry = $instance::getEntry();
$receiptClass = new PaymentReceipt($entry);
return $receiptClass->getItem($property);
}
private function validateFrameLessPage($data)
{
// We should verify the transaction hash from the URL
$transactionHash = sanitize_text_field(ArrayHelper::get($data, 'transaction_hash'));
$submissionId = intval(ArrayHelper::get($data, 'fluentform_payment'));
if (!$submissionId) {
die('Validation Failed');
}
if ($transactionHash) {
$transaction = wpFluent()->table('fluentform_transactions')
->where('submission_id', $submissionId)
->where('transaction_hash', $transactionHash)
->first();
if ($transaction) {
return true;
}
die('Transaction hash is invalid');
}
$uid = sanitize_text_field(ArrayHelper::get($data, 'entry_uid'));
if (!$uid) {
die('Validation Failed');
}
$originalUid = Helper::getSubmissionMeta($submissionId, '_entry_uid_hash');
if ($originalUid != $uid) {
die(__('Transaction UID is invalid', 'fluentform'));
}
return true;
}
public function maybeAssignTransactions($userId)
{
$user = get_user_by('ID', $userId);
if (!$user) {
return false;
}
$userEmail = $user->user_email;
$transactions = wpFluent()->table('fluentform_transactions')
->where('payer_email', $userEmail)
->where(function ($query) {
$query->whereNull('user_id')
->orWhere('user_id', '');
})
->get();
if (!$transactions) {
return false;
}
$submissionIds = [];
$transactionIds = [];
foreach ($transactions as $transaction) {
$submissionIds[] = $transaction->submission_id;
$transactionIds[] = $transaction->id;
}
$submissionIds = array_unique($submissionIds);
$transactionIds = array_unique($transactionIds);
wpFluent()->table('fluentform_submissions')
->whereIn('id', $submissionIds)
->update([
'user_id' => $userId,
'updated_at' => current_time('mysql')
]);
wpFluent()->table('fluentform_transactions')
->whereIn('id', $transactionIds)
->update([
'user_id' => $userId,
'updated_at' => current_time('mysql')
]);
return true;
}
public function paymentTranslations($i18n)
{
$paymentI18n = array(
'Order Details' => __('Order Details', 'fluentform'),
'Product' => __('Product', 'fluentform'),
'Qty' => __('Qty', 'fluentform'),
'Unit Price' => __('Unit Price', 'fluentform'),
'Total' => __('Total', 'fluentform'),
'Sub-Total' => __('Sub-Total', 'fluentform'),
'Discount' => __('Discount', 'fluentform'),
'Price' => __('Price', 'fluentform'),
'Payment Details' => __('Payment Details', 'fluentform'),
'From Subscriptions' => __('From Subscriptions', 'fluentform'),
'Card Last 4' => __('Card Last 4', 'fluentform'),
'Payment Total' => __('Payment Total', 'fluentform'),
'Payment Status' => __('Payment Status', 'fluentform'),
'Transaction ID' => __('Transaction ID', 'fluentform'),
'Payment Method' => __('Payment Method', 'fluentform'),
'Transaction' => __('Transaction', 'fluentform'),
'Refunds' => __('Refunds', 'fluentform'),
'Refund' => __('Refund', 'fluentform'),
'at' => __('at', 'fluentform'),
'View' => __('View', 'fluentform'),
'has been refunded via' => __('has been refunded via', 'fluentform'),
'Note' => __('Note', 'fluentform'),
'Edit Transaction' => __('Edit Transaction', 'fluentform'),
'Billing Name' => __('Billing Name', 'fluentform'),
'Billing Email' => __('Billing Email', 'fluentform'),
'Billing Address' => __('Billing Address', 'fluentform'),
'Shipping Address' => __('Shipping Address', 'fluentform'),
'Reference ID' => __('Reference ID', 'fluentform'),
'refunds-to-be-handled-from-provider-text' => __('Please note that, Actual Refund needs to be handled in your Payment Service Provider.', 'fluentform'),
'Please Provide new refund amount only.' => __('Please Provide new refund amount only.', 'fluentform'),
'Refund Note' => __('Refund Note', 'fluentform'),
'Cancel' => __('Cancel', 'fluentform'),
'Confirm' => __('Confirm', 'fluentform'),
);
return array_merge($i18n,$paymentI18n);
}
public function validateSubscriptionInputs($error, $field, $formData)
{
if (isset($formData[$field['name']])) {
$subscriptionOptions = ArrayHelper::get($field, 'raw.settings.subscription_options', []);
$selectedPlanIndex = $formData[$field['name']];
$acceptedSubscriptionPlan = is_numeric($selectedPlanIndex) && in_array($selectedPlanIndex, array_keys($subscriptionOptions));
if (!$acceptedSubscriptionPlan) {
$error = __('This subscription plan is invalid', 'fluentform');
}
$selectedPlan = ArrayHelper::get($subscriptionOptions, $selectedPlanIndex, []);
if ('yes' === ArrayHelper::get($selectedPlan, 'user_input')) {
$userGivenValue = ArrayHelper::get($formData, "{$field['name']}_custom_$selectedPlanIndex");
$userGivenValue = $userGivenValue ?: 0;
$planMinValue = ArrayHelper::get($selectedPlan, 'user_input_min_value');
if (!is_numeric($userGivenValue) || ($planMinValue && $userGivenValue < $planMinValue)) {
$error = __('This subscription plan value is invalid', 'fluentform');
}
}
}
return $error;
}
public function validatePaymentInputs($error, $field, $formData)
{
if (ArrayHelper::get($formData, $field['name'])) {
$fieldType = ArrayHelper::get($field, 'raw.attributes.type');
if (in_array($fieldType, ['radio', 'select', 'checkbox'])) {
$pricingOptions = array_column(
ArrayHelper::get($field, 'raw.settings.pricing_options', []),
'label'
);
$pricingOptions = array_map('sanitize_text_field', $pricingOptions);
if (in_array($fieldType, ['radio', 'select'])) {
$acceptedPaymentPlan = in_array($formData[$field['name']], $pricingOptions);
} else {
$acceptedPaymentPlan = array_diff($formData[$field['name']], $pricingOptions);
$acceptedPaymentPlan = empty($acceptedPaymentPlan);
}
if (!$acceptedPaymentPlan) {
$error = __('This payment item is invalid', 'fluentform');
}
}
}
return $error;
}
public function validatePaymentMethod($error, $field, $formData, $fields, $form)
{
if ($selectedMethod = ArrayHelper::get($formData, $field['name'])) {
$activeMethods = array_keys(PaymentHelper::getFormPaymentMethods($form->id));
if (!in_array($selectedMethod, $activeMethods)) {
$error = __('This payment method is invalid', 'fluentform');
}
}
return $error;
}
}