A

AppleSearch Ads API

public
andrei.k Nov 25, 2023 Never 26
Clone
PHP AppleSearchTokenBuilder.php 65 lines (51 loc) | 2.35 KB
1
<?php
2
3
namespace App\Component\AppleSearch;
4
5
use App\Entity\AppleSearchAccount;
6
use App\Exception\AppleSearchException;
7
use Firebase\JWT\JWT;
8
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
9
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
10
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
11
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
12
use Symfony\Contracts\HttpClient\HttpClientInterface;
13
14
class AppleSearchTokenBuilder
15
{
16
private const AUDIENCE = 'https://appleid.apple.com';
17
18
private const EXPIRE = 86400 * 180;
19
20
private const ALGORITHM = 'ES256';
21
22
private const GRANT_TYPE = 'client_credentials';
23
24
private const SCOPE = 'searchadsorg';
25
26
private const ENDPOINT = 'https://appleid.apple.com/auth/oauth2/token';
27
28
public function __construct(private HttpClientInterface $client) {}
29
30
public function getToken(AppleSearchAccount $searchAccount): string
31
{
32
try {
33
$response = $this->client->request('POST', self::ENDPOINT, [
34
'body' => [
35
'client_id' => $searchAccount->getClientID(),
36
'client_secret' => $this->generateSecret($searchAccount),
37
'grant_type' => self::GRANT_TYPE,
38
'scope' => self::SCOPE,
39
],
40
]);
41
42
if (200 !== $response->getStatusCode()) {
43
throw new \Exception('Return status code: ' . $response->getStatusCode());
44
}
45
46
return json_decode($response->getContent(), true)['access_token'] ?? '';
47
} catch (\Exception | TransportExceptionInterface | RedirectionExceptionInterface | ServerExceptionInterface | ClientExceptionInterface $ex) {
48
throw new AppleSearchException($ex->getMessage());
49
}
50
}
51
52
private function generateSecret(AppleSearchAccount $searchAccount): string
53
{
54
$payload = [
55
'iss' => $searchAccount->getTeamID(),
56
'aud' => self::AUDIENCE,
57
'sub' => $searchAccount->getClientID(),
58
'lat' => \time(),
59
'exp' => \time() + self::EXPIRE,
60
];
61
$keyID = $searchAccount->getKeyId();
62
63
return JWT::encode($payload, $searchAccount->getCert(), self::ALGORITHM, $keyID);
64
}
65
}
PHP AppleSearchAdClient.php 65 lines (53 loc) | 2.25 KB
1
<?php
2
3
namespace App\Components\AppleSearch;
4
5
use App\Entity\AppleSearchAccount;
6
use App\Exception\AppleSearchException;
7
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
8
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
9
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
10
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
11
use Symfony\Contracts\HttpClient\HttpClientInterface;
12
13
class AppleSearchAdClient
14
{
15
16
public const TIME_FORMAT = 'Y-m-d';
17
18
/**
19
* @var int
20
*/
21
private $maxReplaceRequest = 5;
22
23
public function __construct(
24
private readonly HttpClientInterface $client,
25
private readonly AppleSearchTokenBuilder $tokenBuilder
26
) {}
27
28
public function getCampaignsList(AppleSearchAccount $account): string
29
{
30
try {
31
$response = $this->client->request(
32
'GET',
33
'https://api.searchads.apple.com/api/v4/campaigns?' . http_build_query(['limit' => 100]),
34
[
35
'auth_bearer' => $account->getToken(),
36
'headers' => [
37
'X-AP-Context' => "orgId={$account->getOrgID()}",
38
'Content-Type' => 'application/json',
39
],
40
]
41
);
42
43
if (200 === $response->getStatusCode()) {
44
return $response->getContent();
45
}
46
if ($this->maxReplaceRequest > 0 && 401 === $response->getStatusCode()) {
47
--$this->maxReplaceRequest;
48
49
return $this->getCampaignsList($this->updateToken($account));
50
}
51
52
throw new AppleSearchException('Response status: ' . $response->getStatusCode() . ". {$response->getContent()}");
53
} catch (TransportExceptionInterface | ClientExceptionInterface | RedirectionExceptionInterface | ServerExceptionInterface $e) {
54
throw new AppleSearchException($e->getMessage());
55
}
56
}
57
58
private function updateToken(AppleSearchAccount $account): AppleSearchAccount
59
{
60
$token = $this->tokenBuilder->getToken($account);
61
$account->setToken($token);
62
63
return $account;
64
}
65
}