mpemburn/api-consumer

可配置的RESTful API消费者

v1.0 2020-12-06 20:19 UTC

This package is auto-updated.

Last update: 2024-09-15 00:49:27 UTC


README

Latest Version MIT Licensed Total Downloads

关于

api-consumer 包允许你为RESTful API创建简单的端点包装器。

安装

您可以通过composer安装此包

composer require mpemburn/api-consumer

此包将自动注册服务提供者 ApiConsumerProvider

接下来,您需要发布此包,以便将 api-consumer.php 复制到您的 config 目录

php artisan vendor:publish --provider="Mpemburn\ApiConsumer\ApiConsumerProvider"

如何使用

配置

此包将向您的项目添加文件 config/api-consumer.php。该文件返回一个数组,其中包含您创建的用于消费一个或多个RESTful API的端点类所使用的键和变量。格式如下

'shopify' => [
    'base_uri' => 'https://mystore.myshopify.com/admin/api/2020-10',
    'username' => '5ac3bd00f1ebc6a65caa4c0a6a3b1555',
    'password' => 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
],

为了提高安全性,您应该将实际的变量存储在您的 .env 文件中

SHOPIFY_USERNAME=5ac3bd00f1ebc6a65caa4c0a6a3b1555
SHOPIFY_PASSWORD=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

...并按如下方式引用它们

'shopify' => [
    'base_uri' => 'https://mystore.myshopify.com/admin/api/2020-10',
    'username' => env('SHOPIFY_USERNAME'),
    'password' => env('SHOPIFY_PASSWORD')
],

您可以将所需的任何数量的API添加到配置文件中,只要每个API都在数组的顶层具有API名称(例如,在本例中为“shopify”)。

注意:在修改此配置文件后,运行以下操作很重要

php artisan config:cache

类结构

虽然没有绝对要求以这种方式结构化您的类文件,但建议的层次结构如下

project
│   
└───Api
│   │   
│   └───Shopify
│       │   ShopifyEndpoint
│       │   CreateProduct
│       │   GetProducts
│       │   ...
│       Discourse
│       │   DiscourseEndpoint
│       │   CreateUser
│       │   GetUsers
│       │   ...

父端点类

每个父端点类(例如,上面的 ShopifyEndpointDiscourseEndpoint)需要扩展此包的 AbstractEndpoint 类。然后各个端点扩展其主要类。例如

<?php

namespace App\Api\Shopify;

use Mpemburn\ApiConsumer\Endpoints\AbstractEndpoint;

class ShopifyEndpoint extends AbstractEndpoint
{
    public function __construct()
    {
        parent::__construct();

        $this->addHeader('Content-Type', 'application/json');
    }

    public function getApiName(): string
    {
        return 'shopify';
    }
}

重要的是从 getApiName() 返回与您在 api-consumer 配置文件中指定的相同的名称。

注意:默认情况下不假设任何头信息,因此您应该在构造函数中添加它们,如上所示。

端点类

单个端点应按如下结构组织

<?php

namespace App\Api\Shopify;

class GetProducts extends ShopifyEndpoint
{
    public function getRequestType(): ?string
    {
        return 'GET';
    }

    public function getEndpoint(): ?string
    {
        return '/products.json';
    }

    public function getRequestName(): ?string
    {
        return 'Get Products';
    }
}

发送请求

使用 GET 端点发送请求的简单示例

Route::get('get_products', function () {
    $requestManager = RequestManager::make();
    $products = new Products();
    if ($requestManager) {
        return $requestManager->send($products)
            ->getResponse();
    }
});

POST 请求

要创建一个 POST 端点

<?php

namespace App\Api\Shopify;

class CreateProduct extends ShopifyEndpoint
{
    public function getRequestType(): ?string
    {
        return 'POST';
    }

    public function getEndpoint(): ?string
    {
        return '/products.json';
    }

    public function getRequestName(): ?string
    {
        return 'Create Product';
    }

    public function create(array $product): void
    {
        $this->setParams($product);
    }
}

请求可能看起来像这样

