小程序:UGC自定义发布内容接入微信公众平台内容安全API(imgSecCheck、msgSecCheck、mediaCheckAsync)

文章目录

问题

你好,你的小程序涉及提供UGC自定义发布内容功能,但服务体验流程有特定限制,环节暂无法正常体验小程序功能及确认小程序有内容安全识别能力。为避免您的小程序被滥用,建议接入微信公众平台内容安全API(imgSecCheck、msgSecCheck、mediaCheckAsync)能力参考文档,接入后请按文档"示例"指示进行并保存接口返回值的录屏,将接口调用成功录屏及小程序服务截图上传后再提交代码。

分析

一、msg_sec_check

msgSecCheck 是微信小程序服务端的文本内容安全检测接口,用于检查文本是否含违法违规内容(如涉政、色情、辱骂、广告等),必须在开发者服务器 / 云函数调用,不可在小程序前端直接调用

接口基本信息
核心参数(Body)
javascript 复制代码
{
  "content": "待检测文本",
  "version": 2,// 固定为 2(最新版)
  "scene": 2,// 场景值(1 = 资料 / 昵称,2 = 评论,3 = 论坛,4 = 其他)
  "openid": "用户openid(可选)",
  "title": "标题(可选)",
  "nickname": "用户昵称(可选)"
}
  • scene
javascript 复制代码
1 资料:昵称、头像说明、个性签名
2 评论:短文本、留言、评论、弹幕、许愿墙 / 祈福语
3 论坛:长帖子、文章、主题帖
4 社交日志:个人动态、朋友圈式内容、心愿 / 日记类
返回结果
  • errcode=0:调用成功
  • result.suggest:pass(通过)、risky(可疑)、block(违规)
获取 access_token(调用必备)

access_token 是微信后台接口的全局调用凭证,有效期 2 小时(7200s),需服务端缓存刷新。

  1. 获取 AppID & AppSecret
    小程序后台 → 开发管理 → 开发设置 → 复制 AppID、AppSecret(妥善保管,不可泄露)
  2. 获取接口(GET)
javascript 复制代码
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你的AppID&secret=你的AppSecret
  1. 返回示例
javascript 复制代码
{
  "access_token": "61_9sX...",
  "expires_in": 7200,
  "errcode": 0,
  "errmsg": "ok"
}
Demo 实现(云函数版,推荐)
  1. /msgSecCheck/index.js
javascript 复制代码
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })

exports.main = async (event) => {
  const { content } = event

  try {
    const result = await cloud.openapi.security.msgSecCheck({
      content: content,
      version: 2,
      scene: 2
    })

    return {
      code: 0,
      data: result
    }
  } catch (err) {
    return {
      code: -1,
      msg: err.errMsg
    }
  }
}
  1. 云函数 config.json
javascript 复制代码
{
  "permissions": {
    "openapi": ["security.msgSecCheck"]
  }
}
  1. 小程序端调用
javascript 复制代码
wx.cloud.callFunction({
  name: 'msgSecCheck',
  data: {
    content: '需要检测的文本'
  }
}).then(res => {
  console.log(res.result)
})
Demo实现(原生)
  1. token.js
javascript 复制代码
// 微信小程序原生写法:无感刷新 access_token
let accessToken = ''
let expireTime = 0
let isRefreshing = false
let requests = []

