zfr/zfr-shopify

用于与Shopify REST API交互的PHP库

6.9.0 2023-07-15 03:48 UTC

README

Latest Stable Version Build Status

ZfrShopify是一个基于Guzzle的现代PHP库,用于Shopify

依赖项

安装

仅支持使用Composer安装ZfrShopify

php composer.phar require 'zfr/zfr-shopify:6.0'

REST API

ZfrShopify提供了与Shopify文档中定义的API方法的1:1映射。自版本4起,它还支持与新的GraphQL管理员API的基本集成。

私有应用

为了将ZfrShopify作为私有应用使用,您必须首先实例化客户端

$shopifyClient = new ShopifyClient([
    'private_app' => true,
    'api_key'     => 'YOUR_API_KEY',
    'password'    => 'YOUR_PASSWORD',
    'shop'        => 'domain.myshopify.com',
    'version'     => '2019-04'
]);

务必始终包含版本号。关于Shopify版本信息的更多信息

公开应用

当使用公开应用时,您以不同的方式实例化客户端

$shopifyClient = new ShopifyClient([
    'private_app'   => false,
    'api_key'       => 'YOUR_API_KEY', // In public app, this is the app ID
    'access_token'  => 'MERCHANT_TOKEN',
    'shop'          => 'merchant.myshopify.com',
    'version'       => '2019-04'
]);

务必始终包含版本号。关于Shopify版本信息的更多信息

使用容器

ZfrShopify还提供了内置的container-interop工厂,您可以使用。您必须确保您的容器包含一个名为"config"的服务,它是一个包含键zfr_shopify的数组,包含所需的配置

// myconfig.php

return [
    'zfr_shopify' => [
        'private_app'   => false,
        'api_key'       => 'YOUR_API_KEY', // In public app, this is the app ID
        'access_token'  => 'MERCHANT_TOKEN',
        'shop'          => 'merchant.myshopify.com',
    ],
];

如果您使用的是Zend\ServiceManager 3,您可以使用Zend\ComponentInstaller将我们的工厂自动注册到Zend\ServiceManager中。

但是,如果您使用的是其他框架或其他容器,您仍然可以手动注册我们的工厂,它们位于src/Container文件夹中。

验证请求

ZfrShopify客户端提供了一个简单的方法来验证传入的请求,以确保它来自Shopify通过RequestValidator对象。它需要一个PSR7请求和一个共享密钥

use ZfrShopify\Exception\InvalidRequestException;
use ZfrShopify\Validator\RequestValidator;

$validator = new RequestValidator();

try {
    $validator->validateRequest($psr7Request, 'shared_secret');
} catch (InvalidRequestException $exception) {
    // Request is not valid
}

验证webhook

同样,您可以使用WebhookValidator来验证您的webhook

use ZfrShopify\Exception\InvalidWebhookException;
use ZfrShopify\Validator\WebhookValidator;

$validator = new WebhookValidator();

try {
    $validator->validateWebhook($psr7Request, 'shared_secret');
} catch (InvalidWebhookException $exception) {
    // Request is not valid
}

验证应用请求

最后,您还可以使用ApplicationProxyRequestValidator来验证应用代理请求

use ZfrShopify\Exception\InvalidApplicationProxyRequestException;
use ZfrShopify\Validator\ApplicationProxyRequestValidator;

$validator = new ApplicationProxyRequestValidator();

try {
  $validator->validateApplicationProxyRequest($psr7Request, 'shared_secret');
} catch {
  // Request is not valid
}

创建授权响应

ZfrShopify提供了一个简单的方法来创建PSR7兼容的ResponseInterface以创建授权响应

use ZfrShopify\OAuth\AuthorizationRedirectResponse;

$apiKey         = 'app_123';
$shopDomain     = 'shop_to_authorize.myshopify.com';
$scopes         = ['read_orders', 'read_products'];
$redirectionUri = 'https://myapp.test.com/oauth/redirect';
$nonce          = 'strong_nonce';

$response = new AuthorizationRedirectResponse($apiKey, $shopDomain, $scopes, $redirectionUri, $nonce);

