{"id":13546436,"url":"https://github.com/donutdan4114/shopify","last_synced_at":"2025-04-05T09:10:34.177Z","repository":{"id":37547601,"uuid":"45628706","full_name":"donutdan4114/shopify","owner":"donutdan4114","description":"Shopify PHP SDK to easily interact with the Shopify API.","archived":false,"fork":false,"pushed_at":"2024-08-21T03:45:49.000Z","size":79,"stargazers_count":85,"open_issues_count":17,"forks_count":39,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-03-29T08:11:12.367Z","etag":null,"topics":["shopify","shopify-api","shopify-php-sdk"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/donutdan4114.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-05T17:45:59.000Z","updated_at":"2024-02-28T06:42:58.000Z","dependencies_parsed_at":"2024-11-03T14:41:51.713Z","dependency_job_id":null,"html_url":"https://github.com/donutdan4114/shopify","commit_stats":{"total_commits":68,"total_committers":8,"mean_commits":8.5,"dds":0.4558823529411765,"last_synced_commit":"ec104ccd91b81c5f90383f9377c37079b2daba81"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donutdan4114%2Fshopify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donutdan4114%2Fshopify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donutdan4114%2Fshopify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donutdan4114%2Fshopify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/donutdan4114","download_url":"https://codeload.github.com/donutdan4114/shopify/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247312085,"owners_count":20918344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["shopify","shopify-api","shopify-php-sdk"],"created_at":"2024-08-01T12:00:37.346Z","updated_at":"2025-04-05T09:10:34.150Z","avatar_url":"https://github.com/donutdan4114.png","language":"PHP","funding_links":[],"categories":["Libraries","库"],"sub_categories":["PHP"],"readme":"# Shopify PHP SDK\nA simple Shopify PHP SDK for private apps to easily interact with the Shopify API.  \n[![Travis Build Status](https://travis-ci.org/donutdan4114/shopify.svg?branch=master)](https://travis-ci.org/donutdan4114/shopify)\n\n[Shopify API Documentation](https://docs.shopify.com/api) | [Packagist](https://packagist.org/packages/donutdan4114/shopify) | [Build Status](https://travis-ci.org/donutdan4114/shopify)\n\nFeatures include:\n\n* ability to easily GET, PUT, POST and DELETE resources\n* process and validate incoming webhooks\n* automatic rate limiting to avoid API calls from erroring\n\n## Setup/Installation\nDepends on [guzzlehttp/guzzle](https://packagist.org/packages/guzzlehttp/guzzle).  \nGet via Composer...\n\nGet a stable release:  \n`composer require donutdan4114/shopify:v2020.01.*`\n\nGet the latest unstable version:  \n`composer require donutdan4114/shopify:dev-master`\n\n## API Versions\nThis package now includes versions that match Shopify's API version naming convention.\nVersion format is `vYYYY.MM.V#` where increasing the `V#` will not break backwards compatibility.\nCheck the changelog in releases to see what changes may break backwards compatability.\n\n\n## New in Version 2020.01\nThis update utilizes the new pagination system in the Shopify API. The `page` query param is no longer supported.\nThe \"resource pager\" which automatically loops through pages will handle this change automatically for you.\n\nIf you have custom code using the `page` param you'll need to update your code like:\n```php\n$client = new Shopify\\PublicApp(/* $args */);\n\n// Get the first 25 products.\n$result = $client-\u003eget('products', ['query' =\u003e ['limit' =\u003e 25]]);\n\n// If you're paginating in the same request directly after the first API call\n// you can simply use the getNextPage() method.\nif ($client-\u003ehasNextPage()){\n  // Get the next 25 products.\n  $result = $client-\u003egetNextPage();\n}\n\n// If you're doing multiple page requests or client requests you\n// will need to keep track of the page_info params yourself.\n$page_info = $client-\u003egetNextPageParams();\n\n// To get the next page you can now just pass $page_info into the query.\n// This will get the next 25 products (\"limit\" is automatically set).\n$result = $client-\u003eget('products', ['query' =\u003e $page_info]);\n```\n\n## Private \u0026 Public Apps\nYou can use this library for private or public app creation. Using private apps is easier because their is no `access_token` required.\nHowever, if you want to create a publicly accessible app, you must use the Public App system.\n\n### Private App\nSimply instantiate a private app with the `shop_domain`, `api_key`, `password`, and `shared_secret`.\n```php\n$client = new Shopify\\PrivateApp($SHOPIFY_SHOP_DOMAIN, $SHOPIFY_API_KEY, $SHOPIFY_PASSWORD, $SHOPIFY_SHARED_SECRET);\n$result = $client-\u003eget('shop');\n```\n### Public App\nYou must first setup a public app. [View documentation](https://docs.shopify.com/api/introduction/getting-started).\nYou need an authorization URL.\n\n```php\nsession_start();\n$client = new Shopify\\PublicApp($_GET['shop'], $APP_API_KEY, $APP_SECRET);\n\n// You set a random state that you will confirm later.\n$random_state = 'client-id:' . $_SESSION['client_id'];\n\n$client-\u003eauthorizeUser('[MY_DOMAIN]/redirect.php', [\n  'read_products',\n  'write_products',\n], $random_state);\n```\n\nAt this point, the user is taken to their store to authorize the application to use their information.\nIf the user accepts, they are taken to the redirect URL.\n\n```php\nsession_start();\n$client = new Shopify\\PublicApp($_GET['shop'], $APP_API_KEY, $APP_SECRET);\n\n// Used to check request data is valid.\n$client-\u003esetState('client-id:' . $_SESSION['client_id']);\n\nif ($token = $client-\u003egetAccessToken()) {\n  $_SESSION['shopify_access_token'] = $token;\n  $_SESSION['shopify_shop_domain'] = $_GET['shop'];\n  header(\"Location: dashboard.php\");\n}\nelse {\n  die('invalid token');\n}\n\n```\n\nIt's at this point, in **dashboard.php** you could starting doing API request by setting the `access_token`.\n\n```php\nsession_start();\n$client = new Shopify\\PublicApp($_SESSION['shopify_shop_domain'], $APP_API_KEY, $APP_SECRET);\n$client-\u003esetAccessToken($_SESSION['shopify_access_token']);\n$products = $client-\u003egetProducts();\n```\n\n---\n\n## Methods\n### GET\nGet resource information from the API.\n```php\n$client = new Shopify\\PrivateApp($SHOPIFY_SHOP_DOMAIN, $SHOPIFY_API_KEY, $SHOPIFY_PASSWORD, $SHOPIFY_SHARED_SECRET);\n$result = $client-\u003eget('shop');\n```\n`$result` is a JSON decoded `stdClass`:\n```\nobject(stdClass)#33 (1) {\n  [\"shop\"]=\u003e\n  object(stdClass)#31 (44) {\n    [\"id\"]=\u003e\n    int([YOUR_SHOP_ID])\n    [\"name\"]=\u003e\n    string(15) \"[YOUR_SHOP_NAME]\"\n    [\"email\"]=\u003e\n    string(22) \"[YOUR_SHOP_EMAIL]\"\n    [\"domain\"]=\u003e\n    string(29) \"[YOUR_SHOP_DOMAIN]\"\n    ...\n  }\n}\n```\nGet product IDs by passing query params:\n```php\n$result = $client-\u003eget('products', ['query' =\u003e ['fields' =\u003e 'id']]);\nforeach($result-\u003eproducts as $product) {\n  print $product-\u003eid;\n}\n```\n\n### POST\nCreate new content with a POST request.\n```php\n$data = ['product' =\u003e ['title' =\u003e 'my new product']];\n$result = $client-\u003epost('products', $data);\n```\n\n### PUT\nUpdate existing content with a given ID.\n```php\n$data = ['product' =\u003e ['title' =\u003e 'updated product name']];\n$result = $client-\u003eput('products/' . $product_id, $data);\n```\n\n### DELETE\nEasily delete resources with a given ID.\n```php\n$client-\u003edelete('products/' . $product_id);\n```\n\n## Simple Wrapper\nTo make it easier to work with common API resources, there are several short-hand functions.\n```php\n// Get shop info.\n$shop_info = $client-\u003egetShopInfo();\n\n// Get a specific product.\n$product = $client-\u003egetProduct($product_id);\n\n// Delete a specific product.\n$client-\u003edeleteProduct($product_id);\n\n// Create a product.\n$product = $client-\u003ecreateProduct(['title' =\u003e 'my new product']);\n\n// Count products easily.\n$count = $client-\u003egetProductsCount(['updated_at_min' =\u003e time() - 3600]);\n\n// Easily get all products without having to worry about page limits.\n$products = $client-\u003egetProducts();\n\n// This will fetch all products and will make multiple requests if necessary.\n// You can easily supply filter arguments.\n$products = $client-\u003egetProducts(['query' =\u003e ['vendor' =\u003e 'MY_VENDOR']]);\n\n// For ease-of-use, you should use the getResources() method to automatically handle Shopify's pagination.\n// This will ensure that if there are over 250 orders, you get them all returned to you.\n$orders = $client-\u003egetResources('orders', ['query' =\u003e ['fields' =\u003e 'id,billing_address,customer']]);\n\n// If efficiency and memory limits are a concern,  you can loop over results manually.\nforeach ($this-\u003eclient-\u003egetResourcePager('products', 25) as $product) {\n  // Fetches 25 products at a time.\n  // If you have 500 products, this will create 20 separate requests for you.\n  // PHP memory will only be storing 25 products at a time, which keeps thing memory-efficient.\n}\n```\n\n## Parsing Incoming Webhooks\nIf you have a route setup on your site to accept incoming Shopify webhooks, you can easily parse the data and validate the contents.\nThere are two ways to validate webhooks: manually, or using the client.\n\n```php\n// Process webhook manually.\n$webhook = new Shopify\\IncomingWebhook($SHOPIFY_SHARED_SECRET);\ntry {\n  $webhook-\u003evalidate();\n  $data = $webhook-\u003egetData();\n} catch (Shopify\\WebhookException $e) {\n  // Errors means you should not process the webhook data.\n  error_log($e-\u003egetMessage());\n}\n\n// Process webhook using the $client.\ntry {\n  $data = $client-\u003egetIncomingWebhook($validate = TRUE);\n} catch (Shopify\\ClientException $e) {\n  error_log($e-\u003egetMessage());\n}\nif (!empty($data)) {\n  // Do something with the webhook data.\n}\n```\n\n## Error Handling\nAny API error will throw an instance of `Shopify\\ClientException`.\n```php\ntry {\n  $response = $client-\u003eput('products/BAD_ID');\n} catch (Shopify\\ClientException $e) {\n  // Get request errors.\n  error_log($e-\u003egetErrors());\n  // Get last response object.\n  $last_response = $e-\u003egetLastResponse();\n  $code = $e-\u003egetCode();\n  $code = $last_response-\u003egetStatusCode();\n}\n```\n\n## API Limit Handling\nThis class can handle API rate limiting for you based on Shopify's \"leaky bucket\" algorithm.\nIt will automatically slow down requests to not hit the rate limiter.\nYou can disabled this with:\n```php\n$client-\u003erate_limit = FALSE;\n```\nYou can put in your own rate limiting logic using the `$client-\u003egetCallLimit()` and `$client-\u003ecallLimitReached()` methods.\n\n## Testing\nTests can be run with `phpunit`.\nSince the tests actually modify the connected store, you must explicitly allow tests to be run by settings `SHOPIFY_ALLOW_TESTS` environment variable to `TRUE`.\nWithout that, you will be get a message like:\n```\nShopify tests cannot be run.\nRunning Shopify tests will delete all connected store info.\nSet environment variable SHOPIFY_ALLOW_TESTS=TRUE to allow tests to be run.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonutdan4114%2Fshopify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdonutdan4114%2Fshopify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonutdan4114%2Fshopify/lists"}