seka19 / basic-shopify-api
一个基本的 Shopify API 包装器,支持 REST 和 GraphQL。
Requires
- php: >=7.1.0
- guzzlehttp/guzzle: ^6.3
- guzzlehttp/promises: ^1.3
- psr/log: ^1.1
Requires (Dev)
- phpdocumentor/phpdocumentor: 2.*
- phpunit/phpunit: ^6.2
- squizlabs/php_codesniffer: ^3.0
- dev-fix-logging
- v8.2.0
- v8.1.0
- v8.0.0
- v7.0.0
- v6.2.0
- v6.1.6
- v6.1.5
- v6.1.4
- 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-develop
- dev-fix-request-verification-2
- dev-master
- dev-fix-request-verification
- dev-rewrite
This package is auto-updated.
Last update: 2024-09-10 19:11:23 UTC
README
一个简单的、经过测试的 Shopify API 包装器,使用 Guzzle 实现。它支持 Shopify 提供的 REST 和 GraphQL API,以及基本的速率限制能力。它包含生成安装 URL、授权 URL(离线和按用户)、HMAC 签名验证、调用限制和 API 请求的有用方法。它与 OAuth 和私有 API 应用程序一起工作。
还支持:通过 Guzzle 的承诺进行异步请求。
此库需要 PHP >= 7。
目录
安装
推荐的安装方式是 通过 composer。
$ composer require ohmybrew/basic-shopify-api
用法
将 use OhMyBrew\BasicShopifyAPI;
添加到您的导入中。
公共 API
这假设您已在合作伙伴仪表板中正确设置了应用程序,并具有正确的密钥和重定向 URI。
REST(同步)
对于 REST 调用,需要商店域名和访问令牌。
$api = new BasicShopifyAPI(); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop('your shop here'); $api->setAccessToken('your token here'); // Now run your requests... $resul = $api->rest(...);
REST(异步)
对于 REST 调用,需要商店域名和访问令牌。
$api = new BasicShopifyAPI(); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop('your shop here'); $api->setAccessToken('your token here'); // Now run your requests... $promise = $api->restAsync(...); $promise->then(function ($result) { // ... });
GraphQL
对于 GraphQL 调用,需要商店域名和访问令牌。
$api = new BasicShopifyAPI(); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop('your shop here'); $api->setAccessToken('your token here'); // Now run your requests... $api->graph(...);
获取访问权限(离线)
这是默认模式,返回永久令牌。
在获取用户的商店域名后,然后使用 getAuthUrl
将其重定向到授权屏幕,例如(基本的 PHP)
$api = new BasicShopifyAPI(); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop($_SESSION['shop']); $api->setApiKey(env('SHOPIFY_API_KEY')); $api->setApiSecret(env('SHOPIFY_API_SECRET')); $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); // Above is equiv. to: // // $access = $api->requestAccess($code); // $api->setAccessToken($access->access_token); // // You can use: $api->getAccessToken() and set it into the database or a cookie, etc // You can now make API callsn` $request = $api->rest('GET', '/admin/shop.json'); // or GraphQL }
获取访问权限(按用户)
您还可以将授权模式更改为 per-user
,如 Shopify 文档中概述。这将接收 Shopify 商店中应用程序用户的用户信息。收到的令牌将在特定时间到期。
$api = new BasicShopifyAPI(); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop($_SESSION['shop']); $api->setApiKey(env('SHOPIFY_API_KEY')); $api->setApiSecret(env('SHOPIFY_API_SECRET')); $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); // Above is equiv. to: // // $access = $api->requestAccess($code); // $api->setAccessToken($access->access_token); // $api->setUser($access->associated_user) // // You can use: $api->getAccessToken() and set it into a cookie, etc // You can also get user details with: $api->getUser(), example: $api->getUser()->email // 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 密码。
$api = new BasicShopifyAPI(true); // true sets it to private $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop('example.myshopify.com'); $api->setApiKey('your key here'); $api->setApiPassword('your password here'); // Now run your requests... $result = $api->rest(...);
GraphQL
对于 GraphQL 调用,需要商店域名和 API 密码。
$api = new BasicShopifyAPI(true); // true sets it to private $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setShop('example.myshopify.com'); $api->setApiPassword('your password here'); // Now run your requests... $api->graph(...);
发送请求
REST
请求使用 Guzzle 发送。
$api->rest(string $type, string $path, array $params = null, array $headers = [], bool $sync = true);
type
指的是 GET、POST、PUT、DELETE 等path
指的是 API 路径,例如:/admin/products/1920902.json
params
指的是要传递到路径的参数数组,例如:['handle' => 'cool-coat']
headers
指的是要随请求一起发送的自定义头数组,例如:['X-Shopify-Test' => '123']
sync
指的是请求是否应该是同步的。
您可以使用别名 restAsync
来跳过将 sync
设置为 false
。
如果同步为 true(常规 REST 调用)
请求的返回值将是一个包含的对象
response
是完整的 Guzzle 响应对象body
是解析后的 JSON 响应体
注意: request()
将别名到 rest()
。
如果同步为 false(restAsync 调用)
请求的返回值将是一个 Guzzle 承诺,您可以自己处理。
承诺的返回值将是一个包含的对象
response
是完整的 Guzzle 响应对象body
是解析后的 JSON 响应体
$promise = $api->restAsync(...); $promise->then(function ($result) { // `response` and `body` available in `$result`. });
GraphQL
请求使用 Guzzle 发送。
$api->graph(string $query, array $variables = []);
query
指的是完整的 GraphQL 查询variables
指的是用于查询的变量(如果有)
请求的返回值将是一个包含的对象
response
是完整的 Guzzle 响应对象body
是解析后的 JSON 响应体errors
如果有错误或没有错误
示例查询
$result = $api->graph('{ shop { productz(first: 1) { edges { node { handle, id } } } } }'); echo $result->body->shop->products->edges[0]->node->handle; // test-product
示例突变
$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
API 版本控制
这个库支持请求版本控制,例如
$api = new BasicShopifyAPI(true); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" // ... your code
您可以在任何时候覆盖特定API请求的版本控制,例如
$api = new BasicShopifyAPI(true); $api->setVersion('2019-04'); $api->rest('GET', '/admin/api/unstable/shop.json'); // Will ignore "2019-04" version and use "unstable" for this request // ... your code
检查 API 限制
每次请求后,API调用限制都会更新。要访问它们,只需使用
// Returns an array of left, made, and limit. // Example: ['left' => 79, 'made' => 1, 'limit' => 80] $limits = $api->getApiCalls('rest'); // or 'graph'
对于GraphQL,还有以下值:restoreRate
、requestedCost
、actualCost
。
要快速获取值,您可以在getApiCalls
方法中传递一个可选参数
// As example, this will return 79 // You may pass 'left', 'made', or 'limit' $left = $api->getApiCalls('graph', 'left'); // returns 79 // or $left = $api->getApiCalls('graph')['left']; // returns 79
速率限制
此库内置了一个基本速率限制器,默认禁用。它会暂停x微秒以确保您不会超过与Shopify的调用限制。在非Plus计划中,每500毫秒有1次调用(每秒2次),对于Plus计划,每500毫秒有2次调用(每秒4次)。
默认周期设置为500毫秒,并额外添加了100毫秒的安全缓冲。
启用速率限制
按正常方式设置API实例,并添加了
$api->enableRateLimiting();
这将在默认500毫秒周期和100毫秒缓冲的情况下开启速率限制。要更改此设置,请按照以下步骤操作
$api->enableRateLimiting(0.25 * 1000, 0);
这会将周期设置为250毫秒和0毫秒缓冲。
禁用速率限制
如果您之前已启用它,您只需运行
$api->disableRateLimiting();
检查速率限制状态
$api->isRateLimitingEnabled();
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]);
获取时间戳
该库将跟踪前一个和当前(最后一个)调用的时间戳。要查看此信息
$response = $api->rest('POST', '/admin/gift_cards.json', ['gift_cards' => ['initial_value' => 25.00]]); print_r($response->timestamps); /* Above will return an array of [previous call, current (last) call], example: * [1541119962.965, 1541119963.3121] */
隔离 API 调用
您可以使用API初始化一次,然后用于多个商店。每个实例都将包含在各自的实例中,以避免相互干扰。这对于像后台作业处理这样的任务很有用。
$api->withSession(string $shop, string $accessToken, Closure $closure);
shop
指代Shopify域名accessToken
指代API调用的访问令牌closure
指代用于会话的闭包
$this
将被绑定到当前API。例如
$api = new BasicShopifyAPI(true); $api->setVersion('2019-04'); // "YYYY-MM" or "unstable" $api->setApiKey('your key here'); $api->setApiPassword('your password here'); $api->withSession('some-shop.myshopify.com', 'token from database?', function() { $request = $this->rest('GET', '/admin/shop.json'); echo $request->body->shop->name; // Some Shop }); $api->withSession('some-shop-two.myshopify.com', 'token from database?', function() { $request = $this->rest('GET', '/admin/shop.json'); echo $request->body->shop->name; // Some Shop Two });
错误
此库通过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" }
日志记录
此库接受PSR兼容的日志记录器。
$api->setLogger(... your logger instance ...);
文档
代码文档在此处可用:phpDocumentor通过phpdoc -d src -t doc
。
许可证
该项目根据MIT许可证发布。