虽然nonce参数是必需的,但ZfrShopify不会对如何保存nonce和当Shopify重定向到您的服务器时如何检查nonce做出任何假设。您负责安全地保存nonce。

用代码换取访问令牌

您可以使用TokenExchanger类将代码兑换成长期访问令牌

use GuzzleHttp\Client;
use ZfrShopify\OAuth\TokenExchanger;

$apiKey         = 'app_123';
$sharedSecret   = 'secret_123';
$shopDomain     = 'shop_to_authorize.myshopify.com';
$code           = 'code_123';

$tokenExchanger = new TokenExchanger(new Client());
$accessToken    = $tokenExchanger->exchangeCodeForToken($apiKey, $sharedSecret, $shopDomain, $code);

ZfrShopify还提供了一个符合container-interop的简单工厂,您可以使用ZfrShopify\Container\TokenExchangerFactory将其注册到您选择的容器中。

利用响应

ZfrShopify直接返回Shopify响应。然而,默认情况下,Shopify会将响应包装在一个顶级键中。例如,如果您想检索商店信息,Shopify将返回此有效负载

{
    "shop": {
        "id": 123,
        "domain": "myshop.myshopify.com"
    }
}

这有点不方便使用,因为我们需要这样做

$shopDomain = $shopifyClient->getShop()['shop']['domain'];

相反,ZfrShopify自动“解包”响应,因此您可以使用更简洁的代码

$shopDomain = $shopifyClient->getShop()['domain'];

在阅读Shopify API文档时,确保在解析响应时移除顶级键。

计数

类似地,当您使用其中一个count端点时,ZfrShopify会自动从Shopify的响应中提取值,因此您不需要手动访问计数属性

php $count = $shopifyClient->getOrderCount(); // $count已经是一个整数

使用迭代器

对于大多数“列表”端点(如getProductsgetCollections等),Shopify允许您一次获取最多250个资源。当使用标准get**方法时,您需要自己处理分页。

为了方便,ZfrShopify允许您高效地遍历所有资源(内部我们使用生成器)。以下是如何从一个给定的店铺获取所有产品的方法

foreach ($shopifyClient->getProductsIterator(['fields' => 'id,title']) as $product) {
   // Do something with product
}

当ZfrShopify达到给定页面的末尾时,它会自动处理额外的请求。

并发执行多个请求

出于优化的目的,可能需要同时执行多个请求。为此,ZfrShopify客户端允许您利用底层的Guzzle客户端并发执行多个请求。

为此,您可以手动创建Guzzle命令,并全部执行。ZfrShopify将负责对每个请求进行单独的身份验证,并提取响应负载。例如,以下是如何同时获取商店信息和产品信息的方法

$command1 = $client->getCommand('GetShop', ['fields' => 'id']);
$command2 = $client->getCommand('GetProducts', ['fields' => 'id,title']);

$results = $client->executeAll([$command1, $command2]);

// $results[0] represents the response of $command1, $results[1] represents the response of $command2

如果请求失败,它将包含一个GuzzleHttp\Command\Exception\CommandException实例。例如,以下是如何遍历所有结果的方法

use GuzzleHttp\Command\Exception\CommandException;

foreach ($results as $singleResult) {
   if ($singleResult instanceof CommandException) {
      // Get the command that has failed, and eventually retry
      $command = $singleResult->getCommand();
      continue;
   }

   // Otherwise, $singleResult is just an array that contains the Shopify data
}

GraphQL API

2018年,Shopify推出了一种新的API,称为GraphQL Admin API。与REST API相比,这个新API具有许多优势

  • 它允许更有效地访问各种Shopify资源(例如,您可以使用单个请求获取一个集合及其所有产品和变体)。
  • 它提供对某些通过REST API未公开的资源访问。

ZfrShopify的版本4现在附带了一个基本的GraphQL客户端。尽管如此,它还不支持以下功能

  • 自动分页
  • 自动处理Shopify速率限制

为了使用客户端,您必须实例化它。而不是ShopifyClient,您必须创建一个ZfrShopify\ShopifyGraphQLClient。如果您使用的是私有应用

