| @@ -1,5 +1,6 @@ | |||||
| package cn.binarywang.wx.miniapp.api; | package cn.binarywang.wx.miniapp.api; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaMediaAsyncCheckResult; | |||||
| import java.io.File; | import java.io.File; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| @@ -18,6 +19,8 @@ public interface WxMaSecCheckService { | |||||
| String MSG_SEC_CHECK_URL = "https://api.weixin.qq.com/wxa/msg_sec_check"; | String MSG_SEC_CHECK_URL = "https://api.weixin.qq.com/wxa/msg_sec_check"; | ||||
| String MEDIA_CHECK_ASYNC_URL = "https://api.weixin.qq.com/wxa/media_check_async"; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| * 校验一张图片是否含有违法违规内容. | * 校验一张图片是否含有违法违规内容. | ||||
| @@ -39,5 +42,25 @@ public interface WxMaSecCheckService { | |||||
| * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/sec-check/msgSecCheck.html | * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/sec-check/msgSecCheck.html | ||||
| * </pre> | * </pre> | ||||
| */ | */ | ||||
| boolean checkMessage(String msgString); | |||||
| boolean checkMessage(String msgString) throws WxErrorException; | |||||
| /** | |||||
| * <pre> | |||||
| * 异步校验图片/音频是否含有违法违规内容。 | |||||
| * 应用场景举例: | |||||
| * 语音风险识别:社交类用户发表的语音内容检测; | |||||
| * 图片智能鉴黄:涉及拍照的工具类应用(如美拍,识图类应用)用户拍照上传检测;电商类商品上架图片检测;媒体类用户文章里的图片检测等; | |||||
| * 敏感人脸识别:用户头像;媒体类用户文章里的图片检测;社交类用户上传的图片检测等。 | |||||
| * 频率限制: | |||||
| * 单个 appId 调用上限为 2000 次/分钟,200,000 次/天;文件大小限制:单个文件大小不超过10M | |||||
| * 详情请见: | |||||
| * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.mediaCheckAsync.html | |||||
| * </pre> | |||||
| * @param mediaUrl 要检测的多媒体url | |||||
| * @param mediaType 媒体类型,{@link cn.binarywang.wx.miniapp.constant.WxMaConstants.SecCheckMediaType} | |||||
| * @return | |||||
| */ | |||||
| WxMaMediaAsyncCheckResult mediaCheckAsync(String mediaUrl,int mediaType) throws WxErrorException; | |||||
| } | } | ||||
| @@ -2,14 +2,14 @@ package cn.binarywang.wx.miniapp.api.impl; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaSecCheckService; | import cn.binarywang.wx.miniapp.api.WxMaSecCheckService; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | import cn.binarywang.wx.miniapp.api.WxMaService; | ||||
| import cn.binarywang.wx.miniapp.bean.WxMaMediaAsyncCheckResult; | |||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import java.io.File; | |||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | ||||
| import java.io.File; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| * | * | ||||
| @@ -20,6 +20,7 @@ import java.io.File; | |||||
| */ | */ | ||||
| @AllArgsConstructor | @AllArgsConstructor | ||||
| public class WxMaSecCheckServiceImpl implements WxMaSecCheckService { | public class WxMaSecCheckServiceImpl implements WxMaSecCheckService { | ||||
| private WxMaService service; | private WxMaService service; | ||||
| @Override | @Override | ||||
| @@ -31,16 +32,24 @@ public class WxMaSecCheckServiceImpl implements WxMaSecCheckService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public boolean checkMessage(String msgString) { | |||||
| public boolean checkMessage(String msgString) throws WxErrorException { | |||||
| JsonObject jsonObject = new JsonObject(); | JsonObject jsonObject = new JsonObject(); | ||||
| jsonObject.addProperty("content", msgString); | jsonObject.addProperty("content", msgString); | ||||
| try { | |||||
| this.service.post(MSG_SEC_CHECK_URL, jsonObject.toString()); | |||||
| } catch (WxErrorException e) { | |||||
| return false; | |||||
| } | |||||
| this.service.post(MSG_SEC_CHECK_URL, jsonObject.toString()); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @Override | |||||
| public WxMaMediaAsyncCheckResult mediaCheckAsync(String mediaUrl, int mediaType) | |||||
| throws WxErrorException { | |||||
| JsonObject jsonObject = new JsonObject(); | |||||
| jsonObject.addProperty("media_url", mediaUrl); | |||||
| jsonObject.addProperty("media_type", mediaType); | |||||
| return WxMaMediaAsyncCheckResult | |||||
| .fromJson(this.service.post(MEDIA_CHECK_ASYNC_URL, jsonObject.toString())); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,25 @@ | |||||
| package cn.binarywang.wx.miniapp.bean; | |||||
| import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||||
| import com.google.gson.annotations.SerializedName; | |||||
| import java.io.Serializable; | |||||
| public class WxMaMediaAsyncCheckResult implements Serializable { | |||||
| private static final long serialVersionUID = 3928132365399916183L; | |||||
| /** | |||||
| * 任务id,用于匹配异步推送结果 | |||||
| */ | |||||
| @SerializedName("trace_id") | |||||
| private String traceId; | |||||
| public static WxMaMediaAsyncCheckResult fromJson(String json) { | |||||
| return WxMaGsonBuilder.create().fromJson(json, WxMaMediaAsyncCheckResult.class); | |||||
| } | |||||
| public String toJson() { | |||||
| return WxMaGsonBuilder.create().toJson(this); | |||||
| } | |||||
| } | |||||
| @@ -69,4 +69,20 @@ public class WxMaConstants { | |||||
| */ | */ | ||||
| public static final int ERR_40014 = 40014; | public static final int ERR_40014 = 40014; | ||||
| } | } | ||||
| /** | |||||
| * 内容安全检测的媒体类型 | |||||
| */ | |||||
| public static final class SecCheckMediaType { | |||||
| /** | |||||
| * 音频 | |||||
| */ | |||||
| public static final int VOICE = 1; | |||||
| /** | |||||
| * 图片 | |||||
| */ | |||||
| public static final int IMAGE = 2; | |||||
| } | |||||
| } | } | ||||
| @@ -32,6 +32,8 @@ public class WxMaMessageRouterRule { | |||||
| private String rContent; | private String rContent; | ||||
| private String title; | |||||
| private WxMaMessageMatcher matcher; | private WxMaMessageMatcher matcher; | ||||
| private boolean reEnter = false; | private boolean reEnter = false; | ||||
| @@ -60,6 +62,16 @@ public class WxMaMessageRouterRule { | |||||
| return this; | return this; | ||||
| } | } | ||||
| /** | |||||
| * 标题,发送小程序页卡时有效 | |||||
| * @param title | |||||
| * @return | |||||
| */ | |||||
| public WxMaMessageRouterRule title(String title){ | |||||
| this.title = title; | |||||
| return this; | |||||
| } | |||||
| /** | /** | ||||
| * 如果event等于某值. | * 如果event等于某值. | ||||
| */ | */ | ||||
| @@ -100,6 +112,8 @@ public class WxMaMessageRouterRule { | |||||
| return this; | return this; | ||||
| } | } | ||||
| /** | /** | ||||
| * 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候. | * 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候. | ||||
| */ | */ | ||||
| @@ -164,6 +178,8 @@ public class WxMaMessageRouterRule { | |||||
| return end(); | return end(); | ||||
| } | } | ||||
| /** | /** | ||||
| * 将微信自定义的事件修正为不区分大小写. | * 将微信自定义的事件修正为不区分大小写. | ||||
| * 比如框架定义的事件常量为click,但微信传递过来的却是CLICK | * 比如框架定义的事件常量为click,但微信传递过来的却是CLICK | ||||
| @@ -183,6 +199,9 @@ public class WxMaMessageRouterRule { | |||||
| .matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim())) | .matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim())) | ||||
| && | && | ||||
| (this.matcher == null || this.matcher.match(wxMessage)) | (this.matcher == null || this.matcher.match(wxMessage)) | ||||
| && | |||||
| (this.title == null || this.title | |||||
| .equals(wxMessage.getTitle() == null ? null : wxMessage.getTitle().trim())) | |||||
| ; | ; | ||||
| } | } | ||||
| @@ -38,12 +38,13 @@ public class WxMaSecCheckServiceImplTest { | |||||
| return new Object[][]{ | return new Object[][]{ | ||||
| {"特3456书yuuo莞6543李zxcz蒜7782法fgnv级", false}, | {"特3456书yuuo莞6543李zxcz蒜7782法fgnv级", false}, | ||||
| {"完2347全dfji试3726测asad感3847知qwez到", false}, | {"完2347全dfji试3726测asad感3847知qwez到", false}, | ||||
| {"提现&下载&棋牌游戏&网页", false}, | |||||
| {"hello world!", true} | {"hello world!", true} | ||||
| }; | }; | ||||
| } | } | ||||
| @Test(dataProvider = "secData") | @Test(dataProvider = "secData") | ||||
| public void testCheckMessage(String msg, boolean result) { | |||||
| public void testCheckMessage(String msg, boolean result) throws WxErrorException { | |||||
| assertThat(this.wxService.getSecCheckService() | assertThat(this.wxService.getSecCheckService() | ||||
| .checkMessage(msg)) | .checkMessage(msg)) | ||||
| .isEqualTo(result); | .isEqualTo(result); | ||||