76 lines
2.5 KiB
PHP
76 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
class AgoraTokenService
|
|
{
|
|
private const VERSION = '006';
|
|
private const PRIVILEGE_JOIN_CHANNEL = 1;
|
|
private const PRIVILEGE_PUBLISH_AUDIO_STREAM = 2;
|
|
private const PRIVILEGE_PUBLISH_VIDEO_STREAM = 3;
|
|
private const PRIVILEGE_PUBLISH_DATA_STREAM = 4;
|
|
|
|
public static function generateToken(string $channelName, int $uid, int $expireSeconds = 3600): string
|
|
{
|
|
$appId = config('services.agora.app_id', env('AGORA_APP_ID', ''));
|
|
$appCertificate = config('services.agora.app_certificate', env('AGORA_APP_CERTIFICATE', ''));
|
|
|
|
if (!$appId || !$appCertificate) {
|
|
// Development fallback — no token required when cert is empty
|
|
return '';
|
|
}
|
|
|
|
$currentTimestamp = time();
|
|
$expireTimestamp = $currentTimestamp + $expireSeconds;
|
|
|
|
$nonce = random_int(1, 16777216);
|
|
|
|
$privileges = [
|
|
self::PRIVILEGE_JOIN_CHANNEL => $expireTimestamp,
|
|
self::PRIVILEGE_PUBLISH_AUDIO_STREAM => $expireTimestamp,
|
|
self::PRIVILEGE_PUBLISH_VIDEO_STREAM => 0,
|
|
self::PRIVILEGE_PUBLISH_DATA_STREAM => $expireTimestamp,
|
|
];
|
|
|
|
// Pack message
|
|
$message = self::packUint16(1); // version: 1 (AccessToken)
|
|
$message .= self::packUint32($currentTimestamp);
|
|
$message .= self::packUint32($nonce);
|
|
$message .= self::packString($channelName);
|
|
$message .= self::packUint32($uid);
|
|
$message .= self::packPrivileges($privileges);
|
|
|
|
// HMAC-SHA256 signature
|
|
$signature = hash_hmac('sha256', $appId . $currentTimestamp . $nonce . $channelName . $uid . self::packPrivileges($privileges), $appCertificate, true);
|
|
|
|
$content = self::packString($signature) . $message;
|
|
|
|
return self::VERSION . $appId . base64_encode($content);
|
|
}
|
|
|
|
private static function packUint16(int $v): string
|
|
{
|
|
return pack('n', $v);
|
|
}
|
|
|
|
private static function packUint32(int $v): string
|
|
{
|
|
return pack('N', $v);
|
|
}
|
|
|
|
private static function packString(string $v): string
|
|
{
|
|
return pack('n', strlen($v)) . $v;
|
|
}
|
|
|
|
private static function packPrivileges(array $privileges): string
|
|
{
|
|
ksort($privileges);
|
|
$packed = pack('n', count($privileges));
|
|
foreach ($privileges as $key => $value) {
|
|
$packed .= pack('n', $key) . pack('N', $value);
|
|
}
|
|
return $packed;
|
|
}
|
|
}
|