$client = new ShopifyGraphQLClient([
    'shop'        => 'test.myshopify.com',
    'version'     => '2019-04',
    'private_app' => true,
    'password'    => 'YOUR PASSWORD'
]);

务必始终包含版本号。关于Shopify版本信息的更多信息

如果您使用的是公共应用

$client = new ShopifyGraphQLClient([
    'shop'         => 'test.myshopify.com',
    'version'      => '2019-04',
    'private_app'  => false,
    'access_token' => 'ACCESS TOKEN'
]);

务必始终包含版本号。关于Shopify版本信息的更多信息

查询

要执行查询,只需将查询作为heredoc输入。例如,以下是一个GraphQL查询,获取前5个集合的标题和id,以及这些集合中的前5个产品(在REST API中这通常需要多个查询,而使用GraphQL可以非常高效地完成所有操作)

$request = <<<'EOT'
query
{
  collections(first: 5) {
    edges {
      node {
        id
        title
        products(first: 5) {
          edges {
            node {
              id
              title
            }
          }
        }
      }
    }
  }
}
EOT;

$result = $client->request($request);

ZfrShopify自动解包Shopify响应中的data顶级键,因此您可以按如下方式检索数据

foreach ($result['collections']['edges'] as $collection) {
    var_dump('Collection title: ' . $collection['node']['title']);

    foreach ($collection['node']['products']['edges'] as $product) {
        var_dump('Product title: ' . $product['node']['title']);
    }
}

ZfrShopify不会尝试重写GraphQL响应。

变量

ZfrShopify还完全支持GraphQL变量。例如,以下是如何使用GraphQL变量通过ID检索特定产品的方法

$request = <<<'EOT'
query getProduct($id: ID!)
{
  product(id: $id) {
    id
    title
  }
}
EOT;

$variables = [
    'id' => 'gid://shopify/Product/827442593835'
];

$result = $client->request($request, $variables);

var_dump($result);

突变

同样,ZfrShopify支持突变。为此,您只需使用突变查询。以下是一个创建产品的示例

$request = <<<'EOT'
mutation createProduct($product: ProductInput!)
{
  productCreate(input: $product) {
    userErrors {
      field
      message
    }
    product {
      id
    }
  }
}
EOT;

$variables = [
    'product' => [
        'title' => 'My product'
    ]
];

$result = $client->request($request, $variables);

var_dump($result);

此请求将创建一个标题为“我的产品”的新产品,并返回产品的id。

为了更好地处理错误,您应该始终在响应中包含userErrors对象。

错误处理

当使用GraphQL请求时,有两种类型的错误可以捕获。

请求错误

这些错误是针对格式错误的GraphQL请求。您可以使用\ZfrShopify\Exception\GraphQLErrorException异常来捕获它们

try {
    $result = $client->request($request);
} catch (\ZfrShopify\Exception\GraphQLErrorException $exception) {
    var_dump($exception->getErrors());
}

用户错误

这些错误是针对缺少数据(如错误数据、缺失数据等)的请求。您可以使用 \ZfrShopify\Exception\GraphQLUserErrorException 异常来捕获它们

try {
    $result = $client->request($request);
} catch (\ZfrShopify\Exception\GraphQLUserErrorException $exception) {
    var_dump($exception->getErrors());
}

已实现的端点

以下是一份支持的端点列表(未来还将添加更多)

访问范围相关方法

  • array getAccessScopes(array $args = [])

门店访问令牌相关方法

  • array getStorefrontAccessTokens(array $args = [])
  • array createStorefrontAccessToken(array $args = [])
  • array deleteStorefrontAccessToken(array $args = [])

应用费相关方法

  • array getApplicationCharges(array $args = [])
  • array getApplicationCharge(array $args = [])
  • array createApplicationCharge(array $args = [])
  • array activateApplicationCharge(array $args = [])
  • array deleteApplicationCharge(array $args = [])

