📒
【hubspot-api-php】コンタクトと取引を紐づける
前提
- Laravel 10
-
hubspot/api-client
v11.3- https://github.com/HubSpot/hubspot-api-php
- このライブラリを使って、HubSpot上で以下を実行したい
- 「コンタクト」を新規作成or更新
- 「取引」を新規作成
- 「取引」と「コンタクト」を紐づける
結論
- 以下に対応コードを記述しています
config/services.php
設定値:- HubSpotの管理画面からアクセストークンを取得して設定
- アクセストークンの取得方法はココを参照
- 過去仕様のAPIキーで制御する方法は非推奨になったっぽいので、原則アクセストークンで制御しよう
'hubspot' => [
'access_token' => env('HUBSPOT_ACCESS_TOKEN'),
],
app/Services/Vendor/HubSpot/HubSpotService.php
クライアント:- HubSpotライブラリのラッパークラス
-
email
による既存コンタクト取得 - コンタクトの新規作成
- コンタクトの上書き更新
- コンタクトの
upsert
- 取引の新規作成
- 取引→コンタクトへの紐づけ
-
<?php
namespace App\Services\Vendor\HubSpot;
use HubSpot\Client\Crm\Associations\V4\ApiException as AssociationsApiException;
use HubSpot\Client\Crm\Associations\V4\Model\AssociationSpec;
use HubSpot\Client\Crm\Associations\V4\Model\LabelsBetweenObjectPair as AssociationsLabelsBetweenObjectPair;
use HubSpot\Client\Crm\Contacts\ApiException as ContactsApiException;
use HubSpot\Client\Crm\Contacts\Model\Filter as ContactFilter;
use HubSpot\Client\Crm\Contacts\Model\FilterGroup as ContactFilterGroup;
use HubSpot\Client\Crm\Contacts\Model\PublicObjectSearchRequest as ContactPublicObjectSearchRequest;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObject as ContactSimplePublicObject;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectInput as ContactInput;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectInputForCreate as ContactInputForCreate;
use HubSpot\Client\Crm\Deals\ApiException as DealsApiException;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObject as DealSimplePublicObject;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObjectInputForCreate as DealInput;
use HubSpot\Discovery\Discovery;
use HubSpot\Factory;
readonly class HubSpotService
{
private Discovery $hubSpot;
public function __construct(
) {
$this->hubSpot = Factory::createWithAccessToken(config('services.hubspot.access_token'));
}
/**
* @throws ContactsApiException
*/
public function getContactByEmail(string $email): ?ContactSimplePublicObject
{
$filterGroup = new ContactFilterGroup(['filters' => [new ContactFilter([
'operator' => 'EQ',
'property_name' => 'email',
'value' => $email,
])]]);
$searchRequest = new ContactPublicObjectSearchRequest([
'filter_groups' => [$filterGroup],
'limit' => 1,
'after' => 0,
]);
// HubSpot APIでメールアドレスを使ってコンタクトを検索
$searchResponse = $this
->hubSpot
->crm()
->contacts()
->searchApi()
->doSearch($searchRequest);
$results = $searchResponse->getResults();
return count($results) > 0 ? $results[0] : null;
}
/**
* @throws ContactsApiException
*/
public function upsertContact(array $data): ContactSimplePublicObject
{
$email = $data['properties']['email'];
$contact = $this->getContactByEmail($email);
return $contact
? $this->updateContact($contact->getId(), $data)
: $this->createContact($data);
}
/**
* @throws ContactsApiException
*/
public function createContact(array $data): ContactSimplePublicObject
{
return $this
->hubSpot
->crm()
->contacts()
->basicApi()
->create(new ContactInputForCreate($data));
}
/**
* @throws ContactsApiException
*/
public function updateContact(string $contactId, array $data): ContactSimplePublicObject
{
return $this
->hubSpot
->crm()
->contacts()
->basicApi()
->update($contactId, new ContactInput($data));
}
/**
* @throws DealsApiException
*/
public function createDeal(array $data): DealSimplePublicObject
{
return $this
->hubSpot
->crm()
->deals()
->basicApi()
->create(new DealInput($data));
}
/**
* @throws AssociationsApiException
*/
public function associateDealToContact(ContactSimplePublicObject $contact, DealSimplePublicObject $deal): AssociationsLabelsBetweenObjectPair
{
return $this
->hubSpot
->crm()
->associations()
->v4()
->basicApi()
->create(
'deals',
$deal->getId(),
'contacts',
$contact->getId(),
[new AssociationSpec([
'association_category' => 'HUBSPOT_DEFINED',
// 参考:https://developers.hubspot.com/docs/api/crm/associations Deal to Contact
'association_type_id' => 3,
])],
);
}
}
app/Http/Controllers/HubSpotController.php
実行例:- コンストラクタインジェクションしつつHubSpotのクライアントを呼び出す
- HubSpotのカスタムプロパティを利用すれば任意の値を設定可能
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Services\Vendor\HubSpot\HubSpotService;
use DB;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObject as ContactSimplePublicObject;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObject as DealSimplePublicObject;
use Illuminate\Contracts\Database\Eloquent\Builder as BuilderContract;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Notification;
class HubSpotController extends Controller
{
public function __construct(
private readonly HubSpotService $hubSpotService
) {
}
public function __invoke(Request $request): JsonResponse
{
// HubSpotにコンタクト情報を作成
$hubspotContact = $this->createHubSpotContact($request);
// HubSpotに取引情報を作成
$hubSpotDeal = $this->createHubSpotDeal($request);
// HubSpot上で取引情報とコンタクト情報を関連付け
$this->hubSpotService->associateDealToContact($hubspotContact, $hubSpotDeal);
return response()->json([
'status' => 'success',
'message' => 'Contact form has been submitted successfully.',
]);
}
private function createHubSpotContact(Request $request): ContactSimplePublicObject
{
return $this->hubSpotService->upsertContact([
// 必要に応じてプロパティを追加
'properties' => [
// 名
'firstname' => $request->input('firstname'),
// 姓
'lastname' => $request->input('lastName'),
// 郵便番号
'zip' => $request->input('zip'),
// 都道府県
'state' => $request->input('state'),
// 市区町村以下
'city' => $request->input('city'),
// 電話番号
'phone' => $request->input('phone'),
// 社名
'company' => $request->input('company'),
// メールアドレス(HubSpotのコンタクト上ではユニークなキーとして扱われる
'email' => $request->input('email'),
],
]);
}
private function createHubSpotDeal(Request $request): DealSimplePublicObject
{
// HubSpotに取引情報を作成
return $this->hubSpotService->createDeal([
// 必要に応じてプロパティを追加
'properties' => [
// 取引名
'dealname' => $request->input('dealname'),
// 取引詳細
'description' => $request->input('description'),
],
]);
}
}
-
api.php
では以下のように呼び出す
Route::post('hubspot', HubSpotController::class)->name('contact');
余談
公式でコンタクトのupsertってないの?
- v1ではcreateOrUpdateの関数があったっぽいけど、最新のv3ではオミットされた模様
associate関連の定義がわからん
- 以下に定義値があるので適宜参照しよう
- 参考:https://developers.hubspot.com/docs/api/crm/associations
- 今回は取引→コンタクト(
Deal to Contact
)の紐づけなので3
を利用
Discussion