Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
75.00% |
6 / 8 |
CRAP | |
72.00% |
36 / 50 |
| Shopify\PublicApp | |
0.00% |
0 / 1 |
|
75.00% |
6 / 8 |
26.92 | |
72.00% |
36 / 50 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
8 / 8 |
|||
| setAccessToken | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| getAccessToken | |
0.00% |
0 / 1 |
22.10 | |
23.53% |
4 / 17 |
|||
| prepareAuthorizeUrl | |
100.00% |
1 / 1 |
4 | |
100.00% |
11 / 11 |
|||
| setState | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getState | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| validateHmac | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
| validateState | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
| <?php | |
| namespace Shopify; | |
| use Shopify\Common\AppInterface; | |
| use Shopify\Exception\ApiException; | |
| /** | |
| * Class PublicApp | |
| * @package Shopify | |
| */ | |
| class PublicApp extends Client implements AppInterface | |
| { | |
| /** | |
| * define scope for api access | |
| */ | |
| const SCOPE = 'read_products,read_orders'; | |
| /** | |
| * | |
| * @var string | |
| */ | |
| private $oauth_url = 'https://{shopify_domain}/admin/oauth/'; | |
| /** | |
| * random unique value for each authorization request | |
| * @var state | |
| */ | |
| private $state; | |
| /** | |
| * PublicApp constructor. | |
| * Shopify domain => testshop.myshopify.com | |
| * @param $shop | |
| * Shopify api key | |
| * @param $api_key | |
| * Shopify api secret key | |
| * @param $api_secret_key | |
| * ['version'=>'2020-01'] | |
| * @param array $api_params | |
| * @throws ApiException | |
| */ | |
| public function __construct($shop, $api_key, $api_secret_key, array $api_params = []) | |
| { | |
| $this->setShop($shop); | |
| $this->api_key = $api_key; | |
| $this->api_secret_key = $api_secret_key; | |
| $this->api_params = $api_params; | |
| $this->setApiVersion($this->api_params); | |
| $this->setGraphqlApiUrl($this->graphql_api_url); | |
| $this->setRestApiUrl($this->rest_api_url); | |
| } | |
| /** | |
| * assign access token for api call | |
| * @param $access_token | |
| */ | |
| public function setAccessToken($access_token) | |
| { | |
| $this->access_token = $access_token; | |
| $this->setRestApiHeaders($this->access_token); | |
| $this->setGraphqlApiHeaders($this->access_token); | |
| } | |
| /** | |
| * Once the User has authorized the app, call to get the access token | |
| * @param $get_params | |
| * @return mixed | |
| * @throws ApiException | |
| * @throws ClientException | |
| */ | |
| public function getAccessToken($get_params) | |
| { | |
| if(isset($get_params['code'],$get_params['hmac'])) | |
| { | |
| if(isset($get_params['state']) && !$this->validateState($get_params)) | |
| throw new ApiException("Previous state value('".$this->getState()."') doesn't match with current value('".$get_params['state']."')",0); | |
| if(!$this->validateHmac($get_params,$get_params['hmac'])) | |
| throw new ApiException("Hmac validation failed",0); | |
| $access_token_url = $this->oauth_url.'access_token'; | |
| $access_token_url = strtr($access_token_url,['{shopify_domain}'=> $this->shop]); | |
| $params['client_id'] = $this->api_key; | |
| $params['client_secret'] = $this->api_secret_key; | |
| $params['code'] = $get_params['code']; | |
| $http_response = $this->request('POST', $access_token_url, ['query'=>$params]); | |
| $response = \GuzzleHttp\json_decode($http_response->getBody()->getContents(),true); | |
| if(isset($response['access_token'])) | |
| { | |
| $this->setAccessToken($response['access_token']); | |
| return $response['access_token']; | |
| } | |
| } | |
| else { | |
| throw new ApiException('Unable to authorise app, check your credentials',0); | |
| } | |
| } | |
| /** | |
| * prepare url to authorize public app with Oauth for given shop domain | |
| * @param $scope | |
| * @param null $redirect_url | |
| * @param $state | |
| * @return false|string | |
| */ | |
| public function prepareAuthorizeUrl($redirect_url='', $scope='', $state=false) | |
| { | |
| /*&redirect_uri={redirect_uri}&state={nonce}*/ | |
| $authorise_url = $this->oauth_url.'authorize?client_id={api_key}&scope={scopes}'; | |
| $authorise_url = strtr($authorise_url, [ | |
| '{shopify_domain}'=> $this->shop, | |
| '{api_key}'=> $this->api_key, | |
| '{scopes}'=> !empty($scope)?$scope:self::SCOPE | |
| ] | |
| ); | |
| if($redirect_url){ | |
| $authorise_url.='&redirect_uri='.$redirect_url; | |
| } | |
| if($state){ | |
| $this->setState($state); | |
| $authorise_url.='&state='.$this->getState(); | |
| } | |
| return $authorise_url; | |
| } | |
| /** | |
| * set random unique value for authorization request | |
| * @param $state | |
| */ | |
| public function setState($state) | |
| { | |
| $this->state = $state; | |
| } | |
| /** | |
| * get random unique value for authorization request | |
| * @return string | |
| */ | |
| public function getState() | |
| { | |
| return $this->state; | |
| } | |
| /** | |
| * HMAC verification procedure for OAuth/webhooks | |
| * @param $data | |
| * @param $hmac | |
| * @return bool | |
| */ | |
| public function validateHmac($data, $hmac) | |
| { | |
| if(isset($data['hmac'])) { | |
| unset($data['hmac']); | |
| array_values($data); | |
| } | |
| return ($hmac === hash_hmac('sha256', is_array($data) ? http_build_query($data) : $data, $this->api_secret_key)); | |
| } | |
| /** | |
| * check random value same with previous value set for authorization request | |
| * @param $state | |
| * @return bool | |
| */ | |
| public function validateState($params) | |
| { | |
| if($params['state'] === $this->getState()) | |
| return true; | |
| return false; | |
| } | |
| } |