From 1eb7584c02cf6675cda2440616e870104a51fd54 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 23 Jan 2025 17:28:02 -0400 Subject: [PATCH 001/162] First square commit (copied from Stripe files) --- classes/controllers/FrmHooksController.php | 2 + formidable.php | 44 +- .../FrmSquareLiteActionsController.php | 420 ++++++++++++++++++ .../FrmSquareLiteAppController.php | 30 ++ .../FrmSquareLiteHooksController.php | 43 ++ .../FrmSquareLiteSettingsController.php | 66 +++ square/helpers/FrmSquareLiteAppHelper.php | 53 +++ square/helpers/FrmSquareLiteConnectHelper.php | 9 + square/js/frontend.js | 3 + square/js/settings.js | 3 + square/models/FrmSquareLiteSettings.php | 100 +++++ square/views/settings/form.php | 6 + stripe/helpers/FrmStrpLiteAppHelper.php | 1 + 13 files changed, 766 insertions(+), 14 deletions(-) create mode 100644 square/controllers/FrmSquareLiteActionsController.php create mode 100644 square/controllers/FrmSquareLiteAppController.php create mode 100644 square/controllers/FrmSquareLiteHooksController.php create mode 100644 square/controllers/FrmSquareLiteSettingsController.php create mode 100644 square/helpers/FrmSquareLiteAppHelper.php create mode 100644 square/helpers/FrmSquareLiteConnectHelper.php create mode 100644 square/js/frontend.js create mode 100644 square/js/settings.js create mode 100644 square/models/FrmSquareLiteSettings.php create mode 100644 square/views/settings/form.php diff --git a/classes/controllers/FrmHooksController.php b/classes/controllers/FrmHooksController.php index ec99052bff..219b6ba5dd 100644 --- a/classes/controllers/FrmHooksController.php +++ b/classes/controllers/FrmHooksController.php @@ -112,6 +112,7 @@ public static function load_hooks() { FrmTransLiteHooksController::load_hooks(); FrmStrpLiteHooksController::load_hooks(); + FrmSquareLiteHooksController::load_hooks(); } /** @@ -201,6 +202,7 @@ public static function load_admin_hooks() { FrmDashboardController::load_admin_hooks(); FrmTransLiteHooksController::load_admin_hooks(); FrmStrpLiteHooksController::load_admin_hooks(); + FrmSquareLiteHooksController::load_admin_hooks(); FrmSMTPController::load_hooks(); FrmOnboardingWizardController::load_admin_hooks(); FrmAddonsController::load_admin_hooks(); diff --git a/formidable.php b/formidable.php index 3094c9e6fe..138e68d473 100644 --- a/formidable.php +++ b/formidable.php @@ -107,25 +107,41 @@ function frm_class_autoloader( $class_name, $filepath ) { return; } - if ( ! preg_match( '/^FrmStrpLite.+$/', $class_name ) && ! preg_match( '/^FrmTransLite.+$/', $class_name ) ) { - // Exit early if the class does not match the Stripe Lite prefix. + if ( preg_match( '/^FrmStrpLite.+$/', $class_name ) || preg_match( '/^FrmTransLite.+$/', $class_name ) ) { + // Autoload for /stripe/ folder. + $filepath = $original_filepath . '/stripe/'; + if ( preg_match( '/^.+Helper$/', $class_name ) ) { + $filepath .= 'helpers/'; + } elseif ( preg_match( '/^.+Controller$/', $class_name ) ) { + $filepath .= 'controllers/'; + } else { + $filepath .= 'models/'; + } + + $filepath .= $class_name . '.php'; + + if ( file_exists( $filepath ) ) { + require $filepath; + } + return; } - // Autoload for /stripe/ folder. - $filepath = $original_filepath . '/stripe/'; - if ( preg_match( '/^.+Helper$/', $class_name ) ) { - $filepath .= 'helpers/'; - } elseif ( preg_match( '/^.+Controller$/', $class_name ) ) { - $filepath .= 'controllers/'; - } else { - $filepath .= 'models/'; - } + if ( preg_match( '/^FrmSquareLite.+$/', $class_name ) ) { + $filepath = $original_filepath . '/square/'; + if ( preg_match( '/^.+Helper$/', $class_name ) ) { + $filepath .= 'helpers/'; + } elseif ( preg_match( '/^.+Controller$/', $class_name ) ) { + $filepath .= 'controllers/'; + } else { + $filepath .= 'models/'; + } - $filepath .= $class_name . '.php'; + $filepath .= $class_name . '.php'; - if ( file_exists( $filepath ) ) { - require $filepath; + if ( file_exists( $filepath ) ) { + require $filepath; + } } } diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php new file mode 100644 index 0000000000..63d57cc179 --- /dev/null +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -0,0 +1,420 @@ + $payment_action ) { + $gateway = $payment_action->post_content['gateway']; + $is_square = $gateway === 'square' || ( is_array( $gateway ) && in_array( 'square', $gateway, true ) ); + if ( ! $is_square || empty( $payment_action->post_content['amount'] ) ) { + unset( $payment_actions[ $k ] ); + } + } + return $payment_actions; + } + + /** + * Trigger a Square payment after a form is submitted. + * This is called for both one time and recurring payments. + * + * @param WP_Post $action + * @param stdClass $entry + * @param stdClass $form + * @return array + */ + public static function trigger_gateway( $action, $entry, $form ) { + $response = array( + 'success' => false, + 'run_triggers' => false, + 'show_errors' => true, + ); + $atts = compact( 'action', 'entry', 'form' ); + + $amount = self::prepare_amount( $action->post_content['amount'], $atts ); + if ( empty( $amount ) || $amount == 000 ) { + $response['error'] = __( 'Please specify an amount for the payment', 'formidable' ); + return $response; + } + + if ( ! self::square_is_configured() ) { + $response['error'] = __( 'There was a problem communicating with Stripe. Please try again.', 'formidable' ); + return $response; + } + + $customer = self::set_customer_with_token( $atts ); + if ( ! is_object( $customer ) ) { + $response['error'] = $customer; + return $response; + } + + $one_time_payment_args = compact( 'customer', 'form', 'entry', 'action', 'amount' ); + + // attempt to charge the customer's card + if ( 'recurring' === $action->post_content['type'] ) { + $charge = self::trigger_recurring_payment( compact( 'customer', 'entry', 'action', 'amount' ) ); + } else { + $charge = self::trigger_one_time_payment( $one_time_payment_args ); + $response['run_triggers'] = true; + } + + if ( $charge === true ) { + $response['success'] = true; + } else { + $response['error'] = $charge; + } + + return $response; + } + + /** + * Check if Square integration is enabled. + * + * @return bool true if Square is set up. + */ + private static function square_is_configured() { + // TODO + return false; + } + + /** + * Set a customer object to $_POST['customer'] to use later. + * + * @param array $atts + * @return object|string + */ + private static function set_customer_with_token( $atts ) { + if ( isset( self::$customer ) ) { + // It's an object if this isn't the first Stripe action running. + return self::$customer; + } + + $payment_info = array( + 'user_id' => FrmTransLiteAppHelper::get_user_id_for_current_payment(), + ); + + if ( ! empty( $atts['action']->post_content['email'] ) ) { + $payment_info['email'] = apply_filters( 'frm_content', $atts['action']->post_content['email'], $atts['form'], $atts['entry'] ); + $payment_info['email'] = self::replace_email_shortcode( $payment_info['email'] ); + } + + self::add_customer_name( $atts, $payment_info ); + + $customer = FrmStrpLiteAppHelper::call_stripe_helper_class( 'get_customer', $payment_info ); + // Set for later use. + self::$customer = $customer; + + return $customer; + } + + /** + * Replace an [email] shortcode with the current user email. + * + * @param string $email + * @return string + */ + private static function replace_email_shortcode( $email ) { + if ( false === strpos( $email, '[email]' ) ) { + return $email; + } + + global $current_user; + return str_replace( + '[email]', + ! empty( $current_user->user_email ) ? $current_user->user_email : '', + $email + ); + } + + /** + * Set the customer name based on the mapped first and last name fields in the Stripe action. + * + * @since 6.5, introduced in v2.02 of the Stripe add on. + * + * @param array $atts + * @param array $payment_info + * @return void + */ + private static function add_customer_name( $atts, &$payment_info ) { + if ( empty( $atts['action']->post_content['billing_first_name'] ) ) { + return; + } + + $name = '[' . $atts['action']->post_content['billing_first_name'] . ' show="first"]'; + if ( ! empty( $atts['action']->post_content['billing_last_name'] ) ) { + $name .= ' [' . $atts['action']->post_content['billing_last_name'] . ' show="last"]'; + } + + $payment_info['name'] = apply_filters( 'frm_content', $name, $atts['form'], $atts['entry'] ); + } + + /** + * Convert the amount from 10.00 to 1000. + * + * @param mixed $amount + * @param array $atts + * @return string + */ + public static function prepare_amount( $amount, $atts = array() ) { + $amount = parent::prepare_amount( $amount, $atts ); + $currency = self::get_currency_for_action( $atts ); + return number_format( $amount, $currency['decimals'], '', '' ); + } + + /** + * Filter Square action on save. + * + * @param array $settings + * @param array $action + * @return array + */ + public static function before_save_settings( $settings, $action ) { + $settings['currency'] = strtolower( $settings['currency'] ); + $form_id = absint( $action['menu_order'] ); + + if ( empty( $settings['credit_card'] ) ) { + $credit_card_field_id = FrmDb::get_var( + 'frm_fields', + array( + 'type' => 'credit_card', + 'form_id' => $form_id, + ) + ); + if ( ! $credit_card_field_id ) { + $credit_card_field_id = self::add_a_credit_card_field( $form_id ); + } + if ( $credit_card_field_id ) { + $settings['credit_card'] = $credit_card_field_id; + } + } + + $gateway_field_id = FrmDb::get_var( + 'frm_fields', + array( + 'type' => 'gateway', + 'form_id' => $form_id, + ) + ); + if ( ! $gateway_field_id ) { + self::add_a_gateway_field( $form_id ); + } + + return $settings; + } + + /** + * @param int $form_id + * @param string $field_type + * @param string $field_name + * @return false|int + */ + private static function add_a_field( $form_id, $field_type, $field_name ) { + $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id ); + $new_values['name'] = $field_name; + $field_id = FrmField::create( $new_values ); + return $field_id; + } + + /** + * A credit card field is added automatically if missing before a Stripe action is updated. + * + * @param int $form_id + * @return false|int + */ + private static function add_a_credit_card_field( $form_id ) { + return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) ); + } + + /** + * A gateway field is added automatically for compatibility with the Stripe add on. + * The gateway field is not important for the Stripe Lite implementation. + * + * @param int $form_id + * @return false|int + */ + private static function add_a_gateway_field( $form_id ) { + return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) ); + } + + /** + * If this form submits with ajax, load the scripts on the first page. + * + * @param array $params + * @return void + */ + public static function maybe_load_scripts( $params ) { + if ( $params['form_id'] == $params['posted_form_id'] ) { + // This form has already been posted, so we aren't on the first page. + return; + } + + $form = FrmForm::getOne( $params['form_id'] ); + if ( ! $form ) { + return; + } + + $credit_card_field = FrmField::getAll( + array( + 'fi.form_id' => $form->id, + 'type' => 'credit_card', + ) + ); + if ( ! $credit_card_field ) { + return; + } + + self::load_scripts( (int) $form->id ); + } + + /** + * Load front end JavaScript for a Stripe form. + * + * @param int $form_id + * @return void + */ + public static function load_scripts( $form_id ) { + if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) ) { + return; + } + + if ( wp_script_is( 'formidable-square', 'enqueued' ) ) { + return; + } + + $stripe_connect_is_setup = FrmStrpLiteConnectHelper::stripe_connect_is_setup(); + if ( ! $stripe_connect_is_setup ) { + return; + } + + if ( ! $form_id || ! is_int( $form_id ) ) { + _doing_it_wrong( __METHOD__, '$form_id parameter must be a non-zero integer', '6.5' ); + return; + } + + $settings = FrmStrpLiteAppHelper::get_settings(); + $publishable = $settings->get_active_publishable_key(); + + wp_register_script( + 'stripe', + 'https://js.stripe.com/v3/', + array(), + '3.0', + false + ); + + $suffix = FrmAppHelper::js_suffix(); + $dependencies = array( 'stripe', 'formidable' ); + + if ( '.min' === $suffix && is_readable( FrmAppHelper::plugin_path() . '/js/frmstrp.min.js' ) ) { + // Use the combined file if it is available. + $script_url = FrmAppHelper::plugin_url() . '/js/frmstrp.min.js'; + } else { + if ( ! $suffix && ! is_readable( FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.js' ) ) { + // The unminified file is not included in releases so force the minified script. + $suffix = '.min'; + } + $script_url = FrmStrpLiteAppHelper::plugin_url() . 'js/frmstrp' . $suffix . '.js'; + } + + if ( class_exists( 'FrmProStrpLiteController' ) && ( ! $suffix || ! FrmProAppController::has_combo_js_file() ) ) { + $dependencies[] = 'formidablepro'; + } + + wp_enqueue_script( + 'formidable-square', + $script_url, + $dependencies, + FrmAppHelper::plugin_version(), + false + ); + + $action_settings = self::prepare_settings_for_js( $form_id ); + $square_vars = array( + 'publishable_key' => $publishable, + 'form_id' => $form_id, + 'nonce' => wp_create_nonce( 'frm_square_ajax' ), + 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ), + 'settings' => $action_settings, + 'locale' => self::get_locale(), + ); + + wp_localize_script( 'formidable-square', 'frm_square_vars', $square_vars ); + } + + /** + * Get the language to use for Stripe elements. + * + * @since x.x + * @return string + */ + private static function get_locale() { + $allowed = array( 'ar', 'da', 'de', 'en', 'es', 'fi', 'fr', 'he', 'it', 'ja', 'nl', 'no', 'pl', 'ru', 'sv', 'zh' ); + $current = get_locale(); + $parts = explode( '_', $current ); + $part = strtolower( $parts[0] ); + return in_array( $part, $allowed, true ) ? $part : 'auto'; + } + + /** + * If the names are being used on the CC fields, + * make sure it doesn't prevent the submission if Stripe has approved. + * + * @since x.x + * + * @param array $errors + * @param stdClass $field + * @param array $values + * @return array + */ + public static function remove_cc_validation( $errors, $field, $values ) { + $has_processed = isset( $_POST[ 'frmintent' . $field->form_id ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing + if ( ! $has_processed ) { + return $errors; + } + + $field_id = isset( $field->temp_id ) ? $field->temp_id : $field->id; + + if ( isset( $errors[ 'field' . $field_id . '-cc' ] ) ) { + unset( $errors[ 'field' . $field_id . '-cc' ] ); + } + if ( isset( $errors[ 'field' . $field_id ] ) ) { + unset( $errors[ 'field' . $field_id ] ); + } + + return $errors; + } +} diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php new file mode 100644 index 0000000000..d56fb4ee22 --- /dev/null +++ b/square/controllers/FrmSquareLiteAppController.php @@ -0,0 +1,30 @@ + 'Square', + 'user_label' => __( 'Payment', 'formidable' ), + 'class' => 'SquareLite', + 'recurring' => true, + 'include' => array( + 'billing_first_name', + 'billing_last_name', + 'credit_card', + 'billing_address', + ), + ); + return $gateways; + } +} diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php new file mode 100644 index 0000000000..7bb441b85f --- /dev/null +++ b/square/controllers/FrmSquareLiteHooksController.php @@ -0,0 +1,43 @@ + __CLASS__, + 'function' => 'route', + 'icon' => 'frm_icon_font frm_credit_card_icon', + ); + + return $sections; + } + + /** + * Handle global settings routing. + * + * @return void + */ + public static function route() { + self::global_settings_form(); + } + + /** + * Print the Stripe section for Global settings. + * + * @param array $atts + * @return void + */ + public static function global_settings_form( $atts = array() ) { + include FrmSquareLiteAppHelper::plugin_path() . '/views/settings/form.php'; + } + + /** + * @return array + */ + private static function get_default_settings_atts() { + return array( + 'errors' => array(), + 'message' => '', + ); + } + + /** + * Handle processing changes to global Stripe Settings. + * + * @return void + */ + public static function process_form() { + $settings = FrmSquareLiteAppHelper::get_settings(); + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $settings->update( $_POST ); + $settings->store(); + } +} diff --git a/square/helpers/FrmSquareLiteAppHelper.php b/square/helpers/FrmSquareLiteAppHelper.php new file mode 100644 index 0000000000..8cf312c638 --- /dev/null +++ b/square/helpers/FrmSquareLiteAppHelper.php @@ -0,0 +1,53 @@ +settings->test_mode ? 'test' : 'live'; + } +} diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php new file mode 100644 index 0000000000..59ab439642 --- /dev/null +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -0,0 +1,9 @@ +set_default_options(); + } + + /** + * @return string + */ + public function param() { + return 'square'; + } + + /** + * @return array + */ + public function default_options() { + return array( + 'test_mode' => 1, + ); + } + + /** + * @param mixed $settings + * @return void + */ + public function set_default_options( $settings = false ) { + $default_settings = $this->default_options(); + + if ( ! $settings ) { + $settings = $this->get_options(); + } elseif ( $settings === true ) { + $settings = new stdClass(); + } + + if ( ! isset( $this->settings ) ) { + $this->settings = new stdClass(); + } + + foreach ( $default_settings as $setting => $default ) { + if ( is_object( $settings ) && isset( $settings->{$setting} ) ) { + $this->settings->{$setting} = $settings->{$setting}; + } + + if ( ! isset( $this->settings->{$setting} ) ) { + $this->settings->{$setting} = $default; + } + } + } + + public function get_options() { + $settings = get_option( 'frm_' . $this->param() . '_options' ); + + if ( is_object( $settings ) ) { + $this->set_default_options( $settings ); + } elseif ( $settings ) { + // Workaround for W3 total cache conflict. + $this->settings = unserialize( serialize( $settings ) ); + } else { + $this->set_default_options( true ); + $this->store(); + } + + return $this->settings; + } + + /** + * @param array $params + * @return void + */ + public function update( $params ) { + $settings = $this->default_options(); + + foreach ( $settings as $setting => $default ) { + if ( isset( $params[ 'frm_' . $this->param() . '_' . $setting ] ) ) { + $this->settings->{$setting} = trim( sanitize_text_field( $params[ 'frm_' . $this->param() . '_' . $setting ] ) ); + } + } + + $this->settings->test_mode = isset( $params['frm_' . $this->param() . '_test_mode'] ) ? absint( $params['frm_' . $this->param() . '_test_mode'] ) : 0; + } + + /** + * @return void + */ + public function store() { + // Save the posted value in the database. + update_option( 'frm_' . $this->param() . '_options', $this->settings ); + } +} diff --git a/square/views/settings/form.php b/square/views/settings/form.php new file mode 100644 index 0000000000..c2f6fc3510 --- /dev/null +++ b/square/views/settings/form.php @@ -0,0 +1,6 @@ + Date: Tue, 28 Jan 2025 14:51:21 -0400 Subject: [PATCH 002/162] Start loading scripts --- .../FrmSquareLiteActionsController.php | 37 ++++--------------- 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 63d57cc179..55371f9823 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -315,44 +315,22 @@ public static function load_scripts( $form_id ) { return; } - $stripe_connect_is_setup = FrmStrpLiteConnectHelper::stripe_connect_is_setup(); - if ( ! $stripe_connect_is_setup ) { - return; - } - if ( ! $form_id || ! is_int( $form_id ) ) { - _doing_it_wrong( __METHOD__, '$form_id parameter must be a non-zero integer', '6.5' ); + _doing_it_wrong( __METHOD__, '$form_id parameter must be a non-zero integer', 'x.x' ); return; } - $settings = FrmStrpLiteAppHelper::get_settings(); - $publishable = $settings->get_active_publishable_key(); - wp_register_script( - 'stripe', - 'https://js.stripe.com/v3/', + 'square', + // TODO This will need to change for live payments. + 'https://sandbox.web.squarecdn.com/v1/square.js', array(), - '3.0', + '1.0', false ); - $suffix = FrmAppHelper::js_suffix(); - $dependencies = array( 'stripe', 'formidable' ); - - if ( '.min' === $suffix && is_readable( FrmAppHelper::plugin_path() . '/js/frmstrp.min.js' ) ) { - // Use the combined file if it is available. - $script_url = FrmAppHelper::plugin_url() . '/js/frmstrp.min.js'; - } else { - if ( ! $suffix && ! is_readable( FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.js' ) ) { - // The unminified file is not included in releases so force the minified script. - $suffix = '.min'; - } - $script_url = FrmStrpLiteAppHelper::plugin_url() . 'js/frmstrp' . $suffix . '.js'; - } - - if ( class_exists( 'FrmProStrpLiteController' ) && ( ! $suffix || ! FrmProAppController::has_combo_js_file() ) ) { - $dependencies[] = 'formidablepro'; - } + $dependencies = array( 'square', 'formidable' ); + $script_url = FrmSquareLiteAppHelper::plugin_url() . 'js/frontend.js'; wp_enqueue_script( 'formidable-square', @@ -364,7 +342,6 @@ public static function load_scripts( $form_id ) { $action_settings = self::prepare_settings_for_js( $form_id ); $square_vars = array( - 'publishable_key' => $publishable, 'form_id' => $form_id, 'nonce' => wp_create_nonce( 'frm_square_ajax' ), 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ), From ca7b4620f33b89f706a2d8e231dd442fc31e4c96 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 28 Jan 2025 15:10:28 -0400 Subject: [PATCH 003/162] Adding some basic square JS --- .../frm-fields/back-end/field-credit-card.php | 1 - .../FrmSquareLiteActionsController.php | 8 + square/js/frontend.js | 146 +++++++++++++++++- 3 files changed, 153 insertions(+), 2 deletions(-) diff --git a/classes/views/frm-fields/back-end/field-credit-card.php b/classes/views/frm-fields/back-end/field-credit-card.php index 1842565803..33b5568a7d 100644 --- a/classes/views/frm-fields/back-end/field-credit-card.php +++ b/classes/views/frm-fields/back-end/field-credit-card.php @@ -2,7 +2,6 @@ if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } - if ( ! FrmStrpLiteConnectHelper::at_least_one_mode_is_setup() || ! FrmTransLiteActionsController::get_actions_for_form( $field['form_id'] ) ) { ?> diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 55371f9823..7d4cd3a4f6 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -18,6 +18,14 @@ class FrmSquareLiteActionsController extends FrmTransLiteActionsController { public static function show_card( $field, $field_name, $atts ) { $actions = self::get_actions_before_submit( $field['form_id'] ); + // TODO Fix this. + echo ' + +
+
+ '; + return; + // Use the Pro function when there are no Stripe actions. // This is required for other gateways like Authorize.Net. if ( ! $actions && is_callable( 'FrmProCreditCardsController::show_in_form' ) ) { diff --git a/square/js/frontend.js b/square/js/frontend.js index 6f38e3a345..2e4eb43e92 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -1,3 +1,147 @@ ( function() { - alert( 'Square scripts loaded on front end' ); + const appId = 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; + const locationId = 'L7Q1NBZ6SSJ79'; + + async function initializeCard(payments) { + const card = await payments.card(); + await card.attach('#card-container'); + + return card; + } + + async function createPayment(token, verificationToken) { + const body = JSON.stringify({ + locationId, + sourceId: token, + verificationToken, + idempotencyKey: window.crypto.randomUUID(), + }); + + const paymentResponse = await fetch('/payment', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body, + }); + + if ( paymentResponse.ok ) { + return paymentResponse.json(); + } + + const errorBody = await paymentResponse.text(); + throw new Error( errorBody ); + } + + async function tokenize(paymentMethod) { + const tokenResult = await paymentMethod.tokenize(); + + if (tokenResult.status === 'OK') { + return tokenResult.token; + } + + let errorMessage = `Tokenization failed with status: ${tokenResult.status}`; + if (tokenResult.errors) { + errorMessage += ` and errors: ${JSON.stringify( + tokenResult.errors, + )}`; + } + + throw new Error(errorMessage); + } + + // Required in SCA Mandated Regions: Learn more at https://developer.squareup.com/docs/sca-overview + async function verifyBuyer(payments, token) { + const verificationDetails = { + amount: '1.00', + billingContact: { + givenName: 'John', + familyName: 'Doe', + email: 'john.doe@square.example', + phone: '3214563987', + addressLines: [ '123 Main Street', 'Apartment 1' ], + city: 'London', + state: 'LND', + countryCode: 'GB', + }, + currencyCode: 'GBP', + intent: 'CHARGE', + }; + + const verificationResults = await payments.verifyBuyer( + token, + verificationDetails, + ); + return verificationResults.token; + } + + // status is either SUCCESS or FAILURE; + function displayPaymentResults( status ) { + const statusContainer = document.getElementById( + 'payment-status-container', + ); + if ( status === 'SUCCESS' ) { + statusContainer.classList.remove( 'is-failure' ); + statusContainer.classList.add( 'is-success' ); + } else { + statusContainer.classList.remove( 'is-success' ); + statusContainer.classList.add( 'is-failure' ); + } + + statusContainer.style.visibility = 'visible'; + } + + document.addEventListener('DOMContentLoaded', async function () { + if ( ! window.Square ) { + throw new Error('Square.js failed to load properly'); + } + + let payments; + try { + // This requires HTTPS to work. + payments = window.Square.payments( appId, locationId ); + } catch { + const statusContainer = document.getElementById( + 'payment-status-container', + ); + statusContainer.className = 'missing-credentials'; + statusContainer.style.visibility = 'visible'; + return; + } + + let card; + try { + card = await initializeCard(payments); + } catch ( e ) { + console.error( 'Initializing Card failed', e ); + return; + } + + async function handlePaymentMethodSubmission( event, card ) { + event.preventDefault(); + + try { + // disable the submit button as we await tokenization and make a payment request. + cardButton.disabled = true; + const token = await tokenize(card); + const verificationToken = await verifyBuyer(payments, token); + const paymentResults = await createPayment( + token, + verificationToken, + ); + displayPaymentResults( 'SUCCESS' ); + + console.debug( 'Payment Success', paymentResults ); + } catch ( e ) { + cardButton.disabled = false; + displayPaymentResults( 'FAILURE' ); + console.error( e.message ); + } + } + + const cardButton = document.getElementById( 'card-button' ); + cardButton.addEventListener('click', async function ( event ) { + await handlePaymentMethodSubmission( event, card ); + }); + }); }() ); From 69f1b9b257a762e21c00af06c91f6d03708f16b4 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 28 Jan 2025 15:55:39 -0400 Subject: [PATCH 004/162] Send the token/verification tokens as form inputs and submit form --- .../FrmSquareLiteActionsController.php | 4 +- square/js/frontend.js | 58 +++++++++---------- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 7d4cd3a4f6..3db91a13bf 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -22,7 +22,7 @@ public static function show_card( $field, $field_name, $atts ) { echo '
-
+
Payment Status
'; return; @@ -344,7 +344,7 @@ public static function load_scripts( $form_id ) { 'formidable-square', $script_url, $dependencies, - FrmAppHelper::plugin_version(), + uniqid(), false ); diff --git a/square/js/frontend.js b/square/js/frontend.js index 2e4eb43e92..dfe5c349fd 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -2,56 +2,50 @@ const appId = 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; const locationId = 'L7Q1NBZ6SSJ79'; - async function initializeCard(payments) { + async function initializeCard( payments ) { const card = await payments.card(); - await card.attach('#card-container'); - + await card.attach( '#card-container' ); return card; } - async function createPayment(token, verificationToken) { - const body = JSON.stringify({ - locationId, - sourceId: token, - verificationToken, - idempotencyKey: window.crypto.randomUUID(), - }); + async function createPayment( token, verificationToken ) { + const tokenInput = document.createElement( 'input' ); + tokenInput.type = 'hidden'; + tokenInput.value = token; + tokenInput.setAttribute( 'name', 'square-token' ); - const paymentResponse = await fetch('/payment', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body, - }); + const verificationInput = document.createElement( 'input' ); + verificationInput.type = 'hidden'; + verificationInput.value = verificationToken; + verificationInput.setAttribute( 'name', 'square-verification-token' ); - if ( paymentResponse.ok ) { - return paymentResponse.json(); - } + const form = document.getElementById( 'card-button' ).closest( 'form' ); + form.appendChild( tokenInput ); + form.appendChild( verificationInput ); - const errorBody = await paymentResponse.text(); - throw new Error( errorBody ); + if ( typeof frmFrontForm.submitFormManual === 'function' ) { + const e = new Event( 'submit' ); + frmFrontForm.submitFormManual( e, form ); + } } async function tokenize(paymentMethod) { const tokenResult = await paymentMethod.tokenize(); - if (tokenResult.status === 'OK') { + if ( tokenResult.status === 'OK' ) { return tokenResult.token; } let errorMessage = `Tokenization failed with status: ${tokenResult.status}`; - if (tokenResult.errors) { - errorMessage += ` and errors: ${JSON.stringify( - tokenResult.errors, - )}`; + if ( tokenResult.errors ) { + errorMessage += ` and errors: ${JSON.stringify( tokenResult.errors )}`; } - throw new Error(errorMessage); + throw new Error( errorMessage ); } // Required in SCA Mandated Regions: Learn more at https://developer.squareup.com/docs/sca-overview - async function verifyBuyer(payments, token) { + async function verifyBuyer( payments, token ) { const verificationDetails = { amount: '1.00', billingContact: { @@ -70,7 +64,7 @@ const verificationResults = await payments.verifyBuyer( token, - verificationDetails, + verificationDetails ); return verificationResults.token; } @@ -102,7 +96,7 @@ payments = window.Square.payments( appId, locationId ); } catch { const statusContainer = document.getElementById( - 'payment-status-container', + 'payment-status-container', ); statusContainer.className = 'missing-credentials'; statusContainer.style.visibility = 'visible'; @@ -140,7 +134,7 @@ } const cardButton = document.getElementById( 'card-button' ); - cardButton.addEventListener('click', async function ( event ) { + cardButton.addEventListener( 'click', async function ( event ) { await handlePaymentMethodSubmission( event, card ); }); }); From 72bd0e816167da2dd07cf664260b0e5c0e6b2d85 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 28 Jan 2025 16:02:26 -0400 Subject: [PATCH 005/162] Pass the event, remove test code --- square/js/frontend.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index dfe5c349fd..1d44fe19a4 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -8,7 +8,7 @@ return card; } - async function createPayment( token, verificationToken ) { + async function createPayment( event, token, verificationToken ) { const tokenInput = document.createElement( 'input' ); tokenInput.type = 'hidden'; tokenInput.value = token; @@ -24,8 +24,7 @@ form.appendChild( verificationInput ); if ( typeof frmFrontForm.submitFormManual === 'function' ) { - const e = new Event( 'submit' ); - frmFrontForm.submitFormManual( e, form ); + frmFrontForm.submitFormManual( event, form ); } } @@ -119,17 +118,10 @@ cardButton.disabled = true; const token = await tokenize(card); const verificationToken = await verifyBuyer(payments, token); - const paymentResults = await createPayment( - token, - verificationToken, - ); - displayPaymentResults( 'SUCCESS' ); - - console.debug( 'Payment Success', paymentResults ); + await createPayment( event, token, verificationToken ); } catch ( e ) { cardButton.disabled = false; displayPaymentResults( 'FAILURE' ); - console.error( e.message ); } } From 1df1ab4d9550a7a985a325ec0e087474be67b7d1 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 28 Jan 2025 16:07:16 -0400 Subject: [PATCH 006/162] Clean up --- square/js/frontend.js | 44 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index 1d44fe19a4..6d02ea22c3 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -10,12 +10,12 @@ async function createPayment( event, token, verificationToken ) { const tokenInput = document.createElement( 'input' ); - tokenInput.type = 'hidden'; + tokenInput.type = 'hidden'; tokenInput.value = token; tokenInput.setAttribute( 'name', 'square-token' ); const verificationInput = document.createElement( 'input' ); - verificationInput.type = 'hidden'; + verificationInput.type = 'hidden'; verificationInput.value = verificationToken; verificationInput.setAttribute( 'name', 'square-verification-token' ); @@ -28,7 +28,7 @@ } } - async function tokenize(paymentMethod) { + async function tokenize( paymentMethod ) { const tokenResult = await paymentMethod.tokenize(); if ( tokenResult.status === 'OK' ) { @@ -47,6 +47,7 @@ async function verifyBuyer( payments, token ) { const verificationDetails = { amount: '1.00', + // TODO Use form data instead of hard coded test values. billingContact: { givenName: 'John', familyName: 'Doe', @@ -58,53 +59,38 @@ countryCode: 'GB', }, currencyCode: 'GBP', - intent: 'CHARGE', + intent: 'CHARGE' }; - const verificationResults = await payments.verifyBuyer( - token, - verificationDetails - ); + const verificationResults = await payments.verifyBuyer( token, verificationDetails ); return verificationResults.token; } - // status is either SUCCESS or FAILURE; - function displayPaymentResults( status ) { - const statusContainer = document.getElementById( - 'payment-status-container', - ); - if ( status === 'SUCCESS' ) { - statusContainer.classList.remove( 'is-failure' ); - statusContainer.classList.add( 'is-success' ); - } else { - statusContainer.classList.remove( 'is-success' ); - statusContainer.classList.add( 'is-failure' ); - } - + function displayPaymentFailure() { + const statusContainer = document.getElementById( 'payment-status-container', ); + statusContainer.classList.add( 'is-failure' ); statusContainer.style.visibility = 'visible'; } - document.addEventListener('DOMContentLoaded', async function () { + document.addEventListener( 'DOMContentLoaded', async function () { if ( ! window.Square ) { throw new Error('Square.js failed to load properly'); } let payments; try { - // This requires HTTPS to work. + // Square requires HTTPS to work. payments = window.Square.payments( appId, locationId ); } catch { - const statusContainer = document.getElementById( - 'payment-status-container', - ); - statusContainer.className = 'missing-credentials'; + const statusContainer = document.getElementById( 'payment-status-container' ); + statusContainer.className = 'missing-credentials'; statusContainer.style.visibility = 'visible'; return; } let card; try { - card = await initializeCard(payments); + card = await initializeCard( payments ); } catch ( e ) { console.error( 'Initializing Card failed', e ); return; @@ -121,7 +107,7 @@ await createPayment( event, token, verificationToken ); } catch ( e ) { cardButton.disabled = false; - displayPaymentResults( 'FAILURE' ); + displayPaymentFailure(); } } From 0be809c6f6388cd7771142fe6303f000740a08d2 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 28 Jan 2025 16:11:25 -0400 Subject: [PATCH 007/162] Update comments --- square/js/frontend.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index 6d02ea22c3..fd5282bf00 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -1,4 +1,5 @@ ( function() { + // TODO This needs to support a global var so we can switch between sandbox and production. const appId = 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; const locationId = 'L7Q1NBZ6SSJ79'; @@ -46,6 +47,7 @@ // Required in SCA Mandated Regions: Learn more at https://developer.squareup.com/docs/sca-overview async function verifyBuyer( payments, token ) { const verificationDetails = { + // TODO How do we best handle amount in this case? Usually this isn't set with JS. amount: '1.00', // TODO Use form data instead of hard coded test values. billingContact: { @@ -74,7 +76,7 @@ document.addEventListener( 'DOMContentLoaded', async function () { if ( ! window.Square ) { - throw new Error('Square.js failed to load properly'); + throw new Error( 'Square.js failed to load properly' ); } let payments; From 34f183af0d5135d59431ced92f0c6b2ca4ed981d Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 27 Feb 2025 14:48:37 -0400 Subject: [PATCH 008/162] Add gateways filter and radio button options for selecting gateway --- stripe/helpers/FrmTransLiteAppHelper.php | 5 ++++ stripe/models/FrmTransLiteAction.php | 1 + .../action-settings/payments-options.php | 27 +++++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/stripe/helpers/FrmTransLiteAppHelper.php b/stripe/helpers/FrmTransLiteAppHelper.php index 7254e90927..769634dca9 100755 --- a/stripe/helpers/FrmTransLiteAppHelper.php +++ b/stripe/helpers/FrmTransLiteAppHelper.php @@ -510,4 +510,9 @@ public static function count_completed_payments( $payments ) { return $count; } + + public static function get_gateways() { + $gateways = apply_filters( 'frm_payment_gateways', array() ); + return $gateways; + } } diff --git a/stripe/models/FrmTransLiteAction.php b/stripe/models/FrmTransLiteAction.php index 248350565f..7de9a4163d 100755 --- a/stripe/models/FrmTransLiteAction.php +++ b/stripe/models/FrmTransLiteAction.php @@ -36,6 +36,7 @@ public function form( $instance, $args = array() ) { $field_dropdown_atts = compact( 'form_fields', 'form_action' ); $currencies = FrmCurrencyHelper::get_currencies(); $repeat_times = FrmTransLiteAppHelper::get_repeat_times(); + $gateways = FrmTransLiteAppHelper::get_gateways(); if ( ! isset( $form_action->post_content['payment_limit'] ) ) { $form_action->post_content['payment_limit'] = ''; diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index d7a29c1bcd..c5fc43824d 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -10,8 +10,6 @@ } ?> - -

+

+ $gateway ) { + $gateway_classes = $gateway['recurring'] ? '' : 'frm_gateway_no_recur'; + $gateway_classes .= ( $form_action->post_content['type'] === 'recurring' && ! $gateway['recurring'] ) ? ' frm_hidden' : ''; + $gateway_id = $this->get_field_id( 'gateways' ) . '_' . $gateway_name; + + $radio_atts = array( + 'type' => 'radio', + 'value' => $gateway_name, + 'name' => $this->get_field_name( 'gateway' ), + 'id' => $gateway_id, + ); + ?> + + +

+ Date: Thu, 27 Feb 2025 15:57:08 -0400 Subject: [PATCH 009/162] Conditionally show/hide the capture setting when Square is toggled --- stripe/js/frmtrans_admin.js | 25 +++++++++++++++++++ stripe/models/FrmTransLiteAction.php | 3 ++- .../capture-payments-upsell.php | 14 ++++++++++- .../action-settings/payments-options.php | 2 +- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/stripe/js/frmtrans_admin.js b/stripe/js/frmtrans_admin.js index 4ca36eb821..0c2a0469d3 100755 --- a/stripe/js/frmtrans_admin.js +++ b/stripe/js/frmtrans_admin.js @@ -24,12 +24,37 @@ } } + function toggleGateway() { + if ( ! this.checked ) { + return; + } + + const gateway = this.value; + const checked = this.checked; + + toggleOpts( this, checked, '.show_' + gateway ); + + const toggleOff = 'stripe' === gateway ? 'square' : 'stripe'; + const settings = jQuery( this ).closest( '.frm_form_action_settings' ); + const showClass = 'show_' + settings.find( '.frm_gateway_opt input:checked' ).attr( 'value' ); + const gatewaySettings = settings.get( 0 ).querySelectorAll( '.show_' + toggleOff ); + + gatewaySettings.forEach( + setting => { + if ( ! setting.classList.contains( showClass ) ) { + setting.style.display = 'none'; + } + } + ); + } + function frmTransLiteAdminJS() { return { init: function() { var actions = document.getElementById( 'frm_notification_settings' ); if ( actions !== null ) { jQuery( actions ).on( 'change', '.frm_trans_type', toggleSub ); + jQuery( '.frm_form_settings' ).on( 'change', '.frm_gateway_opt input', toggleGateway ); } document.querySelectorAll( '.frm_trans_ajax_link' ).forEach( diff --git a/stripe/models/FrmTransLiteAction.php b/stripe/models/FrmTransLiteAction.php index 7de9a4163d..50d7eb6ef6 100755 --- a/stripe/models/FrmTransLiteAction.php +++ b/stripe/models/FrmTransLiteAction.php @@ -52,9 +52,10 @@ public function form( $instance, $args = array() ) { * * @since 6.5 * + * @param string $selected_gateway The selected gateway for the given payment action. * @return void */ - public function echo_capture_payment_upsell() { + public function echo_capture_payment_upsell( $selected_gateway = 'stripe' ) { // Add an upsell placeholder for the capture payment setting. $upgrading = FrmAddonsController::install_link( 'stripe' ); $upgrade_params = array(); diff --git a/stripe/views/action-settings/capture-payments-upsell.php b/stripe/views/action-settings/capture-payments-upsell.php index 4fef8fd8d3..a3e8cb5fd3 100755 --- a/stripe/views/action-settings/capture-payments-upsell.php +++ b/stripe/views/action-settings/capture-payments-upsell.php @@ -2,8 +2,20 @@ if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } + +$wrapper_atts = array_merge( + array( + 'class' => 'show_stripe frm_gateway_no_recur frm6 frm_show_upgrade frm_noallow', + 'data-upgrade' => __( 'Additional Stripe settings', 'formidable' ), + ), + $upgrade_params +); + +if ( isset( $selected_gateway ) && 'stripe' !== $selected_gateway ) { + $wrapper_atts['style'] = 'display: none;'; +} ?> -

> +

> diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index c5fc43824d..e7e2df7a4a 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -38,7 +38,7 @@

- echo_capture_payment_upsell(); ?> + echo_capture_payment_upsell( $form_action->post_content['gateway'] ); ?>

Payment Status
'; diff --git a/square/js/frontend.js b/square/js/frontend.js index 73b80f307c..97c74b1437 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -232,21 +232,5 @@ displayPaymentFailure(); } } - - const cardButton = document.getElementById('card-button'); - cardButton.addEventListener('click', async function(event) { - // Only proceed if the card element is complete - if (squareCardElementIsComplete) { - await handlePaymentMethodSubmission(event, card); - } else { - // Optionally show an error message - const statusContainer = document.getElementById('payment-status-container'); - if (statusContainer) { - statusContainer.textContent = 'Please complete all card details before submitting.'; - statusContainer.classList.add('is-failure'); - statusContainer.style.visibility = 'visible'; - } - } - }); }); }() ); From 010d58fab87fda930367bb4f71dba681927a4b26 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 17 Mar 2025 16:28:13 -0300 Subject: [PATCH 015/162] Clean up more --- square/js/frontend.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index 97c74b1437..93dbdec946 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -52,11 +52,11 @@ return; } - thisForm.classList.add('frm_loading_form'); - frmFrontForm.removeSubmitLoading(jQuery(thisForm), 'enable', 0); + thisForm.classList.add( 'frm_loading_form' ); + frmFrontForm.removeSubmitLoading( jQuery( thisForm ), 'enable', 0 ); // Trigger custom event for other scripts to hook into - const event = new CustomEvent('frmSquareLiteEnableSubmit', { + const event = new CustomEvent( 'frmSquareLiteEnableSubmit', { detail: { form: thisForm } }); document.dispatchEvent(event); @@ -68,14 +68,14 @@ * @param {Element} form * @return {void} */ - function disableSubmit(form) { - jQuery(form).find('input[type="submit"],input[type="button"],button[type="submit"]').not('.frm_prev_page').attr('disabled', 'disabled'); + function disableSubmit( form ) { + jQuery( form ).find( 'input[type="submit"],input[type="button"],button[type="submit"]' ).not( '.frm_prev_page' ).attr( 'disabled', 'disabled' ); // Trigger custom event for other scripts to hook into - const event = new CustomEvent('frmSquareLiteDisableSubmit', { + const event = new CustomEvent( 'frmSquareLiteDisableSubmit', { detail: { form: form } }); - document.dispatchEvent(event); + document.dispatchEvent( event ); } async function createPayment( event, token, verificationToken ) { @@ -91,11 +91,11 @@ // Use the thisForm variable that we set earlier if ( thisForm ) { - thisForm.appendChild(tokenInput); - thisForm.appendChild(verificationInput); + thisForm.appendChild( tokenInput ); + thisForm.appendChild( verificationInput ); if ( typeof frmFrontForm.submitFormManual === 'function' ) { - frmFrontForm.submitFormManual(event, thisForm); + frmFrontForm.submitFormManual( event, thisForm ); } else { // Fallback if submitFormManual is not available thisForm.submit(); @@ -214,19 +214,19 @@ disableSubmit( thisForm ); } - const token = await tokenize(card); - const verificationToken = await verifyBuyer(payments, token); - await createPayment(event, token, verificationToken); + const token = await tokenize( card ); + const verificationToken = await verifyBuyer( payments, token ); + await createPayment( event, token, verificationToken ); // Decrement running counter after successful payment running--; - if (running === 0 && thisForm) { + if ( running === 0 && thisForm ) { enableSubmit(); } - } catch (e) { + } catch ( e ) { // Decrement running counter and re-enable submit if appropriate running--; - if (running === 0 && thisForm && squareCardElementIsComplete) { + if ( running === 0 && thisForm && squareCardElementIsComplete ) { enableSubmit(); } displayPaymentFailure(); From 93fd9a6933bf2c32b84ff0e5bcee01f5f90d13be Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 18 Mar 2025 09:38:44 -0300 Subject: [PATCH 016/162] Clean up --- .../FrmSquareLiteActionsController.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index d6908ef7d4..ba63ab52f5 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -18,16 +18,17 @@ class FrmSquareLiteActionsController extends FrmTransLiteActionsController { public static function show_card( $field, $field_name, $atts ) { $actions = self::get_actions_before_submit( $field['form_id'] ); - // TODO Fix this. - echo ' -
-
Payment Status
- '; - return; + if ( $actions ) { + echo ' +
+
Payment Status
+ '; + return; + } // Use the Pro function when there are no Stripe actions. // This is required for other gateways like Authorize.Net. - if ( ! $actions && is_callable( 'FrmProCreditCardsController::show_in_form' ) ) { + if ( is_callable( 'FrmProCreditCardsController::show_in_form' ) ) { FrmProCreditCardsController::show_in_form( $field, $field_name, $atts ); } From 679d421550be370823339ce7f603b61d07db0a53 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 18 Mar 2025 09:52:21 -0300 Subject: [PATCH 017/162] Add some comments --- square/controllers/FrmSquareLiteActionsController.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index ba63ab52f5..7348f2d573 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -19,6 +19,8 @@ public static function show_card( $field, $field_name, $atts ) { $actions = self::get_actions_before_submit( $field['form_id'] ); if ( $actions ) { + // TODO This likely overwrites Stripe. + // We'll need to check $actions for a credit card field match. echo '
Payment Status
@@ -80,7 +82,7 @@ public static function trigger_gateway( $action, $entry, $form ) { } if ( ! self::square_is_configured() ) { - $response['error'] = __( 'There was a problem communicating with Stripe. Please try again.', 'formidable' ); + $response['error'] = __( 'There was a problem communicating with Square. Please try again.', 'formidable' ); return $response; } @@ -127,7 +129,7 @@ private static function square_is_configured() { */ private static function set_customer_with_token( $atts ) { if ( isset( self::$customer ) ) { - // It's an object if this isn't the first Stripe action running. + // It's an object if this isn't the first Square action running. return self::$customer; } From 80774532fcb653b5b85acc321c464f7b4592ea66 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 21 Mar 2025 10:08:10 -0300 Subject: [PATCH 018/162] Stop using the example square IDs. Use formidable card elements like Stripe instead --- square/controllers/FrmSquareLiteActionsController.php | 8 +++++--- square/js/frontend.js | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 7348f2d573..6f2a3b2eee 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -21,6 +21,11 @@ public static function show_card( $field, $field_name, $atts ) { if ( $actions ) { // TODO This likely overwrites Stripe. // We'll need to check $actions for a credit card field match. + + $html_id = $atts['html_id']; + include FrmStrpLiteAppHelper::plugin_path() . '/views/payments/card-field.php'; + return; + echo '
Payment Status
@@ -33,9 +38,6 @@ public static function show_card( $field, $field_name, $atts ) { if ( is_callable( 'FrmProCreditCardsController::show_in_form' ) ) { FrmProCreditCardsController::show_in_form( $field, $field_name, $atts ); } - - $html_id = $atts['html_id']; - include FrmStrpLiteAppHelper::plugin_path() . '/views/payments/card-field.php'; } /** diff --git a/square/js/frontend.js b/square/js/frontend.js index 93dbdec946..2169167766 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -20,7 +20,7 @@ async function initializeCard( payments ) { const card = await payments.card(); - await card.attach( '#card-container' ); + await card.attach( '.frm-card-element' ); // Add event listener to track when the card form is valid card.addEventListener( 'focusClassRemoved', ( e ) => { @@ -143,7 +143,7 @@ } function displayPaymentFailure() { - const statusContainer = document.getElementById( 'payment-status-container', ); + const statusContainer = document.querySelector( '.frm-card-errors', ); statusContainer.classList.add( 'is-failure' ); statusContainer.style.visibility = 'visible'; } @@ -154,7 +154,7 @@ } // Find the form containing the Square payment element - const cardContainer = document.getElementById('card-container'); + const cardContainer = document.querySelector( '.frm-card-element' ); if ( cardContainer ) { thisForm = cardContainer.closest('form'); if ( thisForm ) { @@ -168,7 +168,7 @@ if ( ! squareCardElementIsComplete ) { // Show error message - const statusContainer = document.getElementById('payment-status-container'); + const statusContainer = document.querySelector( '.frm-card-errors' ); if ( statusContainer ) { statusContainer.textContent = 'Please complete all card details before submitting.'; statusContainer.classList.add('is-failure'); @@ -188,7 +188,7 @@ // Square requires HTTPS to work. payments = window.Square.payments( appId, locationId ); } catch { - const statusContainer = document.getElementById( 'payment-status-container' ); + const statusContainer = document.querySelector( '.frm-card-errors' ); statusContainer.className = 'missing-credentials'; statusContainer.style.visibility = 'visible'; return; From 579025e34c2e9a12acab265bb4b0d2c9e7d95fc5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 21 Mar 2025 10:08:45 -0300 Subject: [PATCH 019/162] Remove old code --- square/controllers/FrmSquareLiteActionsController.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 6f2a3b2eee..04ebecff03 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -25,12 +25,6 @@ public static function show_card( $field, $field_name, $atts ) { $html_id = $atts['html_id']; include FrmStrpLiteAppHelper::plugin_path() . '/views/payments/card-field.php'; return; - - echo ' -
-
Payment Status
- '; - return; } // Use the Pro function when there are no Stripe actions. From b4593534f32258045a03c48e898f4fd126fee719 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 21 Mar 2025 14:53:11 -0300 Subject: [PATCH 020/162] Start working on oauth --- square/views/settings/form.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/square/views/settings/form.php b/square/views/settings/form.php index c2f6fc3510..0ce14958ff 100644 --- a/square/views/settings/form.php +++ b/square/views/settings/form.php @@ -3,4 +3,20 @@ die( 'You are not allowed to call this page directly.' ); } -echo 'TODO'; +?> + + From a68307cead0ac819bad34adbdb77a80c2e68c451 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 21 Mar 2025 14:53:24 -0300 Subject: [PATCH 021/162] Start working on oauth --- square/views/settings/form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/views/settings/form.php b/square/views/settings/form.php index 0ce14958ff..bb66933186 100644 --- a/square/views/settings/form.php +++ b/square/views/settings/form.php @@ -15,7 +15,7 @@ // Sandbox uses connect.squareupsandbox.com const baseUrl = 'https://connect.squareupsandbox.com'; // const baseUrl = 'https://connect.squareup.com'; - const url = baseUrl + '/oauth2/authorize?client_id=' + appId + '&scope=CUSTOMERS_WRITE+CUSTOMERS_READ&session=false&state=' + state; + const url = baseUrl + '/oauth2/authorize?client_id=' + appId + '&scope=CUSTOMERS_WRITE+CUSTOMERS_READ&session=false&state=' + state; alert( url ); From 1a9bb7d58d3efabc0079f0bf71e9e3d71316cd13 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 3 Apr 2025 11:47:13 -0300 Subject: [PATCH 022/162] Set up the oauth/api flow --- .../FrmSquareLiteAppController.php | 17 ++ .../FrmSquareLiteHooksController.php | 2 +- square/helpers/FrmSquareLiteConnectHelper.php | 273 ++++++++++++++++++ square/js/settings.js | 14 +- square/views/settings/form.php | 18 +- 5 files changed, 305 insertions(+), 19 deletions(-) diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index d56fb4ee22..9826e564df 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -27,4 +27,21 @@ public static function add_gateway( $gateways ) { ); return $gateways; } + + /** + * Handle the request to initialize with Square Api + * + * @return void + */ + public static function handle_oauth() { + FrmAppHelper::permission_check( 'frm_change_settings' ); + if ( ! check_admin_referer( 'frm_ajax', 'nonce' ) ) { + wp_send_json_error(); + } + + $response_data = array( + 'redirect_url' => FrmSquareLiteConnectHelper::get_oauth_redirect_url(), + ); + wp_send_json_success( $response_data ); + } } diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php index 7bb441b85f..f192cda330 100644 --- a/square/controllers/FrmSquareLiteHooksController.php +++ b/square/controllers/FrmSquareLiteHooksController.php @@ -38,6 +38,6 @@ public static function load_admin_hooks() { * @return void */ private static function load_ajax_hooks() { - + add_action( 'wp_ajax_frm_square_oauth', 'FrmSquareLiteAppController::handle_oauth' ); } } diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 59ab439642..ded387dc28 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -5,5 +5,278 @@ class FrmSquareLiteConnectHelper { + /** + * @return void + */ + public static function render_settings_container() { + self::register_settings_scripts(); + ?> + + + + self::generate_client_password( $mode ), + 'user_id' => get_current_user_id(), + 'frm_square_api_mode' => $mode, + ); + + // Clear the transient so it doesn't fail. + delete_option( 'frm_stripe_lite_last_verify_attempt' ); + $data = self::post_to_connect_server( 'oauth_request', $additional_body ); + + if ( is_string( $data ) ) { + return false; + } + + if ( ! empty( $data->password ) ) { + update_option( self::get_server_side_token_option_name( $mode ), $data->password, 'no' ); + } + + if ( ! is_object( $data ) || empty( $data->redirect_url ) ) { + return false; + } + + return $data->redirect_url; + } + + /** + * @param string $action + * @param array $additional_body + * @return object|string + */ + private static function post_to_connect_server( $action, $additional_body = array() ) { + $body = array( + 'frm_square_api_action' => $action, + 'frm_square_api_mode' => FrmSquareLiteAppHelper::active_mode(), + ); + $body = array_merge( $body, $additional_body ); + $url = self::get_url_to_connect_server(); + $headers = self::build_headers_for_post(); + + if ( ! $headers ) { + return 'Unable to build headers for post. Is your pro license configured properly?'; + } + + // (Seconds) default timeout is 5. we want a bit more time to work with. + $timeout = 45; + + self::try_to_extend_server_timeout( $timeout ); + + $args = compact( 'body', 'headers', 'timeout' ); + $response = wp_remote_post( $url, $args ); + + if ( ! self::validate_response( $response ) ) { + return 'Response from server is invalid'; + } + + $body = self::pull_response_body( $response ); + if ( empty( $body->success ) ) { + if ( ! empty( $body->data ) && is_string( $body->data ) ) { + return $body->data; + } + return 'Response from server was not successful'; + } + + return isset( $body->data ) ? $body->data : array(); + } + + private static function pull_response_body( $response ) { + $http_response = $response['http_response']; + $response_object = $http_response->get_response_object(); + return json_decode( $response_object->body ); + } + + /** + * @param mixed $response + * @return bool + */ + private static function validate_response( $response ) { + return ! is_wp_error( $response ) && is_array( $response ) && isset( $response['http_response'] ); + } + + /** + * @return string + */ + private static function get_url_to_connect_server() { + return 'http://dev-site.local/'; + //return 'https://api.strategy11.com/'; + } + + /** + * @return array + */ + private static function build_headers_for_post() { + $password = self::maybe_get_pro_license(); + if ( false === $password ) { + $password = 'lite_' . self::get_uuid(); + } + + $site_url = home_url(); + $site_url = self::maybe_fix_wpml_url( $site_url ); + // Remove protocol from url (our url cannot include the colon). + $site_url = preg_replace( '#^https?://#', '', $site_url ); + // Remove port from url (mostly helpful in development). + $site_url = preg_replace( '/:[0-9]+/', '', $site_url ); + $site_url = self::strip_lang_from_url( $site_url ); + + // $password is either a Pro license or a uuid (See FrmUsage::uuid). + return array( + 'Authorization' => 'Basic ' . base64_encode( $site_url . ':' . $password ), + ); + } + + /** + * Get a unique ID to use for connecting Lite users. + * + * @return string + */ + private static function get_uuid() { + $usage = new FrmUsage(); + return $usage->uuid(); + } + + /** + * WPML might add a language to the url. Don't send that to the server. + */ + private static function strip_lang_from_url( $url ) { + $split_on_language = explode( '/?lang=', $url ); + if ( 2 === count( $split_on_language ) ) { + $url = $split_on_language[0]; + } + return $url; + } + + /** + * WPML alters the output of home_url. + * If it is active, use the WPML "absolute home" URL which is not modified. + * + * @param string $url + * @return string + */ + private static function maybe_fix_wpml_url( $url ) { + if ( defined( 'ICL_SITEPRESS_VERSION' ) && ! ICL_PLUGIN_INACTIVE && class_exists( 'SitePress' ) ) { + global $wpml_url_converter; + $url = $wpml_url_converter->get_abs_home(); + } + return $url; + } + + /** + * Get a Pro license when Pro is active. + * Otherwise we'll use a uuid to support Lite. + * + * @return false|string + */ + private static function maybe_get_pro_license() { + if ( FrmAppHelper::pro_is_installed() ) { + $pro_license = FrmAddonsController::get_pro_license(); + if ( $pro_license ) { + $password = $pro_license; + } + } + return ! empty( $password ) ? $password : false; + } + + /** + * Try to make sure the server time limit exceeds the request time limit. + * + * @param int $timeout seconds. + * + * @return void + */ + private static function try_to_extend_server_timeout( $timeout ) { + if ( function_exists( 'set_time_limit' ) ) { + set_time_limit( $timeout + 10 ); + } + } + + /** + * @param string $mode either 'auto', 'live', or 'test'. + * @return string + */ + private static function get_server_side_token_option_name( $mode = 'auto' ) { + return self::get_square_connect_option_name( 'server_password', $mode ); + } + + /** + * Generate a new client password for authenticating with Connect Service and save it locally as an option. + * + * @param string $mode 'live' or 'test'. + * @return string the client password. + */ + private static function generate_client_password( $mode ) { + $client_password = wp_generate_password(); + update_option( self::get_client_side_token_option_name( $mode ), $client_password, 'no' ); + return $client_password; + } + + /** + * @param string $mode either 'auto', 'live', or 'test'. + * @return string + */ + private static function get_client_side_token_option_name( $mode = 'auto' ) { + return self::get_square_connect_option_name( 'client_password', $mode ); + } + + /** + * @return string + */ + private static function get_mode_value() { + return 'live'; + } + + /** + * @param string $mode + * @return bool|string + */ + public static function get_account_id( $mode = 'auto' ) { + return get_option( self::get_account_id_option_name( $mode ) ); + } + + /** + * @param string $mode either 'auto', 'live', or 'test'. + * @return string + */ + private static function get_account_id_option_name( $mode = 'auto' ) { + return self::get_square_connect_option_name( 'account_id', $mode ); + } + + /** + * @param string $key 'account_id', 'client_password', 'server_password', 'details_submitted'. + * @param string $mode either 'auto', 'live', or 'test'. + * @return string + */ + private static function get_square_connect_option_name( $key, $mode = 'auto' ) { + return 'frm_square_connect_' . $key . self::get_active_mode_option_name_suffix( $mode ); + } + + /** + * @param string $mode either 'auto', 'live', or 'test'. + * @return string either _test or _live. + */ + private static function get_active_mode_option_name_suffix( $mode = 'auto' ) { + if ( 'auto' !== $mode ) { + return '_' . $mode; + } + return '_' . FrmSquareLiteAppHelper::active_mode(); + } } diff --git a/square/js/settings.js b/square/js/settings.js index c32d5fdf90..b801f27f3a 100644 --- a/square/js/settings.js +++ b/square/js/settings.js @@ -1,3 +1,15 @@ ( function() { - alert( 'Square scripts loaded on settings page' ); + const button = document.getElementById( 'frm_connect_square_with_oauth' ); + if ( button ) { + button.addEventListener( 'click', function() { + const formData = new FormData(); + frmDom.ajax.doJsonPost( 'square_oauth', formData ).then( + function( response ) { + if ( 'undefined' !== typeof response.redirect_url ) { + window.location = response.redirect_url; + } + } + ); + } ); + } }() ); diff --git a/square/views/settings/form.php b/square/views/settings/form.php index bb66933186..f383749cf0 100644 --- a/square/views/settings/form.php +++ b/square/views/settings/form.php @@ -3,20 +3,4 @@ die( 'You are not allowed to call this page directly.' ); } -?> - - +FrmSquareLiteConnectHelper::render_settings_container(); From 42561219cf896ec01c438033fbd062b07b54b161 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 3 Apr 2025 11:53:09 -0300 Subject: [PATCH 023/162] Rename option --- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index ded387dc28..c693d645b6 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -40,7 +40,7 @@ public static function get_oauth_redirect_url() { ); // Clear the transient so it doesn't fail. - delete_option( 'frm_stripe_lite_last_verify_attempt' ); + delete_option( 'frm_square_last_verify_attempt' ); $data = self::post_to_connect_server( 'oauth_request', $additional_body ); if ( is_string( $data ) ) { From 8f36fb0aee8fef63ed7e15ca8c05c6476b488f1f Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 3 Apr 2025 13:30:28 -0300 Subject: [PATCH 024/162] Hard code live mode in a few places for now. Show connected when there is a merchant ID instead of the Connect button. Start checking for the redirect --- .../FrmSquareLiteHooksController.php | 2 + square/helpers/FrmSquareLiteConnectHelper.php | 81 ++++++++++++++++--- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php index f192cda330..91c0ef02e6 100644 --- a/square/controllers/FrmSquareLiteHooksController.php +++ b/square/controllers/FrmSquareLiteHooksController.php @@ -14,6 +14,8 @@ public static function load_hooks() { add_filter( 'frm_payment_gateways', 'FrmSquareLiteAppController::add_gateway' ); + add_action( 'init', 'FrmSquareLiteConnectHelper::check_for_redirects' ); + // This filter flags the Pro credit card field that Stripe is enabled. add_filter( 'frm_pro_show_card_callback', diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index c693d645b6..3414a99d1b 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -10,11 +10,16 @@ class FrmSquareLiteConnectHelper { */ public static function render_settings_container() { self::register_settings_scripts(); - ?> - - - - + + + + get_option( self::get_server_side_token_option_name( $mode ) ), + 'client_password' => get_option( self::get_client_side_token_option_name( $mode ) ), + 'frm_square_api_mode' => $mode, + ); + $data = self::post_to_connect_server( 'oauth_merchant_status', $body ); + + if ( is_object( $data ) && ! empty( $data->merchant_id ) ) { + update_option( self::get_merchant_id_option_name( $mode ), $data->merchant_id, 'no' ); + return true; + } + + return false; + } } From 6db04b4a4e24b7079792f2e7d956ffd8c330c1ff Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 3 Apr 2025 15:33:33 -0300 Subject: [PATCH 025/162] Set up some code for creating payments --- .../FrmSquareLiteActionsController.php | 67 +++++++++---------- square/helpers/FrmSquareLiteConnectHelper.php | 60 +++++++++++++++++ .../FrmTransLiteActionsController.php | 26 ++++++- stripe/helpers/FrmTransLiteAppHelper.php | 13 ++++ 4 files changed, 128 insertions(+), 38 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 04ebecff03..8511ff9e91 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -82,17 +82,11 @@ public static function trigger_gateway( $action, $entry, $form ) { return $response; } - $customer = self::set_customer_with_token( $atts ); - if ( ! is_object( $customer ) ) { - $response['error'] = $customer; - return $response; - } - - $one_time_payment_args = compact( 'customer', 'form', 'entry', 'action', 'amount' ); + $one_time_payment_args = compact( 'form', 'entry', 'action', 'amount' ); // attempt to charge the customer's card if ( 'recurring' === $action->post_content['type'] ) { - $charge = self::trigger_recurring_payment( compact( 'customer', 'entry', 'action', 'amount' ) ); + $charge = self::trigger_recurring_payment( compact( 'entry', 'action', 'amount' ) ); } else { $charge = self::trigger_one_time_payment( $one_time_payment_args ); $response['run_triggers'] = true; @@ -108,43 +102,42 @@ public static function trigger_gateway( $action, $entry, $form ) { } /** - * Check if Square integration is enabled. - * - * @return bool true if Square is set up. - */ - private static function square_is_configured() { - // TODO - return false; - } - - /** - * Set a customer object to $_POST['customer'] to use later. + * Trigger a one time payment. * - * @param array $atts - * @return object|string + * @param array $atts { + * @type stdClass $form + * @type stdClass $entry + * @type WP_Post $action + * @type string $amount + * } + * @return string|true string on error, true on success. */ - private static function set_customer_with_token( $atts ) { - if ( isset( self::$customer ) ) { - // It's an object if this isn't the first Square action running. - return self::$customer; + private static function trigger_one_time_payment( $atts ) { + if ( empty( $_POST['square-token'] ) || empty( $_POST['square-verification-token'] ) ) { + return __( 'Please enter a valid credit card', 'formidable' ); } - $payment_info = array( - 'user_id' => FrmTransLiteAppHelper::get_user_id_for_current_payment(), - ); + $currency = strtoupper( $atts['action']->post_content['currency'] ); + $square_token = sanitize_text_field( $_POST['square-token'] ); + $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); - if ( ! empty( $atts['action']->post_content['email'] ) ) { - $payment_info['email'] = apply_filters( 'frm_content', $atts['action']->post_content['email'], $atts['form'], $atts['entry'] ); - $payment_info['email'] = self::replace_email_shortcode( $payment_info['email'] ); - } + // TODO We'll need to send the square tokens to our API. + $result = FrmSquareLiteConnectHelper::create_payment( $atts['amount'], $currency, $square_token, $verification_token ); - self::add_customer_name( $atts, $payment_info ); + if ( false === $result ) { + return FrmSquareLiteConnectHelper::get_latest_error_from_square_api(); + } - $customer = FrmStrpLiteAppHelper::call_stripe_helper_class( 'get_customer', $payment_info ); - // Set for later use. - self::$customer = $customer; + return true; + } - return $customer; + /** + * Check if Square integration is enabled. + * + * @return bool true if Square is set up. + */ + private static function square_is_configured() { + return (bool) FrmSquareLiteConnectHelper::get_merchant_id(); } /** diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 3414a99d1b..d6eea15057 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -5,6 +5,15 @@ class FrmSquareLiteConnectHelper { + /** + * Track the latest error when calling stripe connect. + * + * @since 6.5 + * + * @var string|null + */ + public static $latest_error_from_square_api; + /** * @return void */ @@ -338,4 +347,55 @@ private static function check_server_for_oauth_merchant_id() { return false; } + + public static function create_payment( $amount, $currency, $square_token, $verification_token ) { + return self::post_with_authenticated_body( + 'create_payment', + array( + 'amount' => $amount, + 'currency' => $currency, + 'square_token' => $square_token, + 'verification_token' => $verification_token, + ) + ); + } + + /** + * @param string $action + * @param array $additional_body + * + * @return false|object + */ + private static function post_with_authenticated_body( $action, $additional_body = array() ) { + $body = array_merge( self::get_standard_authenticated_body(), $additional_body ); + $response = self::post_to_connect_server( $action, $body ); + if ( is_object( $response ) ) { + return $response; + } + if ( is_array( $response ) ) { + // reformat empty arrays as empty objects + // if the response is an array, it's because it's empty. Everything with data is already an object. + return new stdClass(); + } + if ( is_string( $response ) ) { + self::$latest_error_from_square_api = $response; + FrmTransLiteLog::log_message( 'Square API Error', $response ); + } else { + self::$latest_error_from_square_api = ''; + } + return false; + } + + private static function get_standard_authenticated_body() { + $mode = 'live';//self::get_mode_value_from_post(); + return array( + 'merchant_id' => get_option( self::get_merchant_id_option_name( $mode ) ), + 'server_password' => get_option( self::get_server_side_token_option_name( $mode ) ), + 'client_password' => get_option( self::get_client_side_token_option_name( $mode ) ), + ); + } + + public static function get_latest_error_from_square_api() { + return self::$latest_error_from_square_api; + } } diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index a96caca8e9..98ff3e16e7 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -85,13 +85,37 @@ public static function add_trigger_to_action( $options ) { */ public static function trigger_action( $action, $entry, $form ) { self::prepare_description( $action, compact( 'entry', 'form' ) ); - $response = FrmStrpLiteActionsController::trigger_gateway( $action, $entry, $form ); + + $gateway = self::get_gateway_for_action( $action ); + if ( ! $gateway ) { + return; + } + + $class_name = FrmTransLiteAppHelper::get_setting_for_gateway( $gateway, 'class' ); + if ( ! $class_name ) { + return; + } + + $class_name = 'Frm' . $class_name . 'ActionsController'; + $response = $class_name::trigger_gateway( $action, $entry, $form ); + if ( ! $response['success'] && $response['show_errors'] ) { // the payment failed self::show_failed_message( compact( 'action', 'entry', 'form', 'response' ) ); } } + /** + * @param WP_Post $action + * @return string + */ + private static function get_gateway_for_action( $action ) { + if ( isset( $action->post_content['gateway'] ) ) { + return $action->post_content['gateway']; + } + return 'stripe'; + } + /** * @since 6.10 * diff --git a/stripe/helpers/FrmTransLiteAppHelper.php b/stripe/helpers/FrmTransLiteAppHelper.php index 769634dca9..eb939b6648 100755 --- a/stripe/helpers/FrmTransLiteAppHelper.php +++ b/stripe/helpers/FrmTransLiteAppHelper.php @@ -515,4 +515,17 @@ public static function get_gateways() { $gateways = apply_filters( 'frm_payment_gateways', array() ); return $gateways; } + + /** + * @param string $gateway + * @param string $setting + */ + public static function get_setting_for_gateway( $gateway, $setting ) { + $gateways = self::get_gateways(); + $value = ''; + if ( isset( $gateways[ $gateway ] ) ) { + $value = $gateways[ $gateway ][ $setting ]; + } + return $value; + } } From ed17f17a37f02e9525d63850d9fa9ad038bacca1 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 3 Apr 2025 17:20:03 -0300 Subject: [PATCH 026/162] Show error --- square/js/frontend.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index 2169167766..6e504e67a2 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -1,7 +1,8 @@ ( function() { // TODO This needs to support a global var so we can switch between sandbox and production. const appId = 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; - const locationId = 'L7Q1NBZ6SSJ79'; +// const locationId = 'L7Q1NBZ6SSJ79'; // Sandbox + const locationId = 'L2GZQYSMGEKK0'; // Production // Track the state of the Square card element let squareCardElementIsComplete = false; @@ -142,10 +143,9 @@ return verificationResults.token; } - function displayPaymentFailure() { - const statusContainer = document.querySelector( '.frm-card-errors', ); - statusContainer.classList.add( 'is-failure' ); - statusContainer.style.visibility = 'visible'; + function displayPaymentFailure( errorMessage ) { + const statusContainer = document.querySelector( '.frm-card-errors' ); + statusContainer.textContent = errorMessage; } document.addEventListener( 'DOMContentLoaded', async function () { @@ -229,7 +229,7 @@ if ( running === 0 && thisForm && squareCardElementIsComplete ) { enableSubmit(); } - displayPaymentFailure(); + displayPaymentFailure( e.message ); } } }); From 8afc2a0beeb8610f1b99415d40235c6c6186adf5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 10 Apr 2025 15:25:34 -0300 Subject: [PATCH 027/162] Add square test mode checkbox, add cards for mode square modes (incomplete), add square icon --- css/frm_admin.css | 13 +++ images/icons.svg | 1 + .../FrmSquareLiteHooksController.php | 1 + .../FrmSquareLiteSettingsController.php | 2 +- square/helpers/FrmSquareLiteConnectHelper.php | 97 +++++++++++++++++-- 5 files changed, 103 insertions(+), 11 deletions(-) diff --git a/css/frm_admin.css b/css/frm_admin.css index 58cd78dc4d..5be33d318e 100644 --- a/css/frm_admin.css +++ b/css/frm_admin.css @@ -9927,6 +9927,14 @@ Responsive Design .frm-compact-card-item { padding: var(--gap-sm) 35px 10px 35px; } +.frm-card-bottom { + background-color: var(--grey-50); + margin-left: calc( var(--gap-sm) * -1 ); + margin-bottom: calc( var(--gap-sm) * -1 ); + margin-right: calc( var(--gap-sm) * -1 ); + padding: var(--gap-sm); + border-radius: 0 0 var(--small-radius) var(--small-radius); +} /* End card layout */ /* Pirate forms importer */ @@ -10154,3 +10162,8 @@ Responsive Design #frm_view_editor_left .accordion-section-title::after { content: ""; } + +a[href="#square_settings"] svg.frmsvg { + width: 23px !important; + height: 22px !important; +} diff --git a/images/icons.svg b/images/icons.svg index bcad4f6cac..1868ac5fac 100755 --- a/images/icons.svg +++ b/images/icons.svg @@ -838,5 +838,6 @@ + diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php index 91c0ef02e6..e6145a1484 100644 --- a/square/controllers/FrmSquareLiteHooksController.php +++ b/square/controllers/FrmSquareLiteHooksController.php @@ -30,6 +30,7 @@ function () { */ public static function load_admin_hooks() { add_filter( 'frm_add_settings_section', 'FrmSquareLiteSettingsController::add_settings_section' ); + add_action( 'frm_update_settings', 'FrmSquareLiteSettingsController::process_form' ); if ( defined( 'DOING_AJAX' ) ) { self::load_ajax_hooks(); diff --git a/square/controllers/FrmSquareLiteSettingsController.php b/square/controllers/FrmSquareLiteSettingsController.php index 1aea846f42..61781dc229 100644 --- a/square/controllers/FrmSquareLiteSettingsController.php +++ b/square/controllers/FrmSquareLiteSettingsController.php @@ -17,7 +17,7 @@ public static function add_settings_section( $sections ) { $sections['square'] = array( 'class' => __CLASS__, 'function' => 'route', - 'icon' => 'frm_icon_font frm_credit_card_icon', + 'icon' => 'frm_icon_font frm_square_icon', ); return $sections; diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index d6eea15057..5ba5fc479d 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -18,17 +18,91 @@ class FrmSquareLiteConnectHelper { * @return void */ public static function render_settings_container() { + $settings = FrmSquareLiteAppHelper::get_settings(); + self::register_settings_scripts(); - if ( self::get_merchant_id() ) { - echo 'Connected'; - } else { - ?> - - - + ?> + + + +
+
+
+
+ +
+ + +
+
+
+ + + + +
+ 'width: 10px; position: relative; top: 2px; margin-right: 5px;' ) ); + echo 'Connected'; + } else { + echo 'Not configured'; + } + ?> +
+
+
+ +
+
+ + + + + + + +
+
+
+ settings->test_mode ? 'test' : 'live'; } /** @@ -263,7 +338,9 @@ private static function get_mode_value() { * @return bool|string */ public static function get_merchant_id( $mode = 'auto' ) { - $mode = 'live'; + if ( 'auto' === $mode ) { + $mode = self::get_mode_value(); + } return get_option( self::get_merchant_id_option_name( $mode ) ); } From 5f540aa87a8fd6c3c6ef86beb5471dfc574f48df Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 10 Apr 2025 15:52:57 -0300 Subject: [PATCH 028/162] Show the test mode in a table like in Stripe, give connect button a class and add listeners to both --- square/helpers/FrmSquareLiteConnectHelper.php | 25 +++++++++++++------ square/js/settings.js | 7 +++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 5ba5fc479d..82e8a7cf63 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -23,11 +23,19 @@ public static function render_settings_container() { self::register_settings_scripts(); ?> - - + + + + + +
+ + + +
@@ -95,7 +103,7 @@ private static function render_settings_for_mode( $mode ) { - + @@ -114,7 +122,7 @@ private static function register_settings_scripts() { } public static function get_oauth_redirect_url() { - $mode = self::get_mode_value(); + $mode = FrmAppHelper::get_post_param( 'mode', 'test', 'sanitize_text_field' ); if ( self::get_merchant_id( $mode ) ) { // Do not allow for initialize if there is already a configured account id. @@ -403,7 +411,8 @@ private static function get_url_for_square_settings( $connected ) { * @return bool */ private static function check_server_for_oauth_merchant_id() { - $mode = 'live'; + $code = FrmAppHelper::simple_get( 'code' ); + $mode = 0 === strpos( $code, 'sandbox-' ) ? 'test' : 'live'; if ( self::get_merchant_id( $mode ) ) { // Do not allow for initialize if there is already a configured merchant id. diff --git a/square/js/settings.js b/square/js/settings.js index b801f27f3a..0aea4d612c 100644 --- a/square/js/settings.js +++ b/square/js/settings.js @@ -1,8 +1,9 @@ ( function() { - const button = document.getElementById( 'frm_connect_square_with_oauth' ); - if ( button ) { + const buttons = document.querySelectorAll( '.frm-connect-square-with-oauth' ); + buttons.forEach( function( button ) { button.addEventListener( 'click', function() { const formData = new FormData(); + formData.append( 'mode', button.dataset.mode ); frmDom.ajax.doJsonPost( 'square_oauth', formData ).then( function( response ) { if ( 'undefined' !== typeof response.redirect_url ) { @@ -11,5 +12,5 @@ } ); } ); - } + } ); }() ); From de15644afcbe7e488e044e52d84f5c58d6dbfe48 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 10 Apr 2025 16:14:27 -0300 Subject: [PATCH 029/162] Fix mode check --- square/helpers/FrmSquareLiteConnectHelper.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 82e8a7cf63..8ff7d4cbdb 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -411,8 +411,7 @@ private static function get_url_for_square_settings( $connected ) { * @return bool */ private static function check_server_for_oauth_merchant_id() { - $code = FrmAppHelper::simple_get( 'code' ); - $mode = 0 === strpos( $code, 'sandbox-' ) ? 'test' : 'live'; + $mode = 'test' === FrmAppHelper::simple_get( 'mode' ) ? 'test' : 'live'; if ( self::get_merchant_id( $mode ) ) { // Do not allow for initialize if there is already a configured merchant id. From 0fb0f72bc33f4d4c976d29657f7025d15a7687ce Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 10 Apr 2025 16:41:27 -0300 Subject: [PATCH 030/162] Get payment routing mostly working --- square/helpers/FrmSquareLiteConnectHelper.php | 16 +++++++++++++++- square/js/frontend.js | 4 ++-- .../FrmTransLiteActionsController.php | 2 +- stripe/helpers/FrmTransLiteAppHelper.php | 9 ++++++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 8ff7d4cbdb..a518a3e602 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -472,7 +472,7 @@ private static function post_with_authenticated_body( $action, $additional_body } private static function get_standard_authenticated_body() { - $mode = 'live';//self::get_mode_value_from_post(); + $mode = self::get_mode_value_from_post(); return array( 'merchant_id' => get_option( self::get_merchant_id_option_name( $mode ) ), 'server_password' => get_option( self::get_server_side_token_option_name( $mode ) ), @@ -480,6 +480,20 @@ private static function get_standard_authenticated_body() { ); } + /** + * Check $_POST for live or test mode value as it can be updated in real time from Stripe Settings and can be configured before the update is saved. + * + * @return string 'test' or 'live' + */ + private static function get_mode_value_from_post() { + // phpcs:ignore WordPress.Security.NonceVerification.Missing + if ( empty( $_POST ) || ! array_key_exists( 'testMode', $_POST ) ) { + return FrmSquareLiteAppHelper::active_mode(); + } + $test_mode = FrmAppHelper::get_param( 'testMode', '', 'post', 'absint' ); + return $test_mode ? 'test' : 'live'; + } + public static function get_latest_error_from_square_api() { return self::$latest_error_from_square_api; } diff --git a/square/js/frontend.js b/square/js/frontend.js index 6e504e67a2..08c27f27f1 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -1,8 +1,8 @@ ( function() { // TODO This needs to support a global var so we can switch between sandbox and production. const appId = 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; -// const locationId = 'L7Q1NBZ6SSJ79'; // Sandbox - const locationId = 'L2GZQYSMGEKK0'; // Production + const locationId = 'L7Q1NBZ6SSJ79'; // Sandbox +// const locationId = 'L2GZQYSMGEKK0'; // Production // Track the state of the Square card element let squareCardElementIsComplete = false; diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index 98ff3e16e7..9f690919e6 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -107,7 +107,7 @@ public static function trigger_action( $action, $entry, $form ) { /** * @param WP_Post $action - * @return string + * @return array|string */ private static function get_gateway_for_action( $action ) { if ( isset( $action->post_content['gateway'] ) ) { diff --git a/stripe/helpers/FrmTransLiteAppHelper.php b/stripe/helpers/FrmTransLiteAppHelper.php index 100368f78f..1116685add 100755 --- a/stripe/helpers/FrmTransLiteAppHelper.php +++ b/stripe/helpers/FrmTransLiteAppHelper.php @@ -517,12 +517,15 @@ public static function get_gateways() { } /** - * @param string $gateway - * @param string $setting + * @param array|string $gateway + * @param string $setting */ public static function get_setting_for_gateway( $gateway, $setting ) { $gateways = self::get_gateways(); - $value = ''; + $value = ''; + if ( is_array( $gateway ) ) { + $gateway = reset( $gateway ); + } if ( isset( $gateways[ $gateway ] ) ) { $value = $gateways[ $gateway ][ $setting ]; } From c25dda4dffc2e55b7ff8ba43e31a6b2afa4dc4f0 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 11 Apr 2025 13:48:29 -0300 Subject: [PATCH 031/162] Add the payment record into the DB with the charge ID and status --- .../FrmSquareLiteActionsController.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 8511ff9e91..a9ad521b09 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -128,9 +128,46 @@ private static function trigger_one_time_payment( $atts ) { return FrmSquareLiteConnectHelper::get_latest_error_from_square_api(); } + $atts['status'] = $result->status === 'COMPLETED' ? 'complete' : 'failed'; + + $atts['charge'] = new stdClass(); + $atts['charge']->id = $result->id; + $atts['charge']->amount = $atts['amount']; + + self::create_new_payment( $atts ); + return true; } + /** + * Add a payment row for the payments table. + * + * @param array $atts { + * @type object $charge + * @type object $entry + * @type WP_Post $action + * } + * @return int + */ + private static function create_new_payment( $atts ) { + $atts['charge'] = (object) $atts['charge']; + + $new_values = array( + 'amount' => FrmTransLiteAppHelper::get_formatted_amount_for_currency( $atts['charge']->amount, $atts['action'] ), + 'status' => $atts['status'], + 'paysys' => 'square', + 'item_id' => $atts['entry']->id, + 'action_id' => $atts['action']->ID, + 'receipt_id' => $atts['charge']->id, + 'sub_id' => isset( $atts['charge']->sub_id ) ? $atts['charge']->sub_id : '', + 'test' => 'test' === FrmSquareLiteAppHelper::active_mode() ? 1 : 0, + ); + + $frm_payment = new FrmTransLitePayment(); + $payment_id = $frm_payment->create( $new_values ); + return $payment_id; + } + /** * Check if Square integration is enabled. * From 9a46206025caa9983c290415689a9fda6d8c6634 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 11 Apr 2025 14:25:53 -0300 Subject: [PATCH 032/162] Define the location ID and app ID in global vars based on the active mode --- .../FrmSquareLiteActionsController.php | 35 +++++++++++++------ square/js/frontend.js | 10 +++--- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index a9ad521b09..9f8916047d 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -378,28 +378,41 @@ public static function load_scripts( $form_id ) { $action_settings = self::prepare_settings_for_js( $form_id ); $square_vars = array( - 'form_id' => $form_id, + 'formId' => $form_id, 'nonce' => wp_create_nonce( 'frm_square_ajax' ), 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ), 'settings' => $action_settings, - 'locale' => self::get_locale(), + 'appId' => self::get_app_id(), + 'locationId' => self::get_location_id(), ); - wp_localize_script( 'formidable-square', 'frm_square_vars', $square_vars ); + wp_localize_script( 'formidable-square', 'frmSquareVars', $square_vars ); } /** - * Get the language to use for Stripe elements. + * Get the app ID for the Square app. * - * @since x.x * @return string */ - private static function get_locale() { - $allowed = array( 'ar', 'da', 'de', 'en', 'es', 'fi', 'fr', 'he', 'it', 'ja', 'nl', 'no', 'pl', 'ru', 'sv', 'zh' ); - $current = get_locale(); - $parts = explode( '_', $current ); - $part = strtolower( $parts[0] ); - return in_array( $part, $allowed, true ) ? $part : 'auto'; + private static function get_app_id() { + $mode = FrmSquareLiteAppHelper::active_mode(); + if ( 'live' === $mode ) { + return 'sq0idp-eR4XI1xgNduJAXcBvjemTg'; + } + return 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; + } + + /** + * Get the location ID for the Square app. + * + * @return string + */ + private static function get_location_id() { + $mode = FrmSquareLiteAppHelper::active_mode(); + if ( 'live' === $mode ) { + return 'L2GZQYSMGEKK0'; + } + return 'L7Q1NBZ6SSJ79'; } /** diff --git a/square/js/frontend.js b/square/js/frontend.js index 08c27f27f1..5385e38d60 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -1,8 +1,10 @@ ( function() { - // TODO This needs to support a global var so we can switch between sandbox and production. - const appId = 'sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ'; - const locationId = 'L7Q1NBZ6SSJ79'; // Sandbox -// const locationId = 'L2GZQYSMGEKK0'; // Production + if ( ! window.frmSquareVars ) { + return; + } + + const appId = frmSquareVars.appId; + const locationId = frmSquareVars.locationId; // Track the state of the Square card element let squareCardElementIsComplete = false; From a25053332effca9fd8dca96e1d104e895db56df5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 11 Apr 2025 15:30:25 -0300 Subject: [PATCH 033/162] Pull the verification details into a PHP fetch request --- .../FrmSquareLiteAppController.php | 120 ++++++++++++++++++ .../FrmSquareLiteHooksController.php | 3 + square/js/frontend.js | 34 ++--- 3 files changed, 140 insertions(+), 17 deletions(-) diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index 9826e564df..66402ded9c 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -44,4 +44,124 @@ public static function handle_oauth() { ); wp_send_json_success( $response_data ); } + + /** + * Handle the verify buyer action. + * + * @return void + */ + public static function verify_buyer() { + check_ajax_referer( 'frm_square_ajax', 'nonce' ); + // TODO Fill this in based on form data. + + $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' ); + if ( ! $form_id ) { + wp_send_json_error( __( 'Invalid form ID', 'formidable' ) ); + } + + $actions = FrmSquareLiteActionsController::get_actions_before_submit( $form_id ); + if ( empty( $actions ) ) { + wp_send_json_error( __( 'No Square actions found for this form', 'formidable' ) ); + } + + $action = reset( $actions ); + $verification_details = array( + 'amount' => self::get_amount_value_for_verification( $action ), + 'billingContact' => self::get_billing_contact( $action ), + 'currencyCode' => strtoupper( $action->post_content['currency'] ), + 'intent' => 'CHARGE' + ); + + wp_send_json_success( + array( + 'verificationDetails' => $verification_details, + ) + ); + } + + /** + * @param array $actions + * @return string + */ + private static function get_amount_value_for_verification( $action ) { + $amount = $action->post_content['amount']; + if ( strpos( $amount, '[' ) === false ) { + return $amount; + } + + // Update amount based on field shortcodes. + $entry = self::generate_false_entry(); + $amount = FrmSquareLiteActionsController::prepare_amount( $amount, compact( 'form', 'entry', 'action' ) ); + + return $amount; + } + + /** + * @param WP_Post $action + * @return array + */ + private static function get_billing_contact( $action ) { + $first_name_setting = $action->post_content['billing_first_name']; + $last_name_setting = $action->post_content['billing_last_name']; + $address_setting = $action->post_content['billing_address']; + + $entry = self::generate_false_entry(); + $first_name = $first_name_setting && isset( $entry->metas[ $first_name_setting ] ) ? $entry->metas[ $first_name_setting ] : ''; + $last_name = $last_name_setting && isset( $entry->metas[ $last_name_setting ] ) ? $entry->metas[ $last_name_setting ] : ''; + $address = $address_setting && isset( $entry->metas[ $address_setting ] ) ? $entry->metas[ $address_setting ] : ''; + + if ( is_array( $first_name ) && isset( $first_name['first'] ) ) { + $first_name = $first_name['first']; + } + + if ( is_array( $last_name ) && isset( $last_name['last'] ) ) { + $last_name = $last_name['last']; + } + + // TODO + return array( + 'givenName' => $first_name, + 'familyName' => $last_name, + // TODO + 'email' => 'john.doe@square.example', + // TODO Does this mean we need a phone setting? + 'phone' => '3214563987', + // TODO + 'addressLines' => array( '123 Main Street', 'Apartment 1' ), + 'city' => 'London', + 'state' => 'LND', + 'countryCode' => 'GB', + ); + } + + /** + * Create an entry object with posted values. + * + * @since 6.5, introduced in v2.0 of the Stripe add on. + * @return stdClass + */ + private static function generate_false_entry() { + $entry = new stdClass(); + $entry->post_id = 0; + $entry->id = 0; + $entry->metas = array(); + + // phpcs:ignore WordPress.Security.NonceVerification.Missing + foreach ( $_POST as $k => $v ) { + $k = sanitize_text_field( stripslashes( $k ) ); + $v = wp_unslash( $v ); + + if ( $k === 'item_meta' ) { + foreach ( $v as $f => $value ) { + FrmAppHelper::sanitize_value( 'wp_kses_post', $value ); + $entry->metas[ absint( $f ) ] = $value; + } + } else { + FrmAppHelper::sanitize_value( 'wp_kses_post', $v ); + $entry->{$k} = $v; + } + } + + return $entry; + } } diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php index e6145a1484..ddb03c7b74 100644 --- a/square/controllers/FrmSquareLiteHooksController.php +++ b/square/controllers/FrmSquareLiteHooksController.php @@ -42,5 +42,8 @@ public static function load_admin_hooks() { */ private static function load_ajax_hooks() { add_action( 'wp_ajax_frm_square_oauth', 'FrmSquareLiteAppController::handle_oauth' ); + + add_action( 'wp_ajax_frm_verify_buyer', 'FrmSquareLiteAppController::verify_buyer' ); + add_action( 'wp_ajax_nopriv_frm_verify_buyer', 'FrmSquareLiteAppController::verify_buyer' ); } } diff --git a/square/js/frontend.js b/square/js/frontend.js index 5385e38d60..5af6e966bc 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -123,24 +123,24 @@ // Required in SCA Mandated Regions: Learn more at https://developer.squareup.com/docs/sca-overview async function verifyBuyer( payments, token ) { - const verificationDetails = { - // TODO How do we best handle amount in this case? Usually this isn't set with JS. - amount: '1.00', - // TODO Use form data instead of hard coded test values. - billingContact: { - givenName: 'John', - familyName: 'Doe', - email: 'john.doe@square.example', - phone: '3214563987', - addressLines: [ '123 Main Street', 'Apartment 1' ], - city: 'London', - state: 'LND', - countryCode: 'GB', - }, - currencyCode: 'GBP', - intent: 'CHARGE' - }; + const formData = new FormData( thisForm ); + formData.append( 'action', 'frm_verify_buyer' ); + formData.append( 'nonce', frmSquareVars.nonce ); + const response = await fetch( frmSquareVars.ajax, { + method: 'POST', + body: formData + } ); + + if ( ! response.ok ) { + throw new Error( 'Failed to verify buyer' ); + } + + const verificationData = await response.json(); + if ( ! verificationData.success ) { + throw new Error( verificationData.data ); + } + const verificationDetails = verificationData.data.verificationDetails; const verificationResults = await payments.verifyBuyer( token, verificationDetails ); return verificationResults.token; } From 6d6ccf5f68740026eef00a0c64bb9e3edc490e37 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 11 Apr 2025 15:46:59 -0300 Subject: [PATCH 034/162] Properly route the settings for addreses and emails --- .../FrmSquareLiteAppController.php | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index 66402ded9c..1a3d1f9277 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -101,11 +101,12 @@ private static function get_amount_value_for_verification( $action ) { * @return array */ private static function get_billing_contact( $action ) { + $email_setting = $action->post_content['email']; $first_name_setting = $action->post_content['billing_first_name']; $last_name_setting = $action->post_content['billing_last_name']; $address_setting = $action->post_content['billing_address']; - $entry = self::generate_false_entry(); + $entry = self::generate_false_entry(); $first_name = $first_name_setting && isset( $entry->metas[ $first_name_setting ] ) ? $entry->metas[ $first_name_setting ] : ''; $last_name = $last_name_setting && isset( $entry->metas[ $last_name_setting ] ) ? $entry->metas[ $last_name_setting ] : ''; $address = $address_setting && isset( $entry->metas[ $address_setting ] ) ? $entry->metas[ $address_setting ] : ''; @@ -118,20 +119,28 @@ private static function get_billing_contact( $action ) { $last_name = $last_name['last']; } - // TODO - return array( - 'givenName' => $first_name, - 'familyName' => $last_name, - // TODO - 'email' => 'john.doe@square.example', - // TODO Does this mean we need a phone setting? - 'phone' => '3214563987', - // TODO - 'addressLines' => array( '123 Main Street', 'Apartment 1' ), - 'city' => 'London', - 'state' => 'LND', - 'countryCode' => 'GB', + $details = array( + 'givenName' => $first_name, + 'familyName' => $last_name, ); + + if ( $email_setting ) { + $shortcode_atts = array( + 'entry' => $entry, + 'form' => $action->menu_order, + 'value' => $email_setting, + ); + $details['email'] = FrmTransLiteAppHelper::process_shortcodes( $shortcode_atts ); + } + + if ( is_array( $address ) && isset( $address['line1'] ) && isset( $address['line2'] ) && is_callable( 'FrmProAddressesController::get_country_code' ) ) { + $details['addressLines'] = array( $address['line1'], $address['line2'] ); + $details['city'] = $address['city']; + $details['state'] = $address['state']; + $details['countryCode'] = FrmProAddressesController::get_country_code( $address['country'] ); + } + + return $details; } /** From 3c464edc6fcc49c3cd021e411adda63b707c349d Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 24 Apr 2025 09:48:56 -0300 Subject: [PATCH 035/162] Capitalize the Square gateway --- stripe/helpers/FrmTransLiteListHelper.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stripe/helpers/FrmTransLiteListHelper.php b/stripe/helpers/FrmTransLiteListHelper.php index 80d25bd59e..811aca1be0 100755 --- a/stripe/helpers/FrmTransLiteListHelper.php +++ b/stripe/helpers/FrmTransLiteListHelper.php @@ -527,6 +527,8 @@ private function get_paysys_column( $item, $atts ) { return 'Stripe'; case 'paypal': return 'PayPal'; + case 'square': + return 'Square'; } return $item->paysys; } From bd8cdbeb22daf49b160389ef57113e4a2735a107 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 24 Apr 2025 10:42:31 -0300 Subject: [PATCH 036/162] Get refunds working --- square/helpers/FrmSquareLiteConnectHelper.php | 4 ++++ stripe/controllers/FrmTransLitePaymentsController.php | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index a518a3e602..66cc13ebf2 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -497,4 +497,8 @@ private static function get_mode_value_from_post() { public static function get_latest_error_from_square_api() { return self::$latest_error_from_square_api; } + + public static function refund_payment( $receipt_id ) { + return self::post_with_authenticated_body( 'refund_payment', array( 'receipt_id' => $receipt_id ) ); + } } diff --git a/stripe/controllers/FrmTransLitePaymentsController.php b/stripe/controllers/FrmTransLitePaymentsController.php index f367f7ffe0..e31d3f85fc 100755 --- a/stripe/controllers/FrmTransLitePaymentsController.php +++ b/stripe/controllers/FrmTransLitePaymentsController.php @@ -206,7 +206,15 @@ public static function refund_payment() { $frm_payment = new FrmTransLitePayment(); $payment = $frm_payment->get_one( $payment_id ); - $refunded = FrmStrpLiteAppHelper::call_stripe_helper_class( 'refund_payment', $payment->receipt_id ); + + switch ( $payment->paysys ) { + case 'stripe': + $refunded = FrmStrpLiteAppHelper::call_stripe_helper_class( 'refund_payment', $payment->receipt_id ); + break; + case 'square': + $refunded = FrmSquareLiteConnectHelper::refund_payment( $payment->receipt_id ); + break; + } if ( $refunded ) { self::change_payment_status( $payment, 'refunded' ); From e3774dbdb872984fc54b9ee5c0d547c0c34c9bdb Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 24 Apr 2025 10:52:59 -0300 Subject: [PATCH 037/162] Add todo comment --- .../FrmTransLiteSubscriptionsController.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/stripe/controllers/FrmTransLiteSubscriptionsController.php b/stripe/controllers/FrmTransLiteSubscriptionsController.php index 3e61d8571a..e9a28e5892 100755 --- a/stripe/controllers/FrmTransLiteSubscriptionsController.php +++ b/stripe/controllers/FrmTransLiteSubscriptionsController.php @@ -96,7 +96,16 @@ public static function cancel_subscription() { $frm_sub = new FrmTransLiteSubscription(); $sub = $frm_sub->get_one( $sub_id ); if ( $sub ) { - $canceled = FrmStrpLiteAppHelper::call_stripe_helper_class( 'cancel_subscription', $sub->sub_id ); + switch ( $sub->paysys ) { + case 'stripe': + $canceled = FrmStrpLiteAppHelper::call_stripe_helper_class( 'cancel_subscription', $sub->sub_id ); + break; + case 'square': + // TODO + $canceled = false; + break; + } + if ( $canceled ) { self::change_subscription_status( array( From e0bdd6ba79921a6f819c826fb9480b933bfd2398 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 24 Apr 2025 13:38:40 -0300 Subject: [PATCH 038/162] Working on subscriptions (wip) --- .../FrmSquareLiteActionsController.php | 53 +++++++++++++++++-- .../FrmSquareLiteAppController.php | 3 +- square/helpers/FrmSquareLiteConnectHelper.php | 4 ++ square/js/frontend.js | 2 +- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 9f8916047d..05cd306505 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -82,13 +82,13 @@ public static function trigger_gateway( $action, $entry, $form ) { return $response; } - $one_time_payment_args = compact( 'form', 'entry', 'action', 'amount' ); + $payment_args = compact( 'form', 'entry', 'action', 'amount' ); - // attempt to charge the customer's card + // Attempt to charge the customer's card. if ( 'recurring' === $action->post_content['type'] ) { - $charge = self::trigger_recurring_payment( compact( 'entry', 'action', 'amount' ) ); + $charge = self::trigger_recurring_payment( $payment_args ); } else { - $charge = self::trigger_one_time_payment( $one_time_payment_args ); + $charge = self::trigger_one_time_payment( $payment_args ); $response['run_triggers'] = true; } @@ -168,6 +168,51 @@ private static function create_new_payment( $atts ) { return $payment_id; } + /** + * Create a new Square subscription and a subscription and payment for the payments tables. + * + * @param array $atts Includes 'customer', 'entry', 'action', 'amount'. + * @return bool|string True on success, error message on failure + */ + private static function trigger_recurring_payment( $atts ) { + // We can put this all behind our API. + // It will require that we pass the customer info and the catalog info. + // 1. Call the API with the customer and catalog info. + // 2. Add the database rows. + + $action = $atts['action'];; + $billing_contact = FrmSquareLiteAppController::get_billing_contact( $action ); + + $info = array( + 'customer' => array( + 'givenName' => $billing_contact['givenName'], + 'familyName' => $billing_contact['familyName'], + 'emailAddress' => $billing_contact['email'], + ), + 'catalog' => array( + 'name' => $action->post_content['description'], + 'trial_days' => $action->post_content['trial_interval_count'], + 'limit' => $action->post_content['payment_limit'], + 'amount' => $atts['amount'], + 'interval' => $action->post_content['interval'], + 'interval_count' => $action->post_content['interval_count'], + ), + ); + + if ( isset( $billing_contact['addressLines'] ) ) { + $info['customer']['address'] = array( + 'addressLine1' => $billing_contact['addressLines'][0], + 'addressLine2' => $billing_contact['addressLines'][1], + 'locality' => $billing_contact['city'], + 'administrativeDistrictLevel1' => $billing_contact['state'], + 'postalCode' => $billing_contact['postalCode'], + 'country' => $billing_contact['countryCode'], + ); + } + + FrmSquareLiteConnectHelper::create_subscription( $info ); + } + /** * Check if Square integration is enabled. * diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index 1a3d1f9277..8cf0aad448 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -100,7 +100,7 @@ private static function get_amount_value_for_verification( $action ) { * @param WP_Post $action * @return array */ - private static function get_billing_contact( $action ) { + public static function get_billing_contact( $action ) { $email_setting = $action->post_content['email']; $first_name_setting = $action->post_content['billing_first_name']; $last_name_setting = $action->post_content['billing_last_name']; @@ -137,6 +137,7 @@ private static function get_billing_contact( $action ) { $details['addressLines'] = array( $address['line1'], $address['line2'] ); $details['city'] = $address['city']; $details['state'] = $address['state']; + $details['postalCode'] = $address['zip']; $details['countryCode'] = FrmProAddressesController::get_country_code( $address['country'] ); } diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 66cc13ebf2..5d4166947e 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -501,4 +501,8 @@ public static function get_latest_error_from_square_api() { public static function refund_payment( $receipt_id ) { return self::post_with_authenticated_body( 'refund_payment', array( 'receipt_id' => $receipt_id ) ); } + + public static function create_subscription( $info ) { + return self::post_with_authenticated_body( 'create_subscription', compact( 'info' ) ); + } } diff --git a/square/js/frontend.js b/square/js/frontend.js index 5af6e966bc..48c184bb77 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -219,7 +219,7 @@ const token = await tokenize( card ); const verificationToken = await verifyBuyer( payments, token ); await createPayment( event, token, verificationToken ); - + // Decrement running counter after successful payment running--; if ( running === 0 && thisForm ) { From 6ff87d347ea818c8942116dcfcc79cf7f988a57e Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 25 Apr 2025 11:23:51 -0300 Subject: [PATCH 039/162] More work on subscriptions (wip) --- .../FrmSquareLiteActionsController.php | 11 ++++----- square/helpers/FrmSquareLiteAppHelper.php | 24 +++++++++++++++++++ stripe/models/FrmTransLiteAction.php | 1 + .../action-settings/payments-options.php | 24 ++++++++++++------- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 05cd306505..725ffd892c 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -190,12 +190,11 @@ private static function trigger_recurring_payment( $atts ) { 'emailAddress' => $billing_contact['email'], ), 'catalog' => array( - 'name' => $action->post_content['description'], - 'trial_days' => $action->post_content['trial_interval_count'], - 'limit' => $action->post_content['payment_limit'], - 'amount' => $atts['amount'], - 'interval' => $action->post_content['interval'], - 'interval_count' => $action->post_content['interval_count'], + 'name' => $action->post_content['description'], + 'trial_days' => $action->post_content['trial_interval_count'], + 'limit' => $action->post_content['payment_limit'], + 'amount' => $atts['amount'], + 'cadence' => $action->post_content['repeat_cadence'], ), ); diff --git a/square/helpers/FrmSquareLiteAppHelper.php b/square/helpers/FrmSquareLiteAppHelper.php index 8cf312c638..42e1d9acf9 100644 --- a/square/helpers/FrmSquareLiteAppHelper.php +++ b/square/helpers/FrmSquareLiteAppHelper.php @@ -50,4 +50,28 @@ public static function active_mode() { $settings = self::get_settings(); return $settings->settings->test_mode ? 'test' : 'live'; } + + /** + * Square does not support the typical recurring payment repeat settings. + * Instead, we have the choice of the following "cadence" options. + * + * @return array + */ + public static function get_repeat_cadence_options() { + return array( + 'DAILY' => 'Daily', + 'WEEKLY' => 'Weekly', + 'EVERY_TWO_WEEKS' => 'Every Two Weeks', + 'THIRTY_DAYS' => 'Every Thirty Days', + 'SIXTY_DAYS' => 'Every Sixty Days', + 'NINETY_DAYS' => 'Every Ninety Days', + 'MONTHLY' => 'Monthly', + 'EVERY_TWO_MONTHS' => 'Every Two Months', + 'QUARTERLY' => 'Quarterly', + 'EVERY_FOUR_MONTHS' => 'Every Four Months', + 'EVERY_SIX_MONTHS' => 'Every Six Months', + 'ANNUAL' => 'Annual', + 'EVERY_TWO_YEARS' => 'Every Two Years', + ); + } } diff --git a/stripe/models/FrmTransLiteAction.php b/stripe/models/FrmTransLiteAction.php index 50d7eb6ef6..21e4c52e1b 100755 --- a/stripe/models/FrmTransLiteAction.php +++ b/stripe/models/FrmTransLiteAction.php @@ -37,6 +37,7 @@ public function form( $instance, $args = array() ) { $currencies = FrmCurrencyHelper::get_currencies(); $repeat_times = FrmTransLiteAppHelper::get_repeat_times(); $gateways = FrmTransLiteAppHelper::get_gateways(); + $interval_options = FrmSquareLiteAppHelper::get_repeat_cadence_options(); if ( ! isset( $form_action->post_content['payment_limit'] ) ) { $form_action->post_content['payment_limit'] = ''; diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index e7e2df7a4a..4ba19fe8d8 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -42,18 +42,26 @@

- - - + -

+ post_content['gateway'] ) { ?> + + +

+
>

';
 		var_dump( $this->event );
 		die();
 	}
diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php
index 2de0feec54..3fd86f6ae0 100644
--- a/square/helpers/FrmSquareLiteConnectHelper.php
+++ b/square/helpers/FrmSquareLiteConnectHelper.php
@@ -556,4 +556,12 @@ public static function get_event( $event_id ) {
 	public static function process_event( $event_id ) {
 		return self::post_with_authenticated_body( 'process_event', compact( 'event_id' ) );
 	}
+
+	public static function get_payment( $payment_id ) {
+		return self::post_with_authenticated_body( 'get_payment', compact( 'payment_id' ) );
+	}
+
+	public static function get_subscription_id_for_payment( $payment_id ) {
+		return self::post_with_authenticated_body( 'get_subscription_id_for_payment', compact( 'payment_id' ) );
+	}
 }

From 813978c773694657544baba94461106ff8ddfa81 Mon Sep 17 00:00:00 2001
From: Mike Letellier 
Date: Thu, 22 May 2025 09:17:37 -0300
Subject: [PATCH 057/162] Working on webhooks (wip)

---
 .../controllers/FrmSquareLiteEventsController.php | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php
index 66818bc542..84858240cb 100644
--- a/square/controllers/FrmSquareLiteEventsController.php
+++ b/square/controllers/FrmSquareLiteEventsController.php
@@ -170,10 +170,7 @@ private function handle_event() {
 
 				if ( is_object( $subscription ) && isset( $subscription->id ) ) {
 					$subscription_id = $subscription->id;
-
-					// TODO: Add the payment record to the database. Use the subscription ID as well.
-					echo 'TODO: Handle subscription ' . $subscription_id;
-					die();
+					$this->add_subscription_payment( $subscription_id );
 				}
 
 				break;
@@ -188,4 +185,14 @@ private function handle_event() {
 		var_dump( $this->event );
 		die();
 	}
+
+	/**
+	 * Add a payment row for the payments table.
+	 *
+	 * @param int $subscription_id
+	 * @return void
+	 */
+	private function add_subscription_payment( $subscription_id ) {
+		
+	}
 }

From cb3a631bcfda5eb77842af987b4b4086e1ffd889 Mon Sep 17 00:00:00 2001
From: Mike Letellier 
Date: Thu, 22 May 2025 15:14:06 -0300
Subject: [PATCH 058/162] Get cancelling a subscription working

---
 square/helpers/FrmSquareLiteConnectHelper.php              | 4 ++++
 stripe/controllers/FrmTransLiteSubscriptionsController.php | 3 +--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php
index 3fd86f6ae0..a02292965b 100644
--- a/square/helpers/FrmSquareLiteConnectHelper.php
+++ b/square/helpers/FrmSquareLiteConnectHelper.php
@@ -564,4 +564,8 @@ public static function get_payment( $payment_id ) {
 	public static function get_subscription_id_for_payment( $payment_id ) {
 		return self::post_with_authenticated_body( 'get_subscription_id_for_payment', compact( 'payment_id' ) );
 	}
+
+	public static function cancel_subscription( $subscription_id ) {
+		return self::post_with_authenticated_body( 'cancel_subscription', compact( 'subscription_id' ) );
+	}
 }
diff --git a/stripe/controllers/FrmTransLiteSubscriptionsController.php b/stripe/controllers/FrmTransLiteSubscriptionsController.php
index e9a28e5892..5fc0f34cc5 100755
--- a/stripe/controllers/FrmTransLiteSubscriptionsController.php
+++ b/stripe/controllers/FrmTransLiteSubscriptionsController.php
@@ -101,8 +101,7 @@ public static function cancel_subscription() {
 						$canceled = FrmStrpLiteAppHelper::call_stripe_helper_class( 'cancel_subscription', $sub->sub_id );
 						break;
 					case 'square':
-						// TODO
-						$canceled = false;
+						$canceled = FrmSquareLiteConnectHelper::cancel_subscription( $sub->sub_id );
 						break;
 				}
 

From a75efc8371aea3138e47a157de6379c24b4d1694 Mon Sep 17 00:00:00 2001
From: Mike Letellier 
Date: Thu, 22 May 2025 16:08:15 -0300
Subject: [PATCH 059/162] Work on adding the subscription payment to the db
 when handling an event

---
 .../FrmSquareLiteEventsController.php         | 39 ++++++++++++++++---
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php
index 84858240cb..5794ec4d5d 100644
--- a/square/controllers/FrmSquareLiteEventsController.php
+++ b/square/controllers/FrmSquareLiteEventsController.php
@@ -163,8 +163,6 @@ private function track_handled_event( $event_id ) {
 	private function handle_event() {
 		switch ( $this->event->type ) {
 			case 'payment.created':
-				break;
-			case 'payment.updated':
 				$payment_id   = $this->event->data->id;
 				$subscription = FrmSquareLiteConnectHelper::get_subscription_id_for_payment( $payment_id );
 
@@ -172,7 +170,8 @@ private function handle_event() {
 					$subscription_id = $subscription->id;
 					$this->add_subscription_payment( $subscription_id );
 				}
-
+				break;
+			case 'payment.updated':
 				break;
 			case 'subscription.updated':
 				break;
@@ -189,10 +188,40 @@ private function handle_event() {
 	/**
 	 * Add a payment row for the payments table.
 	 *
-	 * @param int $subscription_id
+	 * @param string $subscription_id The Square ID for the current subscription.
 	 * @return void
 	 */
 	private function add_subscription_payment( $subscription_id ) {
-		
+		$payment_id = $this->event->data->id;
+
+		$frm_payment = new FrmTransLitePayment();
+		$payment     = $frm_payment->get_one_by( $payment_id, 'receipt_id' );
+
+		if ( $payment ) {
+			// Avoid adding the same payment twice.
+			return;
+		}
+
+		$frm_sub = new FrmTransLiteSubscription();
+		$sub     = $frm_sub->get_one_by( $subscription_id, 'sub_id' );
+		if ( ! $sub ) {
+			return;
+		}
+
+		$payment_object = $this->event->data->object->payment;
+
+		$frm_payment = new FrmTransLitePayment();
+		$frm_payment->create(
+			array(
+				'paysys'     => 'square',
+				'amount'     => $payment_object->amount_money->amount / 100,
+				'status'     => 'pending',
+				'item_id'    => $sub->item_id,
+				'action_id'  => $sub->action_id,
+				'receipt_id' => $payment_id,
+				'sub_id'     => $sub->id,
+				'test'       => 'test' === FrmSquareLiteAppHelper::active_mode() ? 1 : 0,
+			)
+		);
 	}
 }

From 4456377a88dee2b2be689cfe56360fcc1d51dcdd Mon Sep 17 00:00:00 2001
From: Mike Letellier 
Date: Thu, 22 May 2025 16:14:23 -0300
Subject: [PATCH 060/162] Making progress with webhooks

---
 .../FrmSquareLiteEventsController.php         | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php
index 5794ec4d5d..2dd1449e54 100644
--- a/square/controllers/FrmSquareLiteEventsController.php
+++ b/square/controllers/FrmSquareLiteEventsController.php
@@ -172,17 +172,22 @@ private function handle_event() {
 				}
 				break;
 			case 'payment.updated':
+				$payment_id  = $this->event->data->id;
+				$frm_payment = new FrmTransLitePayment();
+				$payment     = $frm_payment->get_one_by( $payment_id, 'receipt_id' );
+
+				if ( $payment ) {
+					$status = $this->event->data->object->payment->status;
+
+					if ( 'COMPLETED' === $status ) {
+						$frm_payment->update( $payment->id, array( 'status' => 'complete' ) );
+					}
+					return;
+				}
 				break;
 			case 'subscription.updated':
 				break;
 		}
-
-		// TODO: Handle the event.
-		echo 'Handle event';
-		echo '
'; - echo '
';
-		var_dump( $this->event );
-		die();
 	}
 
 	/**

From 8607e097e373bc503465a4cc0108d1d3d56ed9be Mon Sep 17 00:00:00 2001
From: Mike Letellier 
Date: Thu, 22 May 2025 16:25:18 -0300
Subject: [PATCH 061/162] Add comments, start working on handling a deactivated
 subscription event

---
 square/controllers/FrmSquareLiteEventsController.php | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php
index 2dd1449e54..e9fa9dc34a 100644
--- a/square/controllers/FrmSquareLiteEventsController.php
+++ b/square/controllers/FrmSquareLiteEventsController.php
@@ -180,12 +180,24 @@ private function handle_event() {
 					$status = $this->event->data->object->payment->status;
 
 					if ( 'COMPLETED' === $status ) {
+						// TODO Trigger "Payment complete" actions.
 						$frm_payment->update( $payment->id, array( 'status' => 'complete' ) );
 					}
 					return;
 				}
 				break;
 			case 'subscription.updated':
+				$subscription_id = $this->event->data->id;
+				$frm_sub = new FrmTransLiteSubscription();
+				$sub     = $frm_sub->get_one_by( $subscription_id, 'sub_id' );
+
+				if ( $sub ) {
+					$status = $this->event->data->object->subscription->status;
+
+					if ( 'DEACTIVATED' === $status ) {
+						// TODO: Mark subscription as cancelled.
+					}
+				}
 				break;
 		}
 	}

From 8679e2cad86fda3e3c6391706a220ea8c50ac581 Mon Sep 17 00:00:00 2001
From: Mike Letellier 
Date: Fri, 23 May 2025 13:26:16 -0300
Subject: [PATCH 062/162] Make disconnecting functional

---
 .../FrmSquareLiteAppController.php            | 10 ++++++
 .../FrmSquareLiteHooksController.php          |  1 +
 square/helpers/FrmSquareLiteConnectHelper.php | 35 +++++++++++++++++--
 square/js/settings.js                         | 20 +++++++++++
 4 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php
index 8cf0aad448..53a31e5a83 100644
--- a/square/controllers/FrmSquareLiteAppController.php
+++ b/square/controllers/FrmSquareLiteAppController.php
@@ -45,6 +45,16 @@ public static function handle_oauth() {
 		wp_send_json_success( $response_data );
 	}
 
+	public static function handle_disconnect() {
+		FrmAppHelper::permission_check( 'frm_change_settings' );
+		if ( ! check_admin_referer( 'frm_ajax', 'nonce' ) ) {
+			wp_send_json_error();
+		}
+
+		FrmSquareLiteConnectHelper::handle_disconnect();
+		wp_send_json_success();
+	}
+
 	/**
 	 * Handle the verify buyer action.
 	 *
diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php
index 0acae6ce15..b219a8bf06 100644
--- a/square/controllers/FrmSquareLiteHooksController.php
+++ b/square/controllers/FrmSquareLiteHooksController.php
@@ -37,6 +37,7 @@ public static function load_admin_hooks() {
 	 */
 	private static function load_ajax_hooks() {
 		add_action( 'wp_ajax_frm_square_oauth', 'FrmSquareLiteAppController::handle_oauth' );
+		add_action( 'wp_ajax_frm_square_disconnect', 'FrmSquareLiteAppController::handle_disconnect' );
 
 		add_action( 'wp_ajax_frm_verify_buyer', 'FrmSquareLiteAppController::verify_buyer' );
 		add_action( 'wp_ajax_nopriv_frm_verify_buyer', 'FrmSquareLiteAppController::verify_buyer' );
diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php
index a02292965b..48d21c370a 100644
--- a/square/helpers/FrmSquareLiteConnectHelper.php
+++ b/square/helpers/FrmSquareLiteConnectHelper.php
@@ -101,7 +101,7 @@ private static function render_settings_for_mode( $mode ) {
 				
- + @@ -361,7 +361,7 @@ private static function get_merchant_id_option_name( $mode = 'auto' ) { } /** - * @param string $key 'merchant_id', 'client_password', 'server_password', 'details_submitted'. + * @param string $key 'merchant_id', 'client_password', 'server_password' * @param string $mode either 'auto', 'live', or 'test'. * @return string */ @@ -568,4 +568,35 @@ public static function get_subscription_id_for_payment( $payment_id ) { public static function cancel_subscription( $subscription_id ) { return self::post_with_authenticated_body( 'cancel_subscription', compact( 'subscription_id' ) ); } + + /** + * @return void + */ + public static function handle_disconnect() { + self::disconnect(); + self::reset_square_api_integration(); + wp_send_json_success(); + } + + /** + * @return false|object + */ + private static function disconnect() { + $additional_body = array( + 'frm_square_api_mode' => self::get_mode_value_from_post(), + ); + return self::post_with_authenticated_body( 'disconnect', $additional_body ); + } + + /** + * Delete every Square API option, calling when disconnecting. + * + * @return void + */ + public static function reset_square_api_integration() { + $mode = self::get_mode_value_from_post(); + delete_option( self::get_merchant_id_option_name( $mode ) ); + delete_option( self::get_server_side_token_option_name( $mode ) ); + delete_option( self::get_client_side_token_option_name( $mode ) ); + } } diff --git a/square/js/settings.js b/square/js/settings.js index 0aea4d612c..60461afc4e 100644 --- a/square/js/settings.js +++ b/square/js/settings.js @@ -13,4 +13,24 @@ ); } ); } ); + + document.addEventListener( + 'click', + function( event ) { + if ( ! event.target.id.startsWith( 'frm_disconnect_square_' ) ) { + return; + } + + event.preventDefault(); + const formData = new FormData(); + formData.append( 'mode', event.target.id.replace( 'frm_disconnect_square_', '' ) ); + frmDom.ajax.doJsonPost( 'square_disconnect', formData ).then( + function( response ) { + if ( 'undefined' !== typeof response.success && response.success ) { + window.location.reload(); + } + } + ); + } + ); }() ); From 8365960a3432eafbdb34986544bb66452600839a Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:01:29 -0300 Subject: [PATCH 063/162] Remove old comment --- square/controllers/FrmSquareLiteActionsController.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index e5e54f60f6..eda0f37595 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -50,9 +50,6 @@ public static function show_card( $field, $field_name, $atts ) { $actions = self::get_actions_before_submit( $field['form_id'] ); if ( $actions ) { - // TODO This likely overwrites Stripe. - // We'll need to check $actions for a credit card field match. - $html_id = $atts['html_id']; include FrmStrpLiteAppHelper::plugin_path() . '/views/payments/card-field.php'; return; From bd6969eae097f1363094feec0aa7879efac568bb Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:06:52 -0300 Subject: [PATCH 064/162] Add typos exception --- _typos.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_typos.toml b/_typos.toml index 973bc21e41..27c3f3cabd 100644 --- a/_typos.toml +++ b/_typos.toml @@ -35,3 +35,5 @@ atributes = "atributes" fo = "fo" [default.extend-identifiers] 66afe9 = "66afe9" +# `Ags` should be `Ages`, `Tags` +sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ = "sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ" From 64d21e1627cdc61803d58790bad0790f76b61076 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:08:23 -0300 Subject: [PATCH 065/162] Add default case to avoid undefined $canceled case --- stripe/controllers/FrmTransLiteSubscriptionsController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stripe/controllers/FrmTransLiteSubscriptionsController.php b/stripe/controllers/FrmTransLiteSubscriptionsController.php index 5fc0f34cc5..e72c9c6dca 100755 --- a/stripe/controllers/FrmTransLiteSubscriptionsController.php +++ b/stripe/controllers/FrmTransLiteSubscriptionsController.php @@ -103,6 +103,9 @@ public static function cancel_subscription() { case 'square': $canceled = FrmSquareLiteConnectHelper::cancel_subscription( $sub->sub_id ); break; + default: + $canceled = false; + break; } if ( $canceled ) { From e4360bb9aa5d09072446b2a2e58db33c43ae5399 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:08:50 -0300 Subject: [PATCH 066/162] Add default case to avoid undefined $refunded case --- stripe/controllers/FrmTransLitePaymentsController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stripe/controllers/FrmTransLitePaymentsController.php b/stripe/controllers/FrmTransLitePaymentsController.php index e31d3f85fc..e8c62415d9 100755 --- a/stripe/controllers/FrmTransLitePaymentsController.php +++ b/stripe/controllers/FrmTransLitePaymentsController.php @@ -214,6 +214,9 @@ public static function refund_payment() { case 'square': $refunded = FrmSquareLiteConnectHelper::refund_payment( $payment->receipt_id ); break; + default: + $refunded = false; + break; } if ( $refunded ) { From 927dcf2a46465c837b13b037dfbeaf45026888e3 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:11:38 -0300 Subject: [PATCH 067/162] Move some code --- .../FrmSquareLiteActionsController.php | 34 ------------------- .../FrmStrpLiteActionsController.php | 21 ------------ .../FrmTransLiteActionsController.php | 34 +++++++++++++++++++ 3 files changed, 34 insertions(+), 55 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index eda0f37595..02dcf3687f 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -357,40 +357,6 @@ public static function prepare_amount( $amount, $atts = array() ) { return number_format( $amount, $currency['decimals'], '', '' ); } - /** - * @param int $form_id - * @param string $field_type - * @param string $field_name - * @return false|int - */ - private static function add_a_field( $form_id, $field_type, $field_name ) { - $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id ); - $new_values['name'] = $field_name; - $field_id = FrmField::create( $new_values ); - return $field_id; - } - - /** - * A credit card field is added automatically if missing before a Stripe action is updated. - * - * @param int $form_id - * @return false|int - */ - private static function add_a_credit_card_field( $form_id ) { - return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) ); - } - - /** - * A gateway field is added automatically for compatibility with the Stripe add on. - * The gateway field is not important for the Stripe Lite implementation. - * - * @param int $form_id - * @return false|int - */ - private static function add_a_gateway_field( $form_id ) { - return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) ); - } - /** * If this form submits with ajax, load the scripts on the first page. * diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index 1227f99981..37d5644ed7 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -320,27 +320,6 @@ private static function add_a_field( $form_id, $field_type, $field_name ) { return $field_id; } - /** - * A credit card field is added automatically if missing before a Stripe action is updated. - * - * @param int $form_id - * @return false|int - */ - private static function add_a_credit_card_field( $form_id ) { - return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) ); - } - - /** - * A gateway field is added automatically for compatibility with the Stripe add on. - * The gateway field is not important for the Stripe Lite implementation. - * - * @param int $form_id - * @return false|int - */ - private static function add_a_gateway_field( $form_id ) { - return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) ); - } - /** * Create any required Stripe plans, used for subscriptions. * diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index a5000e27a7..f510d74481 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -562,4 +562,38 @@ public static function before_save_settings( $settings, $action ) { return $settings; } + + /** + * A credit card field is added automatically if missing before a Stripe action is updated. + * + * @param int $form_id + * @return false|int + */ + protected static function add_a_credit_card_field( $form_id ) { + return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) ); + } + + /** + * A gateway field is added automatically for compatibility with the Stripe add on. + * The gateway field is not important for the Stripe Lite implementation. + * + * @param int $form_id + * @return false|int + */ + protected static function add_a_gateway_field( $form_id ) { + return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) ); + } + + /** + * @param int $form_id + * @param string $field_type + * @param string $field_name + * @return false|int + */ + protected static function add_a_field( $form_id, $field_type, $field_name ) { + $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id ); + $new_values['name'] = $field_name; + $field_id = FrmField::create( $new_values ); + return $field_id; + } } From 99fac02893b16640b12b2308824b40a4dc3652d7 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:13:24 -0300 Subject: [PATCH 068/162] Fix typo exception --- _typos.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_typos.toml b/_typos.toml index 27c3f3cabd..ab45192b6d 100644 --- a/_typos.toml +++ b/_typos.toml @@ -35,5 +35,5 @@ atributes = "atributes" fo = "fo" [default.extend-identifiers] 66afe9 = "66afe9" -# `Ags` should be `Ages`, `Tags` -sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ = "sandbox-sq0idb-MXl8ilzmhAgsHWKV9c6ycQ" +# `Ags` should be `Ages`, `Tags` in sandbox token +Ags = "Ags" From ef1faa80272df8b1fd7ddfec1914605928ba6b2c Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:14:31 -0300 Subject: [PATCH 069/162] Specify square as a psalm dir --- psalm.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/psalm.xml b/psalm.xml index 11f58a0e00..304eb289dc 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,6 +13,7 @@ + From eb4ee127a0fa115de97acd9018d788ae6a5ebff1 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:18:02 -0300 Subject: [PATCH 070/162] Add some psalm exceptions for square --- psalm.xml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/psalm.xml b/psalm.xml index 304eb289dc..c9a1d5993e 100644 --- a/psalm.xml +++ b/psalm.xml @@ -33,6 +33,7 @@ + @@ -86,6 +87,7 @@ + @@ -94,12 +96,14 @@ + + @@ -108,6 +112,7 @@ + @@ -115,6 +120,7 @@ + @@ -131,30 +137,35 @@ + + + + + @@ -166,6 +177,7 @@ + @@ -178,6 +190,7 @@ + @@ -207,42 +220,49 @@ + + + + + + + @@ -251,30 +271,35 @@ + + + + + @@ -282,12 +307,14 @@ + + @@ -295,12 +322,14 @@ + + @@ -316,18 +345,21 @@ + + + @@ -344,18 +376,21 @@ + + + @@ -418,12 +453,14 @@ + + @@ -466,6 +503,7 @@ + @@ -473,6 +511,7 @@ + From 988a41ade87ecf9186d2356a20284231be007250 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:19:20 -0300 Subject: [PATCH 071/162] Fix exception for typo in wrong place --- _typos.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/_typos.toml b/_typos.toml index ab45192b6d..c60ab99c41 100644 --- a/_typos.toml +++ b/_typos.toml @@ -33,7 +33,9 @@ atributes = "atributes" # fo is used for the Faroese locale. It is not a typo. # fo is also used for a table alias in SQL queries. fo = "fo" -[default.extend-identifiers] -66afe9 = "66afe9" # `Ags` should be `Ages`, `Tags` in sandbox token Ags = "Ags" + +[default.extend-identifiers] +66afe9 = "66afe9" + From 34079b42be2ee7e408a014411a0d8162d3329e9b Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:20:54 -0300 Subject: [PATCH 072/162] Add a missing stub --- stubs.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/stubs.php b/stubs.php index 6c623b4a46..7f22c46072 100644 --- a/stubs.php +++ b/stubs.php @@ -434,7 +434,22 @@ public static function inbox_badge( $count ) {} */ public static function add_currency_settings() {} } -} + class FrmProAddressesController extends FrmProComboFieldsController { + /** + * Maps Country name to Country code. + * + * @since 6.11 + * + * @param string $country Country name. + * @return string $country_code Country code. + */ + public static function get_country_code( $country ) { + } + } + + class FrmProComboFieldsController { + } + namespace Elementor { abstract class Widget_Base { From cd44bbfe7ec70463284bbc91bdc8aed38b6b377d Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:21:38 -0300 Subject: [PATCH 073/162] Drop extra function --- stripe/controllers/FrmStrpLiteActionsController.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index 37d5644ed7..41fb40c907 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -307,19 +307,6 @@ public static function before_save_settings( $settings, $action ) { return $settings; } - /** - * @param int $form_id - * @param string $field_type - * @param string $field_name - * @return false|int - */ - private static function add_a_field( $form_id, $field_type, $field_name ) { - $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id ); - $new_values['name'] = $field_name; - $field_id = FrmField::create( $new_values ); - return $field_id; - } - /** * Create any required Stripe plans, used for subscriptions. * From a7a18c2318c86eea488ad7158453fa9850af8830 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:24:44 -0300 Subject: [PATCH 074/162] Fix broken stubs file --- stubs.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/stubs.php b/stubs.php index 7f22c46072..6df3403049 100644 --- a/stubs.php +++ b/stubs.php @@ -436,12 +436,8 @@ public static function add_currency_settings() {} } class FrmProAddressesController extends FrmProComboFieldsController { /** - * Maps Country name to Country code. - * - * @since 6.11 - * - * @param string $country Country name. - * @return string $country_code Country code. + * @param string $country + * @return string */ public static function get_country_code( $country ) { } @@ -449,7 +445,7 @@ public static function get_country_code( $country ) { class FrmProComboFieldsController { } - +} namespace Elementor { abstract class Widget_Base { From 919be3acdb06ec9e47da8824a528f38cf40bfcd4 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:29:13 -0300 Subject: [PATCH 075/162] Match types better --- square/controllers/FrmSquareLiteActionsController.php | 6 +++--- stripe/controllers/FrmStrpLiteActionsController.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 02dcf3687f..92b694ec7f 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -8,8 +8,8 @@ class FrmSquareLiteActionsController extends FrmTransLiteActionsController { /** * @since x.x * - * @param string $callback - * @param array|object $field + * @param string $callback + * @param array|false|object $field * @return string */ public static function maybe_show_card( $callback, $field = false ) { @@ -88,7 +88,7 @@ public static function get_actions_before_submit( $form_id ) { * * @param WP_Post $action * @param stdClass $entry - * @param stdClass $form + * @param mixed $form * @return array */ public static function trigger_gateway( $action, $entry, $form ) { diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index 41fb40c907..a737a2ab8c 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -13,8 +13,8 @@ class FrmStrpLiteActionsController extends FrmTransLiteActionsController { /** * @since x.x * - * @param string $callback - * @param array|object $field + * @param string $callback + * @param array|false|object $field * @return string */ public static function maybe_show_card( $callback, $field = false ) { @@ -97,7 +97,7 @@ public static function get_stripe_link_action( $form_id ) { * * @param WP_Post $action * @param stdClass $entry - * @param stdClass $form + * @param mixed $form * @return array */ public static function trigger_gateway( $action, $entry, $form ) { From 776dd001de7f27dca6116f25486b2150f4189a5c Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:34:58 -0300 Subject: [PATCH 076/162] Add missing var --- square/controllers/FrmSquareLiteAppController.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index 53a31e5a83..6e18b9bfa1 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -90,7 +90,9 @@ public static function verify_buyer() { } /** - * @param array $actions + * Get the amount value for verification. + * + * @param WP_Post $action * @return string */ private static function get_amount_value_for_verification( $action ) { @@ -99,6 +101,11 @@ private static function get_amount_value_for_verification( $action ) { return $amount; } + $form = FrmForm::getOne( $action->menu_order ); + if ( ! $form ) { + return $amount; + } + // Update amount based on field shortcodes. $entry = self::generate_false_entry(); $amount = FrmSquareLiteActionsController::prepare_amount( $amount, compact( 'form', 'entry', 'action' ) ); From 1c70dd1146aa3a5d2230c7ab254614b83589e275 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 14:55:24 -0300 Subject: [PATCH 077/162] Update Psalm exceptions, add array check --- psalm.xml | 2 ++ square/controllers/FrmSquareLiteAppController.php | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/psalm.xml b/psalm.xml index c9a1d5993e..bd6b83bc3d 100644 --- a/psalm.xml +++ b/psalm.xml @@ -171,6 +171,7 @@ + @@ -203,6 +204,7 @@ + diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index 6e18b9bfa1..f55960a264 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -179,9 +179,11 @@ private static function generate_false_entry() { $v = wp_unslash( $v ); if ( $k === 'item_meta' ) { - foreach ( $v as $f => $value ) { - FrmAppHelper::sanitize_value( 'wp_kses_post', $value ); - $entry->metas[ absint( $f ) ] = $value; + if ( is_array( $v ) ) { + foreach ( $v as $f => $value ) { + FrmAppHelper::sanitize_value( 'wp_kses_post', $value ); + $entry->metas[ absint( $f ) ] = $value; + } } } else { FrmAppHelper::sanitize_value( 'wp_kses_post', $v ); From be6fa267cb9fefc923d7b609ae67b9b41cdcece5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:03:56 -0300 Subject: [PATCH 078/162] Fix psalm exception for wrong class --- psalm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psalm.xml b/psalm.xml index bd6b83bc3d..58c8a1085f 100644 --- a/psalm.xml +++ b/psalm.xml @@ -204,7 +204,7 @@ - + From bd522f9dc99dbba477501adc9dfbebf4f0c34b50 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:07:03 -0300 Subject: [PATCH 079/162] Update comments --- .../FrmSquareLiteActionsController.php | 24 +------------------ .../FrmSquareLiteAppController.php | 3 +-- .../FrmSquareLiteEventsController.php | 2 +- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- 4 files changed, 4 insertions(+), 27 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 92b694ec7f..ab09d98944 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -65,7 +65,7 @@ public static function show_card( $field, $field_name, $atts ) { /** * Get all published payment actions with the Stripe gateway that have an amount set. * - * @since 6.5, introduced in v2.0 of the Stripe add on. + * @since x.x * * @param int|string $form_id * @return array @@ -322,28 +322,6 @@ private static function replace_email_shortcode( $email ) { ); } - /** - * Set the customer name based on the mapped first and last name fields in the Stripe action. - * - * @since 6.5, introduced in v2.02 of the Stripe add on. - * - * @param array $atts - * @param array $payment_info - * @return void - */ - private static function add_customer_name( $atts, &$payment_info ) { - if ( empty( $atts['action']->post_content['billing_first_name'] ) ) { - return; - } - - $name = '[' . $atts['action']->post_content['billing_first_name'] . ' show="first"]'; - if ( ! empty( $atts['action']->post_content['billing_last_name'] ) ) { - $name .= ' [' . $atts['action']->post_content['billing_last_name'] . ' show="last"]'; - } - - $payment_info['name'] = apply_filters( 'frm_content', $name, $atts['form'], $atts['entry'] ); - } - /** * Convert the amount from 10.00 to 1000. * diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index f55960a264..84fc359783 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -62,7 +62,6 @@ public static function handle_disconnect() { */ public static function verify_buyer() { check_ajax_referer( 'frm_square_ajax', 'nonce' ); - // TODO Fill this in based on form data. $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' ); if ( ! $form_id ) { @@ -164,7 +163,7 @@ public static function get_billing_contact( $action ) { /** * Create an entry object with posted values. * - * @since 6.5, introduced in v2.0 of the Stripe add on. + * @since x.x * @return stdClass */ private static function generate_false_entry() { diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php index e9fa9dc34a..db6d7f4154 100644 --- a/square/controllers/FrmSquareLiteEventsController.php +++ b/square/controllers/FrmSquareLiteEventsController.php @@ -45,7 +45,7 @@ private function flush_response() { * @return void */ public function process_events() { - // $this->flush_response(); + $this->flush_response(); $unprocessed_event_ids = FrmSquareLiteConnectHelper::get_unprocessed_event_ids(); diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 48d21c370a..dc7f30944e 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -8,7 +8,7 @@ class FrmSquareLiteConnectHelper { /** * Track the latest error when calling stripe connect. * - * @since 6.5 + * @since x.x * * @var string|null */ From bef420466bcbc37058fe53c34316153b447291f6 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:08:43 -0300 Subject: [PATCH 080/162] Deprecate unused Stripe function --- stripe/helpers/FrmStrpLiteAppHelper.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/stripe/helpers/FrmStrpLiteAppHelper.php b/stripe/helpers/FrmStrpLiteAppHelper.php index cc1f7db6ad..000e6cff8d 100644 --- a/stripe/helpers/FrmStrpLiteAppHelper.php +++ b/stripe/helpers/FrmStrpLiteAppHelper.php @@ -31,14 +31,6 @@ public static function plugin_url() { return FrmAppHelper::plugin_url() . '/stripe/'; } - /** - * @return bool - */ - public static function is_debug() { - // TODO: Deprecate this. - return defined( 'WP_DEBUG' ) && WP_DEBUG; - } - /** * @param string $function * @param array ...$params @@ -144,4 +136,14 @@ public static function not_connected_warning() {
Date: Fri, 23 May 2025 15:09:38 -0300 Subject: [PATCH 081/162] Fix wrong textdomain --- stripe/views/action-settings/payments-options.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index 1438eb872d..cbcd2b9629 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -94,7 +94,7 @@

$gateway ) { $gateway_classes = $gateway['recurring'] ? '' : 'frm_gateway_no_recur'; From 587c455b3a203f71433a7b833f133989d4546ed0 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:18:14 -0300 Subject: [PATCH 082/162] Code styling fixes --- .../controllers/FrmSquareLiteActionsController.php | 14 +++++++------- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- square/models/FrmSquareLiteSettings.php | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index ab09d98944..401cbe9c2f 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -412,13 +412,13 @@ public static function load_scripts( $form_id ) { $action_settings = self::prepare_settings_for_js( $form_id ); $square_vars = array( - 'formId' => $form_id, - 'nonce' => wp_create_nonce( 'frm_square_ajax' ), - 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ), - 'settings' => $action_settings, - 'appId' => self::get_app_id(), - 'locationId' => self::get_location_id(), - 'style' => self::get_style( $form_id ), + 'formId' => $form_id, + 'nonce' => wp_create_nonce( 'frm_square_ajax' ), + 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ), + 'settings' => $action_settings, + 'appId' => self::get_app_id(), + 'locationId' => self::get_location_id(), + 'style' => self::get_style( $form_id ), ); wp_localize_script( 'formidable-square', 'frmSquareVars', $square_vars ); diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index dc7f30944e..7a8275cdaf 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -507,7 +507,7 @@ public static function create_subscription( $info ) { } /** - * @return string|false + * @return false|string */ public static function get_location_id() { $response = self::post_with_authenticated_body( 'get_location_id' ); diff --git a/square/models/FrmSquareLiteSettings.php b/square/models/FrmSquareLiteSettings.php index f56f479b60..08d86f6599 100644 --- a/square/models/FrmSquareLiteSettings.php +++ b/square/models/FrmSquareLiteSettings.php @@ -87,7 +87,7 @@ public function update( $params ) { } } - $this->settings->test_mode = isset( $params['frm_' . $this->param() . '_test_mode'] ) ? absint( $params['frm_' . $this->param() . '_test_mode'] ) : 0; + $this->settings->test_mode = isset( $params[ 'frm_' . $this->param() . '_test_mode' ] ) ? absint( $params[ 'frm_' . $this->param() . '_test_mode' ] ) : 0; } /** From 9b461902bd42ae57bb65dc273b865ef943f266d7 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:22:50 -0300 Subject: [PATCH 083/162] Code styling fixes --- square/controllers/FrmSquareLiteAppController.php | 4 ++-- square/controllers/FrmSquareLiteEventsController.php | 6 +++--- stripe/views/action-settings/payments-options.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index 84fc359783..df04e9f9a9 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -78,7 +78,7 @@ public static function verify_buyer() { 'amount' => self::get_amount_value_for_verification( $action ), 'billingContact' => self::get_billing_contact( $action ), 'currencyCode' => strtoupper( $action->post_content['currency'] ), - 'intent' => 'CHARGE' + 'intent' => 'CHARGE', ); wp_send_json_success( @@ -141,7 +141,7 @@ public static function get_billing_contact( $action ) { ); if ( $email_setting ) { - $shortcode_atts = array( + $shortcode_atts = array( 'entry' => $entry, 'form' => $action->menu_order, 'value' => $email_setting, diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php index db6d7f4154..60c04e5c20 100644 --- a/square/controllers/FrmSquareLiteEventsController.php +++ b/square/controllers/FrmSquareLiteEventsController.php @@ -188,8 +188,8 @@ private function handle_event() { break; case 'subscription.updated': $subscription_id = $this->event->data->id; - $frm_sub = new FrmTransLiteSubscription(); - $sub = $frm_sub->get_one_by( $subscription_id, 'sub_id' ); + $frm_sub = new FrmTransLiteSubscription(); + $sub = $frm_sub->get_one_by( $subscription_id, 'sub_id' ); if ( $sub ) { $status = $this->event->data->object->subscription->status; @@ -199,7 +199,7 @@ private function handle_event() { } } break; - } + }//end switch } /** diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index cbcd2b9629..9c6d965039 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -97,8 +97,8 @@ esc_html_e( 'Gateway(s)', 'formidable' ); foreach ( $gateways as $gateway_name => $gateway ) { - $gateway_classes = $gateway['recurring'] ? '' : 'frm_gateway_no_recur'; - $gateway_classes .= ( $form_action->post_content['type'] === 'recurring' && ! $gateway['recurring'] ) ? ' frm_hidden' : ''; + $gateway_classes = $gateway['recurring'] ? '' : 'frm_gateway_no_recur'; + $gateway_classes .= $form_action->post_content['type'] === 'recurring' && ! $gateway['recurring'] ? ' frm_hidden' : ''; $gateway_id = $this->get_field_id( 'gateways' ) . '_' . $gateway_name; $radio_atts = array( From a19363797e18d01b68c413aae8749a84bf82c626 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:24:33 -0300 Subject: [PATCH 084/162] Drop extra semi colon --- square/controllers/FrmSquareLiteActionsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 401cbe9c2f..e660bef5c8 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -216,7 +216,7 @@ private static function trigger_recurring_payment( $atts ) { // 1. Call the API with the customer and catalog info. // 2. Add the database rows. - $action = $atts['action'];; + $action = $atts['action']; $billing_contact = FrmSquareLiteAppController::get_billing_contact( $action ); $info = array( From d1216de9f87dd95e45e6780dd7cc1d6f3c4b672f Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 15:38:25 -0300 Subject: [PATCH 085/162] Code styling fixes --- .../FrmTransLiteActionsController.php | 2 +- .../FrmTransLiteSubscriptionsController.php | 2 +- stripe/views/action-settings/options.php | 2 +- .../action-settings/payments-options.php | 26 +++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index f510d74481..0784920ced 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -106,7 +106,7 @@ public static function trigger_action( $action, $entry, $form ) { } /** - * @param WP_Post $action + * @param WP_Post $action * @return array|string */ private static function get_gateway_for_action( $action ) { diff --git a/stripe/controllers/FrmTransLiteSubscriptionsController.php b/stripe/controllers/FrmTransLiteSubscriptionsController.php index e72c9c6dca..a19cf6728e 100755 --- a/stripe/controllers/FrmTransLiteSubscriptionsController.php +++ b/stripe/controllers/FrmTransLiteSubscriptionsController.php @@ -122,7 +122,7 @@ public static function cancel_subscription() { } } else { $message = __( 'That subscription was not found', 'formidable' ); - } + }//end if } else { $message = __( 'Oops! No subscription was selected for cancelation.', 'formidable' ); }//end if diff --git a/stripe/views/action-settings/options.php b/stripe/views/action-settings/options.php index 731735169e..9d91d84874 100644 --- a/stripe/views/action-settings/options.php +++ b/stripe/views/action-settings/options.php @@ -3,7 +3,7 @@ die( 'You are not allowed to call this page directly.' ); } -$show_layout_setting = in_array( 'stripe', (array) $form_action->post_content['gateway'], true ); +$show_layout_setting = in_array( 'stripe', (array) $form_action->post_content['gateway'], true ); $layout_setting_wrapper_atts = array( 'class' => 'frm_grid_container show_stripe' ); if ( ! $show_layout_setting ) { $layout_setting_wrapper_atts['class'] .= ' frm_hidden'; diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index 9c6d965039..476ba0530e 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -94,19 +94,19 @@

$gateway ) { - $gateway_classes = $gateway['recurring'] ? '' : 'frm_gateway_no_recur'; - $gateway_classes .= $form_action->post_content['type'] === 'recurring' && ! $gateway['recurring'] ? ' frm_hidden' : ''; - $gateway_id = $this->get_field_id( 'gateways' ) . '_' . $gateway_name; - - $radio_atts = array( - 'type' => 'radio', - 'value' => $gateway_name, - 'name' => $this->get_field_name( 'gateway' ), - 'id' => $gateway_id, - ); + esc_html_e( 'Gateway(s)', 'formidable' ); + + foreach ( $gateways as $gateway_name => $gateway ) { + $gateway_classes = $gateway['recurring'] ? '' : 'frm_gateway_no_recur'; + $gateway_classes .= $form_action->post_content['type'] === 'recurring' && ! $gateway['recurring'] ? ' frm_hidden' : ''; + $gateway_id = $this->get_field_id( 'gateways' ) . '_' . $gateway_name; + + $radio_atts = array( + 'type' => 'radio', + 'value' => $gateway_name, + 'name' => $this->get_field_name( 'gateway' ), + 'id' => $gateway_id, + ); ?>

From b004bade4414d5e6b7eb9abd8c401b950ed64b3d Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:10:24 -0300 Subject: [PATCH 089/162] Clean up --- square/controllers/FrmSquareLiteActionsController.php | 6 +----- square/controllers/FrmSquareLiteEventsController.php | 4 ++-- square/js/frontend.js | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index a66aa5cb53..0b0b451fdc 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -25,8 +25,6 @@ public static function maybe_show_card( $callback, $field = false ) { } $field_id = is_object( $field ) ? $field->id : $field['id']; - - // TODO Make sure the field is mapped to the action. foreach ( $actions as $action ) { if ( (int) $action->post_content['credit_card'] === (int) $field_id ) { return self::class . '::show_card'; @@ -148,9 +146,7 @@ private static function trigger_one_time_payment( $atts ) { $currency = strtoupper( $atts['action']->post_content['currency'] ); $square_token = sanitize_text_field( $_POST['square-token'] ); $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); - - // TODO We'll need to send the square tokens to our API. - $result = FrmSquareLiteConnectHelper::create_payment( $atts['amount'], $currency, $square_token, $verification_token ); + $result = FrmSquareLiteConnectHelper::create_payment( $atts['amount'], $currency, $square_token, $verification_token ); if ( false === $result ) { return FrmSquareLiteConnectHelper::get_latest_error_from_square_api(); diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php index 60c04e5c20..147214f891 100644 --- a/square/controllers/FrmSquareLiteEventsController.php +++ b/square/controllers/FrmSquareLiteEventsController.php @@ -194,9 +194,9 @@ private function handle_event() { if ( $sub ) { $status = $this->event->data->object->subscription->status; - if ( 'DEACTIVATED' === $status ) { + // if ( 'DEACTIVATED' === $status ) { // TODO: Mark subscription as cancelled. - } + // } } break; }//end switch diff --git a/square/js/frontend.js b/square/js/frontend.js index e2e495877c..b83289587b 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -22,7 +22,7 @@ }; async function initializeCard( payments ) { - const card = await payments.card(); + const card = await payments.card(); const cardStyle = frmSquareVars.style; await card.attach( '.frm-card-element' ); From 98709842da185e8166a25a424236b808aa57c9c9 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:16:21 -0300 Subject: [PATCH 090/162] Ignore nonce when making square payments --- .../controllers/FrmSquareLiteActionsController.php | 12 ++++++------ stripe/views/action-settings/payments-options.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 0b0b451fdc..0cf4f06556 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -139,13 +139,13 @@ public static function trigger_gateway( $action, $entry, $form ) { * @return string|true string on error, true on success. */ private static function trigger_one_time_payment( $atts ) { - if ( empty( $_POST['square-token'] ) || empty( $_POST['square-verification-token'] ) ) { + if ( empty( $_POST['square-token'] ) || empty( $_POST['square-verification-token'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return __( 'Please enter a valid credit card', 'formidable' ); } $currency = strtoupper( $atts['action']->post_content['currency'] ); - $square_token = sanitize_text_field( $_POST['square-token'] ); - $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); + $square_token = sanitize_text_field( $_POST['square-token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing + $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $result = FrmSquareLiteConnectHelper::create_payment( $atts['amount'], $currency, $square_token, $verification_token ); if ( false === $result ) { @@ -199,13 +199,13 @@ private static function create_new_payment( $atts ) { * @return bool|string True on success, error message on failure */ private static function trigger_recurring_payment( $atts ) { - if ( empty( $_POST['square-token'] ) || empty( $_POST['square-verification-token'] ) ) { + if ( empty( $_POST['square-token'] ) || empty( $_POST['square-verification-token'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return __( 'Please enter a valid credit card', 'formidable' ); } $currency = strtoupper( $atts['action']->post_content['currency'] ); - $square_token = sanitize_text_field( $_POST['square-token'] ); - $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); + $square_token = sanitize_text_field( $_POST['square-token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing + $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing // We can put this all behind our API. // It will require that we pass the customer info and the catalog info. diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index f852fe7507..8723aa3597 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -119,7 +119,7 @@  

From 5d8a39c3a1dfe60f95d21628516af174ce88508a Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:20:35 -0300 Subject: [PATCH 091/162] Drop type comments to prevent full stop issue --- .../controllers/FrmSquareLiteActionsController.php | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 0cf4f06556..80d45f4a9a 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -130,12 +130,7 @@ public static function trigger_gateway( $action, $entry, $form ) { /** * Trigger a one time payment. * - * @param array $atts { - * @type stdClass $form - * @type stdClass $entry - * @type WP_Post $action - * @type string $amount - * } + * @param array $atts * @return string|true string on error, true on success. */ private static function trigger_one_time_payment( $atts ) { @@ -166,11 +161,7 @@ private static function trigger_one_time_payment( $atts ) { /** * Add a payment row for the payments table. * - * @param array $atts { - * @type object $charge - * @type object $entry - * @type WP_Post $action - * } + * @param array $atts * @return int */ private static function create_new_payment( $atts ) { From a53cd8718d52b860fca0b04855ca421e0b3dea4e Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:21:14 -0300 Subject: [PATCH 092/162] Add full stop --- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index a15f4bc034..9ab8609d63 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -361,7 +361,7 @@ private static function get_merchant_id_option_name( $mode = 'auto' ) { } /** - * @param string $key 'merchant_id', 'client_password', 'server_password' + * @param string $key 'merchant_id', 'client_password', 'server_password'. * @param string $mode either 'auto', 'live', or 'test'. * @return string */ From 87af321732decc15e97c23554de937ebcde953f4 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:22:09 -0300 Subject: [PATCH 093/162] Break up long line --- square/helpers/FrmSquareLiteConnectHelper.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 9ab8609d63..cf55ba91c7 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -101,7 +101,9 @@ private static function render_settings_for_mode( $mode ) {
-
+
+ + + +
Date: Fri, 23 May 2025 16:23:47 -0300 Subject: [PATCH 095/162] Add param comments --- square/controllers/FrmSquareLiteActionsController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 80d45f4a9a..c56a391754 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -130,7 +130,7 @@ public static function trigger_gateway( $action, $entry, $form ) { /** * Trigger a one time payment. * - * @param array $atts + * @param array $atts The arguments for the payment. * @return string|true string on error, true on success. */ private static function trigger_one_time_payment( $atts ) { @@ -161,7 +161,7 @@ private static function trigger_one_time_payment( $atts ) { /** * Add a payment row for the payments table. * - * @param array $atts + * @param array $atts The arguments for the payment. * @return int */ private static function create_new_payment( $atts ) { From f9a853a064a6d5ff2dada11562dca785927f35a4 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:24:43 -0300 Subject: [PATCH 096/162] Change Stripe mention to Square --- square/controllers/FrmSquareLiteActionsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index c56a391754..b57220c62f 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -61,7 +61,7 @@ public static function show_card( $field, $field_name, $atts ) { } /** - * Get all published payment actions with the Stripe gateway that have an amount set. + * Get all published payment actions with the Square gateway that have an amount set. * * @since x.x * From 6d9cf4c3897f1e6b5386bcbf38b5c21e15d6603a Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 23 May 2025 16:26:59 -0300 Subject: [PATCH 097/162] Ignore long line --- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index f78a3c46c1..b512ccc333 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -51,7 +51,7 @@ public static function render_settings_container() {
- +
From a27c559663710215cfc2c54be5fce79c54336667 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 11:03:30 -0300 Subject: [PATCH 098/162] Use trialDays for more consistent case --- .../controllers/FrmSquareLiteActionsController.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index b57220c62f..950de983dd 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -217,12 +217,12 @@ private static function trigger_recurring_payment( $atts ) { 'emailAddress' => $billing_contact['email'], ), 'catalog' => array( - 'name' => $action->post_content['description'], - 'trial_days' => $action->post_content['trial_interval_count'], - 'limit' => $action->post_content['payment_limit'], - 'amount' => $atts['amount'], - 'currency' => $currency, - 'cadence' => $action->post_content['repeat_cadence'] ?? 'DAILY', + 'name' => $action->post_content['description'], + 'trialDays' => $action->post_content['trial_interval_count'], + 'limit' => $action->post_content['payment_limit'], + 'amount' => $atts['amount'], + 'currency' => $currency, + 'cadence' => $action->post_content['repeat_cadence'] ?? 'DAILY', ), ); From 8070375c124d89d198d0c4691a8ea88b4ac4952a Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 12:35:05 -0300 Subject: [PATCH 099/162] Fix hook not working when saving actions, sync merchant currency when saving action with square gateway selected --- square/helpers/FrmSquareLiteConnectHelper.php | 8 ++++++ .../FrmTransLiteActionsController.php | 14 ++++++++-- .../FrmTransLiteHooksController.php | 2 +- stripe/js/frmtrans_admin.js | 28 +++++++++++++++++++ .../action-settings/payments-options.php | 19 ++++++++++++- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index b512ccc333..21483a35a8 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -605,4 +605,12 @@ public static function reset_square_api_integration() { delete_option( self::get_server_side_token_option_name( $mode ) ); delete_option( self::get_client_side_token_option_name( $mode ) ); } + + public static function get_merchant_currency() { + $response = self::post_with_authenticated_body( 'get_merchant_currency' ); + if ( is_object( $response ) && ! empty( $response->currency ) ) { + return $response->currency; + } + return false; + } } diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index 0784920ced..075e8aa07b 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -528,9 +528,19 @@ function () use ( $entry_id, &$destroy_callback ) { * @return array */ public static function before_save_settings( $settings, $action ) { - $settings['currency'] = strtolower( $settings['currency'] ); $settings['gateway'] = ! empty( $settings['gateway'] ) ? (array) $settings['gateway'] : array( 'stripe' ); + if ( in_array( 'square', $settings['gateway'] ) ) { + $currency = FrmSquareLiteConnectHelper::get_merchant_currency(); + if ( false !== $currency ) { + $settings['currency'] = strtolower( $currency ); + } else { + $settings['currency'] = 'usd'; + } + } else { + $settings['currency'] = strtolower( $settings['currency'] ); + } + $form_id = absint( $action['menu_order'] ); if ( empty( $settings['credit_card'] ) ) { @@ -559,7 +569,7 @@ public static function before_save_settings( $settings, $action ) { if ( ! $gateway_field_id ) { self::add_a_gateway_field( $form_id ); } - + return $settings; } diff --git a/stripe/controllers/FrmTransLiteHooksController.php b/stripe/controllers/FrmTransLiteHooksController.php index 8e0aeac370..19321a1ccb 100755 --- a/stripe/controllers/FrmTransLiteHooksController.php +++ b/stripe/controllers/FrmTransLiteHooksController.php @@ -56,7 +56,7 @@ function () { add_filter( 'set-screen-option', 'FrmTransLiteListsController::save_per_page', 10, 3 ); // Use 9 to run before the Stripe Lite and Square Lite code. - add_filter( 'before_save_settings', 'FrmTransLiteActionsController::before_save_settings', 9 ); + add_filter( 'frm_before_save_payment_action', 'FrmTransLiteActionsController::before_save_settings', 9, 2 ); if ( defined( 'DOING_AJAX' ) ) { self::load_ajax_hooks(); diff --git a/stripe/js/frmtrans_admin.js b/stripe/js/frmtrans_admin.js index 0c2a0469d3..b533d10ba5 100755 --- a/stripe/js/frmtrans_admin.js +++ b/stripe/js/frmtrans_admin.js @@ -46,6 +46,34 @@ } } ); + + const currencySetting = settings.get( 0 ).querySelector( '[name*="[post_content][currency]"]' ); + if ( currencySetting ) { + let option = currencySetting.querySelector( 'option.square-currency' ); + + if ( option ) { + if ( 'square' === gateway ) { + currencySetting.value = option.value; + currencySetting.disabled = true; + } else { + currencySetting.disabled = false; + option.remove(); + } + } else { + if ( 'square' === gateway ) { + option = document.createElement( 'option' ); + option.value = 'square'; + option.textContent = 'Use Square Merchant Currency'; + option.classList.add( 'square-currency' ); + currencySetting.appendChild( option ); + + currencySetting.value = option.value; + currencySetting.disabled = true; + } else { + currencySetting.disabled = false; + } + } + } } function frmTransLiteAdminJS() { diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index 8723aa3597..c31421c909 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -82,7 +82,24 @@ - > + post_content['gateway'], true ) ) { + $form_action->post_content['currency'] = 'square'; + ?> + + $currency ) { ?> Date: Mon, 26 May 2025 12:57:11 -0300 Subject: [PATCH 100/162] Add square fee education and update the warning when using a payment action and neither Stripe or Square are configured --- square/helpers/FrmSquareLiteAppHelper.php | 25 +++++++++++++++++++ square/helpers/FrmSquareLiteConnectHelper.php | 9 +++++++ stripe/helpers/FrmStrpLiteAppHelper.php | 2 +- .../action-settings/payments-options.php | 13 +++++++--- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/square/helpers/FrmSquareLiteAppHelper.php b/square/helpers/FrmSquareLiteAppHelper.php index 42e1d9acf9..49ad2fdebb 100644 --- a/square/helpers/FrmSquareLiteAppHelper.php +++ b/square/helpers/FrmSquareLiteAppHelper.php @@ -74,4 +74,29 @@ public static function get_repeat_cadence_options() { 'EVERY_TWO_YEARS' => 'Every Two Years', ); } + + /** + * Add education about Stripe fees. + * + * @return void + */ + public static function fee_education( $medium = 'tip' ) { + $license_type = FrmAddonsController::license_type(); + if ( in_array( $license_type, array( 'elite', 'business' ), true ) ) { + return; + } + + FrmTipsHelper::show_tip( + array( + 'link' => array( + 'content' => 'square-fee', + 'medium' => $medium, + ), + 'tip' => 'Pay as you go pricing: 3% fee per-transaction + Square fees.', + 'call' => __( 'Upgrade to save on fees.', 'formidable' ), + 'class' => 'frm-light-tip', + ), + 'p' + ); + } } diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 21483a35a8..1d941f698b 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -613,4 +613,13 @@ public static function get_merchant_currency() { } return false; } + + /** + * @since x.x + * + * @return bool + */ + public static function at_least_one_mode_is_setup() { + return self::get_merchant_id( 'test' ) || self::get_merchant_id( 'live' ); + } } diff --git a/stripe/helpers/FrmStrpLiteAppHelper.php b/stripe/helpers/FrmStrpLiteAppHelper.php index 000e6cff8d..0cabca57d6 100644 --- a/stripe/helpers/FrmStrpLiteAppHelper.php +++ b/stripe/helpers/FrmStrpLiteAppHelper.php @@ -130,7 +130,7 @@ public static function not_connected_warning() { ', '
' ); + printf( esc_html__( 'Credit Cards will not work without %1$sconnecting Stripe%2$s or %3$sconnecting Square%4$s first.', 'formidable' ), '', '', '', '' ); ?>
diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index c31421c909..0425abf940 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -3,11 +3,18 @@ die( 'You are not allowed to call this page directly.' ); } -if ( ! FrmStrpLiteConnectHelper::at_least_one_mode_is_setup() ) { - FrmStrpLiteAppHelper::not_connected_warning(); -} else { +$stripe_connected = FrmStrpLiteConnectHelper::at_least_one_mode_is_setup(); +$square_connected = FrmSquareLiteConnectHelper::at_least_one_mode_is_setup(); + +if ( $stripe_connected ) { FrmStrpLiteAppHelper::fee_education(); } +if ( $square_connected ) { + FrmSquareLiteAppHelper::fee_education(); +} +if ( ! $stripe_connected && ! $square_connected ) { + FrmStrpLiteAppHelper::not_connected_warning(); +} ?>
From 564f4ba8d74694ca5ad25069b30a73cdc8039d36 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 13:47:41 -0300 Subject: [PATCH 101/162] Add location ID and currency as options to avoid too many requests to our server --- square/helpers/FrmSquareLiteConnectHelper.php | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 1d941f698b..e8c4ad8c30 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -366,6 +366,20 @@ private static function get_merchant_id_option_name( $mode = 'auto' ) { return self::get_square_connect_option_name( 'merchant_id', $mode ); } + /** + * @return string + */ + private static function get_location_id_option_name( $mode = 'auto' ) { + return self::get_square_connect_option_name( 'merchant_location_id', $mode ); + } + + /** + * @return string + */ + private static function get_merchant_currency_option_name( $mode = 'auto' ) { + return self::get_square_connect_option_name( 'merchant_currency', $mode ); + } + /** * @param string $key 'merchant_id', 'client_password', 'server_password'. * @param string $mode either 'auto', 'live', or 'test'. @@ -433,6 +447,18 @@ private static function check_server_for_oauth_merchant_id() { if ( is_object( $data ) && ! empty( $data->merchant_id ) ) { update_option( self::get_merchant_id_option_name( $mode ), $data->merchant_id, 'no' ); + + $currency = self::get_merchant_currency( true ); + $location_id = self::get_location_id( true ); + + if ( $currency ) { + update_option( self::get_merchant_currency_option_name( $mode ), $currency, 'no' ); + } + + if ( $location_id ) { + update_option( self::get_location_id_option_name( $mode ), $location_id, 'no' ); + } + return true; } @@ -513,13 +539,23 @@ public static function create_subscription( $info ) { } /** + * @param bool $force * @return false|string */ - public static function get_location_id() { + public static function get_location_id( $force = false ) { + if ( ! $force ) { + $location_id = get_option( self::get_location_id_option_name() ); + if ( $location_id ) { + return $location_id; + } + } + $response = self::post_with_authenticated_body( 'get_location_id' ); if ( is_object( $response ) ) { + update_option( self::get_location_id_option_name(), $response->id, 'no' ); return $response->id; } + return false; } @@ -604,13 +640,28 @@ public static function reset_square_api_integration() { delete_option( self::get_merchant_id_option_name( $mode ) ); delete_option( self::get_server_side_token_option_name( $mode ) ); delete_option( self::get_client_side_token_option_name( $mode ) ); + delete_option( self::get_merchant_currency_option_name( $mode ) ); + delete_option( self::get_location_id_option_name( $mode ) ); } - public static function get_merchant_currency() { + /** + * @param bool $force + * @return false\string + */ + public static function get_merchant_currency( $force = false ) { + if ( ! $force ) { + $currency = get_option( self::get_merchant_currency_option_name() ); + if ( $currency ) { + return $currency; + } + } + $response = self::post_with_authenticated_body( 'get_merchant_currency' ); if ( is_object( $response ) && ! empty( $response->currency ) ) { + update_option( self::get_merchant_currency_option_name(), $response->currency, 'no' ); return $response->currency; } + return false; } From 2d8c272090f410955a96426fea1ebf7fb8c47dd9 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 13:48:11 -0300 Subject: [PATCH 102/162] Remove old todo comment --- square/controllers/FrmSquareLiteActionsController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 950de983dd..03e37de634 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -429,7 +429,6 @@ private static function get_app_id() { * @return string */ private static function get_location_id() { - // TODO Cache this. return FrmSquareLiteConnectHelper::get_location_id(); } From e468935c3d4d473feccb775e0fb1ce6ed47c152c Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 14:22:16 -0300 Subject: [PATCH 103/162] Update some in-plugin warnings when Stripe is not set up but Square is, install payments when connecting --- classes/views/frm-fields/back-end/field-credit-card.php | 2 +- classes/views/frm-fields/back-end/settings.php | 2 +- square/helpers/FrmSquareLiteConnectHelper.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/classes/views/frm-fields/back-end/field-credit-card.php b/classes/views/frm-fields/back-end/field-credit-card.php index 33b5568a7d..69a423bac0 100644 --- a/classes/views/frm-fields/back-end/field-credit-card.php +++ b/classes/views/frm-fields/back-end/field-credit-card.php @@ -2,7 +2,7 @@ if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } -if ( ! FrmStrpLiteConnectHelper::at_least_one_mode_is_setup() || ! FrmTransLiteActionsController::get_actions_for_form( $field['form_id'] ) ) { +if ( ( ! FrmStrpLiteConnectHelper::at_least_one_mode_is_setup() && ! FrmSquareLiteConnectHelper::at_least_one_mode_is_setup() ) || ! FrmTransLiteActionsController::get_actions_for_form( $field['form_id'] ) ) { ?> diff --git a/classes/views/frm-fields/back-end/settings.php b/classes/views/frm-fields/back-end/settings.php index 8d3f3cbb0b..cfc02608d2 100644 --- a/classes/views/frm-fields/back-end/settings.php +++ b/classes/views/frm-fields/back-end/settings.php @@ -36,7 +36,7 @@ diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index e8c4ad8c30..162adfb8f1 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -459,6 +459,8 @@ private static function check_server_for_oauth_merchant_id() { update_option( self::get_location_id_option_name( $mode ), $location_id, 'no' ); } + FrmTransLiteAppController::install(); + return true; } From d3c291710c5600122dea66d82205760f2a7960f5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 14:30:21 -0300 Subject: [PATCH 104/162] Show the error message from Square --- square/js/frontend.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index b83289587b..a2ea723f0f 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -192,10 +192,11 @@ try { // Square requires HTTPS to work. payments = window.Square.payments( appId, locationId ); - } catch { + } catch ( e ) { const statusContainer = document.querySelector( '.frm-card-errors' ); - statusContainer.className = 'missing-credentials'; + statusContainer.className = 'missing-credentials frm_error'; statusContainer.style.visibility = 'visible'; + statusContainer.textContent = e.message; return; } From 282c4ee27dd376406d3da6c1384ae04cd928d445 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 26 May 2025 14:31:51 -0300 Subject: [PATCH 105/162] Remove mention of live context when showing ssl warning for Square --- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 162adfb8f1..bedc682f21 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -51,7 +51,7 @@ public static function render_settings_container() {
- +
From 7b07b9db6fa0063c89fc49fa545154cb6ef64803 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 09:26:55 -0300 Subject: [PATCH 106/162] Prevent default when clicking connect button --- square/js/settings.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/square/js/settings.js b/square/js/settings.js index 60461afc4e..f45e753f1e 100644 --- a/square/js/settings.js +++ b/square/js/settings.js @@ -1,7 +1,8 @@ ( function() { const buttons = document.querySelectorAll( '.frm-connect-square-with-oauth' ); buttons.forEach( function( button ) { - button.addEventListener( 'click', function() { + button.addEventListener( 'click', function( e ) { + e.preventDefault(); const formData = new FormData(); formData.append( 'mode', button.dataset.mode ); frmDom.ajax.doJsonPost( 'square_oauth', formData ).then( From 2ad9bee87c20a4e18474210bfc36c8887a700431 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 09:41:15 -0300 Subject: [PATCH 107/162] Fix bug with disconnecting Square --- square/js/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/js/settings.js b/square/js/settings.js index f45e753f1e..1b5cf0ccdf 100644 --- a/square/js/settings.js +++ b/square/js/settings.js @@ -24,7 +24,7 @@ event.preventDefault(); const formData = new FormData(); - formData.append( 'mode', event.target.id.replace( 'frm_disconnect_square_', '' ) ); + formData.append( 'testMode', 'test' === event.target.id.replace( 'frm_disconnect_square_', '' ) ? 1 : 0 ); frmDom.ajax.doJsonPost( 'square_disconnect', formData ).then( function( response ) { if ( 'undefined' !== typeof response.success && response.success ) { From b94b25ca4ab8675e30a8d771ba1c5994d8ebd8d0 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 11:55:57 -0300 Subject: [PATCH 108/162] Trigger actions that send on payment success --- square/controllers/FrmSquareLiteActionsController.php | 10 +++++++--- square/controllers/FrmSquareLiteEventsController.php | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 03e37de634..1faebe5182 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -147,13 +147,17 @@ private static function trigger_one_time_payment( $atts ) { return FrmSquareLiteConnectHelper::get_latest_error_from_square_api(); } - $atts['status'] = $result->status === 'COMPLETED' ? 'complete' : 'failed'; - + $atts['status'] = $result->status === 'COMPLETED' ? 'complete' : 'failed'; $atts['charge'] = new stdClass(); $atts['charge']->id = $result->id; $atts['charge']->amount = $atts['amount']; - self::create_new_payment( $atts ); + $payment_id = self::create_new_payment( $atts ); + $frm_payment = new FrmTransLitePayment(); + $payment = $frm_payment->get_one( $payment_id ); + $status = $atts['status']; + + FrmTransLiteActionsController::trigger_payment_status_change( compact( 'status', 'payment' ) ); return true; } diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php index 147214f891..8fe39f66c6 100644 --- a/square/controllers/FrmSquareLiteEventsController.php +++ b/square/controllers/FrmSquareLiteEventsController.php @@ -232,7 +232,7 @@ private function add_subscription_payment( $subscription_id ) { array( 'paysys' => 'square', 'amount' => $payment_object->amount_money->amount / 100, - 'status' => 'pending', + 'status' => 'authorized', 'item_id' => $sub->item_id, 'action_id' => $sub->action_id, 'receipt_id' => $payment_id, From a269ed79f2923458fdc7ef7af5f093c08327656c Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 12:34:56 -0300 Subject: [PATCH 109/162] Add todo comment --- square/controllers/FrmSquareLiteEventsController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php index 8fe39f66c6..0e79d42ae8 100644 --- a/square/controllers/FrmSquareLiteEventsController.php +++ b/square/controllers/FrmSquareLiteEventsController.php @@ -231,6 +231,7 @@ private function add_subscription_payment( $subscription_id ) { $frm_payment->create( array( 'paysys' => 'square', + // TODO Do not divide by 100 for JPY. 'amount' => $payment_object->amount_money->amount / 100, 'status' => 'authorized', 'item_id' => $sub->item_id, From bc743602e604a5f4ad0bd8086348ff52a9b40e14 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 12:38:44 -0300 Subject: [PATCH 110/162] Add JPY check --- square/controllers/FrmSquareLiteEventsController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/square/controllers/FrmSquareLiteEventsController.php b/square/controllers/FrmSquareLiteEventsController.php index 0e79d42ae8..37c9bdde9a 100644 --- a/square/controllers/FrmSquareLiteEventsController.php +++ b/square/controllers/FrmSquareLiteEventsController.php @@ -227,12 +227,18 @@ private function add_subscription_payment( $subscription_id ) { $payment_object = $this->event->data->object->payment; + if ( 'JPY' === $payment_object->amount_money->currency ) { + // Japanese does not include the additional 2 digits. + $amount = $payment_object->amount_money->amount; + } else { + $amount = floatval( $payment_object->amount_money->amount ) / 100; + } + $frm_payment = new FrmTransLitePayment(); $frm_payment->create( array( 'paysys' => 'square', - // TODO Do not divide by 100 for JPY. - 'amount' => $payment_object->amount_money->amount / 100, + 'amount' => $amount, 'status' => 'authorized', 'item_id' => $sub->item_id, 'action_id' => $sub->action_id, From 69185247af66e02f6ad3f3bc6c93bc3833b9b108 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 14:22:28 -0300 Subject: [PATCH 111/162] Stop using dev site, use QA --- square/helpers/FrmSquareLiteConnectHelper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index bedc682f21..e02ecdd4d5 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -219,7 +219,8 @@ private static function validate_response( $response ) { * @return string */ private static function get_url_to_connect_server() { - return 'http://dev-site.local/'; + return 'https://qa.formidableforms.com/mike2/'; + //return 'http://dev-site.local/'; //return 'https://api.strategy11.com/'; } From 5a4761999957c67913f76fe933bd9038914e61e9 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Tue, 27 May 2025 14:34:17 -0300 Subject: [PATCH 112/162] Always include the processor column --- stripe/controllers/FrmTransLiteListsController.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/stripe/controllers/FrmTransLiteListsController.php b/stripe/controllers/FrmTransLiteListsController.php index ed2474c528..d32a4b74e5 100755 --- a/stripe/controllers/FrmTransLiteListsController.php +++ b/stripe/controllers/FrmTransLiteListsController.php @@ -70,13 +70,8 @@ public static function payment_columns( $columns = array() ) { $columns['status'] = esc_html__( 'Status', 'formidable' ); $columns['created_at'] = esc_html__( 'Date', 'formidable' ); - - $paypal_is_active = class_exists( 'FrmPaymentsController', false ); - if ( $paypal_is_active ) { - $columns['paysys'] = esc_html__( 'Processor', 'formidable' ); - } - - $columns['mode'] = esc_html__( 'Mode', 'formidable' ); + $columns['paysys'] = esc_html__( 'Processor', 'formidable' ); + $columns['mode'] = esc_html__( 'Mode', 'formidable' ); return $columns; } From e4401256282c87c096749d98ca2b71bc595cc836 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Wed, 28 May 2025 14:59:31 -0300 Subject: [PATCH 113/162] Stop redirecting to /wp-admin/false on error --- square/controllers/FrmSquareLiteAppController.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteAppController.php b/square/controllers/FrmSquareLiteAppController.php index df04e9f9a9..05d80a70fe 100644 --- a/square/controllers/FrmSquareLiteAppController.php +++ b/square/controllers/FrmSquareLiteAppController.php @@ -39,8 +39,13 @@ public static function handle_oauth() { wp_send_json_error(); } + $redirect_url = FrmSquareLiteConnectHelper::get_oauth_redirect_url(); + if ( false === $redirect_url ) { + wp_send_json_error( 'Unable to connect to Square successfully' ); + } + $response_data = array( - 'redirect_url' => FrmSquareLiteConnectHelper::get_oauth_redirect_url(), + 'redirect_url' => $redirect_url, ); wp_send_json_success( $response_data ); } From 6d52c9487de7fb0e4efe1b1c4e952c56358e8df5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Wed, 28 May 2025 16:39:24 -0300 Subject: [PATCH 114/162] Pass description when creating a one time payment --- square/controllers/FrmSquareLiteActionsController.php | 9 ++++++++- square/helpers/FrmSquareLiteConnectHelper.php | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 1faebe5182..33e4ae7bed 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -141,7 +141,14 @@ private static function trigger_one_time_payment( $atts ) { $currency = strtoupper( $atts['action']->post_content['currency'] ); $square_token = sanitize_text_field( $_POST['square-token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $verification_token = sanitize_text_field( $_POST['square-verification-token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing - $result = FrmSquareLiteConnectHelper::create_payment( $atts['amount'], $currency, $square_token, $verification_token ); + $description = FrmTransLiteAppHelper::process_shortcodes( + array( + 'entry' => $atts['entry'], + 'form' => $atts['entry']->form_id, + 'value' => $atts['action']->post_content['description'], + ) + ); + $result = FrmSquareLiteConnectHelper::create_payment( $atts['amount'], $currency, $square_token, $verification_token, $description ); if ( false === $result ) { return FrmSquareLiteConnectHelper::get_latest_error_from_square_api(); diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index e02ecdd4d5..9c36106c7a 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -468,7 +468,7 @@ private static function check_server_for_oauth_merchant_id() { return false; } - public static function create_payment( $amount, $currency, $square_token, $verification_token ) { + public static function create_payment( $amount, $currency, $square_token, $verification_token, $description ) { return self::post_with_authenticated_body( 'create_payment', array( @@ -476,6 +476,7 @@ public static function create_payment( $amount, $currency, $square_token, $verif 'currency' => $currency, 'square_token' => $square_token, 'verification_token' => $verification_token, + 'description' => $description, ) ); } From d4d3b0f020f6df6815a6b12f406a27c76c94a951 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Fri, 30 May 2025 15:40:30 -0300 Subject: [PATCH 115/162] Work on improving compatibility with the Stripe add-on --- .../FrmSquareLiteActionsController.php | 12 ++++++ square/js/action.js | 38 +++++++++++++++++ .../FrmTransLiteActionsController.php | 2 +- .../FrmTransLiteHooksController.php | 4 +- stripe/helpers/FrmTransLiteAppHelper.php | 41 +++++++++++++++++++ stripe/js/frmtrans_admin.js | 34 ++------------- stripe/models/FrmTransLiteAction.php | 1 - .../action-settings/payments-options.php | 26 +----------- 8 files changed, 100 insertions(+), 58 deletions(-) create mode 100644 square/js/action.js diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 33e4ae7bed..80f7ca75a8 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -560,4 +560,16 @@ public static function remove_cc_validation( $errors, $field, $values ) { return $errors; } + + /** + * @return void + */ + public static function actions_js() { + wp_enqueue_script( + 'frm_square_admin', + FrmSquareLiteAppHelper::plugin_url() . 'js/action.js', + array( 'wp-hooks' ), + FrmAppHelper::plugin_version() + ); + } } diff --git a/square/js/action.js b/square/js/action.js new file mode 100644 index 0000000000..dc82a66c12 --- /dev/null +++ b/square/js/action.js @@ -0,0 +1,38 @@ +( function() { + const hookNamespace = 'formidable-square'; + wp.hooks.addAction( 'frm_trans_toggled_gateway', hookNamespace, onGatewayToggle ); + + function onGatewayToggle( { gateway, settings } ) { + const currencySetting = settings.get( 0 ).querySelector( '[name*="[post_content][currency]"]' ); + if ( ! currencySetting ) { + return; + } + + let option = currencySetting.querySelector( 'option.square-currency' ); + + if ( option ) { + if ( 'square' === gateway ) { + currencySetting.value = option.value; + currencySetting.disabled = true; + } else { + currencySetting.disabled = false; + option.remove(); + } + return; + } + + // Option didn't exist yet, so add it. + if ( 'square' === gateway ) { + option = document.createElement( 'option' ); + option.value = 'square'; + option.textContent = 'Use Square Merchant Currency'; + option.classList.add( 'square-currency' ); + currencySetting.appendChild( option ); + + currencySetting.value = option.value; + currencySetting.disabled = true; + } else { + currencySetting.disabled = false; + } + } +}() ); diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index 075e8aa07b..2a4129a999 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -35,7 +35,7 @@ public static function actions_js() { wp_enqueue_script( 'frmtrans_admin', FrmTransLiteAppHelper::plugin_url() . '/js/frmtrans_admin.js', - array( 'jquery' ), + array( 'jquery', 'wp-hooks' ), FrmAppHelper::plugin_version() ); wp_localize_script( diff --git a/stripe/controllers/FrmTransLiteHooksController.php b/stripe/controllers/FrmTransLiteHooksController.php index 19321a1ccb..9f3e9c36b0 100755 --- a/stripe/controllers/FrmTransLiteHooksController.php +++ b/stripe/controllers/FrmTransLiteHooksController.php @@ -9,8 +9,10 @@ class FrmTransLiteHooksController { * @return void */ public static function load_hooks() { + add_action( 'frm_add_form_option_section', 'FrmSquareLiteActionsController::actions_js' ); + + // Exit early, let the Payments submodule handle everything. if ( class_exists( 'FrmTransHooksController', false ) ) { - // Exit early, let the Payments submodule handle everything. return; } diff --git a/stripe/helpers/FrmTransLiteAppHelper.php b/stripe/helpers/FrmTransLiteAppHelper.php index 1116685add..a0877029e5 100755 --- a/stripe/helpers/FrmTransLiteAppHelper.php +++ b/stripe/helpers/FrmTransLiteAppHelper.php @@ -531,4 +531,45 @@ public static function get_setting_for_gateway( $gateway, $setting ) { } return $value; } + + /** + * Show the currency dropdown for a Payment action. + * When Square is selected, this dropdown is disabled and will always use "Use Square Merchant Currency". + * + * @since x.x + * + * @param string $id + * @param string $name + * @param array $action_settings + */ + public static function show_currency_dropdown( $id, $name, $action_settings ) { + $selected = $action_settings['currency']; + $gateways = (array) $action_settings['gateway']; + $select_attrs = array( + 'id' => $id, + 'name' => $name, + ); + if ( in_array( 'square', $gateways, true ) ) { + $select_attrs['disabled'] = 'disabled'; + $selected = ''; + } + $currencies = FrmCurrencyHelper::get_currencies(); + ?> + + post_content; $form_fields = $this->get_field_options( $args['form']->id ); $field_dropdown_atts = compact( 'form_fields', 'form_action' ); - $currencies = FrmCurrencyHelper::get_currencies(); $repeat_times = FrmTransLiteAppHelper::get_repeat_times(); $gateways = FrmTransLiteAppHelper::get_gateways(); $interval_options = FrmSquareLiteAppHelper::get_repeat_cadence_options(); diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index 0425abf940..52218c86d5 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -89,31 +89,7 @@ - $this->get_field_name( 'currency' ), - 'id' => $this->get_field_id( 'currency' ), - ); - if ( in_array( 'square', (array) $form_action->post_content['gateway'], true ) ) { - $select_attrs['disabled'] = 'disabled'; - } - ?> - + get_field_id( 'currency' ), $this->get_field_name( 'currency' ), $form_action->post_content ); ?>

From 831b6f184f514a3ce8a9c919996f6acbafab4c68 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 12:38:47 -0300 Subject: [PATCH 116/162] Add the functions for verifying a Lite site --- .../FrmSquareLiteHooksController.php | 3 +++ square/helpers/FrmSquareLiteConnectHelper.php | 25 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteHooksController.php b/square/controllers/FrmSquareLiteHooksController.php index b219a8bf06..f5210ab9ac 100644 --- a/square/controllers/FrmSquareLiteHooksController.php +++ b/square/controllers/FrmSquareLiteHooksController.php @@ -45,5 +45,8 @@ private static function load_ajax_hooks() { $frm_square_events_controller = new FrmSquareLiteEventsController(); add_action( 'wp_ajax_nopriv_frm_square_process_events', array( &$frm_square_events_controller, 'process_events' ) ); add_action( 'wp_ajax_frm_square_process_events', array( &$frm_square_events_controller, 'process_events' ) ); + + // Stripe Lite. + add_action( 'wp_ajax_nopriv_frm_square_lite_verify', 'FrmSquareLiteConnectHelper::verify' ); } } diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 9c36106c7a..64e52df7cb 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -142,7 +142,7 @@ public static function get_oauth_redirect_url() { ); // Clear the transient so it doesn't fail. - delete_option( 'frm_square_last_verify_attempt' ); + delete_option( 'frm_square_lite_last_verify_attempt' ); $data = self::post_to_connect_server( 'oauth_request', $additional_body ); if ( is_string( $data ) ) { @@ -677,4 +677,27 @@ public static function get_merchant_currency( $force = false ) { public static function at_least_one_mode_is_setup() { return self::get_merchant_id( 'test' ) || self::get_merchant_id( 'live' ); } + + /** + * Verify a site identifier is a match. + */ + public static function verify() { + $option_name = 'frm_square_lite_last_verify_attempt'; + $last_request = get_option( $option_name ); + + if ( $last_request && $last_request > strtotime( '-1 day' ) ) { + wp_send_json_error( 'Too many requests' ); + } + + $site_identifier = FrmAppHelper::get_post_param( 'site_identifier' ); + $usage = new FrmUsage(); + $uuid = $usage->uuid(); + + update_option( $option_name, time() ); + + if ( $site_identifier === $uuid ) { + wp_send_json_success(); + } + wp_send_json_error(); + } } From e887a03bc8dffe6952f0f7dd1ccaa62f03327002 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 14:47:20 -0300 Subject: [PATCH 117/162] Conditionally toggle the fee education based on the selected gateway --- square/helpers/FrmSquareLiteAppHelper.php | 9 +++++++-- stripe/helpers/FrmStrpLiteAppHelper.php | 9 +++++++-- stripe/views/action-settings/payments-options.php | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/square/helpers/FrmSquareLiteAppHelper.php b/square/helpers/FrmSquareLiteAppHelper.php index 49ad2fdebb..b2593f9af4 100644 --- a/square/helpers/FrmSquareLiteAppHelper.php +++ b/square/helpers/FrmSquareLiteAppHelper.php @@ -80,12 +80,17 @@ public static function get_repeat_cadence_options() { * * @return void */ - public static function fee_education( $medium = 'tip' ) { + public static function fee_education( $medium = 'tip', $gateway = false ) { $license_type = FrmAddonsController::license_type(); if ( in_array( $license_type, array( 'elite', 'business' ), true ) ) { return; } + $classes = 'frm-light-tip show_square'; + if ( $gateway && ! array_intersect( (array) $gateway, array( 'square' ) ) ) { + $classes .= ' frm_hidden'; + } + FrmTipsHelper::show_tip( array( 'link' => array( @@ -94,7 +99,7 @@ public static function fee_education( $medium = 'tip' ) { ), 'tip' => 'Pay as you go pricing: 3% fee per-transaction + Square fees.', 'call' => __( 'Upgrade to save on fees.', 'formidable' ), - 'class' => 'frm-light-tip', + 'class' => $classes, ), 'p' ); diff --git a/stripe/helpers/FrmStrpLiteAppHelper.php b/stripe/helpers/FrmStrpLiteAppHelper.php index 0cabca57d6..4897ffb6bd 100644 --- a/stripe/helpers/FrmStrpLiteAppHelper.php +++ b/stripe/helpers/FrmStrpLiteAppHelper.php @@ -98,12 +98,17 @@ public static function active_mode() { * * @return void */ - public static function fee_education( $medium = 'tip' ) { + public static function fee_education( $medium = 'tip', $gateway = false ) { $license_type = FrmAddonsController::license_type(); if ( in_array( $license_type, array( 'elite', 'business' ), true ) ) { return; } + $classes = 'frm-light-tip show_stripe'; + if ( $gateway && ! array_intersect( (array) $gateway, array( 'stripe' ) ) ) { + $classes .= ' frm_hidden'; + } + FrmTipsHelper::show_tip( array( 'link' => array( @@ -112,7 +117,7 @@ public static function fee_education( $medium = 'tip' ) { ), 'tip' => 'Pay as you go pricing: 3% fee per-transaction + Stripe fees.', 'call' => __( 'Upgrade to save on fees.', 'formidable' ), - 'class' => 'frm-light-tip', + 'class' => $classes, ), 'p' ); diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index 52218c86d5..2939b7eb25 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -7,10 +7,10 @@ $square_connected = FrmSquareLiteConnectHelper::at_least_one_mode_is_setup(); if ( $stripe_connected ) { - FrmStrpLiteAppHelper::fee_education(); + FrmStrpLiteAppHelper::fee_education( 'tip', $form_action->post_content['gateway'] ); } if ( $square_connected ) { - FrmSquareLiteAppHelper::fee_education(); + FrmSquareLiteAppHelper::fee_education( 'tip', $form_action->post_content['gateway'] ); } if ( ! $stripe_connected && ! $square_connected ) { FrmStrpLiteAppHelper::not_connected_warning(); From 63af5e66f85546506e84a728b471fba28a50403e Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 15:51:20 -0300 Subject: [PATCH 118/162] Add more checks before loading Stripe Lite scripts, load the Square scripts the same way Stripe scripts are being loaded --- .../FrmSquareLiteActionsController.php | 13 +++++++++++++ .../controllers/FrmStrpLiteActionsController.php | 15 ++++++++++++++- .../controllers/FrmTransLiteActionsController.php | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 80f7ca75a8..360d04fe18 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -365,6 +365,19 @@ public static function maybe_load_scripts( $params ) { return; } + $found_gateway = false; + foreach ( $payment_actions as $action ) { + $gateways = $action->post_content['gateways']; + if ( in_array( 'square', (array) $gateways, true ) ) { + $found_gateway = true; + break; + } + } + + if ( ! $found_gateway ) { + return; + } + self::load_scripts( (int) $form->id ); } diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index a737a2ab8c..866799ec98 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -424,6 +424,20 @@ public static function load_scripts( $form_id ) { $dependencies[] = 'formidablepro'; } + $action_settings = self::prepare_settings_for_js( $form_id ); + $found_gateway = false; + foreach ( $action_settings as $action ) { + $gateways = $action['gateways']; + if ( ! $gateways || in_array( 'stripe', (array) $gateways, true ) ) { + $found_gateway = true; + break; + } + } + + if ( ! $found_gateway ) { + return; + } + wp_enqueue_script( 'formidable-stripe', $script_url, @@ -432,7 +446,6 @@ public static function load_scripts( $form_id ) { false ); - $action_settings = self::prepare_settings_for_js( $form_id ); $style_settings = self::get_style_settings_for_form( $form_id ); $stripe_vars = array( 'publishable_key' => $publishable, diff --git a/stripe/controllers/FrmTransLiteActionsController.php b/stripe/controllers/FrmTransLiteActionsController.php index 2a4129a999..0efeb6e5c7 100755 --- a/stripe/controllers/FrmTransLiteActionsController.php +++ b/stripe/controllers/FrmTransLiteActionsController.php @@ -451,6 +451,7 @@ public static function hide_gateway_field_on_front_end( $values, $field ) { // With this here, the value of frm_stripe_vars.settings[0].fields is -1 // This is because the amount value is processed and a shortcode is not found in '000'. FrmStrpLiteActionsController::load_scripts( (int) $field->form_id ); + FrmSquareLiteActionsController::load_scripts( (int) $field->form_id ); $values['type'] = 'hidden'; return $values; From ebfb591f830498175d8816705c289c10a997e668 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 15:56:25 -0300 Subject: [PATCH 119/162] Fix square script loading issue --- square/controllers/FrmSquareLiteActionsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 360d04fe18..6d15930da6 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -367,7 +367,7 @@ public static function maybe_load_scripts( $params ) { $found_gateway = false; foreach ( $payment_actions as $action ) { - $gateways = $action->post_content['gateways']; + $gateways = $action->post_content['gateway']; if ( in_array( 'square', (array) $gateways, true ) ) { $found_gateway = true; break; From 3a7cda832177db14d3ab0563dedaab861b17b9fd Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 16:28:11 -0300 Subject: [PATCH 120/162] Improve compatibility with a multi-page form --- square/controllers/FrmSquareLiteActionsController.php | 2 ++ square/js/frontend.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/square/controllers/FrmSquareLiteActionsController.php b/square/controllers/FrmSquareLiteActionsController.php index 6d15930da6..c702fe5368 100644 --- a/square/controllers/FrmSquareLiteActionsController.php +++ b/square/controllers/FrmSquareLiteActionsController.php @@ -48,6 +48,8 @@ public static function show_card( $field, $field_name, $atts ) { $actions = self::get_actions_before_submit( $field['form_id'] ); if ( $actions ) { + self::load_scripts( (int) $field['form_id'] ); + $html_id = $atts['html_id']; include FrmStrpLiteAppHelper::plugin_path() . '/views/payments/card-field.php'; return; diff --git a/square/js/frontend.js b/square/js/frontend.js index a2ea723f0f..7031f38cdb 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -22,6 +22,11 @@ }; async function initializeCard( payments ) { + const cardElement = document.querySelector( '.frm-card-element' ); + if ( ! cardElement ) { + return; + } + const card = await payments.card(); const cardStyle = frmSquareVars.style; await card.attach( '.frm-card-element' ); From 8597bee99cb2237dfc2cf6bab5ac97cd98179d6c Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 16:51:36 -0300 Subject: [PATCH 121/162] Init square on AJAX page change as well --- square/js/frontend.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/square/js/frontend.js b/square/js/frontend.js index 7031f38cdb..90d491262f 100644 --- a/square/js/frontend.js +++ b/square/js/frontend.js @@ -158,11 +158,7 @@ statusContainer.textContent = errorMessage; } - document.addEventListener( 'DOMContentLoaded', async function () { - if ( ! window.Square ) { - throw new Error( 'Square.js failed to load properly' ); - } - + async function squareInit() { // Find the form containing the Square payment element const cardContainer = document.querySelector( '.frm-card-element' ); if ( cardContainer ) { @@ -243,5 +239,17 @@ displayPaymentFailure( e.message ); } } + } + + document.addEventListener( 'DOMContentLoaded', async function () { + if ( ! window.Square ) { + throw new Error( 'Square.js failed to load properly' ); + } + + squareInit(); + + jQuery( document ).on( 'frmPageChanged', function() { + squareInit(); + } ); }); }() ); From dbdee47e45026261962fd7fd979a60a5da3fe7b6 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 17:07:24 -0300 Subject: [PATCH 122/162] Update comment --- square/helpers/FrmSquareLiteConnectHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/helpers/FrmSquareLiteConnectHelper.php b/square/helpers/FrmSquareLiteConnectHelper.php index 64e52df7cb..ab741dc6fb 100644 --- a/square/helpers/FrmSquareLiteConnectHelper.php +++ b/square/helpers/FrmSquareLiteConnectHelper.php @@ -6,7 +6,7 @@ class FrmSquareLiteConnectHelper { /** - * Track the latest error when calling stripe connect. + * Track the latest error when calling the Square API. * * @since x.x * From 74a606bfe59db52ef57325ce6ac605af6b1cd618 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 17:08:30 -0300 Subject: [PATCH 123/162] Fix equals alignment --- stripe/controllers/FrmStrpLiteActionsController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index 866799ec98..88064a7238 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -446,8 +446,8 @@ public static function load_scripts( $form_id ) { false ); - $style_settings = self::get_style_settings_for_form( $form_id ); - $stripe_vars = array( + $style_settings = self::get_style_settings_for_form( $form_id ); + $stripe_vars = array( 'publishable_key' => $publishable, 'form_id' => $form_id, 'nonce' => wp_create_nonce( 'frm_strp_ajax' ), From eb2de31f82ac31dfc093385ab384a7cd235bba31 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 5 Jun 2025 17:11:54 -0300 Subject: [PATCH 124/162] Fix long line issue --- stripe/helpers/FrmTransLiteAppHelper.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/stripe/helpers/FrmTransLiteAppHelper.php b/stripe/helpers/FrmTransLiteAppHelper.php index a0877029e5..d2b1c5ecd2 100755 --- a/stripe/helpers/FrmTransLiteAppHelper.php +++ b/stripe/helpers/FrmTransLiteAppHelper.php @@ -558,8 +558,13 @@ public static function show_currency_dropdown( $id, $name, $action_settings ) { '; + } + } } diff --git a/stripe/controllers/FrmTransLiteHooksController.php b/stripe/controllers/FrmTransLiteHooksController.php index 9f3e9c36b0..6c06c0bd6c 100755 --- a/stripe/controllers/FrmTransLiteHooksController.php +++ b/stripe/controllers/FrmTransLiteHooksController.php @@ -44,6 +44,8 @@ function () { ); if ( class_exists( 'FrmTransHooksController', false ) ) { + add_action( 'frm_pay_show_square_options', 'FrmTransLiteAppController::add_repeat_cadence_value' ); + // Exit early, let the Payments submodule handle everything. return; } diff --git a/stripe/models/FrmTransLiteAction.php b/stripe/models/FrmTransLiteAction.php index 72e4144077..a6c908093e 100755 --- a/stripe/models/FrmTransLiteAction.php +++ b/stripe/models/FrmTransLiteAction.php @@ -36,7 +36,6 @@ public function form( $instance, $args = array() ) { $field_dropdown_atts = compact( 'form_fields', 'form_action' ); $repeat_times = FrmTransLiteAppHelper::get_repeat_times(); $gateways = FrmTransLiteAppHelper::get_gateways(); - $interval_options = FrmSquareLiteAppHelper::get_repeat_cadence_options(); if ( ! isset( $form_action->post_content['payment_limit'] ) ) { $form_action->post_content['payment_limit'] = ''; diff --git a/stripe/views/action-settings/payments-options.php b/stripe/views/action-settings/payments-options.php index 2939b7eb25..968c9fe684 100755 --- a/stripe/views/action-settings/payments-options.php +++ b/stripe/views/action-settings/payments-options.php @@ -51,24 +51,26 @@ - post_content['gateway'], true ) ) { ?> + - + + + - post_content['gateway'], true ) ) { ?> - - -

+

+ + +