微信小程序中基于java后端实现官方的文本内容安全识别msgSecCheck

在开发微信小程序中,发布审核的时候官方审核要求要对用于UGC生成的内容做安全审核,对违规内容进行处理,这里用到了官方给出的文本内容安全识别和多媒体内容安全识别,这次是基于java后端去实现的,过去的文章有写用云开发调用,可以参考以前的文章。

码字不易,看之前麻烦点个赞赞~谢谢!

文本内容安全识别

接口应在服务器端调用,不可在前端(小程序、网页、APP等)直接调用,具体可参考接口调用指南

接口英文名:msgSecCheck

该接口用于检查一段文本是否含有违法违规内容。

应用场景:

  • 用户个人资料违规文字检测;
  • 媒体新闻类用户发表文章,评论内容检测;
  • 游戏类用户编辑上传的素材(如答题类小游戏用户上传的问题及答案)检测等

查询参数 Query String Parameters

参数名 类型 必填 说明
access_token string 接口调用凭证

请求体 Request Payload

参数名 类型 必填 说明
content string 需检测的文本内容,文本字数的上限为2500字,需使用UTF-8编码
version number 接口版本号,2.0版本为固定值2
scene number 场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
openid string 用户的openid(用户需在近两小时访问过小程序)
title string 文本标题,需使用UTF-8编码
nickname string 用户昵称,需使用UTF-8编码
signature string 个性签名,该参数仅在资料类场景有效(scene=1),需使用UTF-8编码

3. 返回参数

返回体 Response Payload

参数名 类型 说明
errcode number 错误码
errmsg string 错误信息
detail objarray 详细检测结果
trace_id string 唯一请求标识,标记单次请求
result object 综合结果

解析

首先是查询参数access_token这个怎么获取?

复制代码
XpayUtils.java
java 复制代码
  public String getAccessToken() throws Exception {
        long now = System.currentTimeMillis();
        if (cachedAccessToken != null && now < tokenExpireMillis) return cachedAccessToken;
        synchronized (this) {
            now = System.currentTimeMillis();
            if (cachedAccessToken != null && now < tokenExpireMillis) return cachedAccessToken;
            String url = "https://api.weixin.qq.com/cgi-bin/token"
                    + "?grant_type=client_credential"
                    + "&appid=" + XpayConfig.APP_ID
                    + "&secret=" + XpayConfig.APP_SECRET;
            String raw = restTemplate.getForObject(url, String.class);
            JSONObject json = JSONObject.fromObject(raw);
            if (!json.containsKey("access_token")) {
                throw new Exception("获取 access_token 失败:" + raw);
            }
            cachedAccessToken = json.getString("access_token");
            long expiresIn = json.getLong("expires_in");
            tokenExpireMillis = now + (expiresIn - 300) * 1000L;
            return cachedAccessToken;
        }
    }

XpayConfig.java

java 复制代码
public class XpayConfig {

    // 小程序 AppID / AppSecret
    public static final String APP_ID     = "";
    public static final String APP_SECRET = "";

}

然后是文本内容安全接口实现

