Relay to CDN Callback

The server relay to CDN callback supports notifying your server of the events generated by the relay to CDN REST API in the form of HTTP/HTTPS requests. To receive such callbacks, you need to configure callback information in the TRTC console.

Callback Information

In order to receive event callback notifications, you need to configure callback information in the Tencent RTC Console.



Note:
You need to provide the following information:
Required: An HTTP/HTTPS server address to receive callback notifications.
Optional: A custom key containing up to 32 uppercase and lowercase letters and digits, which is needed for the calculation of signatures.

Timeout and Retry

A notification will be considered failed if the callback server does not receive a response from your server within five seconds of message sending. It will try again immediately after the first failure and retry 10 seconds after every subsequent failure. The retries will stop one minute after the first try.

Format of Callback Messages

Callbacks are sent to your server in the form of HTTP/HTTPS POST requests.
Character encoding: UTF-8
Request: JSON for the request body
Response: HTTP STATUS CODE = 200. The server ignores the content of the response packet. For protocol-friendliness, we recommend adding JSON: {"code":0}` to the response.
Packet Example: Below is a packet example for the "relay to CDN Event Group - CDN Streaming in Progress" event.
{ "EventGroupId": 4, "EventType": 401, "CallbackTs": 1622186275913, "EventInfo": { "RoomId": "xx", "RoomType": 1, "EventTsMs": 1622186275913, "UserId": "xx", "TaskId": "xx", "Payload": { "Url": "rtmp://tencent-url/xxxx" "Status": 2 //indicates that the CDNs push in progress } } }

Parameters

Callback parameters

The header of a callback message contains the following fields.
Field
Value
Content-Type
application/json
Sign
The signature value.
SdkAppId
The SDK application ID.
The body of a callback message contains the following fields.
Field
Type
Description
EventGroupId
Number
The event group ID, mix relay event fixed as 4.
EventType
Number
The type of the callback event.
CallbackTs
Number
The Unix timestamp (ms) of callback sending.
EventInfo
JSON Object

Event group ID

Field
Value
Description
EVENT_GROUP_CLOUD_PUBLISH
4
Relay event group

Event type

Field
Value
Description
EVENT_TYPE_CLOUD_PUBLISH_CDN_STATUS
401
Cloud relay CDN status callback

Event information

Field
Type
Description
RoomId
String/Number
Room ID (Type consistent with client-side room ID type)
RoomType
Number
0 represents numeric room ID, 1 represents string room ID
EventMsTs
Number
Event's Unix timestamp, unit in milliseconds
UserId
String
User ID of the companion robot specified when initiating the task (AgentParams.UserId)
TaskId
Number
Task ID
Payload
JSON Object
Learn more about the event

Payload (Learn more)

Field
Value
Description
Url
String
Push destination URL
Status
Number
ErrorCode
Number
Error code
ErrorMsg
String
Error message

Relay status

Field
Value
Description
Callback Frequency
PUBLISH_CDN_STREAM_STATE_IDLE
0
Push not started or ended
Callback only once
PUBLISH_CDN_STREAM_STATE_CONNECTING
1
Connecting TRTC Server and CDN Server
Callback every 5 seconds, no more callbacks after 60 seconds timeout
PUBLISH_CDN_STREAM_STATE_RUNNING
2
CDNs push in progress
Callback only once
PUBLISH_CDN_STREAM_STATE_RECOVERING
3
TRTC server and CDN server push interrupted, recovering
Callback every 5 seconds, no more callbacks after 60 seconds timeout
PUBLISH_CDN_STREAM_STATE_FAILURE
4
TRTC server and CDN server push interrupted, and recovery or connection timeout
Callback only once
PUBLISH_CDN_STREAM_STATE_DISCONNECTING
5
Disconnecting TRTC Server and CDN Server
Callback only once

Relay status recommendation processing

Status
Processing Method
PUBLISH_CDN_STREAM_STATE_IDLE
Indicates URL removal successful, no need to handle.
PUBLISH_CDN_STREAM_STATE_CONNECTING
Indicates URL is connecting, callback every 5s, until connected successfully with PUBLISH_CDN_STREAM_STATE_RUNNING, or after 60s callback PUBLISH_CDN_STREAM_STATE_FAILURE. You can replace the problematic URL when receiving PUBLISH_CDN_STREAM_STATE_FAILURE, and call UpdatePublishCdnStream to update Publish parameters.
If your business is time-sensitive, you can replace the problematic URL after receiving 2 or more PUBLISH_CDN_STREAM_STATE_CONNECTING callbacks, and call UpdatePublishCdnStream to update Publish parameters.
PUBLISH_CDN_STREAM_STATE_RUNNING
Indicates URL push successful, no need to handle.
PUBLISH_CDN_STREAM_STATE_RECOVERING
Indicates an interruption occurred during the push process, reconnecting, callback every 5s, until reconnected successfully with PUBLISH_CDN_STREAM_STATE_RUNNING, or after 60s callback PUBLISH_CDN_STREAM_STATE_FAILURE. Usually caused by network jitter, no need to handle.
If PUBLISH_CDN_STREAM_STATE_RECOVERING and PUBLISH_CDN_STREAM_STATE_RUNNING appear alternately in a short time, you need to check if there are multiple tasks using the same push URL.
PUBLISH_CDN_STREAM_STATE_FAILURE
Indicates push URL connection failed or failed to recover push within 60s, you can replace the problematic URL and call UpdatePublishCdnStream to update Publish parameters.
PUBLISH_CDN_STREAM_STATE_DISCONNECTING
Indicates that the push URL is being removed, and after removal successful, it will callback PUBLISH_CDN_STREAM_STATE_IDLE, no need to handle.

Basic Callback Transfer Example

Initiate relay/add relay address to relay success event transfer
PUBLISH_CDN_STREAM_STATE_CONNECTING -> PUBLISH_CDN_STREAM_STATE_RUNNING
Stop relay/delete relay address to stop relay success event transfer
PUBLISH_CDN_STREAM_STATE_RUNNING -> PUBLISH_CDN_STREAM_STATE_DISCONNECTING -> PUBLISH_CDN_STREAM_STATE_IDLE
During the relay process, connection failure to retry connection success event transfer
PUBLISH_CDN_STREAM_STATE_RUNNING -> PUBLISH_CDN_STREAM_STATE_RECOVERING -> PUBLISH_CDN_STREAM_STATE_RUNNING
During the relay process, connection failure to retry connection timeout failure event transfer
PUBLISH_CDN_STREAM_STATE_RUNNING -> PUBLISH_CDN_STREAM_STATE_RECOVERING -> PUBLISH_CDN_STREAM_STATE_FAILURE->PUBLISH_CDN_STREAM_STATE_IDLE
Note:
Push callback may arrive at your callback server out of order. In this case, you need to sort the events based on the EventMsTs in EventInfo. If you only care about the latest status of the URL, you can ignore the expired events that arrive later.

Signature calculation

Signatures are calculated using the HMAC SHA256 encryption algorithm. Upon receiving a callback message, your server will calculate a signature using the same method, and if the results match, it indicates that the callback is from TRTC and not forged. See below for the calculation method.
// In the formula below, `key` is the key used to calculate a signature.
Sign = base64(hmacsha256(key, body))
Note:
body is the original packet body of the callback request you receive. Do not make any modifications. Below is an example.
body="{\n\t\"EventGroupId\":\t1,\n\t\"EventType\":\t103,\n\t\"CallbackTs\":\t1615554923704,\n\t\"EventInfo\":\t{\n\t\t\"RoomId\":\t12345,\n\t\t\"EventTs\":\t1608441737,\n\t\t\"UserId\":\t\"test\",\n\t\t\"UniqueId\":\t1615554922656,\n\t\t\"Role\":\t20,\n\t\t\"Reason\":\t1\n\t}\n}"

Verify signature example

Java
Python
PHP
Golang
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
//# Function: Third-party callback sign verification
//# Parameters:
//# key: The key configured in the console
//# body: The body returned by the Tencent Cloud callback
//# sign: The sign value returned by the Tencent Cloud callback
//# Return Value:
//# Status: OK indicates that the verification has passed, FAIL indicates that the verification has failed, and the specific reason can be found in the Info
//# Info: Success/Failure information

public class checkSign {
    public static String getResultSign(String key, String body) throws Exception {
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
        hmacSha256.init(secret_key);
        return Base64.getEncoder().encodeToString(hmacSha256.doFinal(body.getBytes()));
    }
    public static void main(String[] args) throws Exception {
        String key = "123654";
        String body = "{\n" + "\t\"EventGroupId\":\t2,\n" + "\t\"EventType\":\t204,\n" + "\t\"CallbackTs\":\t1664209748188,\n" + "\t\"EventInfo\":\t{\n" + "\t\t\"RoomId\":\t8489,\n" + "\t\t\"EventTs\":\t1664209748,\n" + "\t\t\"EventMsTs\":\t1664209748180,\n" + "\t\t\"UserId\":\t\"user_85034614\",\n" + "\t\t\"Reason\":\t0\n" + "\t}\n" + "}";
        String Sign = "kkoFeO3Oh2ZHnjtg8tEAQhtXK16/KI05W3BQff8IvGA=";
        String resultSign = getResultSign(key, body);

        if (resultSign.equals(Sign)) {
            System.out.println("{'Status': 'OK', 'Info': 'validation passed'}");
        } else {
            System.out.println("{'Status': 'FAIL', 'Info': 'validation failed'}");
        }
    }
}
# -*- coding: utf8 -*-
import hmac
import base64
from hashlib import sha256

# Function: Third-party callback sign verification
# Parameters:
# key: The key configured in the console
# body: The body returned by the Tencent Cloud callback
# sign: The sign value returned by the Tencent Cloud callback
# Return Value:
# Status: OK indicates that the verification has passed, FAIL indicates that the verification has failed, and the specific reason can be found in the Info
# Info: Success/Failure information

def checkSign(key, body, sign):
    temp_dict = {}
    computSign = base64.b64encode(hmac.new(key.encode('utf-8'), body.encode('utf-8'), digestmod=sha256).digest()).decode('utf-8')
    print(computSign)
    if computSign == sign:
        temp_dict['Status'] = 'OK'
        temp_dict['Info'] = 'validation passed'
        return temp_dict
    else:
        temp_dict['Status'] = 'FAIL'
        temp_dict['Info'] = 'validation failed'
        return temp_dict

if __name__ == '__main__':
    key = '123654'
    body = "{\n" + "\t\"EventGroupId\":\t2,\n" + "\t\"EventType\":\t204,\n" + "\t\"CallbackTs\":\t1664209748188,\n" + "\t\"EventInfo\":\t{\n" + "\t\t\"RoomId\":\t8489,\n" + "\t\t\"EventTs\":\t1664209748,\n" + "\t\t\"EventMsTs\":\t1664209748180,\n" + "\t\t\"UserId\":\t\"user_85034614\",\n" + "\t\t\"Reason\":\t0\n" + "\t}\n" + "}"
    sign = 'kkoFeO3Oh2ZHnjtg8tEAQhtXK16/KI05W3BQff8IvGA='
    result = checkSign(key, body, sign)
    print(result)
<?php

class TlsEventSig {
private $key = false;
private $body = false;
public function __construct( $key, $body ) {
$this->key = $key;
$this->body = $body;
}

private function __hmacsha256() {
$hash = hash_hmac( 'sha256', $this->body, $this->key, true );
return base64_encode( $hash);
}
public function genEventSig() {
return $this->__hmacsha256();
}
}

$key="789";
$data="{\n\t\"EventGroupId\":\t1,\n\t\"EventType\":\t101,\n\t\"CallbackTs\":\t1608086882372,\n\t\"EventInfo\":\t{\n\t\t\"RoomId\":\t20222,\n\t\t\"EventTs\":\t1608086882,\n\t\t\"UserId\":\t\"222222_phone\"\n\t}\n}";

$api = new TlsEventSig($key, $data);
echo $api->genEventSig();
package main
import "fmt"
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
)

func main () {
var data = "{\n\t\"EventGroupId\":\t1,\n\t\"EventType\":\t101,\n\t\"CallbackTs\":\t1608086882372,\n\t\"EventInfo\":\t{\n\t\t\"RoomId\":\t20222,\n\t\t\"EventTs\":\t1608086882,\n\t\t\"UserId\":\t\"222222_phone\"\n\t}\n}"
var key = "789"

//JSRUN engine 2.0, supporting up to 30 types of languages for online running, with full simulation of online interaction for input and output.
fmt.Println(hmacsha256(data,key))
}

func hmacsha256(data string, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}