You need to enable JavaScript to run this app.
导航
接收消息通知回调
最近更新时间:2024.11.26 19:13:39首次发布时间:2021.07.18 15:05:57

你必须在你的业务服务端部署 HTTP(s) 服务以接收回调。

接收回调响应的 HTTP 状态码为 200 时,RTC 服务端即认为回调成功;状态码不为 200,或响应时间超过5秒,都视为回调失败,RTC 服务端会重试。重试最多2次(总计回调不超过3次)。当前不保证回调事件的唯一性。建议你可以使用 EventId 对事件回调进行去重。

RTC 会为服务端回调签名。如果你希望确定来源是否是火山以及内容是否被篡改,你可以检验回调签名;否则,你可以忽略回调签名。如果需要检验签名,参考以下签名算法和实现。

签名算法

RTC 服务端发起回调时,会使用你设置的回调密钥对回调签名。你可以参考以下签名算法进行验签:

1、创建参数字符数组

将用户回调密钥SecretKey和接收到回调字段值:EventTypeEventDataEventTimeEventIdVersionAppIdNonceSecretKey 组成数组:

type Event struct {
	EventType string `json:"EventType"`
	EventData string `json:"EventData"`
	EventTime string `json:"EventTime"`
	EventId   string `json:"EventId"`
	AppId     string `json:"AppId"`
	Version   string `json:"Version"` 
	Nonce      string `json:"Nonce"`
	Signature string `json:"Signature"`
}

var event Event

data := []string{
	event.EventType,
	event.EventData,
	event.EventTime,
	event.EventId,
	event.AppId,
	event.Version,
	event.Nonce,
	secretKey,
}

示例 : [EventTypeVal EventDataVal EventTimeVal EventIdVal VersionVal AppIDVal NonceVal SecretKeyVal]

2、按字母序排列步骤一字符数组

SortedData = Sort(data)

示例 : [AppIDVal EventDataVal EventIdVal EventTimeVal EventTypeVal NonceVal SecretKeyVal VersionVal]

3、将排序后字符数组元素直接拼接成字符串得到 PayloadData:

PayloadData=Join(SortedData)

示例 : [AppIDValEventDataValEventIdValEventTimeValEventTypeValNonceValSecretKeyValVersionVal]

4、对拼接好的字符串进行 SHA256 哈希算法:

HashData=Hash(PayloadData)

示例 : [20 170 104 20 32 203 70 171 95 29 138 214 172 154 178 31 52 30 169 219 249 213 35 112 89 195 196 192 231 49 48 15]

5、进行十六进制编码,得到回调签名

Signature=HexEncode(HashData)

示例 : 14aa681420cb46ab5f1d8ad6ac9ab21f341ea9dbf9d5237059c3c4c0e731300f

备注:SecretKey 是你在控制台上配置的回调密钥。`

签名算法示例

RTC 提供了 Golang 和 Java 语言的示例代码,你可以参考以下示例进行验签:

Golang

import (
   "crypto/sha256"
   "fmt"
   "sort"
   "strings"
)

func main() {
    event := &Event{
        EventType: "RoomCreate",
        EventData: "{\"RoomId\":\"room1\",\"Timestamp\":1679383924691}",
        EventTime: "2023-03-21T15:32:04+08:00",
        EventId:   "123456",
        Version:   "2020-12-01",
        AppId:     "appId",
        Nonce:      "aaBc",
        Signature: "1c7200723842eff514b65fc3f065597432bbb4249e10d33db79b3853d05f3691",
    }
   
    secretKey := "1234"
    ok := CheckSignature(event, secretKey)
    fmt.Printf("the result is %t", ok)
}

type Event struct {
    EventType string `json:"EventType"`
    EventData string `json:"EventData"`
    EventTime string `json:"EventTime"`
    EventId   string `json:"EventId"`
    AppId     string `json:"AppId"`
    Version   string `json:"Version"`
    Signature string `json:"Signature"`
    Nonce      string `json:"Nonce"`
}

func CheckSignature(event *Event, secretKey string) bool {
    data := []string{
        event.EventType,
        event.EventData,
        event.EventTime,
        event.EventId,
        event.AppId,
        event.Version,
        event.Nonce,
        secretKey,
    }
    sort.Strings(data)
    payload := strings.Join(data, "")
    hashData := sha256.Sum256([]byte(payload))
    signature := fmt.Sprintf("%x", hashData)
    fmt.Println("sign:" + signature)
    return signature == event.Signature
}

Java

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.security.NoSuchAlgorithmException;

class Event{
    public String EventType;
    public String EventData;
    public String EventTime;
    public String EventId;
    public String AppId;
    public String Version;
    public String Nonce;
    public String Signature;
}

public class CheckSignature {
    public static void main(String[] args) {
        Event event=new Event();
        event.EventType="RoomCreate";
        event.EventData="{\"RoomId\":\"room1\",\"Timestamp\":1679383924691}";
        event.EventTime="2023-03-21T15:32:04+08:00";
        event.EventId="123456";
        event.Version="2020-12-01";
        event.AppId="appId";
        event.Nonce="aaBc";
        event.Signature="1c7200723842eff514b65fc3f065597432bbb4249e10d33db79b3853d05f3691";
        String secretKey="1234";

        boolean ret=Check(event,secretKey);
        System.out.println(ret);

    }
    private static boolean Check(Event event,String secretKey){
        try {
            List<String> data = new ArrayList<>();
            data.add(event.EventType);
            data.add(event.EventData);
            data.add(event.EventTime);
            data.add(event.EventId);
            data.add(event.AppId);
            data.add(event.Version);
            data.add(event.Nonce);
            data.add(secretKey);

            Collections.sort(data);

            final String payloadData=String.join("",data);
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            digest.update(payloadData.getBytes());
            String signature=byteToHexString(digest.digest());
            System.out.println(signature);

            if(event.Signature.equals(signature)){
                return true;
            }
        } catch (NoSuchAlgorithmException e){
            e.printStackTrace();
        }
        return false;
    }

    private static String byteToHexString(byte[] bytes){
        return String.format("%064x", new BigInteger(1,bytes));
    }
}