Created
February 27, 2025 04:18
-
-
Save chikaibeneme/7b092e0602736c73dd7991bc5c88548a to your computer and use it in GitHub Desktop.
* Patch the PayPal Client request() method to capture arguments once * and avoid re-capturing them on retry.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Patch the PayPal Client request() method to capture arguments once | |
| * and avoid re-capturing them on retry. | |
| * | |
| * Requires the runkit or runkit7 extension. | |
| */ | |
| add_action( 'plugins_loaded', function() { | |
| if ( ! function_exists( 'runkit_method_redefine' ) ) { | |
| error_log( 'Runkit extension is not available; PayPal Client patch was not applied.' ); | |
| return; | |
| } | |
| // Redefine the "request" method of the Client class. | |
| runkit_method_redefine( | |
| 'TEC\Tickets\Commerce\Gateways\PayPal\Client', | |
| 'request', | |
| '$method, $url, array $query_args = array(), array $request_arguments = array(), $raw = false, $retries = 0', | |
| <<<'EOD' | |
| // Capture the arguments the first time this method is called. | |
| $arguments = array($method, $url, $query_args, $request_arguments, $raw, $retries); | |
| $method = strtoupper($method); | |
| // If $url is not a full URL, append query args. | |
| $url = 0 !== strpos($url, 'https://') | |
| ? $this->get_api_url($url, $query_args) | |
| : add_query_arg($query_args, $url); | |
| $default_arguments = [ | |
| 'headers' => [ | |
| 'Accept' => 'application/json', | |
| 'Authorization' => sprintf('Bearer %1$s', $this->get_access_token()), | |
| 'Content-Type' => 'application/json', | |
| ] | |
| ]; | |
| // For non-GET requests, ensure a body exists. | |
| if ('GET' !== $method) { | |
| $default_arguments['body'] = []; | |
| } | |
| foreach ($default_arguments as $key => $default_argument) { | |
| $request_arguments[$key] = array_merge($default_argument, \Tribe__Utils__Array::get($request_arguments, $key, [])); | |
| } | |
| if ('GET' !== $method) { | |
| $content_type = \Tribe__Utils__Array::get($request_arguments, ['headers', 'Content-Type']); | |
| if (empty($content_type)) { | |
| $content_type = \Tribe__Utils__Array::get($request_arguments, ['headers', 'content-type']); | |
| } | |
| // If body is present and content type is JSON, encode it. | |
| if (!empty($request_arguments['body']) && 'application/json' === strtolower($content_type)) { | |
| $request_arguments['body'] = wp_json_encode($request_arguments['body']); | |
| } | |
| } | |
| // Execute the request. | |
| if ('GET' === $method) { | |
| $response = wp_remote_get($url, $request_arguments); | |
| } elseif ('POST' === $method) { | |
| $response = wp_remote_post($url, $request_arguments); | |
| } else { | |
| $request_arguments['method'] = $method; | |
| $response = wp_remote_request($url, $request_arguments); | |
| } | |
| if (is_wp_error($response)) { | |
| tribe('logger')->log_error(sprintf( | |
| '[%s] PayPal "%s" request error: %s', | |
| $method, | |
| $url, | |
| $response->get_error_message() | |
| ), 'tickets-commerce-paypal'); | |
| return $response; | |
| } | |
| if (true === $raw) { | |
| return $response; | |
| } | |
| $response_code = wp_remote_retrieve_response_code($response); | |
| // Store the debug header if available. | |
| $this->set_debug_header(null); | |
| if (!empty($response['headers']['Paypal-Debug-Id'])) { | |
| $this->set_debug_header($response['headers']['Paypal-Debug-Id']); | |
| } | |
| // On 401 error (and not for token generation), retry once. | |
| if ( | |
| 401 === $response_code && | |
| 2 >= $retries && | |
| false === strpos($url, 'v1/oauth2/token') | |
| ) { | |
| $merchant = tribe(Merchant::class); | |
| $token_data = $this->get_access_token_from_client_credentials($merchant->get_client_id(), $merchant->get_client_secret()); | |
| $saved = $merchant->save_access_token_data($token_data); | |
| if ($saved) { | |
| // Use the previously captured $arguments, | |
| // update the retry count and re-call the method. | |
| array_pop($arguments); | |
| $arguments[] = $retries + 1; | |
| return call_user_func_array([$this, 'request'], $arguments); | |
| } | |
| } | |
| // Decode the response body. | |
| $response_body = wp_remote_retrieve_body($response); | |
| $response_body = @json_decode($response_body, true); | |
| if (empty($response_body)) { | |
| return $response; | |
| } | |
| if (!is_array($response_body)) { | |
| tribe('logger')->log_error(sprintf('[%s] Unexpected PayPal %s response', $url, $method), 'tickets-commerce-paypal'); | |
| return new \WP_Error('tec-tickets-commerce-gateway-paypal-client-unexpected', null, [ | |
| 'method' => $method, | |
| 'url' => $url, | |
| 'query_args' => $query_args, | |
| 'request_arguments' => $request_arguments, | |
| 'response' => $response, | |
| ]); | |
| } | |
| return $response_body; | |
| EOD | |
| ); | |
| } ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment