抽取配置文件
appId以及secret需要自行在抖音开放平台获取
dy:
appId: ttb0xxxxx
secret: 12a19a426xxxxxxxxxxxxx
获取access-token
参照文档我们调用此接口需要先获取access-token
获取access-token官方文档地址
注意事项
client_token 的有效时间为 2 个小时,重复获取 client_token 后会使上次的 client_token 失效(但有 5 分钟的缓冲时间,连续多次获取 client_token 只会保留最新的两个 client_token)。
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.hss.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* @author zr 2024/10/12
*/
@Service
@Slf4j
public class DyService {
@Value("${dy.appId}")
private String CLIENT_KEY; // appId
@Value("${dy.secret}")
private String CLIENT_SECRET; // secret
private static final String CLIENT_TOKEN_URL = "https://open.douyin.com/oauth/client_token/";
/**
* 获取 access_token
*
* @return 返回 access_token
*/
public String getAccessToken() {
// 构建请求体
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("grant_type", "client_credential");
requestBody.put("client_key", CLIENT_KEY);
requestBody.put("client_secret", CLIENT_SECRET);
// 发送 POST 请求
HttpResponse response = HttpRequest.post(CLIENT_TOKEN_URL)
.header("Content-Type", "application/json")
.body(JSONUtil.toJsonStr(requestBody)) // 将请求体转换为 JSON 字符串
.timeout(20000) // 设置超时时间为 20 秒
.execute();
// 解析响应
String responseBody = response.body();
JSONObject res = JSON.parseObject(responseBody);
log.info("Url: " + CLIENT_TOKEN_URL);
log.info("body: " + JSONUtil.toJsonStr(requestBody));
log.info("res: " + res);
if (!"success".equals(res.getString("message"))){
throw new ServiceException("抖音token错误:" + res.get("message"));
}
String token = res.getJSONObject("data").getString("access_token").toString();
return token;
}
}
图片检测V3
提供给开发者进行图片合法合规校验
图片检测V3原文档地址
请求参数可以使用图片链接或者base64数据,我使用的图片链接,读者有需要可以更换参数使用base64数据
- censorImage方法传入图片url返回true表示图片合法,false表示图片不合法
- 图片检测一次请求会检测多项如下图:(****predicts下的所有项目都为false图片才检测为合法)
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.hss.common.core.domain.R;
import com.hss.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* @author zr 2024/10/12
*/
@Service
@Slf4j
public class DyService {
@Value("${dy.appId}")
private String CLIENT_KEY; // appId
@Value("${dy.secret}")
private String CLIENT_SECRET; // secret
private static final String CENSOR_IMAGE_URL = "https://open.douyin.com/api/apps/v1/censor/image";
private static final String CLIENT_TOKEN_URL = "https://open.douyin.com/oauth/client_token/";
/**
* 获取 access_token
*
* @return 返回 access_token
*/
public String getAccessToken() {
// 构建请求体
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("grant_type", "client_credential");
requestBody.put("client_key", CLIENT_KEY);
requestBody.put("client_secret", CLIENT_SECRET);
// 发送 POST 请求
HttpResponse response = HttpRequest.post(CLIENT_TOKEN_URL)
.header("Content-Type", "application/json")
.body(JSONUtil.toJsonStr(requestBody)) // 将请求体转换为 JSON 字符串
.timeout(20000) // 设置超时时间为 20 秒
.execute();
// 解析响应
String responseBody = response.body();
JSONObject res = JSON.parseObject(responseBody);
log.info("Url: " + CLIENT_TOKEN_URL);
log.info("body: " + JSONUtil.toJsonStr(requestBody));
log.info("res: " + res);
if (!"success".equals(res.getString("message"))){
throw new ServiceException("抖音token错误:" + res.get("message"));
}
String token = res.getJSONObject("data").getString("access_token").toString();
return token;
}
/**
* 图片合法合规校验
* @param imageUrl
* @return 返回 true/false
*/
public R<Boolean> censorImage(String imageUrl) {
String accessToken = getAccessToken();
// 构建请求体
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("app_id", CLIENT_KEY);
requestBody.put("access-token", accessToken);
requestBody.put("image", imageUrl);
// 发送 POST 请求
HttpResponse response = HttpRequest.post(CENSOR_IMAGE_URL)
.header("access-token", accessToken) // 在请求头中加入 access-token
.header("Content-Type", "application/json") // 设置Content-Type为application/json
.body(JSONUtil.toJsonStr(requestBody)) // 将请求体转换为 JSON 字符串
.timeout(20000) // 设置超时时间
.execute();
// 解析响应
String responseBody = response.body();
log.info("Url: " + CLIENT_TOKEN_URL);
log.info("body: " + JSONUtil.toJsonStr(requestBody));
log.info("res: " + responseBody);
JSONObject res = JSON.parseObject(responseBody);
if (!"0".equals(res.getString("err_no"))){
log.info("抖音图片审核错误:" + res.get("err_msg"));
throw new ServiceException("抖音图片审核错误:" + res.get("err_msg"));
}
List<JSONObject> predicts = res.getList("predicts", JSONObject.class);
// 使用流的方式检查是否有任何 hit 为 true 的项目
boolean anyHitTrue = predicts.stream()
.anyMatch(predict -> predict.getBoolean("hit"));
if (anyHitTrue) {
return R.ok(false, "图片含有敏感信息");
} else {
return R.ok(true);
}
}
}