security.go 7.3 KB

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