osiset / basic-shopify-api
这是一个基于 Guzzle 的 Shopify API 包装器,支持 REST 和 GraphQL。
Requires
- php: >=7.3.0
- ext-json: *
- caseyamcl/guzzle_retry_middleware: ^2.3
- guzzlehttp/guzzle: ^6.5 || ^7.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.8
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^0.12
- phpunit/phpunit: ^6.2 || ^9.3
- dev-master
- v11.0.0
- 10.0.x-dev
- v10.0.6
- v10.0.5
- v10.0.4
- v10.0.3
- v10.0.2
- v10.0.1
- v10.0.0
- 9.1.x-dev
- v9.1.4
- v9.1.3
- v9.1.2
- v9.1.1
- v9.1.0
- 9.0.x-dev
- v9.0.0
- 8.2.x-dev
- v8.2.0
- 8.1.x-dev
- v8.1.0
- 8.0.x-dev
- v8.0.0
- v7.0.0
- v6.1.3
- v6.1.2
- v6.1.1
- v6.1.0
- v6.0.0
- v5.4.0
- v5.3.3
- v5.3.2
- v5.3.1
- v5.3.0
- v5.1.0
- v5.0.0
- v4.0.2
- v4.0.1
- v4.0.0
- v3.0.3
- v3.0.2
- v3.0.1
- v3.0.0
- v2.0.0
- v1.0.1
- v1.0.0
- dev-feature/per-user-data
This package is auto-updated.
Last update: 2024-01-16 18:44:19 UTC
README
一个简单、经过测试的 Shopify API 包装器,使用 Guzzle。
它支持 Shopify 提供的同步/异步 REST 和 GraphQL API,基本的速率限制和请求重试。
它包含生成安装 URL、授权 URL(离线和按用户)、HMAC 签名验证、调用限制和 API 请求的有用方法。
它与 OAuth 和私有 API 应用程序一起工作。
目录
安装
推荐的安装方式是通过 composer。
composer require gnikyt/basic-shopify-api
使用方法
公共 API
这假设您已在合作伙伴仪表板中正确设置了应用,并具有正确的密钥和重定向 URI。
REST(同步)
对于 REST 调用,需要商店域名和访问令牌。
use Gnikyt\BasicShopifyAPI\BasicShopifyAPI; use Gnikyt\BasicShopifyAPI\Options; use Gnikyt\BasicShopifyAPI\Session; // Create options for the API $options = new Options(); $options->setVersion('2020-01'); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session('example.myshopify.com', 'access-token-here')); // Now run your requests... $result = $api->rest(...);
REST(异步)
对于 REST 调用,需要商店域名和访问令牌。
use Gnikyt\BasicShopifyAPI\BasicShopifyAPI; use Gnikyt\BasicShopifyAPI\Options; use Gnikyt\BasicShopifyAPI\Session; // Create options for the API $options = new Options(); $options->setVersion('2020-01'); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session('example.myshopify.com', 'access-token-here')); // Now run your requests... $promise = $api->restAsync(...); $promise->then(function (array $result) { // ... });
GraphQL(同步)
对于 GraphQL 调用,需要商店域名和访问令牌。
use Gnikyt\BasicShopifyAPI\BasicShopifyAPI; use Gnikyt\BasicShopifyAPI\Options; use Gnikyt\BasicShopifyAPI\Session; // Create options for the API $options = new Options(); $options->setVersion('2020-01'); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session('example.myshopify.com', 'access-token-here')); // Now run your requests... $result = $api->graph(...);
GraphQL(异步)
对于 GraphQL 调用,需要商店域名和访问令牌。
use Gnikyt\BasicShopifyAPI\BasicShopifyAPI; use Gnikyt\BasicShopifyAPI\Options; use Gnikyt\BasicShopifyAPI\Session; // Create options for the API $options = new Options(); $options->setVersion('2020-01'); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session('example.myshopify.com', 'access-token-here')); // Now run your requests... $promise = $api->graphAsync(...); $promise->then(function (array $result) { // ... });
获取访问权限(离线)
这是默认模式,返回永久令牌。
在获取用户的商店域名后,然后使用 getAuthUrl
将他们引导到授权屏幕,例如(基本的 PHP)
// Create options for the API $options = new Options(); $options->setVersion('2020-01'); $options->setApiKey(env('SHOPIFY_API_KEY')); $options->setApiSecret(env('SHOPIFY_API_SECRET')); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session($_SESSION['shop'])); $code = $_GET['code']; if (!$code) { /** * No code, send user to authorize screen * Pass your scopes as an array for the first argument * Pass your redirect URI as the second argument */ $redirect = $api->getAuthUrl(env('SHOPIFY_API_SCOPES'), env('SHOPIFY_API_REDIRECT_URI')); header("Location: {$redirect}"); exit; } else { // We now have a code, lets grab the access token $api->requestAndSetAccess($code); // You can now make API calls $request = $api->rest('GET', '/admin/shop.json'); // or GraphQL }
获取访问权限(按用户)
您还可以将授权模式更改为按用户
,如Shopify文档中所述。这将接收Shopify商店中应用程序用户的用户信息。收到的令牌将在特定时间过期。
// Create options for the API $options = new Options(); $options->setVersion('2020-01'); $options->setApiKey(env('SHOPIFY_API_KEY')); $options->setApiSecret(env('SHOPIFY_API_SECRET')); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session($_SESSION['shop'])); $code = $_GET['code']; if (!$code) { /** * No code, send user to authorize screen * Pass your scopes as an array for the first argument * Pass your redirect URI as the second argument * Pass your grant mode as the third argument */ $redirect = $api->getAuthUrl(env('SHOPIFY_API_SCOPES'), env('SHOPIFY_API_REDIRECT_URI'), 'per-user'); header("Location: {$redirect}"); exit; } else { // We now have a code, lets grab the access object $api->requestAndSetAccess($code); // You can now make API calls $request = $api->rest('GET', '/admin/shop.json'); // or GraphQL }
验证HMAC签名
只需传入一个GET参数数组。
// Will return true or false if HMAC signature is good. $valid = $api->verifyRequest($_GET);
私有API
这假设您已在合作伙伴仪表板中正确设置了应用,并具有正确的密钥和重定向 URI。
REST
对于REST(同步)调用,需要请求商店域名、API密钥和API密码。
// Create options for the API $options = new Options(); $options->setType(true); // Makes it private $options->setVersion('2020-01'); $options->setApiKey(env('SHOPIFY_API_KEY')); $options->setApiPassword(env('SHOPIFY_API_PASSWORD')); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session($_SESSION['shop'])); // Now run your requests... $result = $api->rest(...);
GraphQL
对于GraphQL调用,需要商店域名和API密码。
// Create options for the API $options = new Options(); $options->setType(true); // Makes it private $options->setVersion('2020-01'); $options->setApiPassword(env('SHOPIFY_API_PASSWORD')); // Create the client and session $api = new BasicShopifyAPI($options); $api->setSession(new Session($_SESSION['shop'])); // Now run your requests... $result = $api->graph(...);
发送请求
REST
使用Guzzle发送请求。
$api->rest(string $type, string $path, array $params = null, array $headers = [], bool $sync = true); // or $api->getRestClient()->request(....);
type
指的是GET、POST、PUT、DELETE等。path
指的是API路径,例如:/admin/products/1920902.json
params
指的是要传递到路径的参数数组,例如:['handle' => 'cool-coat']
headers
指的是要随请求发送的自定义头数组,例如:['X-Shopify-Test' => '123']
sync
指的是请求是否为同步或异步。
您可以使用别名restAsync
来跳过将sync
设置为false
。
如果sync为true(常规REST调用)
请求的返回值将是一个包含
response
完整的Guzzle响应对象body
JSON解码后的响应体(\Gnikyt\BasicShopifyAPI\ResponseAccess实例)errors
如果检测到任何错误,true/falseexception
如果错误为true,则异常对象是可用的status
HTTP状态码link
一个包含先前/下一个分页值的数组,如果有的话
注意:request()
将别名到rest()
。
如果sync为false(restAsync调用)
请求的返回值将是一个Guzzle承诺,您可以自行处理。
承诺的返回值将是一个包含的对象
response
完整的Guzzle响应对象body
JSON解码后的响应体(\Gnikyt\BasicShopifyAPI\ResponseAccess实例)errors
如果检测到任何错误,true/falseexception
如果错误为true,则异常对象是可用的status
HTTP状态码link
一个包含先前/下一个分页值的数组,如果有的话
$promise = $api->restAsync(...); $promise->then(function (array $result) { // `response` and `body`, etc are available in `$result`. });
重写请求类型
如果您需要强制在非GET端点上使用查询字符串,例如,您可以指定类型为一个键。
$api->rest('PUT', '/admin/themes/12345/assets.json', ['query' => [...]]);
有效的键是query
和json
。
传递额外的请求选项
如果您想向创建的Guzzle客户端传递额外的请求选项,请将它们作为构造函数的第二个参数传递。
// Create options for the API $options = new Options(); $options->setVersion('2020-01'); // ... $options->setGuzzleOptions(['connect_timeout' => 3.0]); // Create the client $api = new BasicShopifyApi($options);
GraphQL
使用Guzzle发送请求。
$api->graph(string $query, array $variables = []);
query
指的是完整的GraphQL查询variables
指的是查询中使用的变量(如果有)
请求的返回值将是一个包含的对象
response
完整的Guzzle响应对象body
JSON解码后的响应体(\Gnikyt\BasicShopifyAPI\ResponseAccess实例)errors
如果有错误或没有,如果有错误,将返回错误status
HTTP状态码
示例查询
$result = $api->graph('{ shop { product(first: 1) { edges { node { handle, id } } } } }'); echo $result['body']['shop']['products']['edges'][0]['node']['handle']; // test-product // or echo $result['body']->shop->products->edges[0]->node->handle;
示例突变
$result = $api->graph( 'mutation collectionCreate($input: CollectionInput!) { collectionCreate(input: $input) { userErrors { field message } collection { id } } }', ['input' => ['title' => 'Test Collection']] ); echo $result['body']['collectionCreate']['collection']['id']; // gid://shopify/Collection/63171592234 // or echo $result['body']->collectionCreate->collection->id;
API 版本控制
此库支持请求版本控制,例如
// Create options for the API $options = new Options(); $options->setVersion('2020-01'); // YYYY-MM or "unstable" is accepted // Create the client $api = new BasicShopifyAPI($options);
您可以在任何时候覆盖特定 API 请求的版本控制,例如
// Create options for the API $options = new Options(); $options->setVersion('2020-01'); // Create the client $api = new BasicShopifyAPI($options); $api->rest('GET', '/admin/api/unstable/shop.json'); // Will ignore "2020-01" version and use "unstable" for this request
速率限制
此库内置了基本的速率限制器,它会在适用的调用之间使用 usleep
。
- 对于 REST:它确保您每秒不超过 2 次调用。
- 对于 GraphQL:它确保您每秒不超过 50 个点。
要调整默认限制,请使用选项类的 setRestLimit
和 setGraphLimit
。
自定义速率限制
您只需禁用内置的速率限制器,并推送自定义 Guzzle 中间件。示例
$options = new Options(); // ... $options->disableRateLimiting(); // ... $api = new BasicShopifyAPI($options); $api->addMiddleware(new CustomRateLimiter($api), 'rate:limiting');
page_info / 分页支持
2019-07 API 版本引入了新的 Link
头部,用于分页(此处解释)。
如果端点支持 page_info,您可以使用 $response->link
获取 page_info 值,以便传递到下一个请求。
示例
$response = $api->rest('GET', '/admin/products.json', ['limit' => 5]); $link = $response['link']['next']; // eyJsYXN0X2lkIjo0MDkw $link2 = $response['link']['previous']; // dkUIsk00wlskWKl $response = $api->rest('GET', '/admin/products.json', ['limit' => 5, 'page_info' => $link]);
隔离的 API 调用
您只需初始化 API 一次,然后就可以用于多个商店。每个实例都将保持独立,不会相互干扰。这对于像后台作业处理这样的任务很有用。
$api->withSession(Session $newSession, Closure $closure);
$this
将绑定到闭包。示例
$api->withSession(new Session('someshop.myshopify.com', 'some-token'), function (): void { $request = $this->rest('GET', '/admin/shop.json'); echo $request['body']['shop']['name']; // Some Shop }); // $api->rest/graph will not be affected by the above code, it will use previously defined session
重试
此库利用 caseyamcl/guzzle_retry_middleware
中间件包。
默认情况下,将重试 429
、500
和 503
错误两次。
对于 REST 调用,它将利用 Shopify 的 X-Retry-After
头部在重试调用之前等待 x 秒。
当所有重试耗尽后,库的标准响应将返回,您可以在其中处理错误。
要更改监视的状态代码或最大重试次数,请使用选项类的 setGuzzleOptions
// Create options for the API $options = new Options(); $options->setVersion('2020-01'); // ... $options->setGuzzleOptions( 'max_retry_attempts' => 3, // Was 2 'retry_on_status' => [429, 503, 400], // Was 439, 503, 500 ); // Create the client $api = new BasicShopifyApi($options);
错误
此库内部只捕获通过 Guzzle 的 400-500 状态范围错误。您可以检查此类错误并获取其响应状态代码和正文。
$call = $api->rest('GET', '/admin/non-existant-route-or-object.json'); if ($call['errors']) { echo "Oops! {$call['status']} error"; var_dump($call['body']); // Original exception can be accessed via `$call['exception']` // Example, if response body was `{"error": "Not found"}`... /// then: `$call['body']` would return "Not Found" }
中间件
此库利用 Guzzle 中间件进行请求/响应检查和修改。您还可以注入中间件。
$api->addMiddleware([callable]);
请参阅 Guzzle 的中间件文档。此外,您还可以浏览此库的中间件以获取示例。
存储
用于存储当前请求时间、API 限制、请求成本等。使用基本内存数组存储 Gnikyt\BasicShopifyAPI\Store\Memory
。
如果您想实现更高级的存储,例如使用 Redis,只需实现 Gnikyt\BasicShopifyAPI\Contracts\StateStorage
并设置客户端使用它,示例
$timeStore = new RedisStore(); $limitStore = new RedisStore(); $api = new BasicShopifyAPI($options, $timeStore, $limitStore);
文档
代码文档可以通过phpDocumentor生成并在此处获取,使用命令phpdoc -d src -t doc
。
许可证
本项目遵循MIT许可证发布。
杂项
使用Python?请查看basic_shopify_api。