java 复制代码
   // ==================== 文本 msg_sec_check ====================

    @Data
    @NoArgsConstructor
    public static class TextSecCheckReq {
        /** 需检测文本,≤2500 字,UTF-8 */
        private String content;
        /** 接口版本,2.0 固定为 2 */
        private Integer version;
        /** 场景:1资料 2评论 3论坛 4社交日志 */
        private Integer scene;
        /** 用户 openid(近两小时需访问过小程序) */
        private String openid;
        private String title;
        private String nickname;
        /** 个性签名,仅 scene=1 有效 */
        private String signature;
    }

    /**
     * 文本内容安全识别(转发 POST https://api.weixin.qq.com/wxa/msg_sec_check)
     */
    @PostMapping("/text/check")
    public String textSecCheck(@RequestBody TextSecCheckReq req) {
        IsInterface<JSONObject> res = new IsInterface<>();
        try {
            if (req.getContent() == null || req.getContent().trim().isEmpty()) {
                res.setCode("fail");
                res.setMsg("content不能为空");
                return String.valueOf(JSONObject.fromObject(res));
            }
            String text = req.getContent();
            if (text.length() > 2500) {
                res.setCode("fail");
                res.setMsg("content超过2500字上限");
                return String.valueOf(JSONObject.fromObject(res));
            }
            if (req.getScene() == null
                    || req.getOpenid() == null || req.getOpenid().trim().isEmpty()) {
                res.setCode("fail");
                res.setMsg("scene、openid不能为空");
                return String.valueOf(JSONObject.fromObject(res));
            }
            int version = req.getVersion() != null ? req.getVersion() : 2;

            JSONObject body = new JSONObject();
            body.put("content", text);
            body.put("version", version);
            body.put("scene", req.getScene());
            body.put("openid", req.getOpenid().trim());
            if (req.getTitle() != null && !req.getTitle().isEmpty()) {
                body.put("title", req.getTitle());
            }
            if (req.getNickname() != null && !req.getNickname().isEmpty()) {
                body.put("nickname", req.getNickname());
            }
            if (req.getSignature() != null && !req.getSignature().isEmpty()) {
                body.put("signature", req.getSignature());
            }

            JSONObject wx = wxaOpenApiUtils.postJson("/wxa/msg_sec_check", body);
            res.setCode("success");
            res.setMsg("ok");
            res.setObj(wx);
            return String.valueOf(JSONObject.fromObject(res));
        } catch (Exception e) {
            res.setCode("fail");
            res.setMsg("调用失败:" + e.getMessage());
            return String.valueOf(JSONObject.fromObject(res));
        }
    }

wxaOpenApiUtils.java

java 复制代码
/**
 * 小程序服务端调用微信开放接口(非米大师 xpay),共用 {@link XpayUtils#getAccessToken()}。
 */
@Component
public class WxaOpenApiUtils {

    private final RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private XpayUtils xpayUtils;

    /**
     * POST JSON 到 api.weixin.qq.com 指定路径(不含域名)
     *
     * @param wxPath 如 {@code /wxa/msg_sec_check}
     * @param body   JSON 请求体
     * @return 微信返回的 JSON
     */
    public JSONObject postJson(String wxPath, JSONObject body) throws Exception {
        String token = xpayUtils.getAccessToken();
        String url = "https://api.weixin.qq.com" + wxPath + "?access_token=" + token;
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(body.toString(), headers);
        String raw = restTemplate.postForObject(url, entity, String.class);
        return JSONObject.fromObject(raw);
    }
}

综合结果可以看下面官方提供的信息,来判断是否违规

Res.result Object Payload

综合结果

参数名 类型 说明
suggest string 建议,有risky、pass、review三种值
label number 命中标签枚举值,100 正常;10001 广告;20001 时政;20002 色情;20003 辱骂;20006 违法犯罪;20008 欺诈;20012 低俗;20013 版权;21000 其他
相关推荐
A__tao1 小时前
JSON 转 Java 实体类工具(支持嵌套与注释解析)
java·python·json
zx2859634001 小时前
Laravel6.x新特性全解析
java·后端·spring
极光代码工作室1 小时前
基于SpringBoot的图书管理系统
java·springboot·web开发·后端开发
许彰午1 小时前
# 从OOM到根治的完整过程——导出大数据的应急、根因分析与游标方案
java·大数据·数据库·系统架构
李李李勃谦2 小时前
鸿蒙PC配色方案工具:取色、配色生成与 CSS 导出
前端·css·华为·harmonyos
上弦月-编程2 小时前
C语言指针超详细教程——从入门到精通(面向初学者)
java·数据结构·算法
ANnianStriver2 小时前
Java中的stream流的用法
java
1104.北光c°2 小时前
【AI核心概念讲解】一口气搞懂 Agent:干翻传统后端!自主循环决策的秘密,ReAct 与 Plan-and-Execute 范式
java·人工智能·程序人生·ai·agent·react·智能体
我不是立达刘宁宇2 小时前
windows信息收集
windows·安全