View source
<?php
namespace Drupal\pardot\Service;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\salesforce\SalesforceAuthProviderPluginManagerInterface;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Drupal\Component\Serialization\Json;
use OAuth\OAuth2\Service\Exception\MissingRefreshTokenException;
use Drupal\Core\Config\ConfigFactory;
class PardotClient implements PardotClientInterface {
use StringTranslationTrait;
protected $configFactory;
protected $pardotSettings;
protected $logger;
protected $httpClient;
protected $state;
protected $time;
protected $authManager;
protected $apibaseUrl;
protected $businessId;
public function __construct(ConfigFactory $configFactory, LoggerChannelFactoryInterface $logger_factory, Client $http_client, StateInterface $state, TranslationInterface $string_translation, TimeInterface $time, SalesforceAuthProviderPluginManagerInterface $authManager) {
$this->configFactory = $configFactory;
$this->pardotSettings = $this->configFactory
->get('pardot.settings');
$this->apibaseUrl = $this->pardotSettings
->get('api_url');
$this->businessId = $this->pardotSettings
->get('salesforce_pardot_business_unit_id');
$this->logger = $logger_factory
->get('pardot');
$this->httpClient = $http_client;
$this->state = $state;
$this->stringTranslation = $string_translation;
$this->time = $time;
$this->authManager = $authManager;
$auth_providers = $authManager
->getProviders();
$selected_auth_provider = $this->pardotSettings
->get('salesforce_auth_provider');
$this->authProvider = !empty($auth_providers[$selected_auth_provider]) ? $auth_providers[$selected_auth_provider] : FALSE;
$this->authConfig = $authManager
->getConfig();
$this->authToken = $authManager
->getToken();
}
public function isInit() {
if (!$this->authProvider || !$this->authToken || !$this->authManager || !$this->apibaseUrl || !$this->businessId) {
$this->logger
->error($this
->t('Unable to authenticate into Pardot API. One of the required parameters is missing'));
return FALSE;
}
return TRUE;
}
public function authenticate($refresh = FALSE) {
if ($this
->isInit()) {
$token = $this->authToken
->getAccessToken();
if ($refresh) {
try {
$token = $this->authProvider
->authManager()
->refreshToken()
->getAccessToken();
} catch (\Exception $e) {
$this->logger
->error("Pardot API could not refesh token.");
return FALSE;
}
}
if ($token) {
return $token;
}
}
return NULL;
}
public function retry($url, $request_data) {
$token = $this
->authenticate(TRUE);
if ($token) {
$request_data['headers']['Authorization'] = "Bearer {$token}";
$request_data['form_params']['api_key'] = $token;
return $this
->executePardotOperation($url, $request_data, TRUE);
}
}
public function executePardotOperation(string $url, array $request_data, $retry = FALSE, $method = 'POST') {
if (!$url) {
$this->logger
->error($this
->t('Attempted to execute a Pardot API operation without the endpoint URL'));
return FALSE;
}
try {
$response = $this->httpClient
->request($method, $url, $request_data);
$decoded_response = Json::decode($response
->getBody()
->getContents());
if (is_array($decoded_response) && isset($decoded_response['err'])) {
$this->logger
->error($this
->t("Pardot API operation failed with code: @code. Message: @message", [
'@code' => $decoded_response['@attributes']['err_code'] ?? 'Unknown Code',
'@message' => $decoded_response['err'],
]));
return FALSE;
}
else {
$this->logger
->notice($this
->t("Pardot submission successful. @code.", [
'@code' => 200,
]));
return $decoded_response;
}
} catch (\Exception $e) {
$decoded_response = Json::decode($e
->getResponse()
->getBody()
->getContents());
$err_code = $decoded_response['@attributes']['err_code'] ?? 0;
$err_codes = [
184,
401,
];
if (is_array($decoded_response) && isset($decoded_response['err']) && in_array($err_code, $err_codes) && !$retry) {
return $this
->retry($url, $request_data);
}
$this->logger
->error("Pardot API operation failed. Operation URL: {$url}. Error message: {$e->getMessage()}");
return FALSE;
}
}
public function getPardotProspect(string $visitor_email) {
$post_data = $this
->buildDefaultPostData();
$prospect_options = [
'email' => $visitor_email,
];
$post_data[RequestOptions::FORM_PARAMS] = array_merge($post_data[RequestOptions::FORM_PARAMS], $prospect_options);
$prospect_endpoint = "{$this->apibaseUrl}/api/prospect/version/4/do/read/email/{$visitor_email}";
$response = $this
->executePardotOperation($prospect_endpoint, $post_data);
if (is_array($response)) {
$prospect_id = $response['prospect']['id'] ?? '';
return $prospect_id;
}
return '';
}
public function assignPardotProspect(string $visitor_id, string $prospect_id) {
if (!$visitor_id || !$prospect_id) {
$this->logger
->error($this
->t('Unable to assign Pardot prospect. Either Visitor ID or Prospect ID are missing.'));
return FALSE;
}
$post_data = $this
->buildDefaultPostData();
$assign_options = [
'id' => $visitor_id,
'prospect_id' => $prospect_id,
];
$post_data[RequestOptions::FORM_PARAMS] = array_merge($post_data[RequestOptions::FORM_PARAMS], $assign_options);
$assign_endpoint = "{$this->apibaseUrl}/api/visitor/version/4/do/assign/id/{$visitor_id}?prospect_id={$prospect_id}";
$response = $this
->executePardotOperation($assign_endpoint, $post_data);
if (is_array($response) && $response['@attributes']['stat'] == 'ok') {
return TRUE;
}
return FALSE;
}
protected function buildDefaultPostData() {
$token = $this
->authenticate();
if (!$token) {
$this->logger
->error($this
->t('Unable to build POST data for Pardot API. One of the required parameters is missing'));
return FALSE;
}
$payload = [
RequestOptions::HEADERS => [
'Authorization' => "Bearer {$token}",
'Content-Type' => 'application/x-www-form-urlencoded',
'Pardot-Business-Unit-Id' => $this->businessId,
],
'data-urlencode' => [
'id' => 7676,
],
RequestOptions::FORM_PARAMS => [
'api_key' => $token,
'format' => 'json',
],
];
return $payload;
}
public function getVisitorId() {
$account_id = $this->pardotSettings
->get('account_id');
$cookie_name = 'visitor_id' . ((int) $account_id - 1000);
if (isset($_COOKIE[$cookie_name])) {
return $_COOKIE[$cookie_name];
}
return NULL;
}
}