Files
translate-laravel/src/Translate/Yandex/Connection.php
T
kor-elf 55b04f0eab Add DTOs, exceptions, and jobs for translation service.
Introduced new Data Transfer Objects (DTOs), exceptions, and jobs to enhance the translation service functionality. Updated namespaces for consistency and added rate limiting to the translation provider. Expanded the README with detailed usage instructions.
2024-10-11 00:22:46 +05:00

113 lines
3.3 KiB
PHP

<?php declare(strict_types=1);
namespace KorElf\TranslateLaravel\Translate\Yandex;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Carbon;
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\Algorithm\PS256;
use Jose\Component\Signature\JWSBuilder;
use Jose\Component\Signature\Serializer\CompactSerializer;
use KorElf\TranslateLaravel\Exceptions\TranslateException;
final class Connection
{
private string $path;
private string $folderId;
private string $privateKey;
private string $keyId;
private string $serviceAccountId;
public function __construct(string $path, string $folderId, string $privateKey, string $keyId, string $serviceAccountId)
{
$this->path = $path;
$this->folderId = $folderId;
// Need to remove header/metadata from private key
if (\strpos($privateKey, "PLEASE DO NOT REMOVE THIS LINE!") === 0) {
$privateKey = \substr($privateKey, \strpos($privateKey, "\n") + 1);
}
$this->privateKey = $privateKey;
$this->keyId = $keyId;
$this->serviceAccountId = $serviceAccountId;
}
public function post(string $path, array $post): array
{
$token = $this->getToken();
$path = $this->path . $path;
$post['folderId'] = $this->folderId;
$response = Http::withToken($token)
->timeout(30)
->post($path, $post);
$data = $response->json();
if ($data !== null && $response->status() === 200) {
return $data;
}
$message = $data['message'] ?? 'Error in request';
throw new TranslateException($message, $response->status());
}
private function getToken(): string
{
$cacheName = self::class . '_token';
$token = Cache::get($cacheName);
if ($token !== null) {
return $token;
}
$token = $this->createNewToken();
Cache::put($cacheName, $token['iamToken'], Carbon::createFromDate($token['expiresAt']));
return $token['iamToken'];
}
private function getJWTToken(): string
{
$jwk = JWKFactory::createFromKey(
$this->privateKey,
null,
[
'alg' => 'PS256',
'use' => 'sig',
'kid' => $this->keyId,
]
);
$algorithmManager = new AlgorithmManager([new PS256()]);
$jwsBuilder = new JWSBuilder($algorithmManager);
$payload = \json_encode([
'iss' => $this->serviceAccountId,
'aud' => "https://iam.api.cloud.yandex.net/iam/v1/tokens",
'iat' => time(),
'nbf' => time(),
'exp' => time() + 600,
]);
$jws = $jwsBuilder
->create()
->withPayload($payload)
->addSignature($jwk, ['alg' => 'PS256', 'typ'=>'JWT', 'kid' => $this->keyId])
->build();
$serializer = new CompactSerializer();
return $serializer->serialize($jws, 0);
}
private function createNewToken(): array
{
$jwtToken = $this->getJWTToken();
$token = Http::timeout(30)
->post('https://iam.api.cloud.yandex.net/iam/v1/tokens', ['jwt' => $jwtToken]);
return $token->json();
}
}