security.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package security
  2. import (
  3. "fmt"
  4. "strconv"
  5. "github.com/silenceper/wechat/v2/miniprogram/context"
  6. "github.com/silenceper/wechat/v2/util"
  7. )
  8. const (
  9. mediaCheckAsyncURL = "https://api.weixin.qq.com/wxa/media_check_async?access_token=%s"
  10. imageCheckURL = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=%s"
  11. msgCheckURL = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=%s"
  12. )
  13. // Security 内容安全
  14. type Security struct {
  15. *context.Context
  16. }
  17. // NewSecurity init
  18. func NewSecurity(ctx *context.Context) *Security {
  19. return &Security{ctx}
  20. }
  21. // MediaCheckAsyncV1Request 图片/音频异步校验请求参数
  22. type MediaCheckAsyncV1Request struct {
  23. MediaURL string `json:"media_url"` // 要检测的图片或音频的url,支持图片格式包括jpg, jepg, png, bmp, gif(取首帧),支持的音频格式包括mp3, aac, ac3, wma, flac, vorbis, opus, wav
  24. MediaType uint8 `json:"media_type"` // 1:音频;2:图片
  25. }
  26. // MediaCheckAsyncV1 异步校验图片/音频是否含有违法违规内容
  27. // Deprecated
  28. // 在2021年9月1日停止更新,请尽快更新至 2.0 接口。建议使用 MediaCheckAsync
  29. func (security *Security) MediaCheckAsyncV1(in *MediaCheckAsyncV1Request) (traceID string, err error) {
  30. accessToken, err := security.GetAccessToken()
  31. if err != nil {
  32. return
  33. }
  34. uri := fmt.Sprintf(mediaCheckAsyncURL, accessToken)
  35. response, err := util.PostJSON(uri, in)
  36. if err != nil {
  37. return
  38. }
  39. // 使用通用方法返回错误
  40. var res struct {
  41. util.CommonError
  42. TraceID string `json:"trace_id"`
  43. }
  44. err = util.DecodeWithError(response, &res, "MediaCheckAsyncV1")
  45. return res.TraceID, err
  46. }
  47. // MediaCheckAsyncRequest 图片/音频异步校验请求参数
  48. type MediaCheckAsyncRequest struct {
  49. MediaURL string `json:"media_url"` // 要检测的图片或音频的url,支持图片格式包括jpg, jepg, png, bmp, gif(取首帧),支持的音频格式包括mp3, aac, ac3, wma, flac, vorbis, opus, wav
  50. MediaType uint8 `json:"media_type"` // 1:音频;2:图片
  51. OpenID string `json:"openid"` // 用户的openid(用户需在近两小时访问过小程序)
  52. Scene uint8 `json:"scene"` // 场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
  53. }
  54. // MediaCheckAsync 异步校验图片/音频是否含有违法违规内容
  55. func (security *Security) MediaCheckAsync(in *MediaCheckAsyncRequest) (traceID string, err error) {
  56. accessToken, err := security.GetAccessToken()
  57. if err != nil {
  58. return
  59. }
  60. var req struct {
  61. MediaCheckAsyncRequest
  62. Version uint `json:"version"` // 接口版本号,2.0版本为固定值2
  63. }
  64. req.MediaCheckAsyncRequest = *in
  65. req.Version = 2
  66. uri := fmt.Sprintf(mediaCheckAsyncURL, accessToken)
  67. response, err := util.PostJSON(uri, req)
  68. if err != nil {
  69. return
  70. }
  71. // 使用通用方法返回错误
  72. var res struct {
  73. util.CommonError
  74. TraceID string `json:"trace_id"`
  75. }
  76. err = util.DecodeWithError(response, &res, "MediaCheckAsync")
  77. return res.TraceID, err
  78. }
  79. // ImageCheckV1 校验一张图片是否含有违法违规内容(同步)
  80. // https://developers.weixin.qq.com/miniprogram/dev/framework/security.imgSecCheck.html
  81. // Deprecated
  82. // 在2021年9月1日停止更新。建议使用 MediaCheckAsync
  83. func (security *Security) ImageCheckV1(filename string) (err error) {
  84. accessToken, err := security.GetAccessToken()
  85. if err != nil {
  86. return
  87. }
  88. uri := fmt.Sprintf(imageCheckURL, accessToken)
  89. response, err := util.PostFile("media", filename, uri)
  90. if err != nil {
  91. return
  92. }
  93. // 使用通用方法返回错误
  94. return util.DecodeWithCommonError(response, "ImageCheckV1")
  95. }
  96. // CheckSuggest 检查建议
  97. type CheckSuggest string
  98. const (
  99. // CheckSuggestRisky 违规风险建议
  100. CheckSuggestRisky CheckSuggest = "risky"
  101. // CheckSuggestPass 安全
  102. CheckSuggestPass CheckSuggest = "pass"
  103. // CheckSuggestReview 需要审查
  104. CheckSuggestReview CheckSuggest = "review"
  105. )
  106. // MsgScene 文本场景
  107. type MsgScene uint8
  108. const (
  109. // MsgSceneMaterial 资料文件检查场景
  110. MsgSceneMaterial MsgScene = iota + 1
  111. // MsgSceneComment 评论
  112. MsgSceneComment
  113. // MsgSceneForum 论坛
  114. MsgSceneForum
  115. // MsgSceneSocialLog 社交日志
  116. MsgSceneSocialLog
  117. )
  118. // CheckLabel 检查命中标签
  119. type CheckLabel int
  120. func (cl CheckLabel) String() string {
  121. switch cl {
  122. case 100:
  123. return "正常"
  124. case 10001:
  125. return "广告"
  126. case 20001:
  127. return "时政"
  128. case 20002:
  129. return "色情"
  130. case 20003:
  131. return "辱骂"
  132. case 20006:
  133. return "违法犯罪"
  134. case 20008:
  135. return "欺诈"
  136. case 20012:
  137. return "低俗"
  138. case 20013:
  139. return "版权"
  140. case 21000:
  141. return "其他"
  142. default:
  143. return strconv.Itoa(int(cl))
  144. }
  145. }
  146. // MsgCheckRequest 文本检查请求
  147. type MsgCheckRequest struct {
  148. OpenID string `json:"openid"` // 用户的openid(用户需在近两小时访问过小程序)
  149. Scene MsgScene `json:"scene"` // 场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
  150. Content string `json:"content"` // 需检测的文本内容,文本字数的上限为 2500 字,需使用 UTF-8 编码
  151. Nickname string `json:"nickname"` // (非必填)用户昵称,需使用UTF-8编码
  152. Title string `json:"title"` // (非必填)文本标题,需使用UTF-8编码
  153. Signature string `json:"signature"` // (非必填)个性签名,该参数仅在资料类场景有效(scene=1),需使用UTF-8编码
  154. }
  155. // MsgCheckResponse 文本检查响应
  156. type MsgCheckResponse struct {
  157. util.CommonError
  158. TraceID string `json:"trace_id"` // 唯一请求标识
  159. Result struct {
  160. Suggest CheckSuggest `json:"suggest"` // 建议
  161. Label CheckLabel `json:"label"` // 命中标签
  162. } `json:"result"` // 综合结果
  163. Detail []struct {
  164. ErrCode int64 `json:"errcode"` // 错误码,仅当该值为0时,该项结果有效
  165. Strategy string `json:"strategy"` // 策略类型
  166. Suggest string `json:"suggest"` // 建议
  167. Label CheckLabel `json:"label"` // 命中标签
  168. Prob uint `json:"prob"` // 置信度。0-100,越高代表越有可能属于当前返回的标签(label)
  169. Keyword string `json:"keyword"` // 命中的自定义关键词
  170. } `json:"detail"` // 详细检测结果
  171. }
  172. // MsgCheckV1 检查一段文本是否含有违法违规内容
  173. // Deprecated
  174. // 在2021年9月1日停止更新,请尽快更新至 2.0 接口。建议使用 MsgCheck
  175. func (security *Security) MsgCheckV1(content string) (res MsgCheckResponse, err error) {
  176. accessToken, err := security.GetAccessToken()
  177. if err != nil {
  178. return
  179. }
  180. var req struct {
  181. Content string `json:"content"`
  182. }
  183. req.Content = content
  184. uri := fmt.Sprintf(msgCheckURL, accessToken)
  185. response, err := util.PostJSON(uri, req)
  186. if err != nil {
  187. return
  188. }
  189. // 使用通用方法返回错误
  190. err = util.DecodeWithError(response, &res, "security.MsgCheckV1")
  191. return
  192. }
  193. // MsgCheck 检查一段文本是否含有违法违规内容
  194. func (security *Security) MsgCheck(in *MsgCheckRequest) (res MsgCheckResponse, err error) {
  195. accessToken, err := security.GetAccessToken()
  196. if err != nil {
  197. return
  198. }
  199. var req struct {
  200. MsgCheckRequest
  201. Version uint `json:"version"`
  202. }
  203. req.MsgCheckRequest = *in
  204. req.Version = 2
  205. uri := fmt.Sprintf(msgCheckURL, accessToken)
  206. response, err := util.PostJSON(uri, req)
  207. if err != nil {
  208. return
  209. }
  210. // 使用通用方法返回错误
  211. err = util.DecodeWithError(response, &res, "security.MsgCheck")
  212. return
  213. }