文章相关方法

  • array getArticles(array $args = [])
  • int getArticleCount(array $args = [])
  • array getBlogArticles(array $args = [])
  • int getBlogArticleCount(array $args = [])
  • array getArticle(array $args = [])
  • array getArticleMetafields(array $args = [])
  • array getBlogArticle(array $args = [])
  • array getArticlesAuthors(array $args = [])
  • array getArticlesTags(array $args = [])
  • array createArticle(array $args = [])
  • array createBlogArticle(array $args = [])
  • array updateArticle(array $args = [])
  • array updateBlogArticle(array $args = [])
  • array deleteArticle(array $args = [])
  • array deleteBlogArticle(array $args = [])

资产相关方法

  • array getAssets(array $args = [])
  • array getAsset(array $args = [])
  • array createAsset(array $args = [])
  • array updateAsset(array $args = [])
  • array deleteAsset(array $args = [])

博客相关方法

  • array getBlogs(array $args = [])
  • array getBlogMetafields(array $args = [])
  • int getBlogCount(array $args = [])
  • array getBlog(array $args = [])
  • array createBlog(array $args = [])
  • array updateBlog(array $args = [])
  • array deleteBlog(array $args = [])

自定义收藏夹相关方法

  • array getCustomCollections(array $args = [])
  • int getCustomCollectionCount(array $args = [])
  • array getCustomCollection(array $args = [])
  • array createCustomCollection(array $args = [])
  • array updateCustomCollection(array $args = [])
  • array deleteCustomCollection(array $args = [])

收藏夹相关方法

  • array getCollection(array $args = [])
  • array getCollectionProducts(array $args = [])
  • array getCollectionMetafields(array $args = [])

收集相关方法

  • array getCollects(array $args = [])
  • int getCollectCount(array $args = [])
  • array getCollect(array $args = [])
  • array createCollect(array $args = [])
  • array deleteCollect(array $args = [])

客户相关方法

  • array getCustomers(array $args = [])
  • int getCustomerCount(array $args = [])
  • array searchCustomers(array $args = [])
  • array getCustomer(array $args = [])
  • array getCustomerMetafields(array $args = [])
  • array createCustomer(array $args = [])
  • array updateCustomer(array $args = [])
  • array deleteCustomer(array $args = [])

客户地址相关方法

  • array getCustomerAddresses(array $args = [])
  • array getCustomerAddress(array $args = [])
  • array createCustomerAddress(array $args = [])
  • array updateCustomerAddress(array $args = [])
  • array deleteCustomerAddress(array $args = [])
  • array setDefaultCustomerAddress(array $args = [])

折扣码相关方法

  • array getDiscountCodes(array $args = [])
  • array getDiscountCode(array $args = [])
  • array createDiscountCode(array $args = [])
  • array deleteDiscountCode(array $args = [])

活动相关方法

  • array getEvents(array $args = [])
  • int getEventCount(array $args = [])
  • array getEvent(array $args = [])

履约相关方法

  • array getFulfillments(array $args = [])
  • int getFulfillmentCount(array $args = [])
  • 获取履约数组 getFulfillment(array $args = [])
  • 创建履约数组 createFulfillment(array $args = [])
  • 更新履约数组 updateFilfillment(array $args = [])
  • 完成履约数组 completeFulfillment(array $args = [])
  • 取消履约数组 cancelFulfillment(array $args = [])

履约订单相关方法

  • 获取履约订单数组 getFulfillmentOrders(array $args = [])
  • 获取履约订单数组 getFulfillmentOrder(array $args = [])
  • 取消履约订单数组 cancelFulfillmentOrder(array $args = [])
  • 关闭履约订单数组 closeFulfillmentOrder(array $args = [])
  • 移动履约订单数组 moveFulfillmentOrder(array $args = [])
  • 打开履约订单数组 openFulfillmentOrder(array $args = [])
  • 重新安排履约订单数组 rescheduleFulfillmentOrder(array $args = [])

礼品卡相关方法

  • 获取礼品卡数组 getGiftCards(array $args = [])
  • 获取礼品卡数量 int getGiftCardCount(array $args = [])
  • 获取礼品卡数组 getGiftCard(array $args = [])
  • 创建礼品卡数组 createGiftCard(array $args = [])
  • 更新礼品卡数组 updateGiftCard(array $args = [])
  • 禁用礼品卡数组 disableGiftCard(array $args = [])

