$record['state'], 'user_id' => (int) $record['user_id'], ); } function x_pixel_oauth_forget_state( $state ) { if ( $state === '' ) { return; } delete_transient( x_pixel_oauth_state_key( $state ) ); delete_transient( x_pixel_oauth_blob_key( $state ) ); } function x_pixel_oauth_start() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have permission to connect X Ads.', 'x-pixel' ) ); } check_admin_referer( 'x_pixel_oauth_start' ); $state = wp_generate_password( 32, false, false ); set_transient( x_pixel_oauth_state_key( $state ), array( 'state' => $state, 'user_id' => get_current_user_id(), ), 20 * MINUTE_IN_SECONDS ); $return_url = add_query_arg( array( 'action' => 'x_pixel_oauth_return', 'wp_state' => $state, ), admin_url( 'admin-post.php' ) ); x_pixel_redirect_to_x( add_query_arg( 'return_url', rawurlencode( $return_url ), x_pixel_broker_connect_url() ) ); } add_action( 'admin_post_x_pixel_oauth_start', 'x_pixel_oauth_start' ); function x_pixel_oauth_request( $key ) { if ( isset( $_POST[ $key ] ) && ! is_array( $_POST[ $key ] ) ) { return sanitize_text_field( wp_unslash( $_POST[ $key ] ) ); } if ( isset( $_GET[ $key ] ) && ! is_array( $_GET[ $key ] ) ) { return sanitize_text_field( wp_unslash( $_GET[ $key ] ) ); } return null; } function x_pixel_oauth_state_param() { $state = (string) x_pixel_oauth_request( 'wp_state' ); return preg_match( '/^[A-Za-z0-9]{32}$/', $state ) === 1 ? $state : ''; } function x_pixel_oauth_opaque_param( $key ) { $value = (string) x_pixel_oauth_request( $key ); return preg_match( '/^[A-Za-z0-9_-]+$/', $value ) === 1 ? $value : ''; } function x_pixel_oauth_state_is_live( $state ) { $record = x_pixel_oauth_state_record( $state ); if ( $record === null ) { return false; } return $record['user_id'] === get_current_user_id() && current_user_can( 'manage_options' ); } function x_pixel_oauth_stash() { $state = x_pixel_oauth_state_param(); $token = x_pixel_oauth_opaque_param( 'oauth_token' ); $blob = x_pixel_oauth_opaque_param( 'blob' ); if ( ! x_pixel_oauth_state_is_live( $state ) || $token === '' || $blob === '' ) { wp_safe_redirect( x_pixel_settings_url( array( 'x_pixel_oauth' => 'bad_state' ) ) ); exit; } set_transient( x_pixel_oauth_blob_key( $state ), $blob, 20 * MINUTE_IN_SECONDS ); x_pixel_redirect_to_x( add_query_arg( 'oauth_token', rawurlencode( $token ), 'https://api.x.com/oauth/authorize' ) ); } add_action( 'admin_post_x_pixel_oauth_stash', 'x_pixel_oauth_stash' ); function x_pixel_oauth_resume() { $state = x_pixel_oauth_state_param(); $token = x_pixel_oauth_opaque_param( 'oauth_token' ); $verifier = x_pixel_oauth_opaque_param( 'oauth_verifier' ); $sealed = x_pixel_oauth_opaque_param( 'r' ); $blob = x_pixel_oauth_state_is_live( $state ) ? get_transient( x_pixel_oauth_blob_key( $state ) ) : false; if ( ! is_string( $blob ) || $blob === '' || $token === '' || $verifier === '' || $sealed === '' ) { wp_safe_redirect( x_pixel_settings_url( array( 'x_pixel_oauth' => 'bad_state' ) ) ); exit; } delete_transient( x_pixel_oauth_blob_key( $state ) ); $fields = array( 'r' => $sealed, 'blob' => $blob, 'oauth_token' => $token, 'oauth_verifier' => $verifier, ); $action = str_replace( '/connect', '/callback', x_pixel_broker_connect_url() ); x_pixel_redirect_to_x( $action . '?' . http_build_query( $fields, '', '&', PHP_QUERY_RFC3986 ), 303 ); } add_action( 'admin_post_x_pixel_oauth_resume', 'x_pixel_oauth_resume' ); function x_pixel_oauth_return() { nocache_headers(); $state = x_pixel_oauth_state_param(); $record = x_pixel_oauth_state_record( $state ); x_pixel_oauth_forget_state( $state ); $owner = $record === null ? 0 : $record['user_id']; if ( $owner <= 0 || ! user_can( $owner, 'manage_options' ) || ( is_user_logged_in() && get_current_user_id() !== $owner ) ) { wp_safe_redirect( x_pixel_settings_url( array( 'x_pixel_oauth' => 'bad_state' ) ) ); exit; } $error = x_pixel_oauth_request( 'error' ); if ( $error !== null ) { $code = sanitize_key( $error ); if ( $code === '' ) { $code = 'exchange_failed'; } wp_safe_redirect( x_pixel_settings_url( array( 'x_pixel_oauth' => $code ) ) ); exit; } $pixel = x_pixel_clean_id( (string) x_pixel_oauth_request( 'pixel_id' ) ); if ( $pixel === '' ) { wp_safe_redirect( x_pixel_settings_url( array( 'x_pixel_oauth' => 'pixel' ) ) ); exit; } $map = array( 'event_purchase' => X_PIXEL_OPTION_EVENT_PURCHASE, 'event_add_to_cart' => X_PIXEL_OPTION_EVENT_ATC, 'event_checkout' => X_PIXEL_OPTION_EVENT_CHECKOUT, 'event_content_view' => X_PIXEL_OPTION_EVENT_VIEW, ); $previous = get_option( X_PIXEL_OPTION_ID, '' ); if ( $previous !== '' && $previous !== $pixel ) { delete_option( X_PIXEL_OPTION_CAPI ); foreach ( $map as $option ) { delete_option( $option ); } } update_option( X_PIXEL_OPTION_ID, $pixel ); $token = x_pixel_clean_token( (string) x_pixel_oauth_request( 'capi_token' ) ); if ( $token !== '' ) { update_option( X_PIXEL_OPTION_CAPI, $token ); } foreach ( $map as $query => $option ) { $value = x_pixel_clean_id( (string) x_pixel_oauth_request( $query ) ); if ( $value !== '' ) { update_option( $option, $value ); } } $complete = get_option( X_PIXEL_OPTION_CAPI, '' ) !== ''; foreach ( $map as $option ) { if ( get_option( $option, '' ) === '' ) { $complete = false; } } wp_safe_redirect( x_pixel_settings_url( array( 'x_pixel_oauth' => $complete ? 'ok' : 'partial' ) ) ); exit; } add_action( 'admin_post_x_pixel_oauth_return', 'x_pixel_oauth_return' ); add_action( 'admin_post_nopriv_x_pixel_oauth_return', 'x_pixel_oauth_return' ); function x_pixel_oauth_notices() { $screen = get_current_screen(); if ( ! $screen || $screen->id !== 'settings_page_x-pixel' || ! current_user_can( 'manage_options' ) ) { return; } if ( ! isset( $_GET['x_pixel_oauth'] ) ) { return; } $code = sanitize_key( wp_unslash( $_GET['x_pixel_oauth'] ) ); if ( $code === 'ok' ) { echo '
'; echo esc_html__( 'Connected to X Ads. Pixel, Conversion API token, and store event IDs were saved.', 'x-pixel' ); echo '
'; echo esc_html__( 'Connected to X Ads and saved the pixel, but the Conversion API token or some store event IDs were not returned. Click Reconnect X Ads to try again, or paste the missing values from Events Manager.', 'x-pixel' ); echo '
'; echo esc_html__( 'X Pixel settings were cleared.', 'x-pixel' ); echo '
' . esc_html( $message ) . '