gateway class format. */ $this->gateways = apply_filters( 'charitable_payment_gateways', array( 'stripe' => 'Charitable_Gateway_Stripe_AM', 'paypal' => 'Charitable_Gateway_Paypal', 'offline' => 'Charitable_Gateway_Offline', ) ); $this->gateways['stripe'] = 'Charitable_Gateway_Stripe_AM'; } /** * Receives a request to enable or disable a payment gateway and validates it before passing it off. * * @since 1.0.0 * * @return void */ public function handle_gateway_settings_request() { if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'gateway' ) ) { wp_die( __( 'Cheatin\' eh?!', 'charitable' ) ); } $gateway = isset( $_REQUEST['gateway_id'] ) ? $_REQUEST['gateway_id'] : false; /* Gateway must be set */ if ( false === $gateway ) { wp_die( __( 'Missing gateway.', 'charitable' ) ); } /* Validate gateway. */ if ( ! isset( $this->gateways[ $gateway ] ) ) { wp_die( __( 'Invalid gateway.', 'charitable' ) ); } switch ( $_REQUEST['charitable_action'] ) { case 'disable_gateway': $this->disable_gateway( $gateway ); break; case 'enable_gateway': $this->enable_gateway( $gateway ); $this->redirect_gateway_settings( $gateway ); break; case 'make_default_gateway': $this->set_default_gateway( $gateway ); break; default: /** * Do something when a gateway settings request takes place. * * @since 1.0.0 * * @param string $action The action taking place. * @param string $gateway_id The gateway ID. */ do_action( 'charitable_gateway_settings_request', $_REQUEST['charitable_action'], $gateway ); } } /** * Returns all available payment gateways. * * @since 1.0.0 * * @return array */ public function get_available_gateways() { if ( isset( $this->gateways['stripe'] ) ) { $this->gateways['stripe'] = charitable()->is_stripe_connect_addon() ? 'Charitable_Gateway_Stripe_AM' : $this->gateways['stripe']; } return $this->gateways; } /** * Returns the current active gateways. * * @since 1.0.0 * * @return string[] */ public function get_active_gateways() { $active_gateways = charitable_get_option( 'active_gateways', array() ); foreach ( $active_gateways as $gateway_id => $gateway_class ) { if ( ! class_exists( $gateway_class ) ) { unset( $active_gateways[ $gateway_id ] ); } } uksort( $active_gateways, array( $this, 'sort_by_default' ) ); // force the strip active gateway normally for stripe addon to point to the stripe built into core. if ( isset( $active_gateways['stripe'] ) ) { $active_gateways['stripe'] = 'Charitable_Gateway_Stripe_AM'; } /** * Filter the list of active gateways. * * @since 1.0.0 * * @param array $gateways Active gateways. */ return apply_filters( 'charitable_active_gateways', $active_gateways ); } /** * Returns an array of the active gateways, in ID => name format. * * This is useful for select/radio input fields. * * @since 1.0.0 * * @return string[] */ public function get_gateway_choices() { $gateways = array(); foreach ( $this->get_active_gateways() as $id => $class ) { $gateway = new $class; $gateways[ $id ] = $gateway->get_label(); } return $gateways; } /** * Returns a text description of the active gateways. * * @since 1.3.0 * * @return string[] */ public function get_active_gateways_names() { $gateways = array(); foreach ( $this->get_active_gateways() as $id => $class ) { $gateway = new $class; $gateways[] = $gateway->get_name(); } return $gateways; } /** * Return the gateway class name for a given gateway. * * @since 1.0.0 * * @param string $gateway Gateway ID. * @return string|false */ public function get_gateway( $gateway ) { return isset( $this->gateways[ $gateway ] ) ? $this->gateways[ $gateway ] : false; } /** * Return the gateway object for a given gateway. * * @since 1.0.0 * * @param string $gateway Gateway ID. * @return Charitable_Gateway|null */ public function get_gateway_object( $gateway ) { $class = $this->get_gateway( $gateway ); $object = $class ? new $class : null; /** * Filter the gateway object. * * @since 1.6.30 * * @param Charitable_Gateway|null $object The gateway object. */ return apply_filters( 'charitable_gateway_object_' . $gateway, $object, $gateway ); } /** * Returns whether the passed gateway is active. * * @since 1.0.0 * * @param string $gateway_id Gateway ID. * @return boolean */ public function is_active_gateway( $gateway_id ) { return array_key_exists( $gateway_id, $this->get_active_gateways() ); } /** * Checks whether the submitted gateway is valid. * * @since 1.4.3 * * @param string $gateway Gateway ID. * @return boolean */ public function is_valid_gateway( $gateway ) { /** * Validate a particular gatewya. * * @since 1.4.3 * * @param boolean $valid Whether a gateway is valid. * @param string $gateway The gateway ID. */ if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) { error_log( 'is_valid_gateway' ); error_log( print_r( $gateway, true ) ); error_log( print_r( $this->gateways, true ) ); } return apply_filters( 'charitable_is_valid_gateway', array_key_exists( $gateway, $this->gateways ), $gateway ); } /** * Returns the default gateway. * * @since 1.0.0 * * @return string */ public function get_default_gateway() { return charitable_get_option( 'default_gateway', '' ); } /** * Provide default gateway settings fields. * * @since 1.0.0 * * @param array $settings Gateway settings. * @param Charitable_Gateway $gateway The gateway's helper object. * @return array */ public function register_gateway_settings( $settings, Charitable_Gateway $gateway ) { add_filter( 'charitable_settings_fields_gateways_gateway_' . $gateway->get_gateway_id(), array( $gateway, 'default_gateway_settings' ), 5 ); add_filter( 'charitable_settings_fields_gateways_gateway_' . $gateway->get_gateway_id(), array( $gateway, 'gateway_settings' ), 15 ); /** * Filter the settings to show for a particular gateway. * * @since 1.0.0 * * @param array $settings Gateway settings. */ return apply_filters( 'charitable_settings_fields_gateways_gateway_' . $gateway->get_gateway_id(), $settings ); } /** * Returns true if test mode is enabled. * * @since 1.0.0 * * @return boolean */ public function in_test_mode() { $enabled = charitable_get_option( 'test_mode', false ); /** * Return whether Charitable is in test mode. * * @since 1.0.0 * * @param boolean $enabled Whether test mode is on. */ return apply_filters( 'charitable_in_test_mode', $enabled ); } /** * Checks whether all of the active gateways support a feature. * * If ANY gateway doesn't support the feature, this returns false. * * @since 1.4.0 * * @param string $feature Feature to search for. * @return boolean */ public function all_gateways_support( $feature ) { foreach ( $this->get_active_gateways() as $gateway_id => $gateway_class ) { $gateway_object = new $gateway_class; if ( false === $gateway_object->supports( $feature ) ) { return false; } } return true; } /** * Checks whether any of the active gateways support a feature. * * If any gateway supports the feature, this returns true. Otherwise false. * * @since 1.4.0 * * @param string $feature Feature to check for. * @return boolean */ public function any_gateway_supports( $feature ) { foreach ( $this->get_active_gateways() as $gateway_id => $gateway_class ) { $gateway_object = new $gateway_class; if ( true === $gateway_object->supports( $feature ) ) { return true; } } return false; } /** * Checks whether all of the active gateways support AJAX. * * If ANY gateway doesn't support AJAX, this returns false. * * @since 1.3.0 * * @return boolean */ public function gateways_support_ajax() { return $this->all_gateways_support( '1.3.0' ); } /** * Return an array of recommended gateways for the current site. * * Note that this will only return gateways that are not already * available on the site. i.e. If you have Stripe installed, it * will not suggest that. * * @since 1.5.0 * * @return array */ public function get_recommended_gateways() { $available = $this->get_available_gateways(); $gateways = array( 'payfast' => __( 'Payfast', 'charitable' ), 'paystack' => __( 'Paystack', 'charitable' ), 'stripe' => __( 'Stripe', 'charitable' ), 'authorize_net' => __( 'Authorize.Net', 'charitable' ), 'windcave' => __( 'Windcave', 'charitable' ), 'braintree' => __( 'Braintree', 'charitable' ), 'mollie' => __( 'Mollie', 'charitable' ), 'gocardless' => __( 'GoCardless', 'charitable' ), 'payrexx' => __( 'Payrexx', 'charitable' ), ); /* If the user has already enabled one of these, leave them alone. :) */ foreach ( $gateways as $gateway_id => $gateway ) { if ( array_key_exists( $gateway_id, $available ) ) { return array(); } } $currency = charitable_get_default_currency(); $locale = get_locale(); if ( 'en_ZA' == $locale || 'ZAR' == $currency ) { return charitable_array_subset( $gateways, array( 'payfast', 'paystack' ) ); } if ( in_array( $currency, array( 'NGN', 'GHS' ) ) ) { return charitable_array_subset( $gateways, array( 'paystack' ) ); } if ( in_array( $locale, array( 'en_NZ', 'en_AU', 'en_GB' ) ) || in_array( $currency, array( 'NZD', 'AUD', 'GBP' ) ) ) { return charitable_array_subset( $gateways, array( 'stripe', 'gocardless' ) ); } if ( in_array( $locale, array( 'ms_MY', 'ja', 'zh_HK' ) ) || in_array( $currency, array( 'MYR', 'JPY', 'HKD' ) ) ) { return charitable_array_subset( $gateways, array( 'stripe', 'windcave' ) ); } if ( in_array( $locale, array( 'th' ) ) || in_array( $currency, array( 'BND', 'FJD', 'KWD', 'PGK', 'SBD', 'THB', 'TOP', 'VUV', 'WST' ) ) ) { return charitable_array_subset( $gateways, array( 'windcave' ) ); } if ( in_array( $currency, array( 'EUR' ) ) ) { return charitable_array_subset( $gateways, array( 'stripe', 'mollie' ) ); } if ( in_array( $currency, array( 'CHF', 'DKK' ) ) ) { return charitable_array_subset( $gateways, array( 'stripe', 'payrexx' ) ); } return charitable_array_subset( $gateways, array( 'stripe', 'braintree' ) ); } /** * Sets the default gateway. * * @since 1.0.0 * * @param string $gateway Gateway ID. * @return void */ protected function set_default_gateway( $gateway ) { $settings = get_option( 'charitable_settings' ); $settings['default_gateway'] = $gateway; update_option( 'charitable_settings', $settings ); charitable_get_admin_notices()->add_success( __( 'Default Gateway Updated', 'charitable' ) ); do_action( 'charitable_set_gateway_gateway', $gateway ); } /** * Enable a payment gateway. * * @since 1.0.0 * * @param string $gateway Gateway ID. * @return void */ protected function enable_gateway( $gateway ) { $settings = get_option( 'charitable_settings' ); $active_gateways = isset( $settings['active_gateways'] ) ? $settings['active_gateways'] : array(); $active_gateways[ $gateway ] = $this->gateways[ $gateway ]; $settings['active_gateways'] = $active_gateways; /* If this is the only gateway, make it the default gateway */ if ( 1 == count( $settings['active_gateways'] ) ) { $settings['default_gateway'] = $gateway; } update_option( 'charitable_settings', $settings ); Charitable_Settings::get_instance()->add_update_message( __( 'Gateway enabled', 'charitable' ), 'success' ); /** * Do something when a payment gateway is enabled. * * @since 1.0.0 * * @param string $gateway The payment gateway. */ do_action( 'charitable_gateway_enable', $gateway ); } /** * Disable a payment gateway. * * @since 1.0.0 * * @param string $gateway Gateway ID. * @return void */ protected function disable_gateway( $gateway ) { $settings = get_option( 'charitable_settings' ); if ( ! isset( $settings['active_gateways'][ $gateway ] ) ) { return; } unset( $settings['active_gateways'][ $gateway ] ); /* Set a new default gateway */ if ( $gateway == $this->get_default_gateway() ) { $settings['default_gateway'] = count( $settings['active_gateways'] ) ? key( $settings['active_gateways'] ) : ''; } update_option( 'charitable_settings', $settings ); Charitable_Settings::get_instance()->add_update_message( __( 'Gateway disabled', 'charitable' ), 'success' ); /** * Do something when a payment gateway is disabled. * * @since 1.0.0 * * @param string $gateway The payment gateway. */ do_action( 'charitable_gateway_disable', $gateway ); } /** * Connects to Stripe by saving account information passed back to the plugin. * * @since 4.2.2 * * @return void */ public function connect_gateways() { // Current user cannot handle this request. if ( ! current_user_can( 'manage_options' ) ) { return; } // Do not need to handle this request, bail. if ( ! isset( $_GET['wpcharitable_gateway_connect_completion'] ) || 'stripe_connect' !== $_GET['wpcharitable_gateway_connect_completion'] || ! isset( $_GET['state'] ) ) { return; } // Unable to redirect, bail. if ( headers_sent() ) { return; } if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) { $current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; } else { $current_url = ''; } $customer_site_url = remove_query_arg( array( 'state', 'wpcharitable_gateway_connect_completion' ), $current_url ); $wpcharitable_credentials_url = add_query_arg( array( 'live_mode' => (int) ! charitable_get_option( 'test_mode' ), // (int) ! $this->is_test_mode(), 'state' => sanitize_text_field( $_GET['state'] ), 'customer_site_url' => urlencode( $customer_site_url ), ), 'https://wpcharitable.com/stripe-connect/?wpcharitable_gateway_connect_credentials=stripe_connect' // todo: filter market site url ); $response = wp_remote_get( esc_url_raw( $wpcharitable_credentials_url ) ); // add add_filter('https_ssl_verify', '__return_false'); here if testing local if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { $stripe_account_settings_url = add_query_arg( array( 'tab' => 'gateways', 'page' => 'charitable-settings', 'group' => 'gateways_stripe', ), admin_url( 'admin.php' ) ); $message = wpautop( sprintf( /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */ __( 'There was an error getting your Stripe credentials. Please %1$stry again%2$s. If you continue to have this problem, please contact support.', 'stripe' ), '', '' ) ); wp_die( $message ); } $body = wp_remote_retrieve_body( $response ); /** @var string $body */ $body = json_decode( $body, true ); /** @var array> $body */ $account_data = $body['data']; $this->save_account_information( $account_data ); // update the option to track that we are using stripe connect. update_option( 'charitable_using_stripe_connect', time() ); /** * Allow further processing after connecting a Stripe account. * * @since 3.6.0 * * @param array $data Stripe response data. */ do_action( 'wpcharitable_stripe_account_connected', $account_data ); // 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. if ( false === $this->get_default_gateway() || 'offline' === $this->get_default_gateway() ) { $this->set_default_gateway( 'stripe' ); } wp_redirect( esc_url_raw( $customer_site_url ) ); exit; } /** * Saves the account information sent back from Stripe, alongside other, to identify the connected account. * * @since 4.4.2 * * @param array $data Stripe oAuth account data. * @return void */ private function save_account_information( $data, $gateway_id = 'stripe' ) { $prefix = $this->in_test_mode() ? 'test' : 'live'; $settings = get_option( 'charitable_settings' ); $settings['gateways_' . $gateway_id ]['live_secret_key'] = ''; $settings['gateways_' . $gateway_id ]['live_public_key'] = ''; $settings['gateways_' . $gateway_id ]['test_secret_key'] = ''; $settings['gateways_' . $gateway_id ]['test_public_key'] = ''; $settings['gateways_' . $gateway_id ][ $prefix . '_secret_key' ] = isset( $data['secret_key'] ) ? sanitize_text_field( $data['secret_key'] ) : false; $settings['gateways_' . $gateway_id ][ $prefix . '_public_key' ] = isset( $data['publishable_key'] ) ? sanitize_text_field( $data['publishable_key'] ) : false; if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) { error_log( 'save_account_information' ); error_log( print_r( $settings, true ) ); } update_option( 'charitable_settings', $settings ); charitable_get_admin_notices()->add_success( __( 'Stripe Information Updated', 'charitable' ) ); do_action( 'charitable_save_account_information_gateway_' . $gateway_id, $settings, $data, $gateway_id ); } /** * Disconnects from Stripe by removing associated account information. * * This does not deauthorize the application within the Stripe account. * * @since 4.2.2 * * @return void */ public function disconnect_gateways() { // Do not need to handle this request, bail. if ( ! ( isset( $_GET['page'] ) && 'charitable-settings' === $_GET['page'] ) || ! isset( $_GET['wpcharitable-stripe-disconnect'] ) ) { return; } // Current user cannot handle this request. if ( ! current_user_can( 'manage_options' ) ) { return; } if ( ! isset( $_GET['_wpnonce'] ) ) { return; } // Invalid nonce, bail. if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'wpcharitable-stripe-connect-disconnect' ) ) { return; } $settings = get_option( 'charitable_settings' ); unset( $settings['gateways_stripe'][ 'live_secret_key' ] ); unset( $settings['gateways_stripe'][ 'live_public_key' ] ); unset( $settings['gateways_stripe'][ 'test_secret_key' ] ); unset( $settings['gateways_stripe'][ 'test_public_key' ] ); update_option( 'charitable_settings', $settings ); // update the option to track that we are using stripe connect. delete_option( 'charitable_using_stripe_connect' ); charitable_get_admin_notices()->add_success( __( 'Stripe Connected Removed', 'charitable' ) ); do_action( 'charitable_remove_connection_gateway_stripe', $settings ); $redirect_url = add_query_arg( array( 'tab' => 'gateways', 'page' => 'charitable-settings', 'group' => 'gateways_stripe', ), admin_url( 'admin.php' ) ); wp_safe_redirect( $redirect_url ); exit; } /** * Redirects to the gateway settings page once a gateway has been activated. * * @since 1.7.0 * * @param string $gateway Gateway ID. * @return void */ public function redirect_gateway_settings( $gateway ) { $settings_url = add_query_arg( array( 'group' => 'gateways_' . $gateway, ), admin_url( 'admin.php?page=charitable-settings&tab=gateways' ) ); wp_safe_redirect( $settings_url ); exit; } /** * Sort the active gateways, placing the default gateway first. * * @since 1.4.0 * * @param string $a Gateway to compare. * @param string $b Gateway to compare against. * @return int */ protected function sort_by_default( $a, $b ) { $default = $this->get_default_gateway(); if ( $a == $default ) { return -1; } if ( $b == $default ) { return 1; } return 0; } /** * Ensure there is a settings option when landing on settings pages, even if init blank. Mostly applicable to new installs. * * @since 1.4.0 * */ public function check_settings() { if ( isset( $_GET['page'] ) && 'charitable-settings' !== $_GET['page'] ) { return; } $settings = get_option( 'charitable_settings' ); // attach this to CHARITABLE_DEBUG constant. if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG && defined( 'CHARITABLE_DEBUG_SETTINGS' ) && CHARITABLE_DEBUG_SETTINGS ) { error_log( 'checking_settings'); error_log( print_r( $settings, true ) ); } if ( false === $settings ||( is_array( $settings ) && empty( $settings ) ) ) { $settings_blank_slate = array( 'default_gateway' => 'stripe' ); // settings are brand new and include setting the default gateway update_option( 'charitable_settings', $settings_blank_slate ); } } /** * Display the test and live fields that represent the manual keys for Stripe that users might be already using prior to 1.7.0. * * @since 1.7.0 * */ public function show_stripe_manual_keys_ajax() { if ( ! isset( $_POST ) || 'charitable-show-stripe-keys' !== $_POST['action'] ) { return; } $settings = get_option( 'charitable_settings' ); if ( false === $settings ) { return; } $gateway_id = 'stripe'; $live_secret_key = $settings['gateways_' . $gateway_id ][ 'live_secret_key' ]; $live_public_key = $settings['gateways_' . $gateway_id ][ 'live_public_key' ]; $test_secret_key = $settings['gateways_' . $gateway_id ][ 'test_secret_key' ]; $test_public_key = $settings['gateways_' . $gateway_id ][ 'test_public_key' ]; $html = 'Live Settings
Live Secret Key Live Publishable Key Test Settings
Test Secret Key Test Publishable Key '; wp_send_json_success( $html ); } } endif;