库存项目相关方法

  • 获取库存项目数组 getInventoryItems(array $args = [])
  • 获取库存项目数组 getInventoryItem(array $args = [])
  • 更新库存项目数组 updateInventoryItem(array $args = [])

库存水平相关方法

  • 获取库存水平数组 getInventoryLevels(array $args = [])
  • 调整库存水平数组 adjustInventoryLevel(array $args = [])
  • 删除库存水平数组 deleteInventoryLevel(array $args = [])
  • 连接库存水平数组 connectInventoryLevel(array $args = [])
  • 设置库存水平数组 setInventoryLevel(array $args = [])

位置相关方法

  • 获取位置数组 getLocations(array $args = [])
  • 获取位置数组 getLocation(array $args = [])
  • 获取位置数量 int getLocationCount(array $args = [])
  • 获取位置库存水平数组 getLocationInventoryLevels(array $args = [])

元字段相关方法

  • 获取元字段数组 getMetafields(array $args = [])
  • 获取元字段数组 getMetafield(array $args = [])
  • 创建元字段数组 createMetafield(array $args = [])
  • 更新元字段数组 updateMetafield(array $args = [])
  • 删除元字段数组 deleteMetafield(array $args = [])

订单相关方法

  • 获取订单数组 getOrders(array $args = [])
  • 获取订单数量 int getOrderCount(array $args = [])
  • 获取订单数组 getOrder(array $args = [])
  • 获取订单元字段数组 getOrderMetafields(array $args = [])
  • 创建订单数组 createOrder(array $args = [])
  • 更新订单数组 updateOrder(array $args = [])
  • 关闭订单数组 closeOrder(array $args = [])
  • 打开订单数组 openOrder(array $args = [])
  • 取消订单数组 cancelOrder(array $args = [])

草稿订单相关方法

  • 获取草稿订单数组 getDraftOrders(array $args = [])
  • 获取草稿订单元字段数组 getDraftOrderMetafields(array $args = [])
  • 获取草稿订单数量 int getDraftOrderCount(array $args = [])
  • 创建草稿订单数组 createDraftOrder(array $args = [])
  • 更新草稿订单数组 updateDraftOrder(array $args = [])
  • 获取草稿订单数组 getDraftOrder(array $args = [])
  • 发送草稿订单发票数组 sendDraftOrderInvoice(array $args = [])
  • 完成草稿订单数组 completeDraftOrder(array $args = [])
  • 删除草稿订单数组 deleteDraftOrder(array $args = [])

页面相关方法

  • 获取页面数组 getPages(array $args = [])
  • 获取页面数量 int getPageCount(array $args = [])
  • 获取页面数组 getPage(array $args = [])
  • 获取页面元字段数组 getPageMetafields(array $args = [])
  • 创建页面数组 createPage(array $args = [])
  • 更新页面数组 updatePage(array $args = [])
  • 删除页面数组 deletePage(array $args = [])

价格规则相关方法

  • 获取价格规则数组 getPriceRules(array $args = [])
  • 获取价格规则数组 getPriceRule(array $args = [])
  • 创建价格规则数组 createPriceRule(array $args = [])
  • 更新价格规则数组 updatePriceRule(array $args = [])
  • 删除价格规则数组 deletePriceRule(array $args = [])

产品相关方法

  • 获取产品数组 getProducts(array $args = [])
  • 获取产品数量 int getProductCount(array $args = [])
  • 获取产品数组 getProduct(array $args = [])
  • 获取产品元字段数组 getProductMetafields(array $args = [])
  • 创建产品数组 createProduct(array $args = [])
  • 更新产品数组 updateProduct(array $args = [])
  • 删除产品数组 deleteProduct(array $args = [])

产品图片相关方法

  • 获取产品图片数组 getProductImages(array $args = [])
  • 获取产品图片数量 int getProductImageCount(array $args = [])
  • 获取产品图片数组 getProductImage(array $args = [])
  • 创建产品图片数组 createProductImage(array $args = [])
  • 更新产品图片数组 updateProductImage(array $args = [])
  • 删除产品图片数组 deleteProductImage(array $args = [])

