@cnskis 已经搞定了,谢谢大佬
问题已经解决,欢迎各位过来拿金币
应该是接口有问题
兄弟们燃尽了,自己写了个本地的违禁词,现在可以了,受不了,后面拦不住我再加其他违禁词进去,微信这个接口有 bug,我看有很多人都说拦不住,我已经提交了工单,看看微信后续什么结果吧,总的来说就是多媒体违禁拦截的接口没问题,文本违禁拦截的接口有问题,不一定全部可以拦截,需要自己写本地的违禁词拦截 😒
idr 吗,那你也会出现我这种情况吗
这个是微信接口检测的
@libra2 2 是评论的类型,所以传的是 2,3 是帖子类型
打印了,传的就是这个
文本检测 {'content': '我想草拟', 'openid': 'ozxtT15kwJZrIeer7GsJQ9nMphqA', 'scene': 2, 'version': 2} {'errcode': 0, 'errmsg': 'ok', 'detail': [{'strategy': 'keyword', 'errcode': 0}, {'strategy': 'content_model', 'errcode': 0, 'suggest': 'pass', 'label': 100, 'prob': 90}], 'trace_id': '6968a9a1-40bcc957-15249ba8', 'result': {'suggest': 'pass', 'label': 100}}
有可能哈哈哈哈

