password ) || empty( $data->account_id ) || empty( $data->connect_url ) ) { wp_send_json_error(); } $response_data = array( 'connect_url' => $data->connect_url, ); wp_send_json_success( $response_data ); } /** * Initialize a Stripe Connect integration with the connect server * * @return object|string */ private static function initialize() { $mode = self::get_mode_value_from_post(); if ( self::get_account_id( $mode ) ) { // Do not allow for initialize if there is already a configured account id. return 'Cannot initialize another account'; } $additional_body = array( 'password' => self::generate_client_password( $mode ), 'user_id' => get_current_user_id(), 'frm_strp_connect_mode' => $mode, ); $data = self::post_to_connect_server( 'initialize', $additional_body ); if ( is_string( $data ) ) { return $data; } if ( ! empty( $data->password ) ) { update_option( self::get_server_side_token_option_name( $mode ), $data->password, false ); } if ( ! empty( $data->account_id ) ) { update_option( self::get_account_id_option_name( $mode ), $data->account_id, false ); } return $data; } /** * 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, false ); return $client_password; } /** * @param string $action * @param array $additional_body * * @return object|string */ private static function post_to_connect_server( $action, $additional_body = array() ) { $body = array( 'frm_strp_connect_action' => $action, 'frm_strp_connect_mode' => FrmStrpLiteAppHelper::active_mode(), ); $body = array_merge( $body, $additional_body ); $url = self::get_url_to_connect_server(); $headers = self::build_headers_for_post(); // (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 $body->data ?? array(); } /** * 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 either _test or _live. */ private static function get_active_mode_option_name_suffix( $mode = 'auto' ) { if ( 'auto' !== $mode ) { return '_' . $mode; } return '_' . FrmStrpLiteAppHelper::active_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_strp_connect_option_name( $key, $mode = 'auto' ) { return 'frm_strp_connect_' . $key . self::get_active_mode_option_name_suffix( $mode ); } /** * @param string $mode either 'auto', 'live', or 'test'. * * @return string */ private static function get_account_id_option_name( $mode = 'auto' ) { return self::get_strp_connect_option_name( 'account_id', $mode ); } /** * @param string $mode either 'auto', 'live', or 'test'. * * @return string */ private static function get_client_side_token_option_name( $mode = 'auto' ) { return self::get_strp_connect_option_name( 'client_password', $mode ); } /** * @param string $mode either 'auto', 'live', or 'test'. * * @return string */ private static function get_server_side_token_option_name( $mode = 'auto' ) { return self::get_strp_connect_option_name( 'server_password', $mode ); } /** * @param string $mode either 'auto', 'live', or 'test'. * * @return string */ private static function get_stripe_details_submitted_option_name( $mode = 'auto' ) { return self::get_strp_connect_option_name( 'details_submitted', $mode ); } /** * @return string */ private static function get_url_to_connect_server() { return 'https://api.strategy11.com/'; } /** * @return void */ private static function handle_disconnect() { self::disconnect(); self::reset_stripe_connect_integration(); FrmTransLiteAppHelper::trigger_gateway_disconnected_hook( 'stripe', self::get_mode_value_from_post() ); wp_send_json_success(); } /** * Delete every Stripe connect option, calling when disconnecting. * * @return void */ public static function reset_stripe_connect_integration() { $mode = self::get_mode_value_from_post(); delete_option( self::get_account_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_stripe_details_submitted_option_name( $mode ) ); } /** * @return false|object */ private static function disconnect() { $mode = self::get_mode_value_from_post(); $additional_body = self::get_body_for_mode( $mode ); return self::post_with_authenticated_body( 'disconnect', $additional_body ); } /** * @since 6.5 * * @return bool */ public static function at_least_one_mode_is_setup() { return self::stripe_connect_is_setup( 'test' ) || self::stripe_connect_is_setup( 'live' ); } /** * @return void */ private static function handle_reauth() { $mode = self::get_mode_value_from_post(); $additional_body = self::get_body_for_mode( $mode ); $data = self::post_with_authenticated_body( 'reauth', $additional_body ); if ( false === $data ) { // Check account status. if ( self::check_server_for_connected_account_status( $mode ) ) { wp_send_json_success(); } wp_send_json_error(); } $response_data = array( 'connect_url' => $data->connect_url, ); wp_send_json_success( $response_data ); } /** * @return array */ private static function get_standard_authenticated_body() { return self::get_body_for_mode( FrmStrpLiteAppHelper::active_mode() ); } /** * Get the standard body with account id, mode, and passwords to send to the connect server. * * @since 6.32.1 * * @param string $mode 'live' or 'test'. * * @return array */ private static function get_body_for_mode( $mode ) { return array( 'account_id' => get_option( self::get_account_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 ) ), 'frm_strp_connect_mode' => $mode, ); } private static function redirect() { $connected = self::check_server_for_connected_account_status(); wp_safe_redirect( self::get_url_for_stripe_settings( $connected ) ); exit; } private static function redirect_oauth() { $connected = self::check_server_for_oauth_account_id(); wp_safe_redirect( self::get_url_for_stripe_settings( $connected ) ); exit; } /** * @return bool */ private static function check_server_for_oauth_account_id() { $mode = FrmAppHelper::get_param( 'mode', '', 'get', 'sanitize_text_field' ); if ( 'live' !== $mode ) { $mode = 'test'; } if ( self::get_account_id( $mode ) ) { // Do not allow for initialize if there is already a configured account id. return false; } $body = array( 'server_password' => get_option( self::get_server_side_token_option_name( $mode ) ), 'client_password' => get_option( self::get_client_side_token_option_name( $mode ) ), 'frm_strp_connect_mode' => $mode, ); $data = self::post_to_connect_server( 'oauth_account_status', $body ); if ( is_object( $data ) && ! empty( $data->account_id ) ) { update_option( self::get_account_id_option_name( $mode ), $data->account_id, false ); if ( ! empty( $data->details_submitted ) ) { self::set_stripe_details_as_submitted( $mode ); } return true; } return false; } /** * On a successful account status check, set details_submitted option. * * @param string $mode 'live' or 'test'. * * @return void */ private static function set_stripe_details_as_submitted( $mode ) { update_option( self::get_stripe_details_submitted_option_name( $mode ), true, false ); FrmTransLiteAppController::install(); } /** * @return void */ private static function handle_oauth() { $response_data = array( 'redirect_url' => self::get_oauth_redirect_url(), ); wp_send_json_success( $response_data ); } /** * @return false|string */ private static function get_oauth_redirect_url() { $mode = self::get_mode_value_from_post(); if ( self::get_account_id( $mode ) ) { // Do not allow for initialize if there is already a configured account id. return false; } $additional_body = array( 'password' => self::generate_client_password( $mode ), 'user_id' => get_current_user_id(), 'frm_strp_connect_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, false ); } if ( ! is_object( $data ) || empty( $data->redirect_url ) ) { return false; } return $data->redirect_url; } /** * @param string $mode * * @return bool true if our account is onboarded */ public static function check_server_for_connected_account_status( $mode = 'check_get' ) { if ( 'check_get' === $mode ) { $mode = FrmAppHelper::get_param( 'mode', '', 'get', 'sanitize_text_field' ); if ( 'live' !== $mode ) { $mode = 'test'; } } if ( self::stripe_connect_is_setup( $mode ) ) { return false; } $additional_body = self::get_body_for_mode( $mode ); $data = self::post_with_authenticated_body( 'account_status', $additional_body ); $success = false !== $data && ! empty( $data->details_submitted ); if ( $success ) { self::set_stripe_details_as_submitted( $mode ); } return $success; } /** * @param string $mode * * @return bool */ public static function stripe_connect_is_setup( $mode = 'auto' ) { return get_option( self::get_stripe_details_submitted_option_name( $mode ) ); } /** * @param mixed $response * * @return bool */ private static function validate_response( $response ) { return ! is_wp_error( $response ) && is_array( $response ) && isset( $response['http_response'] ); } /** * @param array $response * * @return object|null */ 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 ); } /** * @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 ), ); } /** * 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; } /** * WPML might add a language to the url. Don't send that to the server. * * @param string $url URL. * * @return string */ private static function strip_lang_from_url( $url ) { $split_on_language = explode( '/?lang=', $url ); return 2 === count( $split_on_language ) ? $split_on_language[0] : $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; } /** * Get a unique ID to use for connecting Lite users. * * @return string */ private static function get_uuid() { $usage = new FrmUsage(); return $usage->uuid(); } /** * @param bool $connected * * @return string */ private static function get_url_for_stripe_settings( $connected ) { return admin_url( 'admin.php?page=formidable-settings&t=stripe_settings&connected=' . intval( $connected ) ); } /** * @return void */ public static function render_stripe_connect_settings_container() { self::register_settings_scripts(); // phpcs:disable Generic.WhiteSpace.ScopeIndent ?>