周期性应用程序收费相关方法

  • 获取周期性应用程序收费数组 getRecurringApplicationCharges(array $args = [])
  • 获取周期性应用程序收费数组 getRecurringApplicationCharge(array $args = [])
  • 创建周期性应用收费数组 createRecurringApplicationCharge(array $args = [])
  • 激活周期性应用收费数组 activateRecurringApplicationCharge(array $args = [])
  • 删除周期性应用收费数组 deleteRecurringApplicationCharge(array $args = [])

与退款相关的功能方法

  • 获取退款数组 getRefunds(array $args = [])
  • 获取单个退款数组 getRefund(array $args = [])
  • 计算退款数组 calculateRefund(array $args = [])
  • 创建退款数组 createRefund(array $args = [])

与商店相关的功能方法

  • 获取商店数组 getShop(array $args = [])

与智能收藏夹相关的功能方法

  • 获取智能收藏夹数组 getSmartCollections(array $args = [])
  • 获取智能收藏夹数量 int getSmartCollectionCount(array $args = [])
  • 获取单个智能收藏夹数组 getSmartCollection(array $args = [])
  • 创建智能收藏夹数组 createSmartCollection(array $args = [])
  • 更新智能收藏夹数组 updateSmartCollection(array $args = [])
  • 删除智能收藏夹数组 deleteSmartCollection(array $args = [])

与主题相关的功能方法

  • 获取主题数组 getThemes(array $args = [])
  • 获取单个主题数组 getTheme(array $args = [])
  • 创建主题数组 createTheme(array $args = [])
  • 更新主题数组 updateTheme(array $args = [])
  • 删除主题数组 deleteTheme(array $args = [])

与产品变体相关的功能方法

  • 获取产品变体数组 getProductVariants(array $args = [])
  • 获取产品变体数量 int getProductVariantCount(array $args = [])
  • 获取单个产品变体数组 getProductVariant(array $args = [])
  • 获取产品变体元字段数组 getProductVariantMetafields(array $args = [])
  • 创建产品变体数组 createProductVariant(array $args = [])
  • 更新产品变体数组 updateProductVariant(array $args = [])
  • 删除产品变体数组 deleteProductVariant(array $args = [])

与重定向相关的功能方法

  • 获取重定向数组 getRedirects(array $args = [])
  • 获取重定向数量 int getRedirectCount(array $args = [])
  • 获取单个重定向数组 getRedirect(array $args = [])
  • 创建重定向数组 createRedirect(array $args = [])
  • 更新重定向数组 updateRedirect(array $args = [])
  • 删除重定向数组 deleteRedirect(array $args = [])

与脚本标签相关的功能方法

  • 获取脚本标签数组 getScriptTags(array $args = [])
  • 获取脚本标签数量 int getScriptTagCount(array $args = [])
  • 获取单个脚本标签数组 getScriptTag(array $args = [])
  • 创建脚本标签数组 createScriptTag(array $args = [])
  • 更新脚本标签数组 updateScriptTag(array $args = [])
  • 删除脚本标签数组 deleteScriptTag(array $args = [])

与交易相关的功能方法

  • 获取交易数组 getTransactions(array $args = [])
  • 获取交易数量 int getTransactionCount(array $args = [])
  • 获取单个交易数组 getTransaction(array $args = [])
  • 创建交易数组 createTransaction(array $args = [])

与使用费用相关的功能方法

  • 获取使用费用数组 getUsageCharges(array $args = [])
  • 获取单个使用费用数组 getUsageCharge(array $args = [])
  • 创建使用费用数组 createUsageCharge(array $args = [])

与Webhook相关的功能方法

  • 获取Webhook数组 getWebhooks(array $args = [])
  • 获取Webhook数量 int getWebhookCount(array $args = [])
  • 获取单个Webhook数组 getWebhook(array $args = [])
  • 创建Webhook数组 createWebhook(array $args = [])
  • 更新Webhook数组 updateWebhook(array $args = [])
  • 删除Webhook数组 deleteWebhook(array $args = [])

其他功能方法

  • 创建委托访问令牌数组 createDelegateAccessToken(array $args = [])