studio98 / basic-shopify-api
一个基本的 Shopify API 包装器,支持 REST 和 GraphQL,由 Guzzle 提供。
Requires
- php: >=7.2.0
- caseyamcl/guzzle_retry_middleware: ^2.3
- guzzlehttp/guzzle: ^6.5|^7.0
Requires (Dev)
- phpdocumentor/phpdocumentor: ^3.0
- phpunit/phpunit: ^6.2|^9.3
- squizlabs/php_codesniffer: ^3.5
- dev-master
- 10.0.x-dev
- 10.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
This package is auto-updated.
Last update: 2024-09-25 01:54:41 UTC
README
一个简单的、经过测试的 Shopify API 包装器,使用 Guzzle。
它支持 Shopify 提供的同步/异步 REST 和 GraphQL API,基本速率限制和请求重试。
它包含生成安装 URL、授权 URL(离线和按用户)、HMAC 签名验证、调用限制和 API 请求的有用方法。
它与 OAuth 和私有 API 应用程序一起工作。
目录
安装
推荐的安装方式是 通过 composer。
composer require studdio98/basic-shopify-api
用法
公共 API
这假设您已在合作伙伴仪表板中正确设置您的应用程序,并具有正确的密钥和重定向 URI。
REST(同步)
对于 REST 调用,需要商店域名和访问令牌。
use Osiset\BasicShopifyAPI\BasicShopifyAPI; use Osiset\BasicShopifyAPI\Options; use Osiset\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 Osiset\BasicShopifyAPI\BasicShopifyAPI; use Osiset\BasicShopifyAPI\Options; use Osiset\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 Osiset\BasicShopifyAPI\BasicShopifyAPI; use Osiset\BasicShopifyAPI\Options; use Osiset\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 Osiset\BasicShopifyAPI\BasicShopifyAPI; use Osiset\BasicShopifyAPI\Options; use Osiset\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 }
获取访问权限(按用户)
您还可以将授权模式更改为 per-user,如 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->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.jsonparams指的是您希望传递到路径的参数数组,例如:['handle' => 'cool-coat']headers指的是您希望与请求一起发送的自定义头数组,例如:['X-Shopify-Test' => '123']sync指的是请求是否应该是同步的或异步的。
您可以使用别名 restAsync 来跳过将 sync 设置为 false。
如果同步为真(常规 REST 调用)
请求的返回值将是一个包含以下内容的数组
response完整的 Guzzle 响应对象bodyJSON 解码的响应正文(\Osiset\BasicShopifyAPI\ResponseAccess 实例)errors如果检测到任何错误,则为 true/falseexception如果 errors 为真,则异常对象可用statusHTTP 状态码link如果可用,则包含先前/下一个分页值的数组
注意:request() 也会重命名为 rest()。
如果同步为假(restAsync 调用)
请求的返回值将是一个 Guzzle 承诺,您可以自行处理。
承诺的返回值将是一个包含的对象
response完整的 Guzzle 响应对象bodyJSON 解码的响应正文(\Osiset\BasicShopifyAPI\ResponseAccess 实例)errors如果检测到任何错误,则为 true/falseexception如果 errors 为真,则异常对象可用statusHTTP 状态码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 响应对象bodyJSON 解码的响应正文(\Osiset\BasicShopifyAPI\ResponseAccess 实例)errors如果有错误或没有错误,如果有错误则返回错误statusHTTP 状态码
示例查询
$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 限制、请求成本等,使用了一个基本的内存数组存储 Osiset\BasicShopifyAPI\Store\Memory。
如果您想实现一个更高级的存储,例如带有 Redis 的存储,只需实现 Osiset\BasicShopifyAPI\Contracts\StateStorage 并将客户端设置为使用它,示例
$redisStore = new RedisStore($connection); $api = new BasicShopifyAPI($options, $redisStore, $redisStore, $redisStore);
文档
代码文档在此处提供,通过 phpDocumentor 的 phpdoc -d src -t doc。
许可证
此项目在 MIT许可下发布。
其他
使用 Python?请查看 basic_shopify_api。