diff --git a/README.md b/README.md index 2981aab..9698f68 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,8 @@ Simple [Shopify API](http://api.shopify.com/) client in PHP ## Usage and Quickstart Skeleton Project -See [phpish/shopify_app-skeleton](https://github.com/phpish/shopify_app-skeleton) and [phpish/shopify_private_app-skeleton](https://github.com/phpish/shopify_private_app-skeleton) \ No newline at end of file +See [phpish/shopify_app-skeleton](https://github.com/phpish/shopify_app-skeleton) and [phpish/shopify_private_app-skeleton](https://github.com/phpish/shopify_private_app-skeleton) + +## FIXED + +I had to fix it so it works with the latest HMAC protocols. Unable to reach creator for pull request. diff --git a/shopify.php b/shopify.php index 76ac4d4..cdf4985 100644 --- a/shopify.php +++ b/shopify.php @@ -1,41 +1,29 @@ $val) $params[] = "$key=$val"; - sort($params); - - return (md5($shared_secret.implode('', $params)) === $signature); + function is_valid_request($query_params, $shared_secret) { + if(!is_array($query_params)) return false; + if(array_key_exists('shop',$query_params) && array_key_exists('timestamp',$query_params) && array_key_exists('hmac',$query_params)) { + $hmac = $query_params['hmac']; + unset($query_params['signature']); + unset($query_params['hmac']); + ksort($query_params); + return $hmac == hash_hmac('sha256', http_build_query($query_params), $shared_secret); + } + return false; } - function authorization_url($shop, $api_key, $scopes=array(), $redirect_uri='') { $scopes = empty($scopes) ? '' : '&scope='.implode(',', $scopes); $redirect_uri = empty($redirect_uri) ? '' : '&redirect_uri='.urlencode($redirect_uri); return "https://$shop/admin/oauth/authorize?client_id=$api_key$scopes$redirect_uri"; } - - function access_token($shop, $api_key, $shared_secret, $code) { try @@ -44,27 +32,35 @@ function access_token($shop, $api_key, $shared_secret, $code) } catch (http\CurlException $e) { throw new CurlException($e->getMessage(), $e->getCode(), $e->getRequest()); } catch (http\ResponseException $e) { throw new ApiException($e->getMessage(), $e->getCode(), $e->getRequest(), $e->getResponse()); } - return $response['access_token']; } - - function client($shop, $api_key, $oauth_token, $private_app=false) { $base_uri = $private_app ? _private_app_base_url($shop, $api_key, $oauth_token) : "https://$shop/"; - return function ($method_uri, $query='', $payload='', &$response_headers=array(), $request_headers=array(), $curl_opts=array()) use ($base_uri, $oauth_token, $private_app) { if (!$private_app) $request_headers['X-Shopify-Access-Token'] = $oauth_token; $request_headers['content-type'] = 'application/json; charset=utf-8'; - $http_client = http\client($base_uri, $request_headers); - + $http_client = http\client($base_uri, $request_headers, array( + CURLOPT_HEADER => true, + CURLOPT_RETURNTRANSFER => true, + # http://www.php.net/manual/en/function.curl-setopt.php#71313 + # CURLOPT_FOLLOWLOCATION => true, + CURLOPT_MAXREDIRS => 3, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_SSL_VERIFYHOST => 2, + CURLOPT_USERAGENT => 'phpish/http', + CURLOPT_CONNECTTIMEOUT => 25, + CURLOPT_TIMEOUT => 25, + CURLOPT_SSLVERSION => 1 + )); try { $response = $http_client($method_uri, $query, $payload, $response_headers, $request_headers, $curl_opts); } catch (http\CurlException $e) { throw new CurlException($e->getMessage(), $e->getCode(), $e->getRequest()); } catch (http\ResponseException $e) { throw new ApiException($e->getMessage(), $e->getCode(), $e->getRequest(), $e->getResponse()); } + catch (http\Exception $e) { throw new Exception($e->getMessage(), $e->getCode(), $e->getRequest()); } if (isset($response['errors'])) { list($method, $uri) = explode(' ', $method_uri, 2); @@ -74,43 +70,30 @@ function client($shop, $api_key, $oauth_token, $private_app=false) $response = array('headers'=>$response_headers, 'body'=>$response); throw new ApiException($response_headers['http_status_message'].": $uri", $response_headers['http_status_code'], $request, $response); } - return (is_array($response) and !empty($response)) ? array_shift($response) : $response; - }; } - - function _private_app_base_url($shop, $api_key, $password) - { - return "https://$api_key:$password@$shop/"; - } - - + function _private_app_base_url($shop, $api_key, $password) + { + return "https://$api_key:$password@$shop/"; + } function calls_made($response_headers) { return _shop_api_call_limit_param(0, $response_headers); } - - function call_limit($response_headers) { return _shop_api_call_limit_param(1, $response_headers); } - - - function calls_left($response_headers) + function calls_left($response_headers) { return call_limit($response_headers) - calls_made($response_headers); } - - - function _shop_api_call_limit_param($index, $response_headers) - { - $params = explode('/', $response_headers['http_x_shopify_shop_api_call_limit']); - return (int) $params[$index]; - } - - + function _shop_api_call_limit_param($index, $response_headers) + { + $params = explode('/', $response_headers['http_x_shopify_shop_api_call_limit']); + return (int) $params[$index]; + } class Exception extends http\Exception { } class CurlException extends Exception { } class ApiException extends Exception @@ -124,5 +107,4 @@ function __construct($message, $code, $request, $response=array(), Exception $pr parent::__construct($this->message, $code, $request, $response, $previous); } } - -?> \ No newline at end of file +?>