Files
2026-04-28 15:13:50 +02:00

169 lines
6.2 KiB
PHP

<?php
/**
* Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
*
* You are hereby granted a non-exclusive, worldwide, royalty-free license to
* use, copy, modify, and distribute this software in source code or binary
* form for use in connection with the web services and APIs provided by
* Facebook.
*
* As with any software that integrates with the Facebook platform, your use
* of this software is subject to the Facebook Developer Principles and
* Policies [http://developers.facebook.com/policy/]. This copyright notice
* shall be included in all copies or substantial portions of the software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
namespace FacebookPixelPlugin\FacebookAds\Object\ServerSide;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Utils;
use Psr\Http\Message\ResponseInterface;
/**
* Implementation of Custom Endpoint Request that sends events to CAPIG /events endpoint
*
* @category Class
*/
class CAPIGatewayEndpoint implements CustomEndpointRequest {
private Client $client;
private string $access_key;
private string $endpoint_URL;
private bool $sendToEndpointOnly;
private ?Filter $filter = null;
/**
* Constructor
* @param string $endpoint_URL endpoint_URL
* @param string $access_key access_key
* @throws Exception
*/
public function __construct(string $endpoint_URL, string $access_key) {
$this->validateEndpoint($endpoint_URL);
$this->endpoint_URL = $endpoint_URL;
$this->access_key = $access_key;
$this->client= new Client(['headers' => ['Content-Type' => 'application/json; charset=utf-8']]);
$this->sendToEndpointOnly = false;
}
/**
* Validates URL
* @param string $endpoint_URL
* @throws Exception
*/
private function validateEndpoint(string $endpoint_URL):void {
if (!filter_var($endpoint_URL, FILTER_VALIDATE_URL)) {
throw new Exception('URL is in invalid format ');
}
}
/**
* Synchronously send events to specified CAPIG /events endpoint
* @throws GuzzleException
* @throws Exception
*/
public function sendEvent(string $pixel_id, array $events): CustomEndpointResponse
{
try {
if (!is_null($this->filter)) {
$events = array_filter($events, function(Event $var){
return $this->filter->shouldSendEvent($var);
});
}
if (count($events) == 0) {
return new CustomEndpointResponse(array('message' => 'No events to send'));
}
$response = $this->client->request('POST', $this->endpoint_URL.'/capi/'.$pixel_id.'/events', ['http_errors'=> false, 'body' => $this->createRequestBody($events)]);
if ($response->getStatusCode() != '202') {
// a HTTP response code of 202 means the events were accepted
throw new Exception('Server response code is '.$response->getStatusCode().' expect: 202');
} else {
return new CustomEndpointResponse(array('message' => $response->getBody()->getContents(), 'response_code'=> $response->getStatusCode()));
}
} catch (Exception $e) {
throw new Exception('Server failed to accept events. '.$e->getMessage());
}
}
/**
* Asynchronously send events to specified CAPIG /events endpoint
* @throws Exception
* returns PromiseInterface
*/
public function sendEventAsync(string $pixel_id, array $events): PromiseInterface
{
if (!is_null($this->filter)) {
$events = array_filter($events, function (Event $var) {
return $this->filter->shouldSendEvent($var);
});
}
$promise = $this->client->requestAsync('POST', $this->endpoint_URL.'/capi/'.$pixel_id.'/events', ['http_errors'=> false, 'body' => $this->createRequestBody($events)]);
$promise->then(
function (ResponseInterface $response) {
if ($response->getStatusCode() != '202') {
// a HTTP response code of 202 means the events were accepted
throw new Exception('Server response code is '.$response->getStatusCode().' expect: 202');
} else {
return new CustomEndpointResponse(array('message' => $response->getBody()->getContents(), 'response_code'=> $response->getStatusCode()));
}
},
function (RequestException $e) {
throw new Exception('Server failed to accept events. '.$e->getMessage());
}
);
return $promise;
}
private function createRequestBody($events): string
{
$events = $this->normalize($events);
$body = array();
$body['data'] = $events;
$body['accessKey'] = $this->access_key;
return Utils::jsonEncode($body);
}
private function normalize(array $events): array
{
// we need to normalize the event fields before sending
$normalized_events = array();
foreach ($events as $event) {
$normalized_event = $event->normalize();
$normalized_events[] = $normalized_event;
}
return $normalized_events;
}
public function setFilter(Filter $filter)
{
$this->filter = $filter;
}
public function setSendToEndpointOnly(bool $setSendToEndpointOnly)
{
$this->sendToEndpointOnly = $setSendToEndpointOnly;
}
public function isSendToEndpointOnly(): bool
{
return $this->sendToEndpointOnly;
}
public function getEndpoint(): string
{
return $this->endpoint_URL;
}
}