Files
sundynix-plant-be/utils/wechat/safety.go
T
2026-02-14 13:07:55 +08:00

157 lines
4.0 KiB
Go

package wechat
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"sundynix-go/global"
"go.uber.org/zap"
)
// WeChatCommonResponse 微信通用响应
type WeChatCommonResponse struct {
Errcode int `json:"errcode"`
Errmsg string `json:"errmsg"`
}
// MsgSecCheckDetail 文本检测结果详情
type MsgSecCheckDetail struct {
Strategy string `json:"strategy"`
Errcode int `json:"errcode"`
Suggest string `json:"suggest"`
Label int `json:"label"`
Prob int `json:"prob"`
}
// MsgSecCheckResult 文本检测结果
type MsgSecCheckResult struct {
Suggest string `json:"suggest"`
Label int `json:"label"`
}
// MsgSecCheckResponse 文本检测响应
type MsgSecCheckResponse struct {
WeChatCommonResponse
Result MsgSecCheckResult `json:"result"`
Detail []MsgSecCheckDetail `json:"detail"`
}
// MediaCheckAsyncResponse 媒体检测异步响应
type MediaCheckAsyncResponse struct {
WeChatCommonResponse
TraceId string `json:"trace_id"`
}
// MsgSecCheck 文本内容安全识别
// content: 需检测的文本内容
// openid: 用户的openid(用户需在近两小时访问过小程序)
// return: true-通过, false-不通过
func MsgSecCheck(content string, openid string) bool {
// 2024-05-15: 微信api调整
// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/sec-center/sec-check/msgSecCheck.html
accessToken := GetMiniAccessToken()
url := "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + accessToken
payload := map[string]interface{}{
"version": 2,
"openid": openid,
"scene": 2, // 2-资料说明
"content": content,
}
jsonData, err := json.Marshal(payload)
if err != nil {
global.Logger.Error("MsgSecCheck json marshal error", zap.Error(err))
return false
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
global.Logger.Error("MsgSecCheck http post error", zap.Error(err))
return false
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
global.Logger.Error("MsgSecCheck read body error", zap.Error(err))
return false
}
var response MsgSecCheckResponse
if err := json.Unmarshal(body, &response); err != nil {
global.Logger.Error("MsgSecCheck json unmarshal error", zap.Error(err))
return false
}
if response.Errcode != 0 {
global.Logger.Error("MsgSecCheck api error", zap.Int("errcode", response.Errcode), zap.String("errmsg", response.Errmsg))
return false
}
// 检查 result.suggest
if response.Result.Suggest == "pass" {
return true
}
global.Logger.Warn("MsgSecCheck risky content",
zap.String("content", content),
zap.String("suggest", response.Result.Suggest),
zap.Int("label", response.Result.Label),
)
return false
}
// MediaCheckAsync 多媒体内容安全识别(异步)
// mediaUrl: 需检测的多媒体url
// mediaType: 1:音频; 2:图片
// openid: 用户的openid
// return: trace_id, error
func MediaCheckAsync(mediaUrl string, mediaType int, openid string) (string, error) {
accessToken := GetMiniAccessToken()
url := "https://api.weixin.qq.com/wxa/media_check_async?access_token=" + accessToken
payload := map[string]interface{}{
"media_url": mediaUrl,
"media_type": mediaType,
"version": 2,
"openid": openid,
"scene": 2,
}
jsonData, err := json.Marshal(payload)
if err != nil {
return "", err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
var response MediaCheckAsyncResponse
if err := json.Unmarshal(body, &response); err != nil {
return "", err
}
if response.Errcode != 0 {
global.Logger.Error("MediaCheckAsync api error", zap.Int("errcode", response.Errcode), zap.String("errmsg", response.Errmsg))
return "", fmt.Errorf("errcode: %d, errmsg: %s", response.Errcode, response.Errmsg)
}
if response.TraceId != "" {
return response.TraceId, nil
}
return "", fmt.Errorf("no trace_id returned")
}