class-wc-helper-api.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit;
  4. }
  5. /**
  6. * WC_Helper_API Class
  7. *
  8. * Provides a communication interface with the WooCommerce.com Helper API.
  9. */
  10. class WC_Helper_API {
  11. public static $api_base;
  12. /**
  13. * Load
  14. *
  15. * Allow devs to point the API base to a local API development or staging server.
  16. * Note that sslverify will be turned off for the woocommerce.dev + WP_DEBUG combination.
  17. * The URL can be changed on plugins_loaded before priority 10.
  18. */
  19. public static function load() {
  20. self::$api_base = apply_filters( 'woocommerce_helper_api_base', 'https://woocommerce.com/wp-json/helper/1.0' );
  21. }
  22. /**
  23. * Perform an HTTP request to the Helper API.
  24. *
  25. * @param string $endpoint The endpoint to request.
  26. * @param array $args Additional data for the request. Set authenticated to a truthy value to enable auth.
  27. *
  28. * @return array|WP_Error The response from wp_safe_remote_request()
  29. */
  30. public static function request( $endpoint, $args = array() ) {
  31. $url = self::url( $endpoint );
  32. if ( ! empty( $args['authenticated'] ) ) {
  33. if ( ! self::_authenticate( $url, $args ) ) {
  34. return new WP_Error( 'authentication', 'Authentication failed.' );
  35. }
  36. }
  37. /**
  38. * Allow developers to filter the request args passed to wp_safe_remote_request().
  39. * Useful to remove sslverify when working on a local api dev environment.
  40. */
  41. $args = apply_filters( 'woocommerce_helper_api_request_args', $args, $endpoint );
  42. // TODO: Check response signatures on certain endpoints.
  43. return wp_safe_remote_request( $url, $args );
  44. }
  45. /**
  46. * Adds authentication headers to an HTTP request.
  47. *
  48. * @param string $url The request URI.
  49. * @param array $args By-ref, the args that will be passed to wp_remote_request().
  50. * @return bool Were the headers added?
  51. */
  52. private static function _authenticate( $url, &$args ) {
  53. $auth = WC_Helper_Options::get( 'auth' );
  54. if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) {
  55. return false;
  56. }
  57. $request_uri = parse_url( $url, PHP_URL_PATH );
  58. $query_string = parse_url( $url, PHP_URL_QUERY );
  59. if ( is_string( $query_string ) ) {
  60. $request_uri .= '?' . $query_string;
  61. }
  62. $data = array(
  63. 'host' => parse_url( $url, PHP_URL_HOST ),
  64. 'request_uri' => $request_uri,
  65. 'method' => ! empty( $args['method'] ) ? $args['method'] : 'GET',
  66. );
  67. if ( ! empty( $args['body'] ) ) {
  68. $data['body'] = $args['body'];
  69. }
  70. $signature = hash_hmac( 'sha256', json_encode( $data ), $auth['access_token_secret'] );
  71. if ( empty( $args['headers'] ) ) {
  72. $args['headers'] = array();
  73. }
  74. $args['headers'] = array(
  75. 'Authorization' => 'Bearer ' . $auth['access_token'],
  76. 'X-Woo-Signature' => $signature,
  77. );
  78. return true;
  79. }
  80. /**
  81. * Wrapper for self::request().
  82. *
  83. * @param string $endpoint The helper API endpoint to request.
  84. * @param array $args Arguments passed to wp_remote_request().
  85. *
  86. * @return array The response object from wp_safe_remote_request().
  87. */
  88. public static function get( $endpoint, $args = array() ) {
  89. $args['method'] = 'GET';
  90. return self::request( $endpoint, $args );
  91. }
  92. /**
  93. * Wrapper for self::request().
  94. *
  95. * @param string $endpoint The helper API endpoint to request.
  96. * @param array $args Arguments passed to wp_remote_request().
  97. *
  98. * @return array The response object from wp_safe_remote_request().
  99. */
  100. public static function post( $endpoint, $args = array() ) {
  101. $args['method'] = 'POST';
  102. return self::request( $endpoint, $args );
  103. }
  104. /**
  105. * Using the API base, form a request URL from a given endpoint.
  106. *
  107. * @param string $endpoint The endpoint to request.
  108. *
  109. * @return string The absolute endpoint URL.
  110. */
  111. public static function url( $endpoint ) {
  112. $endpoint = ltrim( $endpoint, '/' );
  113. $endpoint = sprintf( '%s/%s', self::$api_base, $endpoint );
  114. $endpoint = esc_url_raw( $endpoint );
  115. return $endpoint;
  116. }
  117. }
  118. WC_Helper_API::load();