我发现是小程序无法拦截,但是调试工具确实是确认违规了,我后端代码那也传的是正确的 content,有点奇怪了
@cnskis OK,那我再看看。谢谢大佬
@libra2 是啊,我感觉他这个接口是不是就有问题,恶心死我了
@libra2 一直说让我接微信的文本检测接口,我已经接了,而且也同步判断了,我上传图片也是这个写法,上传黄图就会自动拦截,但是文本就不行,说些涉黄的言论还是可以通过
OK 谢谢大佬
那没有,我就是想知道这是什么问题,这个涉黄评论微信小程序审核那卡了我半个月了,恶心死我了
现在我发布的评论涉黄,但是微信的文本监管接口没有拦截我发布的涉黄评论,直接让通过了
import logging
from dataclasses import dataclass
from typing import Any, Optional, Iterable, List
import requests
from django.conf import settings
from django.core.cache import cache
from rest_framework.exceptions import ValidationError
logger = logging.getLogger(name)
def _normalize_wx_resp(raw: Optional[dict]) -> dict:
raw = raw or {}
return {
"errcode": raw.get("errcode", 0),
"errmsg": raw.get("errmsg", ""),
"trace_id": raw.get("trace_id", ""),
"result": raw.get("result") or {},
"detail": raw.get("detail") or [],
}
def check_text_and_report(
*,
user,
text: str,
scene: int,
strict: bool = True,
require_openid: bool = True,
) -> dict:
appid = getattr(settings, "WECHAT_APPID", "") or getattr(settings, "WX_MINI_APPID", "")
secret = getattr(settings, "WECHAT_SECRET", "") or getattr(settings, "WX_MINI_SECRET", "")
if not appid or not secret:
raise ValidationError("未配置 WECHAT_APPID/WECHAT_SECRET,无法进行内容审核")
client = WeChatMiniProgramSecCheck(appid=appid, secret=secret)
openid = get_user_openid(user)
if require_openid and not openid:
raise ValidationError({"message": "未获取到 openid,无法完成内容审核", "sec_check": {"suggest": "no_openid"}})
parts_reports: List[dict] = []
for part in _split_text(text, max_len=2000):
res = client.msg_sec_check(content=part, openid=openid, scene=int(scene), version=2)
report = _normalize_wx_resp(res.raw)
report.update({"suggest": res.suggest, "label": res.label})
parts_reports.append(report)
logger.info("wx sec_check: uid=%s scene=%s suggest=%s label=%s trace=%s",
getattr(user, "id", None), scene, res.suggest, res.label, report.get("trace_id"))
if res.ok:
continue
# review/risky:明确不通过
if res.suggest in ("review", "risky"):
raise ValidationError({"message": "内容可能包含敏感信息,请修改后再提交", "sec_check": report})
# 其它异常:strict=True 直接拒绝(并把微信返回带出去)
if strict:
raise ValidationError({"message": "内容审核服务异常,请稍后重试", "sec_check": report})
# strict=False:按你原来策略(这里默认还是拒绝更安全)
raise ValidationError({"message": "内容审核失败,请稍后重试", "sec_check": report})
# 多段合并返回:给前端 parts,必要时也能取最后一次
return {
"scene": int(scene),
"openid": (openid or "")[:8] + "..." if openid else "",
"parts": parts_reports,
"result": parts_reports[-1].get("result") if parts_reports else {},
"detail": sum((p.get("detail", []) for p in parts_reports), []),
}
@dataclass
class WxSecCheckResult:
ok: bool
suggest: str = ""
label: Optional[int] = None
raw: Optional[dict] = None
class WeChatMiniProgramSecCheck:
TOKEN_URL = " https://api.weixin.qq.com/cgi-bin/token "
MSG_SEC_CHECK_URL = " https://api.weixin.qq.com/wxa/msg_sec_check "
TOKEN_INVALID_CODES = {40001, 40014, 42001}
def __init__(self, appid: str, secret: str):
self.appid = appid
self.secret = secret
def _cache_key(self) -> str:
return f"wx:mp:access_token:{self.appid}"
def _get_access_token(self) -> str:
ck = self._cache_key()
cached = cache.get(ck)
if cached:
return cached
resp = requests.get(
self.TOKEN_URL,
params={
"grant_type": "client_credential",
"appid": self.appid,
"secret": self.secret,
},
timeout=6,
)
data = resp.json()
if "access_token" not in data:
raise RuntimeError(f"get_access_token failed: {data}")
token = data["access_token"]
expires_in = int(data.get("expires_in", 7200))
cache.set(ck, token, timeout=max(expires_in - 300, 60))
return token
def _invalidate_access_token(self) -> None:
cache.delete(self._cache_key())
def msg_sec_check(self, *, content: str, openid: Optional[str] = None, scene: int = 2,
version: int = 2) -> WxSecCheckResult:
content = (content or "").strip()
if not content:
return WxSecCheckResult(ok=False, suggest="empty")
if not getattr(settings, "WECHAT_SEC_CHECK_ENABLED", True):
return WxSecCheckResult(ok=True, suggest="pass (disabled)")
if not openid:
return WxSecCheckResult(ok=False, suggest="no_openid", raw={"errmsg": "missing openid"})
def _do_call(token: str) -> dict:
payload: dict[str, Any] = {
"content": content,
"openid": openid,
"scene": int(scene),
"version": int(version),
}
r = requests.post(self.MSG_SEC_CHECK_URL, params={"access_token": token}, json=payload, timeout=6)
return r.json()
token = self._get_access_token()
data = _do_call(token)
if int(data.get("errcode") or 0) in self.TOKEN_INVALID_CODES:
self._invalidate_access_token()
token = self._get_access_token()
data = _do_call(token)
errcode = int(data.get("errcode") or 0)
if errcode != 0:
logger.warning("wx msg_sec_check error: %s", data)
return WxSecCheckResult(ok=False, suggest="api_error", raw=data)
if "result" not in data:
logger.warning("wx msg_sec_check bad response (no result): %s", data)
return WxSecCheckResult(ok=False, suggest="bad_response", raw=data)
result = data.get("result") or {}
suggest = result.get("suggest") or "pass"
label = result.get("label")
return WxSecCheckResult(ok=(suggest == "pass"), suggest=suggest, label=label, raw=data)
def get_user_openid(user) -> Optional[str]:
for key in ("openid", "wx_openid", "wechat_openid"):
v = getattr(user, key, None)
if v:
return v
info = getattr(user, "info", None)
if info:
for key in ("openid", "wx_openid", "wechat_openid"):
v = getattr(info, key, None)
if v:
return v
return None
def _split_text(text: str, max_len: int = 2000) -> Iterable[str]:
"""
微信 msg_sec_check 文本长度通常不超过 2000 字符:contentReference[oaicite:2]{index=2}
超长就分段逐段检测。
"""
s = (text or "").strip()
if not s:
return []
buf = []
cur = ""
for ch in s:
if len(cur) >= max_len:
buf.append(cur)
cur = ""
cur += ch
if cur:
buf.append(cur)
return buf
def check_text_or_raise(*, user, text: str, scene: int, strict: bool = False, require_openid: bool = False) -> None:
appid = getattr(settings, "WECHAT_APPID", "") or getattr(settings, "WX_MINI_APPID", "")
secret = getattr(settings, "WECHAT_SECRET", "") or getattr(settings, "WX_MINI_SECRET", "")
if not appid or not secret:
raise ValidationError("未配置 WECHAT_APPID/WECHAT_SECRET,无法进行内容审核")
client = WeChatMiniProgramSecCheck(appid=appid, secret=secret)
openid = get_user_openid(user)
if require_openid and not openid:
raise ValidationError("未获取到 openid,无法完成内容审核,请退出重进小程序或重新登录后再试")
for part in _split_text(text, max_len=2000):
res = client.msg_sec_check(
content=part,
openid=openid,
scene=int(scene),
version=2,
)
if res.ok:
continue
logger.warning("wx sec_check block: suggest=%s label=%s raw=%s", res.suggest, res.label, res.raw)
if res.suggest in ("review", "risky"):
raise ValidationError("内容可能包含敏感信息,请修改后再提交")
if res.suggest == "empty":
raise ValidationError("内容不能为空")
# api_error:严格模式一律拒绝;非严格按 fail-open 配置决定
if res.suggest == "api_error":
if strict:
raise ValidationError("内容审核服务异常,请稍后重试")
if getattr(settings, "WECHAT_SEC_CHECK_FAIL_OPEN", False):
continue
raise ValidationError("内容审核失败,请稍后重试")
raise ValidationError("内容审核失败,请稍后重试")

各位大佬看看这是为什么,我说这些涉黄的,微信的文本检测接口还是可以通过,我服了
图片我不知道怎么发出来,有大佬教我一下怎么发图片吗