const getUGCToken = async () => {
  return new Promise((resolve, reject) => {
    const now = Date.now()

    // 1. 如果 token 有效,直接返回
    if (accessToken && now < expireTime) {
      resolve(accessToken)
      return
    }

    // 2. 防止重复刷新
    if (isRefreshing) {
      requests.push(() => resolve(accessToken))
      return
    }

    isRefreshing = true

    // 3. 原生 wx.request 获取 token
    const appid = '你的appid'
    const secret = '你的secret'

    wx.request({
      url: 'https://api.weixin.qq.com/cgi-bin/token',
      method: 'GET',
      data: {
        grant_type: 'client_credential',
        appid: appid,
        secret: secret
      },
      success: (res) => {
        const data = res.data
        if (data.access_token) {
          accessToken = data.access_token
          expireTime = now + (data.expires_in - 60) * 1000

          // 执行等待中的请求
          requests.forEach((cb) => cb(accessToken))
          requests = []
          resolve(accessToken)
        } else {
          reject(data.errmsg || '获取token失败')
        }
      },
      fail: (err) => {
        reject(err)
      },
      complete: () => {
        isRefreshing = false
      }
    })
  })
}
// 文本安全检测
async function msgSecCheck(content) {
  const token = await getUGCToken()
  const openid = wx.getStorageSync('openId')

  return new Promise((resolve, reject) => {
    wx.request({
      url: `https://api.weixin.qq.com/wxa/msg_sec_check?access_token=${token}`,
      method: 'POST',
      header: {
        'Content-Type': 'application/json'
      },
      data: {
        openid: openid,
        content: content,
        version: 2,
        scene: 2
      },
      success(res) {
        const data = res.data
        // errcode 0 成功
        // 违规会返回 87014 等
        resolve(data)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}
module.exports = {
  getUGCToken,
  msgSecCheck
}
  • 使用
javascript 复制代码
try {
   const result = await msgSecCheck(this.data.wish)
   if (result.errcode === 0) {
     // 通过
     // wx.showToast({ title: '内容正常', icon: 'success' })
   } else {
     // 违规/风险
     wx.showToast({ title: result.errmsg || '内容违规', icon: 'none' })
     return
   }
 } catch (err) {
   console.error(err)
   wx.showToast({ title: '检测失败', icon: 'none' })
 }

二、media_check_async

mediaCheckAsync 是图片 / 音频异步安全检测,用于检测图片是否违规(涉政、色情、敏感等)。

接口地址:POST https://api.weixin.qq.com/wxa/media_check_async?access_token=TOKEN

  • 支持:图片(网络 URL)
  • 方式:异步检测(结果通过 回调 / 事件 推送)
  • scene 场景:
    • 1 用户资料
    • 2 评论 / 许愿 / 留言(用的这个)
    • 3 帖子
    • 4 其他
javascript 复制代码
// 微信小程序原生写法:无感刷新 access_token
let accessToken = ''
let expireTime = 0
let isRefreshing = false
let requests = []

const getUGCToken = async () => {
  return new Promise((resolve, reject) => {
    const now = Date.now()

    // 1. 如果 token 有效,直接返回
    if (accessToken && now < expireTime) {
      resolve(accessToken)
      return
    }

    // 2. 防止重复刷新
    if (isRefreshing) {
      requests.push(() => resolve(accessToken))
      return
    }

    isRefreshing = true

    // 3. 原生 wx.request 获取 token
    const appid = 'appid '
    const secret = 'secret '

    wx.request({
      url: 'https://api.weixin.qq.com/cgi-bin/token',
      method: 'GET',
      data: {
        grant_type: 'client_credential',
        appid: appid,
        secret: secret
      },
      success: (res) => {
        const data = res.data
        if (data.access_token) {
          accessToken = data.access_token
          expireTime = now + (data.expires_in - 60) * 1000

          // 执行等待中的请求
          requests.forEach((cb) => cb(accessToken))
          requests = []
          resolve(accessToken)
        } else {
          reject(data.errmsg || '获取token失败')
        }
      },
      fail: (err) => {
        reject(err)
      },
      complete: () => {
        isRefreshing = false
      }
    })
  })
}
// 文本安全检测
async function msgSecCheck(content) {
  const token = await getUGCToken()
  const openid = wx.getStorageSync('openId')

  return new Promise((resolve, reject) => {
    wx.request({
      url: `https://api.weixin.qq.com/wxa/msg_sec_check?access_token=${token}`,
      method: 'POST',
      header: {
        'Content-Type': 'application/json'
      },
      data: {
        openid: openid,
        content: content,
        version: 2,
        scene: 2
      },
      success(res) {
        const data = res.data
        // errcode 0 成功
        // 违规会返回 87014 等
        resolve(data)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}
/**
 * 图片异步安全检测
 * @param {String} media_url 图片网络地址(必须公网可访问)
 * @param {String} openid 用户openid
 */
async function mediaCheckAsync(media_url, openid) {
  const token = await getUGCToken()
  const openid = wx.getStorageSync('openId')

  return new Promise((resolve, reject) => {
    wx.request({
      url: `https://api.weixin.qq.com/wxa/media_check_async?access_token=${token}`,
      method: 'POST',
      header: {
        'Content-Type': 'application/json'
      },
      data: {
        media_url: media_url,
        media_type: 2,        // 1=音频 2=图片
        version: 2,           // 固定2
        scene: 2,             // 2=评论/许愿/留言
        openid: openid        // 必填
      },
      success(res) {
        resolve(res.data)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}


module.exports = {
  getUGCToken,
  msgSecCheck,
  mediaCheckAsync
}
  • 使用
javascript 复制代码
const { mediaCheckAsync } = require('../../utils/imageCheck')

Page({
  // 选择图片 + 检测
  async chooseAndCheckImage() {
    wx.chooseMedia({
      count: 1,
      mediaType: ['image'],
      success: async (res) => {
        const filePath = res.tempFiles[0].tempFilePath

        // 1. 上传到你的服务器获得 网络URL
        // 这里必须是 https 公网地址
        // const onlineUrl = await 你的上传接口(filePath)

        // 示例(替换成你真实的图片地址)
        const onlineUrl = 'https://pic.baidu.com/xxx.jpg'
        const openid = wx.getStorageSync('openid')

        // 2. 图片安全检测
        const result = await mediaCheckAsync(onlineUrl, openid)
        console.log('图片检测结果:', result)

        if (result.errcode === 0) {
          wx.showToast({ title: '图片已提交检测,等待结果' })
        } else {
          wx.showToast({ title: '图片违规', icon: 'none' })
        }
      }
    })
  }
})
相关推荐
2601_961963381 天前
技术解剖:哈希值、区块链与CA认证如何守护电子合同安全?
网络·人工智能·安全·区块链·智能合约·政务
科技林总1 天前
解决vllm服务漏扫问题
python·安全
YM52e1 天前
男孩子在外自我保护指南——用鸿蒙 ArkTS 构建交互式安全教育应用
学习·安全·华为·harmonyos·鸿蒙·鸿蒙系统
Par@ish1 天前
【网络安全】Web安全扫描工具Nikto安装和使用详细教程
安全·web安全·ubuntu
namexingyun1 天前
拆解Fable 5三重安全护栏:模型路由、蒸馏防护与生物安全分类器的技术原理 - 微元算力(weytoken)
java·人工智能·python·安全·架构·ai编程
OpenAnolis小助手1 天前
如何利用 AI Agent 实现热补丁的自动化生成
人工智能·安全·ai·操作系统·agent·龙蜥
一拳一个娘娘腔1 天前
CVE-2026-31431 — “Copy Fail“ 深度拆解
linux·安全
持敬chijing1 天前
Web渗透之前后端漏洞-文件包含漏洞
前端·安全·web安全·网络安全·网络攻击模型·安全威胁分析
leagsoft_10031 天前
某航终端安全治理实践:以一体化建设夯实数字办公安全底座
安全
持敬chijing1 天前
Web渗透之前后端漏洞-文件上传漏洞-过滤绕过与配置文件漏洞-条件竞争漏洞
前端·安全·web安全·网络安全·网络攻击模型·安全威胁分析