You've already forked FrameTour-BE
- 集成 WxMpUtil 工具类用于微信小程序消息安全检测 - 在用户更新昵称时添加内容安全校验逻辑 - 使用景区配置的微信小程序 AppId 和 AppSecret 进行检测 - 当昵称包含违规内容时抛出参数错误异常 - 实现 msgSecCheck 方法调用微信小程序内容安全接口 - 添加 MSG_SEC_CHECK_URL 常量定义检测接口地址
172 lines
8.7 KiB
Java
172 lines
8.7 KiB
Java
package com.ycwl.basic.utils;
|
|
|
|
import cn.hutool.http.HttpResponse;
|
|
import cn.hutool.http.HttpUtil;
|
|
import org.apache.commons.lang3.Strings;
|
|
|
|
import java.util.HashMap;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.InputStream;
|
|
import java.util.Date;
|
|
import java.util.Map;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
public class WxMpUtil {
|
|
private static final String GET_WXA_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s";
|
|
private static final String GET_WXA_CODE_UNLIMITED_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
|
|
private static final String GET_URL_LINK_URL = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=%s";
|
|
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
|
private static final String STABLE_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token?grant_type=client_credential&appid=%s&secret=%s&force_refresh=false";
|
|
public static final String GET_USER_PHONE_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";
|
|
private static final String MSG_SEC_CHECK_URL = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=%s";
|
|
private static final Map<String, String> tokens = new ConcurrentHashMap<>();
|
|
private static final Map<String, Date> expireTimes = new ConcurrentHashMap<>();
|
|
private static final ReentrantLock lock = new ReentrantLock();
|
|
|
|
private static String getAccessToken(String appId, String appSecret) {
|
|
lock.lock();
|
|
try {
|
|
if (expireTimes.containsKey(appId)) {
|
|
Date expireTime = expireTimes.get(appId);
|
|
if (expireTime.getTime() < System.currentTimeMillis()) {
|
|
tokens.remove(appId);
|
|
}
|
|
} else {
|
|
tokens.remove(appId);
|
|
}
|
|
return tokens.computeIfAbsent(appId, (k) -> {
|
|
String token;
|
|
if (!System.getProperty("os.name").toLowerCase().startsWith("win")) {
|
|
String url = String.format(STABLE_ACCESS_TOKEN_URL, appId, appSecret);
|
|
Map<String, Object> params = new HashMap<>();
|
|
params.put("grant_type", "client_credential");
|
|
params.put("appid", appId);
|
|
params.put("secret", appSecret);
|
|
params.put("force_refresh", false);
|
|
String response = HttpUtil.post(url, JacksonUtil.toJSONString(params));
|
|
Map<String, Object> jsonObject = JacksonUtil.parseObject(response, Map.class);
|
|
token = (String) jsonObject.get("access_token");
|
|
Date expireTime = new Date(System.currentTimeMillis() + ((Integer) jsonObject.get("expires_in")) * 1000 / 2);
|
|
expireTimes.put(appId, expireTime);
|
|
} else {
|
|
String url = String.format(ACCESS_TOKEN_URL, appId, appSecret);
|
|
String response = HttpUtil.get(url);
|
|
Map<String, Object> jsonObject = JacksonUtil.parseObject(response, Map.class);
|
|
token = (String) jsonObject.get("access_token");
|
|
Date expireTime = new Date(System.currentTimeMillis() + ((Integer) jsonObject.get("expires_in")) * 1000 / 2);
|
|
expireTimes.put(appId, expireTime);
|
|
}
|
|
return token;
|
|
});
|
|
} finally {
|
|
lock.unlock();
|
|
}
|
|
}
|
|
|
|
public static void generateWXAQRCode(String appId, String appSecret, String envVersion, String path, String filePath) throws Exception {
|
|
String url = String.format(GET_WXA_CODE_URL, getAccessToken(appId, appSecret));
|
|
Map<String, Object> json = new HashMap<>();
|
|
json.put("env_version", envVersion);
|
|
json.put("path", path);
|
|
json.put("width", 1000);
|
|
|
|
try (HttpResponse response = HttpUtil.createPost(url).body(JacksonUtil.toJSONString(json)).header("Content-Type", "application/json").execute()) {
|
|
if (response.getStatus() != 200) {
|
|
throw new Exception("获取小程序二维码失败,原因为:" + response.body());
|
|
}
|
|
InputStream inputStream = response.bodyStream();
|
|
try (FileOutputStream fos = new FileOutputStream(filePath)) {
|
|
int len;
|
|
byte[] buffer = new byte[1024];
|
|
while ((len = inputStream.read(buffer)) != -1) {
|
|
fos.write(buffer, 0, len);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void generateUnlimitedWXAQRCode(String appId, String appSecret, String path, String scene, File targetFile) throws Exception {
|
|
String url = String.format(GET_WXA_CODE_UNLIMITED_URL, getAccessToken(appId, appSecret));
|
|
Map<String, Object> json = new HashMap<>();
|
|
json.put("page", path);
|
|
json.put("scene", scene);
|
|
json.put("check_path", false);
|
|
|
|
try (HttpResponse response = HttpUtil.createPost(url).body(JacksonUtil.toJSONString(json)).header("Content-Type", "application/json").execute()) {
|
|
if (response.getStatus() != 200) {
|
|
throw new Exception("获取小程序二维码失败,原因为:" + response.body());
|
|
}
|
|
InputStream inputStream = response.bodyStream();
|
|
try (FileOutputStream fos = new FileOutputStream(targetFile)) {
|
|
int len;
|
|
byte[] buffer = new byte[1024];
|
|
while ((len = inputStream.read(buffer)) != -1) {
|
|
fos.write(buffer, 0, len);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static String generateUrlLink(String appId, String appSecret, String path, String query) throws Exception {
|
|
String url = String.format(GET_URL_LINK_URL, getAccessToken(appId, appSecret));
|
|
Map<String, Object> json = new HashMap<>();
|
|
json.put("path", path);
|
|
json.put("query", query);
|
|
|
|
try (HttpResponse response = HttpUtil.createPost(url).body(JacksonUtil.toJSONString(json)).header("Content-Type", "application/json").execute()) {
|
|
String responseStr = response.body();
|
|
|
|
Map<String, Object> jsonObject = JacksonUtil.parseObject(responseStr, Map.class);
|
|
if ((Integer) jsonObject.get("errcode") != 0) {
|
|
throw new Exception("获取url_link失败,原因为:" + (String) jsonObject.get("errmsg"));
|
|
}
|
|
return (String) jsonObject.get("url_link");
|
|
}
|
|
}
|
|
|
|
public static String getUserPhone(String appId, String appSecret, String code) throws Exception {
|
|
String url = String.format(GET_USER_PHONE_URL, getAccessToken(appId, appSecret));
|
|
Map<String, Object> json = new HashMap<>();
|
|
json.put("code", code);
|
|
|
|
try (HttpResponse response = HttpUtil.createPost(url).body(JacksonUtil.toJSONString(json)).header("Content-Type", "application/json").execute()) {
|
|
String responseStr = response.body();
|
|
|
|
Map<String, Object> jsonObject = JacksonUtil.parseObject(responseStr, Map.class);
|
|
if ((Integer) jsonObject.get("errcode") != 0) {
|
|
throw new Exception("获取用户手机号失败,原因为:" + (String) jsonObject.get("errmsg"));
|
|
}
|
|
return (String) ((Map<String, Object>) jsonObject.get("phone_info")).get("phoneNumber");
|
|
}
|
|
}
|
|
|
|
public static boolean msgSecCheck(String appId, String appSecret, String content, String openId, int scene) {
|
|
String url = String.format(MSG_SEC_CHECK_URL, getAccessToken(appId, appSecret));
|
|
Map<String, Object> json = new HashMap<>();
|
|
json.put("content", content);
|
|
json.put("version", 2);
|
|
json.put("scene", scene);
|
|
json.put("openid", openId);
|
|
|
|
String response = HttpUtil.post(url, JacksonUtil.toJSONString(json));
|
|
Map<String, Object> jsonObject = JacksonUtil.parseObject(response, Map.class);
|
|
Object errcode = jsonObject.get("errcode");
|
|
boolean success = errcode != null && (Integer) errcode == 0;
|
|
if (!success) {
|
|
// 接口调用失败,认为检测成功。
|
|
return true;
|
|
}
|
|
Map<String, Object> result = JacksonUtil.getObject(response, "result", Map.class);
|
|
if (result == null) {
|
|
return false;
|
|
}
|
|
String suggest = result.getOrDefault("suggest", "").toString();
|
|
return Strings.CI.equals(suggest, "pass");
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
generateWXAQRCode("wxe7ff26af70bfc37c", "5252fbbc68513bc77b7cc0052b9f9695", "trial", "pages/home/index?scenicId=3930324797233434624&morphId=22", "zt_p_t.jpg");
|
|
}
|
|
} |