helpscout / api
Help Scout API v2 客户端
Requires
- php: ^7.3|^8.0
- guzzlehttp/guzzle: ^6.3|^7.0.1
- rize/uri-template: 0.3.5
- webmozart/assert: ^1.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.4
- mockery/mockery: ^1.1
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^8.4
- ramsey/uuid: ^4.1
Suggests
- helpscout/api-laravel: API adapters for use with Laravel and Lumen
- dev-master
- 3.9.0
- 3.8.0
- 3.7.0
- 3.6.6
- 3.6.5
- 3.6.4
- 3.6.3
- 3.6.2
- 3.6.1
- 3.6.0
- 3.5.2
- 3.5.1
- 3.5.0
- 3.4.0
- 3.3.2
- 3.3.1
- 3.3.0
- 3.2.1
- 3.2.0
- 3.1.0
- 3.0.1
- 3.0.0
- v2.x-dev
- 2.7.0
- 2.6.0
- 2.5.0
- 2.4.1
- 2.4.0
- 2.3.10
- 2.3.9
- 2.3.8
- 2.3.7
- 2.3.6
- 2.3.5
- 2.3.4
- 2.3.3
- 2.3.2
- 2.3.1
- 2.3.0
- 2.2.5
- 2.2.4
- 2.2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.4
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- 2.0.0-beta
- v1.x-dev
- 1.9.6
- 1.9.5
- 1.9.4
- 1.9.3
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.0
- 1.3.11
- dev-travis-to-github-actions
- dev-report-endpoints
- dev-develop
This package is auto-updated.
Last update: 2024-08-31 11:27:56 UTC
README
这是官方的 Help Scout PHP 客户端。此客户端包含与 Help Scout 邮箱 API 交互的方法。
目录
安装
推荐使用 Composer 安装客户端。
composer require helpscout/api "^3.0"
对于 Laravel 项目,请查看 helpscout/api-laravel
用法
应在您的应用程序中使用 Composer 的自动加载器来自动加载类。以下所有示例都假设您已在代码中包含此内容。
require_once 'vendor/autoload.php';
认证
使用工厂创建一个客户端。创建后,您可以设置各种凭证来发送请求。
use HelpScout\Api\ApiClientFactory; $client = ApiClientFactory::createClient(); // Set Client credentials if using that grant type. Using this approach will lazily fetch an access token on-demand // when needed. $client->useClientCredentials($appId, $appSecret); // Set Access token directly if you have it $client->setAccessToken('abc123'); // Use a refresh token to get a new access token $client->useRefreshToken($appId, $appSecret, $refreshToken);
注意
所有凭证类型都将触发一个预检请求来获取访问令牌(HTTP 'POST' 请求)。为了避免这种情况,请在请求前使用客户端上的 setAccessToken
方法设置访问令牌。
$client = ApiClientFactory::createClient(); $client->setAccessToken('asdfasdf');
如果可用,将始终使用访问令牌,无论是否设置了其他凭证。
自动刷新过期令牌
当请求因认证错误失败时,SDK 可以自动尝试获取新的刷新令牌,然后自动重试请求。要启用此功能,您可以在创建 ApiClient 时提供一个回调,该回调可用于根据您的需求在其他进程中持久化令牌。
$client = ApiClientFactory::createClient([], function (Authenticator $authenticator) { // This $authenticator contains the refreshed token echo 'New token: '.$authenticator->accessToken().PHP_EOL; });
该回调也可以是任何实现 HelpScout\Api\Http\Auth\HandlesTokenRefreshes
的类实例。
use HelpScout\Api\Http\Auth\HandlesTokenRefreshes; use HelpScout\Api\Http\Authenticator; $callback = new class implements HandlesTokenRefreshes { public function whenTokenRefreshed(Authenticator $authenticator) { // @todo Persist the token } }; $client = ApiClientFactory::createClient([], $callback);
授权代码流
由于 授权代码 只适用于单次使用,您需要在进行其他 API 调用之前用代码交换访问令牌和刷新令牌。您还需要持久化令牌以供以后重用。
$client = ApiClientFactory::createClient(); $client = $client->swapAuthorizationCodeForReusableTokens( $appId, $appSecret, $authorizationCode ); $credentials = $client->getAuthenticator()->getTokens(); echo $credentials['access_token'].PHP_EOL; echo $credentials['refresh_token'].PHP_EOL; echo $credentials['expires_in'].PHP_EOL;
除了提供访问/刷新令牌外,这还将设置当前认证以使用这些令牌,因此您可以在不重新初始化客户端的情况下自由地进行后续请求。
// uses the one-time authorization code for auth
$client = $client->swapAuthorizationCodeForReusableTokens(
$appId,
$appSecret,
$authorizationCode
);
// uses access/refresh tokens for auth
$client->users()->list();
示例
此 README 包含许多示例,但在 ./examples
中还有更多示例供您实验。
客户
获取客户。获取客户时,其所有实体(电子邮件地址、电话号码、社交档案等)都会在同一个请求中预加载。
$customer = $client->customers()->get($customerId);
获取客户。
$customers = $client->customers()->list();
通过过滤器获取客户。
如 API 文档中所述,客户列表 可以通过多种字段进行筛选。CustomerFields 类提供了一个简单的接口来设置筛选值。例如
use HelpScout\Api\Customers\CustomerFilters; $filter = (new CustomerFilters()) ->byFirstName('Tom') ->byLastName('Graham'); $customers = $client->customers()->list($filter);
创建客户。
use HelpScout\Api\Customers\Customer; $customer = new Customer(); $customer->setFirstName('Bob'); // ... try { $customerId = $client->customers()->create($customer); } catch (\HelpScout\Api\Exception\ValidationErrorException $e) { var_dump($e->getError()->getErrors()); }
更新客户。
// ... $customer->setFirstName('Bob'); $client->customers()->update($customer);
电子邮件
创建客户电子邮件。
use HelpScout\Api\Customers\Entry\Email; $email = new Email(); $email->setValue('lucy@helpscout.com'); $email->setType('work'); // ... $client->customerEntry()->createEmail($customerId, $email);
更新客户电子邮件。
// ... $email->setType('home'); $client->customerEntry()->updateEmail($customerId, $email);
删除客户电子邮件。
$client->customerEntry()->deleteEmail($customerId, $emailId);
地址
创建客户地址。
use HelpScout\Api\Customers\Entry\Address; $address = new Address(); $address->setCity('Boston'); // ... $client->customerEntry()->createAddress($customerId, $address);
更新客户地址。
// ... $address->setCity('Boston'); $client->customerEntry()->updateAddress($customerId, $address);
删除客户地址。
$client->customerEntry()->deleteAddress($customerId);
电话号码
创建客户电话。
use HelpScout\Api\Customers\Entry\Phone; $phone = new Phone(); $phone->setValue('123456789'); $phone->setType('work'); // ... $client->customerEntry()->createPhone($customerId, $phone);
更新客户电话。
// ... $phone->setType('home'); $client->customerEntry()->updatePhone($customerId, $phone);
删除客户电话。
$client->customerEntry()->deletePhone($customerId, $phoneId);
聊天处理
创建客户聊天。
use HelpScout\Api\Customers\Entry\ChatHandle; $chat = new ChatHandle(); $chat->setValue('1239134812348'); $chat->setType('icq'); // ... $client->customerEntry()->createChat($customerId, $chat);
更新客户聊天。
// ... $chat->setValue('1230148584583'); $client->customerEntry()->updateChat($customerId, $chat);
删除客户聊天。
$client->customerEntry()->deleteChat($customerId, $chatId);
社交档案
创建客户社交档案。
use HelpScout\Api\Customers\Entry\SocialProfile; $socialProfile = new SocialProfile(); $socialProfile->setValue('helpscout'); $socialProfile->setType('twitter'); // ... $client->customerEntry()->createSocialProfile($customerId, $socialProfile);
更新客户社交档案。
// ... $socialProfile->setType('facebook'); $client->customerEntry()->updateSocialProfile($customerId, $socialProfile);
删除客户社交档案。
$client->customerEntry()->deleteSocialProfile($customerId, $socialProfileId);
网站
创建客户网站。
use HelpScout\Api\Customers\Entry\Website; $website = new Website(); $website->setValue('https://www.helpscout.com'); // ... $client->customerEntry()->createWebsite($customerId, $website);
更新客户网站。
// ... $website->setValue('https://www.helpscout.net'); $client->customerEntry()->updateWebsite($customerId, $website);
删除客户网站。
$client->customerEntry()->deleteWebsite($customerId, $websiteId);
属性
获取客户的属性及其值。
$customer = $client->customers()->get(418048101); // ... foreach ($customer->getProperties() as $property) { echo $property->getName().': '.$property->getValue().PHP_EOL; }
更新客户的属性。
use HelpScout\Api\Entity\Collection; use HelpScout\Api\Entity\Patch; $operations = new Collection( [ new Patch('remove', 'property-1'), new Patch('replace', 'property-2', 'value'), ]; ); $client->customerEntry()->updateProperties($customerId, $operations);
邮箱
获取邮箱。
$mailbox = $client->mailboxes()->get($mailboxId);
获取包含预加载子实体的邮箱。
邮箱实体有两个相关子实体
- 字段
- 文件夹
在获取邮箱时,可以预先加载这些子实体以减少多次方法调用的需求。使用MailboxRequest
类来描述应预加载哪些子实体。例如
use HelpScout\Api\Mailboxes\MailboxRequest; $request = (new MailboxRequest) ->withFields() ->withFolders(); $mailbox = $client->mailboxes()->get($mailboxId, $request); $fields = $mailbox->getFields(); $folders = $mailbox->getFolders();
获取邮箱。
$mailboxes = $client->mailboxes()->list();
获取包含预加载子实体的邮箱。
use HelpScout\Api\Mailboxes\MailboxRequest; $request = (new MailboxRequest) ->withFields() ->withFolders(); $mailboxes = $client->mailboxes()->list($request);
对话
获取对话。
$conversation = $client->conversations()->get($conversationId);
您可以轻松地获取对话的额外信息/关系。例如
use HelpScout\Api\Conversations\ConversationRequest; $request = (new ConversationRequest) ->withMailbox() ->withPrimaryCustomer() ->withCreatedByCustomer() ->withCreatedByUser() ->withClosedBy() ->withThreads() ->withAssignee(); $conversation = $client->conversations()->get($conversationId, $request); $mailbox = $conversation->getMailbox(); $primaryCustomer = $conversation->getCustomer();
获取对话。
$conversations = $client->conversations()->list();
获取包含预加载子实体的对话。
use HelpScout\Api\Conversations\ConversationRequest; $request = (new ConversationRequest) ->withMailbox() ->withPrimaryCustomer() ->withCreatedByCustomer() ->withCreatedByUser() ->withClosedBy() ->withThreads() ->withAssignee(); $conversations = $client->conversations()->list(null, $request);
基于一组过滤器缩小对话列表。
use HelpScout\Api\Conversations\ConversationFilters; $filters = (new ConversationFilters()) ->inMailbox(1) ->inFolder(13) ->inStatus('all') ->hasTag('testing') ->assignedTo(1771) ->modifiedSince(new DateTime('2017-05-06T09:04:23+05:00')) ->byNumber(42) ->sortField('createdAt') ->sortOrder('asc') ->withQuery('query') ->byCustomField(123, 'blue'); $conversations = $client->conversations()->list($filters);
您甚至可以在一个请求中将过滤器与预加载的子实体结合使用
use HelpScout\Api\Conversations\ConversationRequest; use HelpScout\Api\Conversations\ConversationFilters; $request = (new ConversationRequest) ->withMailbox() ->withThreads(); $filters = (new ConversationFilters()) ->inMailbox(1) ->inFolder(13) ->byCustomField(123, 'blue'); $conversations = $client->conversations()->list($filters, $request);
更新对话上的自定义字段
$customField = new CustomField(); $customField->setId(10524); $customField->setValue(new DateTime('today')); $client->conversations()->updateCustomFields($conversationId, [$customField]);
创建新的对话,就像客户向您邮箱发送电子邮件一样。
// We can specify either the id or email for the Customer $customer = new Customer(); $customer->addEmail('my-customer@company.com'); $thread = new CustomerThread(); $thread->setCustomer($customer); $thread->setText('Test'); $conversation = new Conversation(); $conversation->setSubject('Testing the PHP SDK v2: Phone Thread'); $conversation->setStatus('active'); $conversation->setType('email'); $conversation->setMailboxId(80261); $conversation->setCustomer($customer); $conversation->setThreads(new Collection([ $thread, ])); // You can optionally add tags $tag = new Tag(); $tag->setName('testing'); $conversation->addTag($tag); try { $conversationId = $client->conversations()->create($conversation); } catch (ValidationErrorException $e) { var_dump($e->getError()->getErrors()); }
以下是一些您可能创建对话的其他示例场景
电话对话,由Help Scout用户发起
$user = $client->users()->get(31231);
$customer = new Customer();
$customer->setId(193338443);
$thread = new PhoneThread();
$thread->setCustomer($customer);
$thread->setCreatedByUser($user);
$thread->setText('Test');
$conversation = new Conversation();
$conversation->setSubject('Testing the PHP SDK v2: Phone Thread');
$conversation->setStatus('active');
$conversation->setType('phone');
$conversation->setMailboxId(80261);
$conversation->setCustomer($noteCustomer);
$conversation->setCreatedByUser($user);
$conversation->setThreads(new Collection([
$thread,
]));
聊天对话,由客户发起
$noteCustomer = new Customer();
$noteCustomer->setId(163315601);
$thread = new ChatThread();
$thread->setCustomer($noteCustomer);
$thread->setText('Test');
$conversation = new Conversation();
$conversation->setSubject('Testing the PHP SDK v2: Chat Thread');
$conversation->setStatus('active');
$conversation->setType('chat');
$conversation->setAssignTo(271315);
$conversation->setMailboxId(138367);
$conversation->setCustomer($noteCustomer);
$conversation->setThreads(new Collection([
$thread,
]));
// Also adding a tag to this conversation
$tag = new Tag();
$tag->setName('testing');
$conversation->addTag($tag);
$conversationId = $client->conversations()->create($conversation);
删除对话
$client->conversations()->delete($conversationId);
更新现有对话
$client->conversations()->move($conversationId, 18); $client->conversations()->updateSubject($conversationId, 'Need more help please'); $client->conversations()->updateCustomer($conversationId, 6854); $client->conversations()->publishDraft($conversationId); $client->conversations()->updateStatus($conversationId, 'closed'); $client->conversations()->assign($conversationId, 127); $client->conversations()->unassign($conversationId);
线程
聊天线程
为对话创建新的聊天线程。
use HelpScout\Api\Customers\Customer; use HelpScout\Api\Conversations\Threads\ChatThread; $thread = new ChatThread(); $customer = new Customer(); $customer->setId(163487350); $thread->setCustomer($customer); $thread->setText('Thanks for reaching out to us!'); $client->threads()->create($conversationId, $thread);
客户线程
为对话创建新的客户线程。
use HelpScout\Api\Customers\Customer; use HelpScout\Api\Conversations\Threads\CustomerThread; $thread = new CustomerThread(); $customer = new Customer(); $customer->setId(163487350); $thread->setCustomer($customer); $thread->setText('Please help me figure this out'); $client->threads()->create($conversationId, $thread);
笔记线程
为对话创建新的笔记线程。
use HelpScout\Api\Conversations\Threads\NoteThread; $thread->setText('We are still looking into this'); $client->threads()->create($conversationId, $thread);
电话线程
为对话创建新的电话线程。
use HelpScout\Api\Customers\Customer; use HelpScout\Api\Conversations\Threads\PhoneThread; $thread = new PhoneThread(); $customer = new Customer(); $customer->setId(163487350); $thread->setCustomer($customer); $thread->setText('This customer called and spoke with us directly about the delay on their order'); $client->threads()->create($conversationId, $thread);
回复线程
为对话创建新的回复线程。
use HelpScout\Api\Customers\Customer; use HelpScout\Api\Conversations\Threads\ReplyThread; $thread = new ReplyThread(); $customer = new Customer(); $customer->setId(163487350); $thread->setCustomer($customer); $thread->setText("Thanks, we'll be with you shortly!"); $client->threads()->create($conversationId, $thread);
获取对话的线程。
$threads = $client->threads()->list($conversationId);
附件
获取附件。
$attachment = $client->attachments()->get($conversationId, $attachmentId); $attachment->getData(); // attached file's contents
创建附件
use HelpScout\Api\Conversations\Threads\Attachments\AttachmentFactory; use HelpScout\Api\Support\Filesystem; $attachmentFactory = new AttachmentFactory(new Filesystem()); $attachment = $attachmentFactory->make('path/to/profile.jpg'); $attachment->getMimeType(); // image/jpeg $attachment->getFilename(); // profile.jpg $attachment->getData(); // base64 encoded contents of the file $client->attachments()->create($conversationId, $threadId, $attachment);
删除附件
$client->attachments()->delete($conversationId, $attachmentId);
聊天
获取聊天
$chat = $client->chats()->get($chatId);
列出聊天事件
$events = $client->chats()->events($chatId);
标签
列出标签
$tags = $client->tags()->list();
团队
列出团队
$teams = $client->teams()->list();
列出团队成员
$users = $client->teams()->members($teamId);
用户
获取用户。
$user = $client->users()->get($userId);
获取用户。
$users = $client->users()->list();
基于一组过滤器缩小用户列表。
use HelpScout\Api\Users\UserFilters; $filters = (new UserFilters()) ->inMailbox(1) ->byEmail('tester@test.com'); $users = $client->users()->list($filters);
报告
当使用SDK运行报告时,请参阅开发者文档以获取确切的端点、参数和响应格式。虽然此SDK中的大多数端点不过是调用API的透传方法,但也有一些便利之处。
首先,对于start
、end
、previousStart
和previousEnd
参数,您可以将格式化的日期时间字符串或实现\DateTimeInterface
接口的对象作为参数传递。客户端将自动将这些对象转换为正确的格式。
对于接受多个值(mailboxes
、tags
、types
和folders
)的参数,您可以传递值数组,并让客户端将其转换为正确的格式。如果您愿意,也可以传递单个值(或以逗号分隔的值列表)。
要运行报告,请使用在 ApiClient
实例上可用的 runReport
方法。将您想使用的 报告类 的类路径作为第一个参数,将报告参数数组作为第二个参数传递。确保参数数组中的键与文档中指定的 URL 参数相匹配。客户端会将 API 返回的 JSON 响应转换为数组。
// Example of running the Company Overall Report // https://developer.helpscout.com/mailbox-api/endpoints/reports/company/reports-company-overall/ use HelpScout\Api\Reports\Company; $params = [ // Date interval fields can be passed as an object implementing the \DateTimeInterface // or as a string in the 'Y-m-d\Th:m:s\Z' format. All times should be in UTC. 'start' => new \DateTime('-7 days'), 'end' => new \DateTimeImmutable(), 'previousStart' => '2015-01-01T00:00:00Z', 'previousEnd' => '2015-01-31T23:59:59Z', // Fields accepting multiple values can be passed as an array or a comma-separated string 'mailboxes' => [123, 321], 'tags' => '987,789', 'types' => ['chat', 'email'], 'folders' => [111, 222] ]; $report = $client->runReport(Company\Overall::class, $params);
Webhooks
获取 webhook。
$webhook = $client->webhooks()->get($webhookId);
列出 webhook。
$webhooks = $client->webhooks()->list();
创建 webhook。
新创建的 webhook 的默认状态是 启用
。
use HelpScout\Api\Webhooks\Webhook; $data = [ 'url' => 'http://bad-url.com', 'events' => ['convo.assigned', 'convo.moved'], 'secret' => 'notARealSecret' ]; $webhook = new Webhook(); $webhook->hydrate($data); // ... $client->webhooks()->create($webhook);
更新 webhook。
此操作会替换整个 webhook 实体,因此您必须再次提供密钥。更新后,webhook 将再次处于 启用
状态。
$webhook->setUrl('http://bad-url.com/really_really_bad'); $webhook->setSecret('mZ9XbGHodY'); $client->webhooks()->update($webhook);
删除 webhook。
$client->webhooks()->delete($webhookId);
处理传入 webhook。
您还可以使用 SDK 轻松处理传入 webhook。在创建新对象时会进行签名验证,因此无需检查是否有效。如果签名不匹配,则 IncomingWebhook
对象的构造函数将抛出 InvalidSignatureException
异常,让您知道有问题。
// Build it from globals $incoming = IncomingWebhook::makeFromGlobals($secret);
// or build using a request object that satisfies the PSR-7 RequestInterface /** @var RequestInterface $request */ $request = new Request(...); $secret = 'superSekretKey'; $incoming = new IncomingWebhook($request, $secret);
一旦您有了传入 webhook 对象,您可以检查有效负载的类型(客户、对话或测试),以及检索数据(查看示例)。如果是客户或对话,您可以检索相关的模型。否则,您可以以关联数组或标准类对象的形式获取有效负载。
工作流程
获取所有工作流程的分页列表。
$workflows = $client->workflows()->list();
在对话列表上手动运行工作流程。
$convos = [ 123, 321 ]; $client->workflows()->runWorkflow($id, $convos);
将工作流程状态更改为“活动”或“非活动”。
$client->workflows()->updateStatus($id, 'active');
错误处理
客户端抛出的任何异常都将实现 HelpScout\Api\Exception
,HTTP 错误将导致抛出 Http\Client\Exception\RequestException
。
如果未提供 OAuth2 令牌或令牌无效,则抛出 HelpScout\Api\Exception\AuthenticationException
。
验证
如果提交给 API 的请求中存在验证错误,则会遇到 ValidationErrorException
。以下是如何使用该异常的快速示例
try { // do something } catch (\HelpScout\Api\Exception\ValidationErrorException $e) { $error = $e->getError(); var_dump( // A reference id for that request. Including this anytime you contact Help Scout will // empower us to dig right to the heart of the issue $error->getCorrelationId(), // Details about the invalid fields in the request $error->getErrors() ); exit; }
分页
在获取实体集合时,客户端将返回 HelpScout\Api\Entity\Collection
的实例。如果端点支持分页,则返回 HelpScout\Api\Entity\PagedCollection
的实例。
/** @var PagedCollection $users */ $users = $client->users()->list(); // Iterate over the first page of results foreach ($users as $user) { echo $users->getFirstName(); } // The current page number $users->getPageNumber(); // The total number of pages $users->getTotalPageCount(); // Load the next page $nextUsers = $users->getNextPage(); // Load the previous page $previousUsers = $users->getPreviousPage(); // Load the first page $firstUsers = $users->getFirstPage(); // Load the last page $lastUsers = $users->getLastPage(); // Load a specific page $otherUsers = $users->getPage(12); // Paged results are accessible as normal arrays, so you can simply iterate over them foreach ($otherUsers as $user) { echo $user->getFirstName(); }
测试
SDK 在 ApiClient
类上提供了一个方便的 mock
方法。要使用此方法,请传递您想模拟的端点名称。您将获得一个 \Mockery\MockInterface
对象。一旦设置了模拟,对该端点的任何后续调用都将返回模拟对象。
// From within the tests/ApiClientTest.php file... public function testMockReturnsProperMock() { $client = ApiClientFactory::createClient(); $mockedWorkflows = $client->mock('workflows'); $this->assertInstanceOf(WorkflowsEndpoint::class, $mockedWorkflows); $this->assertInstanceOf(MockInterface::class, $mockedWorkflows); $this->assertSame( $mockedWorkflows, $client->workflows() ); }
一旦您模拟了一个端点,您可能希望稍后清除它。为此,您可以在 ApiClient
上使用 clearMock($endpoint)
方法。
获取支持
请为任何 SDK 相关问题或功能请求 提交一个问题。对于可能涉及敏感客户或账户数据的问题,请通过电子邮件联系我们在 help@helpscout.com。