PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
← All changes | includes/gateways/class-charitable-gateways.php +1154 -81 1.7.0.12 → 1.8.13 View file →
@@ -3,12 +3,13 @@
3 3 * Class that sets up the gateways.
4 4 *
5 5 * @package Charitable/Classes/Charitable_Gateways
6 6 * @author David Bisset
7 - * @copyright Copyright (c) 2022, WP Charitable LLC
7 + * @copyright Copyright (c) 2023, WP Charitable LLC
8 8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 9 * @since 1.0.0
10 10 * @version 1.6.57
11 + * @version 1.8.7 - Added Square.
11 12 */
12 13
13 14 // Exit if accessed directly.
14 15 if ( ! defined( 'ABSPATH' ) ) {
@@ -51,12 +52,13 @@
51 52 *
52 53 * @since 1.0.0
53 54 */
54 55 protected function __construct() {
55 - add_action( 'init', array( $this, 'check_settings' ) );
56 - add_action( 'init', array( $this, 'register_gateways' ) );
57 - add_action( 'init', array( $this, 'connect_gateways' ), 99 );
58 - add_action( 'init', array( $this, 'disconnect_gateways' ), 99 );
56 + add_action( 'init', array( $this, 'check_settings' ), 10 );
57 + add_action( 'init', array( $this, 'register_gateways' ), 1 );
58 + add_action( 'init', array( $this, 'connect_gateways' ), 99 ); // Stripe.
59 + add_action( 'init', array( $this, 'disconnect_gateways' ), 99 ); // Stripe.
60 +
59 61 add_action( 'charitable_make_default_gateway', array( $this, 'handle_gateway_settings_request' ) );
60 62 add_action( 'charitable_enable_gateway', array( $this, 'handle_gateway_settings_request' ) );
61 63 add_action( 'charitable_disable_gateway', array( $this, 'handle_gateway_settings_request' ) );
62 64 add_filter( 'charitable_settings_fields_gateways_gateway', array( $this, 'register_gateway_settings' ), 10, 2 );
@@ -62,14 +64,32 @@
62 64 add_filter( 'charitable_settings_fields_gateways_gateway', array( $this, 'register_gateway_settings' ), 10, 2 );
63 65
64 66 add_action( 'charitable_disable_gateway', array( $this, 'handle_gateway_settings_request' ) );
65 67
68 + /**
69 + * Square Connect
70 + */
71 + add_action( 'init', array( $this, 'disconnect_gateways_square' ), 99 ); // Square.
72 + add_action( 'init', array( $this, 'refresh_square_token' ), 99 ); // Square.
73 +
74 + add_action( 'init', array( $this, 'get_gateway_error_message' ), 99 );
75 +
66 76 do_action( 'charitable_gateway_start', $this );
67 77
68 - add_action( 'wp_ajax_charitable-show-stripe-keys', array( $this, 'show_stripe_manual_keys_ajax'), 10 );
78 + add_action( 'wp_ajax_charitable-show-stripe-keys', array( $this, 'show_stripe_manual_keys_ajax' ), 10 );
79 + add_action( 'wp_ajax_charitable_switch_square_gateways', array( $this, 'handle_square_gateway_switch' ) );
80 + add_action( 'wp_ajax_charitable_switch_square_core_to_legacy', array( $this, 'handle_square_core_to_legacy_switch' ) );
69 81
82 + // Dequeue Square Legacy scripts if Square Legacy is not active.
83 + add_action( 'wp_enqueue_scripts', array( $this, 'maybe_dequeue_square_legacy_scripts' ), 999 );
84 +
85 + // PayPal Hard Fork (1.8.11): last-word defense against third-party
86 + // callbacks that re-inject the hidden PayPal gateway. Mirrors the
87 + // register_gateways + get_active_gateways strips.
88 + add_filter( 'charitable_active_gateways', array( $this, 'apply_paypal_tier_visibility' ), PHP_INT_MAX );
70 89 }
71 90
91 +
72 92 /**
73 93 * Returns and/or create the single instance of this class.
74 94 *
75 95 * @since 1.2.0
@@ -97,25 +117,90 @@
97 117 public function register_gateways() {
98 118 /**
99 119 * Filter the list of payment gateways.
100 120 *
101 - * @since 1.2.0
121 + * @since 1.2.0
122 + * @version 1.8.7
102 123 *
103 124 * @param array $gateways The list of gateways in gateway ID => gateway class format.
104 125 */
126 +
127 + $gateways = array(
128 + 'stripe' => 'Charitable_Gateway_Stripe_AM',
129 + 'paypal' => 'Charitable_Gateway_Paypal',
130 + 'paypal_commerce' => 'Charitable_Gateway_Paypal_Commerce',
131 + 'offline' => 'Charitable_Gateway_Offline',
132 + );
133 +
134 + // Always add Square Core to the available gateways.
135 + $gateways['square_core'] = 'Charitable_Gateway_Square';
136 +
105 137 $this->gateways = apply_filters(
106 138 'charitable_payment_gateways',
107 - array(
108 - 'stripe' => 'Charitable_Gateway_Stripe_AM',
109 - 'paypal' => 'Charitable_Gateway_Paypal',
110 - 'offline' => 'Charitable_Gateway_Offline',
111 - )
139 + $gateways
112 140 );
113 - $this->gateways['stripe'] = 'Charitable_Gateway_Stripe_AM';
114 141
142 + // PayPal Hard Fork (1.8.11): hide the off-tier PayPal gateway entirely so it
143 + // cannot be enabled, listed in admin, or referenced in active_gateways.
144 + $this->gateways = $this->apply_paypal_tier_visibility( $this->gateways );
145 +
146 + // If Legacy mode is active and Square Legacy gateway is active, deactivate Square Core.
147 + if ( charitable_square_legacy_mode() && $this->is_active_gateway( 'square' ) ) {
148 + $this->disable_gateway( 'square_core' );
149 +
150 + if ( charitable_is_debug( 'square' ) ) {
151 + error_log( '[Charitable Square Core] Deactivated Square Core because Square Legacy is active' ); // phpcs:ignore
152 + }
153 + }
115 154 }
116 155
117 156 /**
157 + * Read the locked PayPal user tier set by the 1.8.11 detection upgrade.
158 + *
159 + * The result is escapable at runtime via the standard `pre_option_*` filter
160 + * (`pre_option_charitable_paypal_user_tier`) since this is a vanilla `get_option`
161 + * read. See `Charitable_Upgrade::detect_paypal_user_tier()` for how the value
162 + * is computed and persisted.
163 + *
164 + * @since 1.8.11
165 + *
166 + * @return string `legacy` or `commerce`. Defaults to `commerce` when unset.
167 + */
168 + public function get_paypal_tier() {
169 + $tier = get_option( 'charitable_paypal_user_tier', 'commerce' );
170 + return ( 'legacy' === $tier ) ? 'legacy' : 'commerce';
171 + }
172 +
173 + /**
174 + * Strip the off-tier PayPal gateway from a gateways map.
175 + *
176 + * `legacy` tier hides `paypal_commerce`. `commerce` tier hides `paypal`.
177 + * Used in three places to layer defense:
178 + * 1. `register_gateways()` — strips before `$this->gateways` is exposed.
179 + * 2. `get_active_gateways()` — inline cleanup mirroring the Square pattern.
180 + * 3. `charitable_active_gateways` filter (PHP_INT_MAX priority) — last word
181 + * against third-party callbacks that re-inject the hidden gateway.
182 + *
183 + * @since 1.8.11
184 + *
185 + * @param array $gateways Map of gateway_id => class_name (or anything keyed by id).
186 + * @return array Same shape, with the off-tier PayPal key removed when present.
187 + */
188 + public function apply_paypal_tier_visibility( $gateways ) {
189 + if ( ! is_array( $gateways ) ) {
190 + return $gateways;
191 + }
192 +
193 + if ( 'legacy' === $this->get_paypal_tier() ) {
194 + unset( $gateways['paypal_commerce'] );
195 + } else {
196 + unset( $gateways['paypal'] );
197 + }
198 +
199 + return $gateways;
200 + }
201 +
202 + /**
118 203 * Receives a request to enable or disable a payment gateway and validates it before passing it off.
119 204 *
120 205 * @since 1.0.0
121 206 *
@@ -121,25 +206,29 @@
121 206 *
122 207 * @return void
123 208 */
124 209 public function handle_gateway_settings_request() {
125 - if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'gateway' ) ) {
126 - wp_die( __( 'Cheatin\' eh?!', 'charitable' ) );
210 + // phpcs:disable WordPress.Security.NonceVerification.Missing
211 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_verify_nonce handles validation
212 + if ( ! isset( $_REQUEST['_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['_nonce'] ), 'gateway' ) ) {
213 + wp_die( __( 'Cheatin\' eh?!', 'charitable' ) ); // phpcs:ignore
127 214 }
128 215
129 - $gateway = isset( $_REQUEST['gateway_id'] ) ? $_REQUEST['gateway_id'] : false;
216 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Gateway ID, sanitized below
217 + $gateway = isset( $_REQUEST['gateway_id'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['gateway_id'] ) ) : false;
218 + // phpcs:enable WordPress.Security.NonceVerification.Missing
130 219
131 220 /* Gateway must be set */
132 221 if ( false === $gateway ) {
133 - wp_die( __( 'Missing gateway.', 'charitable' ) );
222 + wp_die( __( 'Missing gateway.', 'charitable' ) ); // phpcs:ignore
134 223 }
135 224
136 225 /* Validate gateway. */
137 226 if ( ! isset( $this->gateways[ $gateway ] ) ) {
138 - wp_die( __( 'Invalid gateway.', 'charitable' ) );
227 + wp_die( __( 'Invalid gateway.', 'charitable' ) ); // phpcs:ignore
139 228 }
140 229
141 - switch ( $_REQUEST['charitable_action'] ) {
230 + switch ( $_REQUEST['charitable_action'] ) { // phpcs:ignore
142 231 case 'disable_gateway':
143 232 $this->disable_gateway( $gateway );
144 233 break;
145 234 case 'enable_gateway':
@@ -157,11 +246,10 @@
157 246 *
158 247 * @param string $action The action taking place.
159 248 * @param string $gateway_id The gateway ID.
160 249 */
161 - do_action( 'charitable_gateway_settings_request', $_REQUEST['charitable_action'], $gateway );
250 + do_action( 'charitable_gateway_settings_request', $_REQUEST['charitable_action'], $gateway ); // phpcs:ignore
162 251 }
163 -
164 252 }
165 253
166 254 /**
167 255 * Returns all available payment gateways.
@@ -186,8 +274,11 @@
186 274 */
187 275 public function get_active_gateways() {
188 276 $active_gateways = charitable_get_option( 'active_gateways', array() );
189 277
278 + // Force cleanup of 'square' gateway if charitable-square plugin is not active (runs once per 24 hours).
279 + $this->maybe_force_cleanup_square_gateway( $active_gateways );
280 +
190 281 foreach ( $active_gateways as $gateway_id => $gateway_class ) {
191 282 if ( ! class_exists( $gateway_class ) ) {
192 283 unset( $active_gateways[ $gateway_id ] );
193 284 }
@@ -192,8 +283,17 @@
192 283 unset( $active_gateways[ $gateway_id ] );
193 284 }
194 285 }
195 286
287 + // Remove 'square' gateway if charitable-square plugin is not active.
288 + if ( isset( $active_gateways['square'] ) && ! $this->is_square_addon_active() ) {
289 + unset( $active_gateways['square'] );
290 + }
291 +
292 + // PayPal Hard Fork (1.8.11): strip the off-tier PayPal gateway in case both
293 + // were saved into active_gateways (direct DB edit, multisite weirdness, etc.).
294 + $active_gateways = $this->apply_paypal_tier_visibility( $active_gateways );
295 +
196 296 uksort( $active_gateways, array( $this, 'sort_by_default' ) );
197 297
198 298 // force the strip active gateway normally for stripe addon to point to the stripe built into core.
199 299 if ( isset( $active_gateways['stripe'] ) ) {
@@ -222,9 +322,9 @@
222 322 public function get_gateway_choices() {
223 323 $gateways = array();
224 324
225 325 foreach ( $this->get_active_gateways() as $id => $class ) {
226 - $gateway = new $class;
326 + $gateway = new $class();
227 327 $gateways[ $id ] = $gateway->get_label();
228 328 }
229 329
230 330 return $gateways;
@@ -240,9 +340,9 @@
240 340 public function get_active_gateways_names() {
241 341 $gateways = array();
242 342
243 343 foreach ( $this->get_active_gateways() as $id => $class ) {
244 - $gateway = new $class;
344 + $gateway = new $class();
245 345 $gateways[] = $gateway->get_name();
246 346 }
247 347
248 348 return $gateways;
@@ -269,9 +369,9 @@
269 369 * @return Charitable_Gateway|null
270 370 */
271 371 public function get_gateway_object( $gateway ) {
272 372 $class = $this->get_gateway( $gateway );
273 - $object = $class ? new $class : null;
373 + $object = $class ? new $class() : null;
274 374
275 375 /**
276 376 * Filter the gateway object.
277 377 *
@@ -311,12 +411,14 @@
311 411 * @param boolean $valid Whether a gateway is valid.
312 412 * @param string $gateway The gateway ID.
313 413 */
314 414
315 - if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
415 + if ( charitable_is_debug( 'webhook' ) ) {
416 + // phpcs:disable
316 417 error_log( 'is_valid_gateway' );
317 418 error_log( print_r( $gateway, true ) );
318 419 error_log( print_r( $this->gateways, true ) );
420 + // phpcs:enable
319 421 }
320 422
321 423 return apply_filters( 'charitable_is_valid_gateway', array_key_exists( $gateway, $this->gateways ), $gateway );
322 424 }
@@ -387,9 +489,9 @@
387 489 */
388 490 public function all_gateways_support( $feature ) {
389 491 foreach ( $this->get_active_gateways() as $gateway_id => $gateway_class ) {
390 492
391 - $gateway_object = new $gateway_class;
493 + $gateway_object = new $gateway_class();
392 494
393 495 if ( false === $gateway_object->supports( $feature ) ) {
394 496 return false;
395 497 }
@@ -410,9 +512,9 @@
410 512 */
411 513 public function any_gateway_supports( $feature ) {
412 514 foreach ( $this->get_active_gateways() as $gateway_id => $gateway_class ) {
413 515
414 - $gateway_object = new $gateway_class;
516 + $gateway_object = new $gateway_class();
415 517
416 518 if ( true === $gateway_object->supports( $feature ) ) {
417 519 return true;
418 520 }
@@ -525,15 +627,26 @@
525 627 *
526 628 * @since 1.0.0
527 629 *
528 630 * @param string $gateway Gateway ID.
631 + * @param bool $show_update_message Whether to show the update message.
529 632 * @return void
530 633 */
531 - protected function enable_gateway( $gateway ) {
634 + protected function enable_gateway( $gateway, $show_update_message = true ) {
532 635 $settings = get_option( 'charitable_settings' );
533 636
637 + if ( false === $settings || ! is_array( $settings ) ) {
638 + echo 'settings is false';
639 + $settings = array();
640 + }
641 +
534 642 $active_gateways = isset( $settings['active_gateways'] ) ? $settings['active_gateways'] : array();
535 643 $active_gateways[ $gateway ] = $this->gateways[ $gateway ];
644 +
645 + if ( ! isset( $settings['active_gateways'] ) ) {
646 + $settings['active_gateways'] = array();
647 + }
648 +
536 649 $settings['active_gateways'] = $active_gateways;
537 650
538 651 /* If this is the only gateway, make it the default gateway */
539 652 if ( 1 == count( $settings['active_gateways'] ) ) {
@@ -541,9 +654,11 @@
541 654 }
542 655
543 656 update_option( 'charitable_settings', $settings );
544 657
545 - Charitable_Settings::get_instance()->add_update_message( __( 'Gateway enabled', 'charitable' ), 'success' );
658 + if ( $show_update_message ) {
659 + Charitable_Settings::get_instance()->add_update_message( __( 'Gateway enabled', 'charitable' ), 'success' );
660 + }
546 661
547 662 /**
548 663 * Do something when a payment gateway is enabled.
549 664 *
@@ -594,9 +709,10 @@
594 709
595 710 /**
596 711 * Connects to Stripe by saving account information passed back to the plugin.
597 712 *
598 - * @since 4.2.2
713 + * @since 4.2.2
714 + * @version 1.8.9
599 715 *
600 716 * @return void
601 717 */
602 718 public function connect_gateways() {
@@ -606,11 +722,11 @@
606 722 }
607 723
608 724 // Do not need to handle this request, bail.
609 725 if (
610 - ! isset( $_GET['wpcharitable_gateway_connect_completion'] ) ||
611 - 'stripe_connect' !== $_GET['wpcharitable_gateway_connect_completion'] ||
612 - ! isset( $_GET['state'] )
726 + ! isset( $_GET['wpcharitable_gateway_connect_completion'] ) || // phpcs:ignore
727 + 'stripe_connect' !== $_GET['wpcharitable_gateway_connect_completion'] || // phpcs:ignore
728 + ! isset( $_GET['state'] ) // phpcs:ignore
613 729 ) {
614 730 return;
615 731 }
616 732
@@ -618,10 +734,11 @@
618 734 if ( headers_sent() ) {
619 735 return;
620 736 }
621 737
622 - if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
623 - $current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
738 + if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Server variables for URL construction
739 + $current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . wp_unslash( $_SERVER['HTTP_HOST'] ) . wp_unslash( $_SERVER['REQUEST_URI'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Server variables are unslashed and then sanitized via esc_url_raw()
740 + $current_url = esc_url_raw( $current_url ); // phpcs:ignore
624 741 } else {
625 742 $current_url = '';
626 743 }
627 744
@@ -627,9 +744,9 @@
627 744
628 745 $customer_site_url = remove_query_arg(
629 746 array(
630 747 'state',
631 - 'wpcharitable_gateway_connect_completion'
748 + 'wpcharitable_gateway_connect_completion',
632 749 ),
633 750 $current_url
634 751 );
635 752
@@ -634,16 +751,17 @@
634 751 );
635 752
636 753 $wpcharitable_credentials_url = add_query_arg(
637 754 array(
638 - 'live_mode' => (int) ! charitable_get_option( 'test_mode' ), // (int) ! $this->is_test_mode(),
639 - 'state' => sanitize_text_field( $_GET['state'] ),
755 + 'live_mode' => (int) ! charitable_get_option( 'test_mode' ),
756 + 'state' => sanitize_text_field( $_GET['state'] ), // phpcs:ignore
640 757 'customer_site_url' => urlencode( $customer_site_url ),
641 758 ),
642 - 'https://wpcharitable.com/stripe-connect/?wpcharitable_gateway_connect_credentials=stripe_connect' // todo: filter market site url
759 + 'https://wpcharitable.com/stripe-connect/?wpcharitable_gateway_connect_credentials=stripe_connect'
643 760 );
644 761
645 - $response = wp_remote_get( esc_url_raw( $wpcharitable_credentials_url ) ); // add add_filter('https_ssl_verify', '__return_false'); here if testing local
762 + // You might need to add add_filter('https_ssl_verify', '__return_false'); here if testing locally.
763 + $response = wp_remote_get( esc_url_raw( $wpcharitable_credentials_url ) );
646 764
647 765 if (
648 766 is_wp_error( $response ) ||
649 767 200 !== wp_remote_retrieve_response_code( $response )
@@ -648,8 +766,21 @@
648 766 is_wp_error( $response ) ||
649 767 200 !== wp_remote_retrieve_response_code( $response )
650 768 ) {
651 769
770 + // Log error details for debugging.
771 + if ( is_wp_error( $response ) ) {
772 + if ( charitable_is_debug( 'stripe' ) ) {
773 + error_log( 'Charitable Stripe Connect Error: ' . $response->get_error_message() . ' | URL: ' . $wpcharitable_credentials_url ); // phpcs:ignore
774 + }
775 + } else {
776 + $response_code = wp_remote_retrieve_response_code( $response );
777 + $response_body = wp_remote_retrieve_body( $response );
778 + if ( charitable_is_debug( 'stripe' ) ) {
779 + error_log( 'Charitable Stripe Connect Error: HTTP ' . $response_code . ' | URL: ' . $wpcharitable_credentials_url . ' | Response: ' . substr( $response_body, 0, 500 ) ); // phpcs:ignore
780 + }
781 + }
782 +
652 783 $stripe_account_settings_url = add_query_arg(
653 784 array(
654 785 'tab' => 'gateways',
655 786 'page' => 'charitable-settings',
@@ -662,9 +793,9 @@
662 793 sprintf(
663 794 /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
664 795 __(
665 796 'There was an error getting your Stripe credentials. Please %1$stry again%2$s. If you continue to have this problem, please contact support.',
666 - 'stripe'
797 + 'charitable'
667 798 ),
668 799 '<a href="' . esc_url( $stripe_account_settings_url ) . '">',
669 800 '</a>'
670 801 )
@@ -669,9 +800,9 @@
669 800 '</a>'
670 801 )
671 802 );
672 803
673 - wp_die( $message );
804 + wp_die( $message ); // phpcs:ignore
674 805 }
675 806
676 807 $body = wp_remote_retrieve_body( $response );
677 808
@@ -692,25 +823,322 @@
692 823 * @since 3.6.0
693 824 *
694 825 * @param array $data Stripe response data.
695 826 */
696 - do_action( 'wpcharitable_stripe_account_connected', $account_data );
827 + do_action( 'wpcharitable_stripe_account_connected', $account_data ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- This is a legacy hook used by other Charitable code. Changing it would break existing functionality.
697 828
698 - // If you configure Stripe and the offline gateway is the default gateway, after you have connected successfully with Stripe, it should automatically be set as the default gateway.
699 - if ( false === $this->get_default_gateway() || 'offline' === $this->get_default_gateway() ) {
700 - $this->set_default_gateway( 'stripe' );
829 + wp_safe_redirect( esc_url_raw( $customer_site_url ) );
830 + exit;
831 + }
832 +
833 + /**
834 + * Refreshes the Square token.
835 + *
836 + * @since 1.8.7
837 + *
838 + * @return void
839 + */
840 + public function refresh_square_token() {
841 + // Current user cannot handle this request.
842 + if ( ! current_user_can( 'manage_options' ) || charitable_square_legacy_mode() ) {
843 + return;
701 844 }
702 845
703 - wp_redirect( esc_url_raw( $customer_site_url ) );
846 + // Do not need to handle this request, bail.
847 + if (
848 + ! isset( $_GET['wpcharitable_gateway_refresh_token_completion'] ) || // phpcs:ignore
849 + 'square_connect' !== $_GET['wpcharitable_gateway_refresh_token_completion'] || // phpcs:ignore
850 + ! isset( $_GET['state'] ) // phpcs:ignore
851 + ) {
852 + return;
853 + }
854 +
855 + // Unable to redirect, bail.
856 + if ( headers_sent() ) {
857 + return;
858 + }
859 +
860 + if ( charitable_is_debug( 'square' ) ) {
861 + error_log( 'checking for use: refresh_square_token' ); // phpcs:ignore
862 + }
863 +
864 + if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
865 + $current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // phpcs:ignore
866 + } else {
867 + $current_url = '';
868 + }
869 +
870 + $customer_site_url = remove_query_arg(
871 + array(
872 + 'state',
873 + 'wpcharitable_gateway_refresh_token_completion',
874 + 'message',
875 + ),
876 + $current_url
877 + );
878 +
879 + $wpcharitable_credentials_url = add_query_arg(
880 + array(
881 + 'live_mode' => (int) ! charitable_get_option( 'test_mode' ),
882 + 'state' => sanitize_text_field( $_GET['state'] ), // phpcs:ignore
883 + 'code' => 'request_credentials',
884 + 'customer_site_url' => urlencode( $customer_site_url ),
885 + ),
886 + 'https://connect.wpcharitable.com/square-connect/'
887 + );
888 +
889 + $response = wp_remote_get( esc_url_raw( $wpcharitable_credentials_url ) );
890 +
891 + if (
892 + is_wp_error( $response ) ||
893 + 200 !== wp_remote_retrieve_response_code( $response )
894 + ) {
895 +
896 + $square_account_settings_url = add_query_arg(
897 + array(
898 + 'tab' => 'gateways',
899 + 'page' => 'charitable-settings',
900 + 'group' => 'gateways_square_core',
901 + ),
902 + admin_url( 'admin.php' )
903 + );
904 +
905 + $message = wpautop(
906 + sprintf(
907 + /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
908 + __(
909 + 'There was an error getting your Square credentials. Please %1$stry again%2$s. If you continue to have this problem, please contact support.',
910 + 'charitable'
911 + ),
912 + '<a href="' . esc_url( $square_account_settings_url ) . '">',
913 + '</a>'
914 + )
915 + );
916 +
917 + wp_die( $message ); // phpcs:ignore
918 + }
919 +
920 + $body = wp_remote_retrieve_body( $response );
921 +
922 + $body = json_decode( $body, true );
923 +
924 + $account_data = $body['data'];
925 +
926 + $this->save_account_information_square( $account_data );
927 +
928 + // Don't show the success message if we are on the welcome / getting started page (otherwise it's fine).
929 + if ( ! isset( $_GET['page'] ) || 'charitable-getting-started' !== $_GET['page'] ) { // phpcs:ignore
930 + // translators: %s is the mode of the connection.
931 + charitable_get_admin_notices()->add_success( sprintf( __( 'You have reconnected and updated your access token for Square in %s mode.', 'charitable' ), charitable_get_option( 'test_mode' ) ? 'test' : 'live' ) );
932 + }
933 +
934 + // update the option to track that we are using square connect.
935 + // Get the value and update it.
936 + $charitable_using_square_connect = get_option( 'charitable_using_square_connect', array() );
937 + if ( ! is_array( $charitable_using_square_connect ) ) {
938 + $charitable_using_square_connect = array();
939 + }
940 + $charitable_using_square_connect['test'] = time();
941 + update_option( 'charitable_using_square_connect', $charitable_using_square_connect );
942 +
943 + /**
944 + * Allow further processing after reconnecting a Square account.
945 + *
946 + * @since 3.6.0
947 + *
948 + * @param array $data Square response data.
949 + */
950 + do_action( 'wpcharitable_square_token_refreshed', $account_data ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- This is a legacy hook used by other Charitable code. Changing it would break existing functionality.
951 +
952 + wp_safe_redirect( esc_url_raw( $customer_site_url ) );
704 953 exit;
705 954 }
706 955
707 956 /**
957 + * Schedule the Square token renewal cron job.
958 + *
959 + * @since 1.8.7
960 + *
961 + * @param string $mode The mode to schedule the cron for (test/live).
962 + * @return void
963 + */
964 + private function schedule_square_token_renewal_cron( $mode ) {
965 + // Clear any existing cron jobs for this mode.
966 + wp_clear_scheduled_hook( 'charitable_square_token_renewal', array( $mode ) );
967 +
968 + // Schedule the cron job to run every 14 days.
969 + wp_schedule_event( time() + ( 14 * DAY_IN_SECONDS ), '14days', 'charitable_square_token_renewal', array( $mode ) );
970 + }
971 +
972 + /**
973 + * Renew the Square token via cron job.
974 + *
975 + * @since 1.8.7
976 + *
977 + * @param string $mode The mode to renew the token for (test/live).
978 + * @return void
979 + */
980 + public function renew_square_token_cron( $mode ) {
981 + if ( charitable_is_debug( 'square' ) ) {
982 + // phpcs:disable
983 + error_log( 'renew_square_token_cron for test mode: ' . $mode );
984 + // phpcs:enable
985 + }
986 +
987 + // Get the URL to renew the token.
988 + $url = Charitable_Gateway_Square::get_instance()->get_square_renew_token_url( '', true );
989 +
990 + if ( charitable_is_debug( 'square' ) ) {
991 + // phpcs:disable
992 + error_log( 'url: ' . $url );
993 + // phpcs:enable
994 + }
995 +
996 + // Clear both failed and success options.
997 + delete_option( 'wpcharitable_square_failed_token_renewal_' . $mode );
998 + delete_option( 'wpcharitable_square_token_refreshed_' . $mode );
999 +
1000 + if ( empty( $url ) ) {
1001 + update_option( 'wpcharitable_square_failed_token_renewal_' . $mode, time() );
1002 + return;
1003 + }
1004 +
1005 + // Add SSL verification argsget_square_renew_token_url.
1006 + $args = array(
1007 + 'timeout' => 30,
1008 + 'sslverify' => false, // Temporarily disable SSL verification.
1009 + 'headers' => array(
1010 + 'Content-Type' => 'application/json',
1011 + ),
1012 + );
1013 +
1014 + // Make the request to the proxy server.
1015 + $response = wp_remote_get( esc_url_raw( $url ), $args );
1016 +
1017 + if ( charitable_is_debug( 'square' ) ) {
1018 + // phpcs:disable
1019 + error_log( 'response: ' . print_r( $response, true ) );
1020 + // phpcs:enable
1021 + }
1022 +
1023 + if ( is_wp_error( $response ) ) {
1024 + if ( charitable_is_debug( 'square' ) ) {
1025 + // phpcs:disable
1026 + error_log( 'The cron job url has failed with a wp_error: ' . $response->get_error_message() );
1027 + // phpcs:enable
1028 + }
1029 + update_option( 'wpcharitable_square_failed_token_renewal_' . $mode, time() );
1030 + return;
1031 + }
1032 +
1033 + $response_code = wp_remote_retrieve_response_code( $response );
1034 + if ( 200 !== $response_code ) {
1035 + if ( charitable_is_debug( 'square' ) ) {
1036 + // phpcs:disable
1037 + error_log( 'The cron job url has failed with response code: ' . $response_code );
1038 + // phpcs:enable
1039 + }
1040 + update_option( 'wpcharitable_square_failed_token_renewal_' . $mode, time() );
1041 + return;
1042 + }
1043 +
1044 + $body = wp_remote_retrieve_body( $response );
1045 + $data = json_decode( $body, true );
1046 +
1047 + if ( charitable_is_debug( 'square' ) ) {
1048 + // phpcs:disable
1049 + error_log( 'data: ' . print_r( $data, true ) );
1050 + error_log( 'body: ' . print_r( $body, true ) );
1051 + // phpcs:enable
1052 + }
1053 +
1054 + if ( empty( $data ) || ! isset( $data['data'] ) ) {
1055 + if ( charitable_is_debug( 'square' ) ) {
1056 + // phpcs:disable
1057 + error_log( 'The cron job url has failed - no data returned.' );
1058 + // phpcs:enable
1059 + }
1060 + update_option( 'wpcharitable_square_failed_token_renewal_' . $mode, time() );
1061 + return;
1062 + }
1063 +
1064 + // Update the stored tokens.
1065 + $settings = get_option( 'charitable_settings' );
1066 + $settings['gateways_square'][ $mode ]['access_token'] = isset( $data['data']['access_token'] ) ? sanitize_text_field( $data['data']['access_token'] ) : false;
1067 + $settings['gateways_square'][ $mode ]['refresh_token'] = isset( $data['data']['refresh_token'] ) ? sanitize_text_field( $data['data']['refresh_token'] ) : false;
1068 + $settings['gateways_square'][ $mode ]['token_refresh_date'] = time();
1069 +
1070 + update_option( 'charitable_settings', $settings );
1071 +
1072 + // Clear any failure notices.
1073 + delete_option( 'wpcharitable_square_failed_token_renewal_' . $mode );
1074 +
1075 + // Add a success notice.
1076 + update_option( 'wpcharitable_square_token_refreshed_' . $mode, time() );
1077 +
1078 + if ( charitable_is_debug( 'square' ) ) {
1079 + // phpcs:disable
1080 + error_log( 'wpcharitable_square_token_refreshed_' . $mode . ' updated to: ' . time() );
1081 + // phpcs:enable
1082 + }
1083 + }
1084 +
1085 + /**
1086 + * Saves the account information sent back from Square, alongside other, to identify the connected account.
1087 + *
1088 + * @since 1.8.7
1089 + *
1090 + * @param array<string> $data Square oAuth account data.
1091 + * @param string $gateway_id The gateway ID.
1092 + * @return void
1093 + */
1094 + private function save_account_information_square( $data, $gateway_id = 'square' ) {
1095 + if ( charitable_is_debug( 'square' ) ) {
1096 + // phpcs:disable
1097 + error_log( 'save_account_information_square' );
1098 + error_log( print_r( $data, true ) );
1099 + // phpcs:enable
1100 + }
1101 +
1102 + $mode = $this->in_test_mode()
1103 + ? 'test'
1104 + : 'live';
1105 +
1106 + $settings = get_option( 'charitable_settings' );
1107 +
1108 + $settings[ 'gateways_' . $gateway_id ][ $mode ]['access_token'] = isset( $data['access_token'] ) ? sanitize_text_field( $data['access_token'] ) : false;
1109 + $settings[ 'gateways_' . $gateway_id ][ $mode ]['refresh_token'] = isset( $data['refresh_token'] ) ? sanitize_text_field( $data['refresh_token'] ) : false;
1110 + $settings[ 'gateways_' . $gateway_id ][ $mode ]['merchant_id'] = isset( $data['merchant_id'] ) ? sanitize_text_field( $data['merchant_id'] ) : false;
1111 + $settings[ 'gateways_' . $gateway_id ][ $mode ]['location_id'] = isset( $data['location_id'] ) ? sanitize_text_field( $data['location_id'] ) : false;
1112 + $settings[ 'gateways_' . $gateway_id ][ $mode ]['token_refresh_date'] = time();
1113 +
1114 + update_option( 'charitable_settings', $settings );
1115 +
1116 + // We save the AES key in it's own WordPress options field, marked as 'charitable_square_aes_key_test' or 'charitable_square_aes_key_live'.
1117 + $aes_key = isset( $data['aes_key'] ) ? sanitize_text_field( $data['aes_key'] ) : false;
1118 +
1119 + if ( charitable_is_debug( 'square' ) ) {
1120 + // phpcs:disable
1121 + error_log( 'aes_key: ' . $aes_key );
1122 + // phpcs:enable
1123 + }
1124 +
1125 + update_option( 'charitable_square_aes_key_' . $mode, $aes_key );
1126 +
1127 + // Schedule the token renewal cron job.
1128 + $this->schedule_square_token_renewal_cron( $mode );
1129 +
1130 + do_action( 'charitable_save_account_information_gateway_' . $gateway_id, $settings, $data, $gateway_id );
1131 + }
1132 +
1133 + /**
708 1134 * Saves the account information sent back from Stripe, alongside other, to identify the connected account.
709 1135 *
710 1136 * @since 4.4.2
1137 + * @version 1.8.1.12
711 1138 *
712 1139 * @param array<string> $data Stripe oAuth account data.
1140 + * @param string $gateway_id The gateway ID.
713 1141 * @return void
714 1142 */
715 1143 private function save_account_information( $data, $gateway_id = 'stripe' ) {
716 1144
@@ -719,27 +1147,31 @@
719 1147 : 'live';
720 1148
721 1149 $settings = get_option( 'charitable_settings' );
722 1150
723 - $settings['gateways_' . $gateway_id ]['live_secret_key'] = '';
724 - $settings['gateways_' . $gateway_id ]['live_public_key'] = '';
725 - $settings['gateways_' . $gateway_id ]['test_secret_key'] = '';
726 - $settings['gateways_' . $gateway_id ]['test_public_key'] = '';
1151 + $settings[ 'gateways_' . $gateway_id ]['live_secret_key'] = '';
1152 + $settings[ 'gateways_' . $gateway_id ]['live_public_key'] = '';
1153 + $settings[ 'gateways_' . $gateway_id ]['test_secret_key'] = '';
1154 + $settings[ 'gateways_' . $gateway_id ]['test_public_key'] = '';
727 1155
728 - $settings['gateways_' . $gateway_id ][ $prefix . '_secret_key' ] = isset( $data['secret_key'] ) ? sanitize_text_field( $data['secret_key'] ) : false;
729 - $settings['gateways_' . $gateway_id ][ $prefix . '_public_key' ] = isset( $data['publishable_key'] ) ? sanitize_text_field( $data['publishable_key'] ) : false;
1156 + $settings[ 'gateways_' . $gateway_id ][ $prefix . '_secret_key' ] = isset( $data['secret_key'] ) ? sanitize_text_field( $data['secret_key'] ) : false;
1157 + $settings[ 'gateways_' . $gateway_id ][ $prefix . '_public_key' ] = isset( $data['publishable_key'] ) ? sanitize_text_field( $data['publishable_key'] ) : false;
730 1158
731 - if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
1159 + if ( charitable_is_debug( 'webhook' ) ) {
1160 + // phpcs:disable
732 1161 error_log( 'save_account_information' );
733 1162 error_log( print_r( $settings, true ) );
1163 + // phpcs:enable
734 1164 }
735 1165
736 1166 update_option( 'charitable_settings', $settings );
737 1167
738 - charitable_get_admin_notices()->add_success( __( 'Stripe Information Updated', 'charitable' ) );
1168 + // Don't show the success message if we are on the welcome / getting started page (otherwise it's fine).
1169 + if ( ! isset( $_GET['page'] ) || 'charitable-getting-started' !== $_GET['page'] ) { // phpcs:ignore
1170 + charitable_get_admin_notices()->add_success( __( 'Stripe Information Updated', 'charitable' ) );
1171 + }
739 1172
740 1173 do_action( 'charitable_save_account_information_gateway_' . $gateway_id, $settings, $data, $gateway_id );
741 -
742 1174 }
743 1175
744 1176 /**
745 1177 * Disconnects from Stripe by removing associated account information.
@@ -764,23 +1196,25 @@
764 1196 if ( ! current_user_can( 'manage_options' ) ) {
765 1197 return;
766 1198 }
767 1199
1200 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display/routing parameter
768 1201 if ( ! isset( $_GET['_wpnonce'] ) ) {
769 1202 return;
770 1203 }
771 1204
772 1205 // Invalid nonce, bail.
773 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'wpcharitable-stripe-connect-disconnect' ) ) {
1206 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_verify_nonce handles validation
1207 + if ( ! wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'wpcharitable-stripe-connect-disconnect' ) ) {
774 1208 return;
775 1209 }
776 1210
777 1211 $settings = get_option( 'charitable_settings' );
778 1212
779 - unset( $settings['gateways_stripe'][ 'live_secret_key' ] );
780 - unset( $settings['gateways_stripe'][ 'live_public_key' ] );
781 - unset( $settings['gateways_stripe'][ 'test_secret_key' ] );
782 - unset( $settings['gateways_stripe'][ 'test_public_key' ] );
1213 + unset( $settings['gateways_stripe']['live_secret_key'] );
1214 + unset( $settings['gateways_stripe']['live_public_key'] );
1215 + unset( $settings['gateways_stripe']['test_secret_key'] );
1216 + unset( $settings['gateways_stripe']['test_public_key'] );
783 1217
784 1218 update_option( 'charitable_settings', $settings );
785 1219
786 1220 // update the option to track that we are using stripe connect.
@@ -800,9 +1234,84 @@
800 1234 );
801 1235
802 1236 wp_safe_redirect( $redirect_url );
803 1237 exit;
1238 + }
804 1239
1240 + /**
1241 + * Disconnects from Square by removing associated account information.
1242 + * Also remove webhooks from the Square account.
1243 + *
1244 + * This does not deauthorize the application within the Square account.
1245 + * LEGIT BEING CALLED.
1246 + *
1247 + * @since 1.8.7
1248 + *
1249 + * @return void
1250 + */
1251 + public function disconnect_gateways_square() {
1252 +
1253 + // Do not need to handle this request, bail.
1254 + if (
1255 + ! ( isset( $_GET['page'] ) && 'charitable-settings' === $_GET['page'] ) ||
1256 + ! isset( $_GET['wpcharitable-square-disconnect'] ) ||
1257 + charitable_square_legacy_mode()
1258 + ) {
1259 + return;
1260 + }
1261 +
1262 + // We need to know if this is a sandbox or live disconnect.
1263 + if ( ! isset( $_GET['mode'] ) ) {
1264 + return;
1265 + }
1266 +
1267 + $mode = sanitize_text_field( wp_unslash( $_GET['mode'] ) );
1268 + $mode = 'sandbox' === $mode ? 'test' : 'live';
1269 +
1270 + // Current user cannot handle this request or nonce is invalid.
1271 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_verify_nonce handles validation
1272 + if ( ! current_user_can( 'manage_options' ) || ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'wpcharitable-square-connect-disconnect' ) ) {
1273 + if ( charitable_is_debug( 'webhook' ) ) {
1274 + error_log( 'disconnect_gateways_square - user cannot manage options or nonce is invalid' ); // phpcs:ignore
1275 + }
1276 + return;
1277 + }
1278 +
1279 + $settings = get_option( 'charitable_settings' );
1280 +
1281 + // Delete the Square connection error notice.
1282 + delete_option( 'charitable_square_connection_error_notice' );
1283 +
1284 + // Attempt to disconnect / remove webhooks from the Square account.
1285 + $this->remove_webhooks_from_square_account( $mode, $settings );
1286 +
1287 + $settings['gateways_square'][ $mode ] = array();
1288 +
1289 + update_option( 'charitable_settings', $settings );
1290 +
1291 + // remove the option to track that we are using square connect (test or live).
1292 + $charitable_using_square_connect = get_option( 'charitable_using_square_connect', array() );
1293 + if ( isset( $charitable_using_square_connect[ $mode ] ) ) {
1294 + unset( $charitable_using_square_connect[ $mode ] );
1295 + update_option( 'charitable_using_square_connect', $charitable_using_square_connect );
1296 + }
1297 +
1298 + // translators: %s is the mode of the connection.
1299 + charitable_get_admin_notices()->add_success( sprintf( __( 'Your connection to Square in %s mode has been removed.', 'charitable' ), $mode ) );
1300 +
1301 + do_action( 'charitable_remove_connection_gateway_square', $settings );
1302 +
1303 + $redirect_url = add_query_arg(
1304 + array(
1305 + 'tab' => 'gateways',
1306 + 'page' => 'charitable-settings',
1307 + 'group' => 'gateways_square_core',
1308 + ),
1309 + admin_url( 'admin.php' )
1310 + );
1311 +
1312 + wp_safe_redirect( $redirect_url );
1313 + exit;
805 1314 }
806 1315
807 1316 /**
808 1317 * Redirects to the gateway settings page once a gateway has been activated.
@@ -813,11 +1322,14 @@
813 1322 * @return void
814 1323 */
815 1324 public function redirect_gateway_settings( $gateway ) {
816 1325
817 - $settings_url = add_query_arg( array(
818 - 'group' => 'gateways_' . $gateway,
819 - ), admin_url( 'admin.php?page=charitable-settings&tab=gateways' ) );
1326 + $settings_url = add_query_arg(
1327 + array(
1328 + 'group' => 'gateways_' . $gateway,
1329 + ),
1330 + admin_url( 'admin.php?page=charitable-settings&tab=gateways' )
1331 + );
820 1332
821 1333 wp_safe_redirect( $settings_url );
822 1334 exit;
823 1335 }
@@ -833,13 +1345,13 @@
833 1345 */
834 1346 protected function sort_by_default( $a, $b ) {
835 1347 $default = $this->get_default_gateway();
836 1348
837 - if ( $a == $default ) {
1349 + if ( $a == $default ) { // phpcs:ignore
838 1350 return -1;
839 1351 }
840 1352
841 - if ( $b == $default ) {
1353 + if ( $b == $default ) { // phpcs:ignore
842 1354 return 1;
843 1355 }
844 1356
845 1357 return 0;
@@ -845,16 +1357,67 @@
845 1357 return 0;
846 1358 }
847 1359
848 1360 /**
1361 + * Remove webhooks from the Square account.
1362 + *
1363 + * @since 1.8.7
1364 + *
1365 + * @param string $mode The mode to remove the webhooks from.
1366 + * @param array $settings The settings array.
1367 + * @param bool $force_remove Whether to force remove the webhooks.
1368 + * @return void
1369 + */
1370 + public function remove_webhooks_from_square_account( $mode, $settings = array(), $force_remove = true ) {
1371 +
1372 + if ( charitable_is_debug( 'square' ) ) {
1373 + error_log( 'remove_webhooks_from_square_account' ); // phpcs:ignore
1374 + }
1375 +
1376 + // Check if settings are empty and if so, get the settings from the database.
1377 + if ( empty( $settings ) ) {
1378 + $settings = get_option( 'charitable_settings' );
1379 + }
1380 +
1381 + $access_token = $settings['gateways_square'][ $mode ]['access_token'];
1382 +
1383 + // Test to see if we have the access token.
1384 + if ( empty( $access_token ) ) {
1385 + // if force_remove is true, we can remove the webhooks from the Square account in Charitable.
1386 + if ( $force_remove ) {
1387 + if ( charitable_is_debug( 'square' ) ) {
1388 + error_log( 'remove_webhooks_from_square_account:force_remove' ); // phpcs:ignore
1389 + }
1390 + $settings['gateways_square'][ $mode ]['webhooks'] = array();
1391 + update_option( 'charitable_settings', $settings );
1392 + return;
1393 +
1394 + }
1395 + return;
1396 + } elseif ( isset( $settings['gateways_square'][ $mode ]['webhook_id'] ) ) {
1397 + $webhook_manager = new Charitable_Square_WebhooksManager( $mode, $access_token );
1398 + $result = $webhook_manager->remove_webhook( $access_token, $settings['gateways_square'][ $mode ]['webhook_id'] );
1399 +
1400 + }
1401 +
1402 + if ( charitable_is_debug( 'square' ) ) {
1403 + error_log( 'remove_webhooks_from_square_account:deactivate_webhook' ); // phpcs:ignore
1404 + }
1405 +
1406 + return $result;
1407 + }
1408 +
1409 + /**
849 1410 * Ensure there is a settings option when landing on settings pages, even if init blank. Mostly applicable to new installs.
850 1411 *
851 1412 * @since 1.4.0
1413 + * @since 1.8.1.11
852 1414 *
1415 + * @return void
853 1416 */
854 1417 public function check_settings() {
855 1418
856 - if ( isset( $_GET['page'] ) && 'charitable-settings' !== $_GET['page'] ) {
1419 + if ( isset( $_GET['page'] ) && 'charitable-settings' !== $_GET['page'] ) { // phpcs:ignore
857 1420 return;
858 1421 }
859 1422
860 1423 $settings = get_option( 'charitable_settings' );
@@ -859,35 +1422,101 @@
859 1422
860 1423 $settings = get_option( 'charitable_settings' );
861 1424
862 1425 // attach this to CHARITABLE_DEBUG constant.
863 - if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG && defined( 'CHARITABLE_DEBUG_SETTINGS' ) && CHARITABLE_DEBUG_SETTINGS ) {
864 - error_log( 'checking_settings');
865 - error_log( print_r( $settings, true ) );
1426 + if ( charitable_is_debug() ) {
1427 + // phpcs:disable
1428 + // error_log( 'checking_settings' );
1429 + // error_log( print_r( $settings, true ) );
1430 + // phpcs:enable
866 1431 }
867 1432
868 - if ( false === $settings ||( is_array( $settings ) && empty( $settings ) ) ) {
869 - $settings_blank_slate = array( 'default_gateway' => 'stripe' ); // settings are brand new and include setting the default gateway
870 - update_option( 'charitable_settings', $settings_blank_slate );
1433 + // If there is no settings, or the settings are empty, set the test mode to true and stripe is default gateway.
1434 + if ( false === $settings || ( is_array( $settings ) && empty( $settings ) ) ) {
1435 + $this->enable_gateway( 'stripe', false );
1436 + $settings = (array) get_option( 'charitable_settings' );
1437 + $settings['test_mode'] = true;
1438 + update_option( 'charitable_settings', $settings );
871 1439 }
1440 + }
872 1441
1442 + /**
1443 + * Check the setup stored value of the payment methods.
1444 + *
1445 + * @since 1.8.4
1446 + *
1447 + * @return bool
1448 + */
1449 + public function check_setup_payment_methods() {
1450 +
1451 + $payment_methods = get_option( 'charitable_setup_payment_methods', array() );
1452 +
1453 + if ( ! is_array( $payment_methods ) ) {
1454 + return false;
1455 + }
1456 +
1457 + $payment_methods = array_map( 'sanitize_text_field', $payment_methods );
1458 +
1459 + if ( empty( $payment_methods ) ) {
1460 + return false;
1461 + }
1462 +
1463 + $gateways_enbled = 0;
1464 +
1465 + if ( in_array( 'stripe', $payment_methods, true ) ) {
1466 + // check if this gateway is already enabled.
1467 + if ( ! $this->is_active_gateway( 'stripe' ) ) {
1468 + $this->enable_gateway( 'stripe', false );
1469 + ++$gateways_enbled;
1470 + }
1471 + }
1472 +
1473 + if ( in_array( 'paypal', $payment_methods, true ) ) {
1474 + // check if this gateway is already enabled.
1475 + if ( ! $this->is_active_gateway( 'paypal' ) ) {
1476 + $this->enable_gateway( 'paypal', false );
1477 + ++$gateways_enbled;
1478 + }
1479 + }
1480 +
1481 + if ( in_array( 'offline', $payment_methods, true ) ) {
1482 + // check if this gateway is already enabled.
1483 + if ( ! $this->is_active_gateway( 'offline' ) ) {
1484 + $this->enable_gateway( 'offline', false );
1485 + }
1486 + }
1487 +
1488 + if ( $gateways_enbled > 0 && class_exists( 'Charitable_Checklist' ) ) {
1489 + $checklist_class = Charitable_Checklist::get_instance();
1490 + $checklist_class->mark_step_completed( 'connect-payment' );
1491 + }
1492 +
1493 + return true;
873 1494 }
874 1495
875 -
876 1496 /**
877 1497 * Display the test and live fields that represent the manual keys for Stripe that users might be already using prior to 1.7.0.
878 1498 *
879 1499 * @since 1.7.0
880 - *
881 1500 */
882 1501 public function show_stripe_manual_keys_ajax() {
883 1502
884 - if ( ! isset( $_POST ) || 'charitable-show-stripe-keys' !== $_POST['action'] ) {
1503 + if ( ! isset( $_POST ) || 'charitable-show-stripe-keys' !== $_POST['action'] ) { // phpcs:ignore
885 1504 return;
886 1505 }
887 1506
888 - $settings = get_option( 'charitable_settings' );
1507 + // Invalid nonce, bail.
1508 + if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'charitable-show-stripe-keys' ) ) { // phpcs:ignore
1509 + return;
1510 + }
889 1511
1512 + // Current user cannot handle this request.
1513 + if ( ! current_user_can( 'manage_options' ) ) {
1514 + return;
1515 + }
1516 +
1517 + $settings = get_option( 'charitable_settings' );
1518 +
890 1519 if ( false === $settings ) {
891 1520 return;
892 1521 }
893 1522
@@ -892,12 +1521,12 @@
892 1521 }
893 1522
894 1523 $gateway_id = 'stripe';
895 1524
896 - $live_secret_key = $settings['gateways_' . $gateway_id ][ 'live_secret_key' ];
897 - $live_public_key = $settings['gateways_' . $gateway_id ][ 'live_public_key' ];
898 - $test_secret_key = $settings['gateways_' . $gateway_id ][ 'test_secret_key' ];
899 - $test_public_key = $settings['gateways_' . $gateway_id ][ 'test_public_key' ];
1525 + $live_secret_key = $settings[ 'gateways_' . $gateway_id ]['live_secret_key'];
1526 + $live_public_key = $settings[ 'gateways_' . $gateway_id ]['live_public_key'];
1527 + $test_secret_key = $settings[ 'gateways_' . $gateway_id ]['test_secret_key'];
1528 + $test_public_key = $settings[ 'gateways_' . $gateway_id ]['test_public_key'];
900 1529
901 1530 $html = '<tr><th scope="row">Live Settings</th><td><hr />
902 1531 </td></tr><tr class="wide"><th scope="row">Live Secret Key</th><td><input type="text"
903 1532 id="charitable_settings_gateways_stripe_live_secret_key"
@@ -926,11 +1555,455 @@
926 1555 />
927 1556 </td></tr>';
928 1557
929 1558 wp_send_json_success( $html );
1559 + }
930 1560
1561 + /**
1562 + * Returns the error message for the square connect gateway.
1563 + *
1564 + * @since 1.8.7
1565 + *
1566 + * @return void
1567 + */
1568 + public function get_gateway_error_message() {
1569 +
1570 + if ( ! isset( $_GET['square_connect_error'] ) && ! isset( $_GET['square_connect_error_description'] ) ) { // phpcs:ignore
1571 + return;
1572 + }
1573 +
1574 + $square_connect_error = sanitize_text_field( wp_unslash( $_GET['square_connect_error'] ) ); // phpcs:ignore
1575 + $square_connect_error_description = sanitize_text_field( wp_unslash( $_GET['square_connect_error_description'] ) ); // phpcs:ignore
1576 + $support_link = 'https://wpcharitable.com/support';
1577 +
1578 + switch ( $square_connect_error ) {
1579 + case 'access_denied':
1580 + switch ( $square_connect_error_description ) {
1581 + case 'user_denied':
1582 + $message = __( 'You have denied access to Square Connect.', 'charitable' );
1583 + break;
1584 + case 'missing_state_or_code':
1585 + $message = sprintf(
1586 + /* translators: %s: Support link URL */
1587 + __( 'There has been an issue with your request. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1588 + $support_link
1589 + );
1590 + break;
1591 + case 'missing_init_request':
1592 + $message = sprintf(
1593 + /* translators: %s: Support link URL */
1594 + __( 'There has been an issue confirming your request. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1595 + $support_link
1596 + );
1597 + break;
1598 + default:
1599 + $message = sprintf(
1600 + /* translators: %s: Support link URL */
1601 + __( 'Your connect to Square has been canceled for an unknown reason. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1602 + $support_link
1603 + );
1604 + break;
1605 + }
1606 + break;
1607 + case 'connect_error':
1608 + switch ( $square_connect_error_description ) {
1609 + case 'error_refreshing_token':
1610 + $refresh_by_date = Charitable_Gateway_Square::get_instance()->get_personal_access_token_should_refresh( 'test' );
1611 + $message = sprintf(
1612 + /* translators: %s: Refresh by date */
1613 + __( 'There has been an issue refreshing your Square token. Token should be refreshed by: %1$s. Please try again or <a href="%2$s">contact support</a>.', 'charitable' ),
1614 + $refresh_by_date,
1615 + $support_link
1616 + );
1617 + break;
1618 + case 'missing_response_fields':
1619 + case 'credentials_not_saved':
1620 + $message = sprintf(
1621 + /* translators: %s: Support link URL */
1622 + __( 'There has been an issue confirming your Square token. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1623 + $support_link
1624 + );
1625 + break;
1626 + case 'response_error':
1627 + case 'merchant_id_not_found':
1628 + case 'save_credentials_error':
1629 + case 'missing_state_or_code':
1630 + case 'invalid_request':
1631 + case 'error_getting_credentials':
1632 + case 'missing_state_or_site_url':
1633 + case 'error_getting_credentials':
1634 + case 'missing_information_for_gateway_connect':
1635 + case 'error_saving_init_request':
1636 + $message = sprintf(
1637 + /* translators: %s: Support link URL */
1638 + __( 'There has been an issue communicating with Square. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1639 + $support_link
1640 + );
1641 + break;
1642 + default:
1643 + $message = sprintf(
1644 + /* translators: %s: Support link URL */
1645 + __( 'There has been an issue with your request. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1646 + $support_link
1647 + );
1648 + break;
1649 + }
1650 + break;
1651 + default:
1652 + $message = sprintf(
1653 + /* translators: %s: Support link URL */
1654 + __( 'There has been an issue with your request. Please try again or <a href="%s">contact support</a>.', 'charitable' ),
1655 + $support_link
1656 + );
1657 + }
1658 +
1659 + charitable_get_admin_notices()->add_notice( $message, 'error', false, true );
931 1660 }
932 1661
1662 + /**
1663 + * Get the personal access refresh token.
1664 + *
1665 + * @since 1.8.7
1666 + *
1667 + * @param string $mode The mode to get the personal access refresh token for.
1668 + * @return string
1669 + */
1670 + private function get_personal_access_refresh_token( $mode = 'test' ) {
1671 + $square_settings = charitable_get_option( 'gateways_square', array() );
933 1672
1673 + if ( ! empty( $square_settings[ $mode ]['refresh_token'] ) ) {
1674 + return $square_settings[ $mode ]['refresh_token'];
1675 + }
1676 +
1677 + return '';
1678 + }
1679 +
1680 + /**
1681 + * Add custom cron schedules.
1682 + *
1683 + * @since 1.8.7
1684 + *
1685 + * @param array $schedules Existing cron schedules.
1686 + * @return array
1687 + */
1688 + public function add_cron_schedules( $schedules ) {
1689 + $schedules['14days'] = array(
1690 + 'interval' => 14 * DAY_IN_SECONDS,
1691 + 'display' => __( 'Every 14 days', 'charitable' ),
1692 + );
1693 + return $schedules;
1694 + }
1695 +
1696 + /**
1697 + * Handle Square gateway switch.
1698 + *
1699 + * @since 1.8.7
1700 + * @version 1.8.9.1
1701 + *
1702 + * @return void
1703 + */
1704 + public function handle_square_gateway_switch() {
1705 + // phpcs:disable WordPress.Security.NonceVerification.Missing
1706 + // Verify nonce.
1707 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_verify_nonce handles validation
1708 + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'charitable_admin_nonce' ) ) {
1709 + wp_send_json_error( array( 'message' => __( 'Security check failed.', 'charitable' ) ) );
1710 + }
1711 + // phpcs:enable WordPress.Security.NonceVerification.Missing
1712 +
1713 + // Check user permissions.
1714 + if ( ! current_user_can( 'manage_options' ) ) {
1715 + wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'charitable' ) ) );
1716 + }
1717 +
1718 + // Check if Square Legacy is active and Square Core is not active.
1719 + if ( ! $this->is_active_gateway( 'square' ) || $this->is_active_gateway( 'square_core' ) ) {
1720 + wp_send_json_error( array( 'message' => __( 'Invalid gateway state for switching.', 'charitable' ) ) );
1721 + }
1722 +
1723 + // Disable Square Legacy.
1724 + $this->disable_gateway( 'square' );
1725 +
1726 + // Enable Square Core.
1727 + $this->enable_gateway( 'square_core', false );
1728 +
1729 + // Get the redirect URL for Square Core settings.
1730 + $redirect_url = add_query_arg(
1731 + array(
1732 + 'page' => 'charitable-settings',
1733 + 'tab' => 'gateways',
1734 + 'group' => 'gateways_square_core',
1735 + ),
1736 + admin_url( 'admin.php' )
1737 + );
1738 +
1739 + wp_send_json_success( array( 'redirect_url' => $redirect_url ) );
1740 + }
1741 +
1742 + /**
1743 + * Handle Square core to legacy switch.
1744 + *
1745 + * @since 1.8.7
1746 + * @version 1.8.9.1
1747 + *
1748 + * @return void
1749 + */
1750 + public function handle_square_core_to_legacy_switch() {
1751 + // phpcs:disable WordPress.Security.NonceVerification.Missing
1752 + // Verify nonce.
1753 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_verify_nonce handles validation
1754 + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'charitable_admin_nonce' ) ) {
1755 + wp_send_json_error( array( 'message' => __( 'Security check failed.', 'charitable' ) ) );
1756 + }
1757 + // phpcs:enable WordPress.Security.NonceVerification.Missing
1758 +
1759 + // Check user permissions.
1760 + if ( ! current_user_can( 'manage_options' ) ) {
1761 + wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'charitable' ) ) );
1762 + }
1763 +
1764 + // Check if Square Core is active and Square Legacy is not active.
1765 + if ( ! $this->is_active_gateway( 'square_core' ) || $this->is_active_gateway( 'square' ) ) {
1766 + wp_send_json_error( array( 'message' => __( 'Invalid gateway state for switching.', 'charitable' ) ) );
1767 + }
1768 +
1769 + if ( charitable_is_debug() ) {
1770 + error_log( 'Charitable: Starting Square Core to Legacy gateway switch process.' ); // phpcs:ignore
1771 + }
1772 +
1773 + // Disconnect Square Core connections for both live and test modes.
1774 + $this->disconnect_square_core_connections();
1775 +
1776 + // Disable Square Core.
1777 + $this->disable_gateway( 'square_core' );
1778 +
1779 + // Enable Square Legacy.
1780 + $this->enable_gateway( 'square', false );
1781 +
1782 + if ( charitable_is_debug() ) {
1783 + error_log( 'Charitable: Successfully switched from Square Core to Square Legacy gateway.' ); // phpcs:ignore
1784 + }
1785 +
1786 + // Get the redirect URL for Square Legacy settings.
1787 + $redirect_url = add_query_arg(
1788 + array(
1789 + 'page' => 'charitable-settings',
1790 + 'tab' => 'gateways',
1791 + 'group' => 'gateways_square',
1792 + ),
1793 + admin_url( 'admin.php' )
1794 + );
1795 +
1796 + wp_send_json_success( array( 'redirect_url' => $redirect_url ) );
1797 + }
1798 +
1799 + /**
1800 + * Disconnect Square Core connections for both live and test modes.
1801 + *
1802 + * @since 1.8.7
1803 + *
1804 + * @return void
1805 + */
1806 + private function disconnect_square_core_connections() {
1807 +
1808 + if ( charitable_is_debug() ) {
1809 + error_log( 'Charitable: Starting Square Core connection disconnection process.' ); // phpcs:ignore
1810 + }
1811 +
1812 + // Check if Charitable_Square_Connection class exists.
1813 + if ( ! class_exists( 'Charitable_Square_Connection' ) ) {
1814 + if ( charitable_is_debug() ) {
1815 + error_log( 'Charitable: Charitable_Square_Connection class not found. Skipping disconnect process.' ); // phpcs:ignore
1816 + }
1817 + return;
1818 + }
1819 +
1820 + // Check and disconnect live mode connection.
1821 + $live_connection = Charitable_Square_Connection::get( 'live' );
1822 + if ( $live_connection && $live_connection->is_configured() ) {
1823 + if ( charitable_is_debug() ) {
1824 + error_log( 'Charitable: Found active Square Core live connection. Attempting to disconnect.' ); // phpcs:ignore
1825 + }
1826 + $this->disconnect_square_core_mode( $live_connection, 'live' );
1827 + } elseif ( charitable_is_debug() ) {
1828 + error_log( 'Charitable: No active Square Core live connection found.' ); // phpcs:ignore
1829 +
1830 + }
1831 +
1832 + // Check and disconnect test mode connection.
1833 + $test_connection = Charitable_Square_Connection::get( 'test' );
1834 + if ( $test_connection && $test_connection->is_configured() ) {
1835 + if ( charitable_is_debug() ) {
1836 + error_log( 'Charitable: Found active Square Core test connection. Attempting to disconnect.' ); // phpcs:ignore
1837 + }
1838 + $this->disconnect_square_core_mode( $test_connection, 'test' );
1839 + } elseif ( charitable_is_debug() ) {
1840 + error_log( 'Charitable: No active Square Core test connection found.' ); // phpcs:ignore
1841 +
1842 + }
1843 +
1844 + if ( charitable_is_debug() ) {
1845 + error_log( 'Charitable: Completed Square Core connection disconnection process.' ); // phpcs:ignore
1846 + }
1847 + }
1848 +
1849 + /**
1850 + * Disconnect Square Core connection for a specific mode.
1851 + *
1852 + * @since 1.8.7
1853 + *
1854 + * @param Charitable_Square_Connection $connection The connection object.
1855 + * @param string $mode The mode (live/test).
1856 + * @return void
1857 + */
1858 + private function disconnect_square_core_mode( $connection, $mode ) {
1859 +
1860 + if ( charitable_is_debug() ) {
1861 + error_log( 'Charitable: Disconnecting Square Core connection for mode: ' . $mode ); // phpcs:ignore
1862 + }
1863 +
1864 + // Check if Charitable_Square_Connect class exists.
1865 + if ( ! class_exists( 'Charitable_Square_Connect' ) ) {
1866 + if ( charitable_is_debug() ) {
1867 + error_log( 'Charitable: Charitable_Square_Connect class not found. Cannot disconnect mode: ' . $mode ); // phpcs:ignore
1868 + }
1869 + return;
1870 + }
1871 +
1872 + try {
1873 + // Get the Square Connect instance.
1874 + $square_connect = Charitable_Square_Connect::get_instance();
1875 +
1876 + // Use reflection to access the private handle_disconnect method.
1877 + $reflection = new ReflectionClass( $square_connect );
1878 + $method = $reflection->getMethod( 'handle_disconnect' );
1879 + $method->setAccessible( true );
1880 +
1881 + // Set the live_mode parameter for the disconnect process.
1882 + $_GET['live_mode'] = ( $mode === 'live' ) ? 1 : 0;
1883 +
1884 + // Call the disconnect method without redirect.
1885 + $method->invoke( $square_connect, false );
1886 +
1887 + if ( charitable_is_debug() ) {
1888 + error_log( 'Charitable: Successfully disconnected Square Core connection for mode: ' . $mode ); // phpcs:ignore
1889 + }
1890 + } catch ( Exception $e ) {
1891 + if ( charitable_is_debug() ) {
1892 + error_log( 'Charitable: Error disconnecting Square Core connection for mode ' . $mode . ': ' . $e->getMessage() ); // phpcs:ignore
1893 + }
1894 + }
1895 + }
1896 +
1897 + /**
1898 + * Dequeue Square Legacy scripts if Square Legacy is not active.
1899 + *
1900 + * @since 1.8.7
1901 + *
1902 + * @return void
1903 + */
1904 + public function maybe_dequeue_square_legacy_scripts() {
1905 + // Only run on frontend.
1906 + if ( is_admin() ) {
1907 + return;
1908 + }
1909 +
1910 + // Debug: Log the status checks.
1911 + if ( charitable_is_debug( 'square' ) ) {
1912 + error_log( '[Charitable Square] Script dequeue check - Legacy mode: ' . ( charitable_square_legacy_mode() ? 'true' : 'false' ) ); // phpcs:ignore
1913 + error_log( '[Charitable Square] Script dequeue check - Square gateway active: ' . ( $this->is_active_gateway( 'square' ) ? 'true' : 'false' ) ); // phpcs:ignore
1914 + }
1915 +
1916 + // Check if Square Legacy is active.
1917 + if ( ! charitable_square_legacy_mode() || ! $this->is_active_gateway( 'square' ) ) {
1918 + // Dequeue Square Legacy scripts and styles.
1919 + wp_dequeue_script( 'charitable-square' );
1920 + wp_dequeue_script( 'square' );
1921 + wp_dequeue_style( 'charitable-square' );
1922 +
1923 + // Deregister scripts to prevent them from being loaded.
1924 + wp_deregister_script( 'charitable-square' );
1925 + wp_deregister_script( 'square' );
1926 + wp_deregister_style( 'charitable-square' );
1927 +
1928 + if ( charitable_is_debug( 'square' ) ) {
1929 + error_log( '[Charitable Square] Dequeued Square Legacy scripts - Square Legacy is not active' ); // phpcs:ignore
1930 + }
1931 + } elseif ( charitable_is_debug( 'square' ) ) {
1932 + error_log( '[Charitable Square] Square Legacy scripts will remain loaded - Square Legacy is active' ); // phpcs:ignore
1933 +
1934 + }
1935 + }
1936 +
1937 + /**
1938 + * Check if charitable-square plugin is active.
1939 + *
1940 + * @since 1.8.7
1941 + *
1942 + * @return boolean
1943 + */
1944 + private function is_square_addon_active() {
1945 + return is_plugin_active( 'charitable-square/charitable-square.php' );
1946 + }
1947 +
1948 + /**
1949 + * Force cleanup of 'square' gateway if charitable-square plugin is not active.
1950 + * Runs once per 24 hours (adjustable via filter) to avoid constant database checks.
1951 + *
1952 + * @since 1.8.7
1953 + *
1954 + * @param array $active_gateways The current active gateways array.
1955 + * @return void
1956 + */
1957 + private function maybe_force_cleanup_square_gateway( $active_gateways ) {
1958 + // Check if we need to run cleanup (once per 24 hours).
1959 + $transient_name = 'charitable_square_cleanup_last_run';
1960 + $check_interval = apply_filters( 'charitable_square_cleanup_check_interval', 24 * HOUR_IN_SECONDS );
1961 +
1962 + if ( get_transient( $transient_name ) ) {
1963 + return;
1964 + }
1965 +
1966 + // Check if 'square' gateway exists and charitable-square plugin is not active.
1967 + if ( isset( $active_gateways['square'] ) && ! $this->is_square_addon_active() ) {
1968 + try {
1969 + // Get current settings.
1970 + $settings = get_option( 'charitable_settings', array() );
1971 +
1972 + if ( ! empty( $settings['active_gateways']['square'] ) ) {
1973 + // Remove 'square' gateway from active gateways.
1974 + unset( $settings['active_gateways']['square'] );
1975 +
1976 + // Update default gateway if it was set to 'square'.
1977 + if ( isset( $settings['default_gateway'] ) && 'square' === $settings['default_gateway'] ) {
1978 + $settings['default_gateway'] = '';
1979 + }
1980 +
1981 + // Remove the option that warns users about incorrect square settings.
1982 + delete_option( 'charitable_square_mode_connection_warning' );
1983 +
1984 + // Save updated settings.
1985 + $updated = update_option( 'charitable_settings', $settings );
1986 +
1987 + if ( $updated ) {
1988 + if ( charitable_is_debug( 'square' ) ) {
1989 + error_log( '[Charitable Square] Successfully removed legacy square gateway from active gateways' ); // phpcs:ignore
1990 + }
1991 + } else {
1992 + if ( charitable_is_debug( 'square' ) ) {
1993 + error_log( '[Charitable Square] Failed to update settings when removing legacy square gateway' ); // phpcs:ignore
1994 + }
1995 + }
1996 + }
1997 + } catch ( Exception $e ) {
1998 + if ( charitable_is_debug( 'square' ) ) {
1999 + error_log( '[Charitable Square] Error during square gateway cleanup: ' . $e->getMessage() ); // phpcs:ignore
2000 + }
2001 + }
2002 + }
2003 +
2004 + // Set transient to prevent running again for the specified interval.
2005 + set_transient( $transient_name, time(), $check_interval );
2006 + }
934 2007 }
935 2008
936 2009 endif;