Skip to content

Commit 72c10db

Browse files
committed
replaced guzzlehttp with illuminate support http
1 parent 2531480 commit 72c10db

File tree

5 files changed

+123
-86
lines changed

5 files changed

+123
-86
lines changed

README.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ in your `.env` file set these values from your app
4444
`SHOPIFY_APIKEY=your-api-key`
4545
`SHOPIFY_SECRET=your-secret-key`
4646

47-
## Optional Configuration
47+
## Optional Configuration (publishing)
4848

4949
Laravel Shopify requires api key configuration. You will need to publish configs assets
5050

@@ -95,6 +95,8 @@ Route::get("process_oauth_result",function(\Illuminate\Http\Request $request)
9595
$token = $shopifyApi
9696
->setShopDomain($myShopifyDomain)
9797
->getAccessToken($code);
98+
//this gets access token from shopify and set it to the current instance which will be passed in further api calls
99+
98100

99101
dd($accessToken);
100102
//store the access token for future api calls on behalf of the shop
@@ -105,11 +107,13 @@ Route::get("process_oauth_result",function(\Illuminate\Http\Request $request)
105107
To verify request(hmac)
106108

107109
```php5
110+
use ClarityTech\Shopify\Facades\Shopify;
111+
108112
public function verifyRequest(Request $request)
109113
{
110-
$queryString = $request->getQueryString();
114+
$params = $request->all();
111115

112-
if(Shopify::verifyRequest($queryString)){
116+
if (Shopify::verifyRequest($params)){
113117
logger("verification passed");
114118
}else{
115119
logger("verification failed");
@@ -121,11 +125,12 @@ public function verifyRequest(Request $request)
121125
To verify webhook(hmac)
122126

123127
```php5
128+
use ClarityTech\Shopify\Facades\Shopify;
124129

125130
public function verifyWebhook(Request $request)
126131
{
127132
$data = $request->getContent();
128-
$hmacHeader = $request->server('HTTP_X_SHOPIFY_HMAC_SHA256');
133+
$hmacHeader = $request->header('x-shopify-hmac-sha256');
129134

130135
if (Shopify::verifyWebHook($data, $hmacHeader)) {
131136
logger("verification passed");
@@ -150,17 +155,19 @@ Let use our access token to get products from shopify.
150155
**NB:** You can use this to access any resource on shopify (be it Product, Shop, Order, etc)
151156

152157
```php5
158+
use ClarityTech\Shopify\Facades\Shopify;
159+
153160
$shopUrl = "example.myshopify.com";
154-
$accessToken = "xxxxxxxxxxxxxxxxxxxxx";
155-
$products = Shopify::setShopUrl($shopUrl)->setAccessToken($accessToken)->get("admin/products.json");
161+
$accessToken = "xxxxxxxxxxxxxxxxxxxxx"; //retrieve from your storage(db)
162+
$products = Shopify::setShop($myShopifyDomain, $accessToken)->get("admin/products.json");
156163
```
157164

158165
To pass query params
159166

160167
```php5
161168
// returns Collection
162-
$shopify = Shopify::setShopUrl($shopUrl)->setAccessToken($accessToken);
163-
$products = $shopify->get("admin/products.json", ["limit"=>20, "page" => 1]);
169+
Shopify::setShop($myShopifyDomain, $accessToken);
170+
$products = Shopify::get('admin/products.json', ["limit"=>20, "page" => 1]);
164171
```
165172

166173
## Controller Example
@@ -181,17 +188,15 @@ class Foo
181188
}
182189

183190
/*
184-
* returns Collection
191+
* returns products
185192
*/
186193
public function getProducts(Request $request)
187194
{
188-
$products = $this->shopify->setShopUrl($shopUrl)
189-
->setAccessToken($accessToken)
195+
$accessToken = 'xxxxxxxxxxxxxxxxxxxxx';//retrieve from your storage(db)
196+
$products = $this->shopify->setShop($request->shop, $accessToken)
190197
->get('admin/products.json');
191198

192-
$products->each(function($product){
193-
\Log::info($product->title);
194-
});
199+
dump($products);
195200
}
196201
}
197202
```

composer.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
],
1111
"require": {
1212
"php": ">=7.3.0",
13-
"guzzlehttp/guzzle": "^7.0.1",
14-
"illuminate/support": "^7.0|^8.0"
13+
"illuminate/support": "^7.0|^8.0",
14+
"psr/http-message": "^1.0"
1515
},
1616
"autoload": {
1717
"psr-4": {
@@ -28,6 +28,9 @@
2828
}
2929
}
3030
},
31+
"suggest": {
32+
"guzzlehttp/guzzle": "Must Required to use the HTTP Client."
33+
},
3134
"config": {
3235
"preferred-install": "dist"
3336
}

src/Shopify/Api/Entity.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ protected function request(string $method, $entityUrl, array $params = [])
8484

8585
$response = Shopify::$method($url, $params);
8686

87+
//$response = $response->json();
88+
8789
return static::buildEntity($response);
8890
}
8991

src/Shopify/Shopify.php

Lines changed: 96 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,43 @@
22

33
namespace ClarityTech\Shopify;
44

5-
use GuzzleHttp\Client;
65
use Illuminate\Support\Facades\Config;
6+
use Illuminate\Support\Facades\Http;
77
use ClarityTech\Shopify\Exceptions\ShopifyApiException;
88
use ClarityTech\Shopify\Exceptions\ShopifyApiResourceNotFoundException;
9+
use Psr\Http\Message\ResponseInterface;
910

1011
class Shopify
1112
{
12-
protected Client $client;
13-
1413
protected static ?string $key = null;
1514
protected static ?string $secret = null;
1615
protected static ?string $shopDomain = null;
1716
protected static ?string $accessToken = null;
1817

1918
public const VERSION = '2020-01';
2019
public const PREFIX = 'admin/api/';
20+
21+
public bool $debug = false;
2122

2223
protected array $requestHeaders = [];
2324
protected array $responseHeaders = [];
2425
protected $responseStatusCode;
2526
protected $reasonPhrase;
2627

27-
public function __construct(Client $client)
28+
// public function __construct(Client $client)
29+
// {
30+
// $this->client = $client;
31+
// self::$key = Config::get('shopify.key');
32+
// self::$secret = Config::get('shopify.secret');
33+
// }
34+
public function __construct()
2835
{
29-
$this->client = $client;
3036
self::$key = Config::get('shopify.key');
3137
self::$secret = Config::get('shopify.secret');
3238
}
3339

40+
//use Illuminate\Support\Facades\Http;
41+
3442
public function api()
3543
{
3644
return $this;
@@ -133,9 +141,13 @@ public function getAccessToken(string $code)
133141

134142
$response = $this->makeRequest('POST', $uri, $payload);
135143

136-
$this->setAccessToken($response);
144+
$response = $response->json();
145+
146+
$accessToken = $response['access_token'] ?? null;
147+
148+
$this->setAccessToken($accessToken);
137149

138-
return $response ?? '';
150+
return $accessToken ?? '';
139151
}
140152

141153
public function setAccessToken($accessToken)
@@ -152,7 +164,12 @@ public function setShop(string $domain, string $accessToken)
152164
return $this;
153165
}
154166

155-
protected function getXShopifyAccessToken() : array
167+
public function isTokenSet() : bool
168+
{
169+
return !is_null(self::$accessToken);
170+
}
171+
172+
protected function getXShopifyAccessTokenHeader() : array
156173
{
157174
return ['X-Shopify-Access-Token' => self::$accessToken];
158175
}
@@ -171,78 +188,94 @@ public function removeHeaders() : self
171188
return $this;
172189
}
173190

191+
public function setDebug(bool $status = true)
192+
{
193+
$this->debug = $status;
194+
195+
return $this;
196+
}
197+
174198
/*
175199
* $args[0] is for route uri and $args[1] is either request body or query strings
176200
*/
177201
public function __call($method, $args)
178202
{
179-
list($uri, $params) = [ltrim($args[0], "/"), $args[1] ?? []];
180-
$response = $this->makeRequest($method, $uri, $params, $this->getXShopifyAccessToken());
203+
list($uri, $params) = [ltrim($args[0], '/'), $args[1] ?? []];
204+
$response = $this->makeRequest($method, $uri, $params);
205+
206+
if (is_array($array = $response->json()) && count($array) == 1) {
207+
return array_shift($array);
208+
}
181209

182-
//return (is_array($response)) ? $this->convertResponseToCollection($response) : $response;
183210
return $response;
184211
}
185212

186-
public function makeRequest(string $method, string $path, array $params = [], array $headers = [])
213+
public function getHeadersForSend() : array
187214
{
188-
$query = in_array($method, ['get','delete']) ? 'query' : 'json';
215+
$headers = [];
189216

190-
$rateLimit = explode('/', $this->getHeader('X-Shopify-Shop-Api-Call-Limit'));
191-
192-
if ($rateLimit[0] >= 38) {
193-
sleep(15);
217+
if ($this->isTokenSet()) {
218+
$headers = $this->getXShopifyAccessTokenHeader();
194219
}
220+
return array_merge($headers, $this->requestHeaders);
221+
}
222+
223+
public function makeRequest(string $method, string $path, array $params = [])
224+
{
225+
//TODO apply ratelimit or handle it outside from caller function
226+
// aso that we can have more control when we can retry etc
195227

196228
$url = self::getBaseUrl() . $path;
197229

198-
$response = $this->client
199-
->request(strtoupper($method), $url, [
200-
'headers' => array_merge($headers, $this->requestHeaders),
201-
$query => $params,
202-
'timeout' => 120.0,
203-
'connect_timeout' => 120.0,
204-
'http_errors' => false,
205-
"verify" => false
206-
]);
207-
208-
$this->parseResponse($response);
209-
$responseBody = $this->responseBody($response);
210-
211-
logger('shopify request ENDPOINT '. $url);
212-
logger('shopify request params ', (array) $params);
213-
logger('shopify request requestHeaders ', (array) array_merge($headers, $this->requestHeaders));
214-
215-
if (isset($responseBody['errors']) || $response->getStatusCode() >= 400) {
216-
logger('shopify error responseheaders ', (array) $this->responseHeaders);
217-
logger('shopify error response ', (array) $responseBody);
218-
219-
if (! is_null($responseBody)) {
220-
$errors = is_array($responseBody['errors'])
221-
? json_encode($responseBody['errors'])
222-
: $responseBody['errors'];
223-
224-
if ($response->getStatusCode() == 404) {
225-
throw new ShopifyApiResourceNotFoundException(
226-
$errors ?? $response->getReasonPhrase(),
227-
$response->getStatusCode()
228-
);
229-
}
230-
}
230+
$method = strtolower($method);
231231

232-
throw new ShopifyApiException(
233-
$errors ?? $response->getReasonPhrase(),
234-
$response->getStatusCode()
235-
);
232+
$response = Http::withOptions(['debug' => $this->debug,])
233+
->withHeaders($this->getHeadersForSend())
234+
->$method($url, $params);
235+
236+
$this->parseResponse($response->toPsrResponse());
237+
238+
if ($response->successful()) {
239+
return $response;
236240
}
237241

238-
return (is_array($responseBody) && (count($responseBody) > 0)) ? array_shift($responseBody) : $responseBody;
242+
return $this->throwErrors($response);
243+
}
244+
245+
protected function parseResponse(ResponseInterface $response)
246+
{
247+
$this
248+
->setResponseHeaders($response->getHeaders())
249+
->setStatusCode($response->getStatusCode())
250+
->setReasonPhrase($response->getReasonPhrase());
239251
}
240252

241-
private function parseResponse($response)
253+
protected function throwErrors($httpResponse)
242254
{
243-
$this->parseHeaders($response->getHeaders());
244-
$this->setStatusCode($response->getStatusCode());
245-
$this->setReasonPhrase($response->getReasonPhrase());
255+
$response = $httpResponse->json();
256+
$psrResponse = $httpResponse->toPsrResponse();
257+
258+
$statusCode = $psrResponse->getStatusCode();
259+
260+
if (isset($response['errors']) || $statusCode >= 400) {
261+
$errorString = null;
262+
263+
if (!is_null($response)) {
264+
$errorString = is_array($response['errors']) ? json_encode($response['errors']) : $response['errors'];
265+
}
266+
267+
if ($statusCode == 404) {
268+
throw new ShopifyApiResourceNotFoundException(
269+
$errorString ?? $psrResponse->getReasonPhrase(),
270+
$statusCode
271+
);
272+
}
273+
274+
throw new ShopifyApiException(
275+
$errorString ?? $psrResponse->getReasonPhrase(),
276+
$statusCode
277+
);
278+
}
246279
}
247280

248281
public function verifyRequest($queryParams)
@@ -287,6 +320,7 @@ public function verifyWebHook($data, $hmacHeader) : bool
287320
private function setStatusCode($code)
288321
{
289322
$this->responseStatusCode = $code;
323+
return $this;
290324
}
291325

292326
public function getStatusCode()
@@ -304,11 +338,10 @@ public function getReasonPhrase()
304338
return $this->reasonPhrase;
305339
}
306340

307-
private function parseHeaders($headers)
341+
private function setResponseHeaders($headers)
308342
{
309-
foreach ($headers as $name => $values) {
310-
$this->responseHeaders = array_merge($this->responseHeaders, [$name => implode(', ', $values)]);
311-
}
343+
$this->responseHeaders = $headers;
344+
return $this;
312345
}
313346

314347
public function getHeaders()
@@ -325,9 +358,4 @@ public function hasHeader($header)
325358
{
326359
return array_key_exists($header, $this->responseHeaders);
327360
}
328-
329-
private function responseBody($response)
330-
{
331-
return json_decode($response->getBody(), true);
332-
}
333361
}

src/Shopify/ShopifyServiceProvider.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace ClarityTech\Shopify;
44

5-
use GuzzleHttp\Client;
65
use Illuminate\Support\ServiceProvider;
76

87
class ShopifyServiceProvider extends ServiceProvider
@@ -41,7 +40,7 @@ public function register()
4140
$this->mergeConfigFrom(__DIR__.'/../config/shopify.php', 'shopify');
4241

4342
$this->app->singleton('shopify', function ($app) {
44-
return new Shopify(new Client);
43+
return new Shopify();
4544
});
4645
}
4746

0 commit comments

Comments
 (0)