Route::post('create_product', function (Request $request) {
    $requestManager = RequestManager::make();
    $createProduct = new CreateProduct();
    $createProduct->create($request->toArray());

    if ($requestManager) {
        return $requestManager->send($createProduct)
            ->getResponse();
    }
});

在这种情况下,$request 应包含与API文档中指定的键匹配的数组。

包含变量的URL

某些API端点需要URL字符串中的变量部分。例如,如果您需要更新用户,API端点可能包括用户ID作为URL的一部分

https://roster.org/api/v1/users/update/123

在这种情况下,您将端点设置如下

<?php

namespace App\Api\Roster;

class UpdateUser extends RosterEndpoint
{
    public function getRequestType(): ?string
    {
        return 'PUT';
    }

    public function getEndpoint(): ?string
    {
        return $this->hydrateUrlParams('/users/update/{user_id}', $this->getUrlParams());
    }

    public function getRequestName(): ?string
    {
        return 'Update User';
    }

    public function update(int $userId, array $userData): void
    {
        $this->setParams($userData);
        $this->addUrlParam('user_id', $userId);
    }
}

在这里,update 方法接受 $userId 和要更新的数据数组($userData)。setParams 方法将所有的 $userData 添加到一个Laravel Collection中,而 addUrlParam 方法将 $memberId 添加到类似的集合中。

接下来,在 getEndpoint 方法中,我们可以传递一个包含 user_id 的URL字符串,并将其用大括号括起来,这将使其被视为变量。通过将此传递给 hydrateUrlParams 方法以及调用 getUrlParams,将 {user_id} 替换为传递给 update 方法的任何内容。

注意:您可以使用此方法传递所需的所有变量。

使用认证(auth)令牌的API

某些API要求您为每个端点调用使用认证令牌。典型模式是通过发送包含由API开发者控制台提供的秘密键的 GET 请求到API来获取认证令牌。一旦您有了认证令牌,您就将其添加到后续调用请求的参数中。

本包通过允许您创建一个特殊端点来实现对该模型的支撑。例如

https://roster.org/api/v1/get_auth?key=V2hhdCBpcyB0aGF0IHN0cmFuZ2Ugc291bmQ

要调用此功能,您的 GetAuthToken 端点应如下所示

<?php

namespace App\Api\Roster;

class GetAuthToken extends RosterEndpoint
{
    protected ?string $authTokenFetchKeyName = 'key';
    protected ?string $authTokenResponseName = 'auth_token';

    public function getRequestType(): ?string
    {
        return 'GET';
    }

    public function getEndpoint(): ?string
    {
        return '/get_auth';
    }

    public function getRequestName(): ?string
    {
        return 'Get Auth Token';
    }
}

在这里,$authTokenFetchKeyName 属性指的是API密钥的参数名称,而 $authTokenResponseName 则是指API为认证令牌指定的名称。响应可能如下所示

{
  "auth_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdXRoX2tleSI6IlYyaGhkQ0JwY3lCMGFHRjBJSE4wY21GdVoyVWdjMjkxYm1RIiwibm93IjoxNjA3NDM1MTQ2fQ.DKgv6rTKnRa2k_WOT5LbvNRUhgSt6uRAnnO84Weka0CVifs6tZhkDHAXQQJibJYQVjWmYooCLtFQfNkFc4oS-z3X-rgj80qpjh8dFFfq3mM5zBvbbyhxWFKzhLmownsOJZCjOiJE5nGTazenMH-0bc5CjWW8SzlXPgksIRRK8bg"
}

此外,您的父端点需要包含对 GetAuthToken 类的引用

...
class RosterEndpoint extends AbstractEndpoint
{
    protected ?string $authTokenEndpoint = GetAuthToken::class;
...

默认情况下,每次请求后都会丢弃令牌。这通常是个好主意,因为许多/大多数认证令牌都有时间限制。在您需要连续快速发送一系列请求的情况下,可以使用 RequestManagerpreserveAuthToken 方法

$requestManager = RequestManager::make();
$members = new GetMembers();

if ($requestManager) {
return $requestManager->preserveAuthToken()
    ->send($members)
    ->getResponse();
}

注意preserveAuthToken 调用必须在调用 send 之前进行。