"github.com/gin-gonic/gin"
voicePrintStatusHeader = "stat"
exampleSignature = "your_custom_secure_signature" // 替换为您在 StartVoiceChat 中配置的真实密钥
// RtsMessage 对应回调请求的整体结构
type RtsMessage struct {
Message string `json:"message"`
Signature string `json:"signature"`
// VoicePrintStatusMsg 对应 "stat" 消息的 JSON 载荷
type VoicePrintStatusMsg struct {
Event string `json:"event"`
Status string `json:"status"`
func HandleVoicePrintStatusMsg(c *gin.Context) {
if err := c.BindJSON(&msg); err != nil {
fmt.Printf("BindJson failed, err: %v\n", err)
c.String(400, "Bad Request")
if msg.Signature != exampleSignature {
fmt.Printf("Signature not match\n")
c.String(403, "Forbidden")
statusMsg, err := Unpack(msg.Message)
fmt.Printf("Unpack failed, err: %v\n", err)
c.String(400, "Bad Message Format")
if statusMsg.Event == "VoicePrintStatus" {
fmt.Printf("Received VoicePrint Status: %s\n", statusMsg.Status)
// Unpack 解析 Base64 编码的二进制消息
func Unpack(msg string) (*VoicePrintStatusMsg, error) {
data, err := base64.StdEncoding.DecodeString(msg)
return nil, fmt.Errorf("DecodeString failed, err: %v", err)
return nil, fmt.Errorf("data invalid: length is less than 8")
dataHeader := string(data[:4])
if dataHeader != voicePrintStatusHeader {
return nil, fmt.Errorf("header not match: expected '%s', got '%s'", voicePrintStatusHeader, dataHeader)
dataSize := binary.BigEndian.Uint32(data[4:8])
if dataSize+8 != uint32(len(data)) {
return nil, fmt.Errorf("size not match: expected %d, got %d", dataSize+8, len(data))
status := &VoicePrintStatusMsg{}
err = json.Unmarshal(subData, status)
return nil, fmt.Errorf("unmarshal JSON failed, err: %v", err)
// 回调路径:这里的路径 ("/example_path/callback") 必须与您在 StartVoiceChat 中配置的 ServerMessageURLForRTS 的路径部分完全一致。
r.POST("/example_path/callback", HandleVoicePrintStatusMsg)