Hi! Could we please enable some services and cookies to improve your experience and our website?

PHPize Online / SQLize Online  /  SQLtest Online

A A A
Login    Share code      Blog   FAQ

Online Sandbox for SQL and PHP: Write, Run, Test, and Share SQL Queries and PHP Code

Copy Format Clear

Stuck with a problem? Got Error? Ask AI support!

Copy Clear
Copy Format Clear
<?php class AgoraTokenService { public static function generateTokens($uid, $channelName, $role = RtcTokenBuilder::RolePublisher) { $appId = "7048e5cfc9d6493c9e8c6c458fbc2b6c"; // Sample App ID $appCertificate = "0e5c91746e4643dab22ad1580469352d"; // Sample Certificate if (empty($appId) || empty($appCertificate)) { throw new Exception("AGORA_APP_ID and AGORA_APP_CERTIFICATE must be set."); } $expireTimeInSeconds = 50000; // Get current time in specified US timezone $utcTime = new DateTime("now", new DateTimeZone('UTC')); $currentTimestamp = $utcTime->getTimestamp(); $privilegeExpiredTs = $currentTimestamp + $expireTimeInSeconds; echo "DEBUG TIMESTAMPS:\n"; echo "Current UTC Timestamp: $currentTimestamp\n"; echo "Current UTC Time: " . (new DateTime("@$currentTimestamp"))->format('Y-m-d H:i:s') . "\n"; echo "Expiration UTC Timestamp: $privilegeExpiredTs\n"; echo "Expiration UTC Time: " . (new DateTime("@$privilegeExpiredTs"))->format('Y-m-d H:i:s') . "\n"; echo "Current EAT Time: " . (new DateTime("now", new DateTimeZone('Africa/Nairobi')))->format('Y-m-d H:i:s') . "\n"; echo "Seconds until expiration: " . ($privilegeExpiredTs - $currentTimestamp) . "\n\n"; $uidStr = (string) $uid; $tokenUid = RtcTokenBuilder::buildTokenWithUid( $appId, $appCertificate, $channelName, (int)$uid, $role, $privilegeExpiredTs ); $tokenAccount = RtcTokenBuilder::buildTokenWithUserAccount( $appId, $appCertificate, $channelName, $uidStr, $role, $privilegeExpiredTs ); return [ 'token_with_uid' => $tokenUid, 'token_with_user_account' => $tokenAccount, 'expires_at' => (new DateTime("@$privilegeExpiredTs"))->format('c'), ]; } } class RtcTokenBuilder { const RoleAttendee = 0; const RolePublisher = 1; const RoleSubscriber = 2; const RoleAdmin = 101; public static function buildTokenWithUid($appID, $appCertificate, $channelName, $uid, $role, $privilegeExpireTs) { return RtcTokenBuilder::buildTokenWithUserAccount($appID, $appCertificate, $channelName, $uid, $role, $privilegeExpireTs); } public static function buildTokenWithUserAccount($appID, $appCertificate, $channelName, $userAccount, $role, $privilegeExpireTs) { $token = AccessToken::init($appID, $appCertificate, $channelName, $userAccount); $Privileges = AccessToken::Privileges; $token->addPrivilege($Privileges["kJoinChannel"], $privilegeExpireTs); if (($role == RtcTokenBuilder::RoleAttendee) || ($role == RtcTokenBuilder::RolePublisher) || ($role == RtcTokenBuilder::RoleAdmin) ) { $token->addPrivilege($Privileges["kPublishVideoStream"], $privilegeExpireTs); $token->addPrivilege($Privileges["kPublishAudioStream"], $privilegeExpireTs); $token->addPrivilege($Privileges["kPublishDataStream"], $privilegeExpireTs); } return $token->build(); } } class Message { public $salt; public $ts; public $privileges; public function __construct() { $this->salt = rand(0, 100000); $date = new DateTime("now", new DateTimeZone('UTC')); $this->ts = $date->getTimestamp() + 24 * 3600; $this->privileges = array(); } public function packContent() { $buffer = unpack("C*", pack("V", $this->salt)); $buffer = array_merge($buffer, unpack("C*", pack("V", $this->ts))); $buffer = array_merge($buffer, unpack("C*", pack("v", sizeof($this->privileges)))); foreach ($this->privileges as $key => $value) { $buffer = array_merge($buffer, unpack("C*", pack("v", $key))); $buffer = array_merge($buffer, unpack("C*", pack("V", $value))); } return $buffer; } public function unpackContent($msg) { $pos = 0; $salt = unpack("V", substr($msg, $pos, 4))[1]; $pos += 4; $ts = unpack("V", substr($msg, $pos, 4))[1]; $pos += 4; $size = unpack("v", substr($msg, $pos, 2))[1]; $pos += 2; $privileges = array(); for ($i = 0; $i < $size; $i++) { $key = unpack("v", substr($msg, $pos, 2)); $pos += 2; $value = unpack("V", substr($msg, $pos, 4)); $pos += 4; $privileges[$key[1]] = $value[1]; } $this->salt = $salt; $this->ts = $ts; $this->privileges = $privileges; } } class AccessToken { const Privileges = array( "kJoinChannel" => 1, "kPublishAudioStream" => 2, "kPublishVideoStream" => 3, "kPublishDataStream" => 4, "kRtmLogin" => 1000, ); public $appID, $appCertificate, $channelName, $uid; public $message; function __construct() { $this->message = new Message(); } function setUid($uid) { if ($uid === 0) { $this->uid = ""; } else { $this->uid = $uid . ''; } } function is_nonempty_string($name, $str) { if (is_string($str) && $str !== "") { return true; } echo $name . " check failed, should be a non-empty string"; return false; } static function init($appID, $appCertificate, $channelName, $uid) { $accessToken = new AccessToken(); if (!$accessToken->is_nonempty_string("appID", $appID) || !$accessToken->is_nonempty_string("appCertificate", $appCertificate) || !$accessToken->is_nonempty_string("channelName", $channelName)) { return null; } $accessToken->appID = $appID; $accessToken->appCertificate = $appCertificate; $accessToken->channelName = $channelName; $accessToken->setUid($uid); $accessToken->message = new Message(); return $accessToken; } static function initWithToken($token, $appCertificate, $channel, $uid) { $accessToken = new AccessToken(); if (!$accessToken->extract($token, $appCertificate, $channel, $uid)) { return null; } return $accessToken; } function addPrivilege($key, $expireTimestamp) { $this->message->privileges[$key] = $expireTimestamp; return $this; } function extract($token, $appCertificate, $channelName, $uid) { $ver_len = 3; $appid_len = 32; $version = substr($token, 0, $ver_len); if ($version !== "006") { echo 'invalid version ' . $version; return false; } if (!$this->is_nonempty_string("token", $token) || !$this->is_nonempty_string("appCertificate", $appCertificate) || !$this->is_nonempty_string("channelName", $channelName)) { return false; } $appid = substr($token, $ver_len, $appid_len); $content = (base64_decode(substr($token, $ver_len + $appid_len, strlen($token) - ($ver_len + $appid_len)))); $pos = 0; $len = unpack("v", $content . substr($pos, 2))[1]; $pos += 2; $sig = substr($content, $pos, $len); $pos += $len; $crc_channel = unpack("V", substr($content, $pos, 4))[1]; $pos += 4; $crc_uid = unpack("V", substr($content, $pos, 4))[1]; $pos += 4; $msgLen = unpack("v", substr($content, $pos, 2))[1]; $pos += 2; $msg = substr($content, $pos, $msgLen); $this->appID = $appid; $message = new Message(); $message->unpackContent($msg); $this->message = $message; //non reversable values $this->appCertificate = $appCertificate; $this->channelName = $channelName; $this->setUid($uid); return true; } function build() { $msg = $this->message->packContent(); $val = array_merge(unpack("C*", $this->appID), unpack("C*", $this->channelName), unpack("C*", $this->uid), $msg); $sig = hash_hmac('sha256', implode(array_map("chr", $val)), $this->appCertificate, true); $crc_channel_name = crc32($this->channelName) & 0xffffffff; $crc_uid = crc32($this->uid) & 0xffffffff; $content = array_merge( unpack("C*", $this->packString($sig)), unpack("C*", pack("V", $crc_channel_name)), unpack("C*", pack("V", $crc_uid)), unpack("C*", pack("v", count($msg))), $msg ); $version = "006"; $ret = $version . $this->appID . base64_encode(implode(array_map("chr", $content))); return $ret; } private function packString($value) { return pack("v", strlen($value)) . $value; } } // Test the token generation try { $tokens = AgoraTokenService::generateTokens("fwwf-geqg", "joinChannel"); echo "Token with UID: " . $tokens['token_with_uid'] . "\n"; echo "Token with User Account: " . $tokens['token_with_user_account'] . "\n"; echo "Expires at: " . $tokens['expires_at'] . "\n"; } catch (Exception $e) { echo "Error: " . $e->getMessage(); }
Copy Clear