| 名称 | 描述 |
|---|---|
| appKey | 应用key,网关会根据应用key调用对应服务,每个接口详情中均有对应appKey。 |
| apiName | 调用api名称,网关会根据apiName调用具体的接口。 |
| accessKey | 密钥ak |
| secret | 密钥sk |
| sign | MD5加密字符串 对应用Key, 密钥ak,时间戳 ,密钥sk 加密后的结果 |
| requestId | 请求id,建议使用uuid 用于链路追踪使用 |
| timestamp | 时间戳 |
目前提供三种接入方式选择
package com.demo.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 简化版API测试类:GET/POST调用+签名生成(单类解决)
*/
public class TestRquest {
// 1. 基础配置(集中管理,改起来方便)
private static final Logger log = LoggerFactory.getLogger(TestRquest.class);
private static final String API_URL = "http://open.metac-inc.com/api"; // 接口地址
private static final int TIMEOUT = 8000; // 超时时间(毫秒)
// 2. 主方法:直接执行API调用(核心逻辑)
public static void main(String[] args) {
// 2.1 接口参数配置(按需修改这里即可)
//生产环境ak sk 替换此处ak和sk为自己的
String accessKey = "xxxxx";
String secret = "xxxxxx";
// String accessKey = "xxxxxxx";
// String secret = "xxxxxxxxxx";
// String appKey = "marketing-server";
// String apiName = "marketing_algorithm_pattern_seg";
// String method = "post"; // get 或 post
// String postJson = "{\"image\":\"https://miaobi-lite.bj.bcebos.com/miaobi/5mao/b%27LV8xNzM0MzA3NTAwLjU1ODU5Mjg%3D%27/0.png\",\"return_view_image\":false}";
// invokeRquest(accessKey, apiName, appKey, secret, method, null,postJson);
String appKey = "marketing-server";
String apiName = "marketing_model_task_fetchWithMarketingModelTaskOutputPO_id";
String method = "get"; // get 或 post
HashMap getParams = new HashMap<>();
getParams.put("id", 3991374);
invokeRquest(accessKey, apiName, appKey, secret, method, getParams,null);
}
private static void invokeRquest(String accessKey, String apiName, String appKey, String secret, String method, Map getParams ,String postJson) {
// 2.2 构建请求头(含签名)
HashMap headers = new HashMap<>();
Long timestamp = System.currentTimeMillis();
//请求id,建议使用uuid
headers.put("requestId", UUID.randomUUID().toString());
//密钥ak
headers.put("accessKey", accessKey);
//调用api名称,比如:check
headers.put("apiName", apiName);
//应用key (appKey请找对应接口人获取)比如: test
headers.put("appKey", appKey);
headers.put("timestamp", String.valueOf(timestamp));
headers.put("Content-Type", "application/json");
//MD5加密字符串 应用Key, 密钥ak,时间戳 ,密钥sk
String sign = generateSign(appKey, accessKey, timestamp, secret);
headers.put("sign", sign);
log.info("请求头:{} | 签名原始串:{}", headers, appKey + accessKey + timestamp + secret);
// 2.3 转换参数并发送请求
String response = null;
if ("get".equals(method)) {
response = HttpUtils.get(API_URL, getParams, headers, TIMEOUT);
} else if ("post".equals(method)) {
log.info("POST请求参数:{}", postJson);
response = HttpUtils.postJson(API_URL, postJson, headers, TIMEOUT);
}
// 2.4 打印结果
log.info("接口响应:{}", response == null ? "无响应体" : response);
}
// 3. 签名生成工具(核心方法,独立抽取)
/**
* 生成MD5加密sign
*
* @param appKey 应用key,
* @param accessKey 密钥ak,联系接口人获取
* @param timestamp 时间戳,以毫秒为单位的当前时间,例如 java 获取方式:Long timestamp = System.currentTimeMillis();
* @param secret 密钥sk,联系接口人获取
* @return
*/
private static String generateSign(String appKey, String accessKey, Long timestamp, String secret) {
try {
String src = appKey + accessKey + timestamp + secret;
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(StandardCharsets.UTF_8.encode(src));
return String.format("%032x", new BigInteger(1, md5.digest()));
} catch (NoSuchAlgorithmException e) {
log.error("MD5签名生成失败", e);
throw new RuntimeException("签名生成异常", e);
}
}
}
package com.demo.utils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.Map;
public class HttpUtils {
// 单例 RestTemplate 实例(Spring 环境中建议通过 @Bean 注入,此处简化为静态实例)
private static final RestTemplate restTemplate = new RestTemplate();
/**
* 发送 POST 请求(表单参数),返回响应体字符串
*
* @param url 请求地址
* @param params 表单参数(键值对)
* @param headers 请求头
* @param timeout 超时时间(毫秒)
* @return 响应体字符串
*/
public static String postForm(String url, MultiValueMap params,
Map headers, int timeout) {
// 构建请求头(表单格式)
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
if (headers != null && !headers.isEmpty()) {
headers.forEach(httpHeaders::add);
}
// 构建请求实体(MultiValueMap 可直接被 RestTemplate 转换为表单格式)
HttpEntity> requestEntity = new HttpEntity<>(params, httpHeaders);
// 发送请求并返回响应体
return restTemplate.postForObject(url, requestEntity, String.class);
}
/**
* 发送 POST 请求(JSON 参数),返回响应体字符串
*
* @param url 请求地址
* @param jsonParam JSON 格式参数字符串
* @param headers 请求头
* @param timeout 超时时间(毫秒)
* @return 响应体字符串
*/
public static String postJson(String url, String jsonParam, Map headers, int timeout) {
// 构建请求头(JSON 格式)
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
if (headers != null && !headers.isEmpty()) {
headers.forEach(httpHeaders::add);
}
// 构建请求实体
HttpEntity requestEntity = new HttpEntity<>(jsonParam, httpHeaders);
// 发送请求并返回响应体
return restTemplate.postForObject(url, requestEntity, String.class);
}
/**
* 发送 POST 请求(JSON 参数),返回指定类型的 Java 对象(类似 @ResponseBody 自动解析)
*
* @param url 请求地址
* @param jsonParam JSON 格式参数字符串
* @param headers 请求头
* @param responseType 响应体要转换的目标类(例如:User.class)
* @param 目标类型
* @return 解析后的 Java 对象
*/
public static T postJsonForObject(String url, String jsonParam, Map headers, Class responseType) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
if (headers != null && !headers.isEmpty()) {
headers.forEach(httpHeaders::add);
}
HttpEntity requestEntity = new HttpEntity<>(jsonParam, httpHeaders);
return restTemplate.postForObject(url, requestEntity, responseType);
}
/**
* 发送 GET 请求(带 Query 参数),返回响应体字符串
* @param url 请求地址(如:http://xxx.com/api)
* @param params Query 参数(键值对,会拼在 URL 后,如 ?key1=value1&key2=value2)
* @param headers 请求头
* @param timeout 超时时间(毫秒)
* @return 响应体字符串
*/
public static String get(String url, Map params, Map headers, int timeout) {
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);
if (params != null && !params.isEmpty()) {
params.forEach(uriBuilder::queryParam);
}
String finalUrl = uriBuilder.toUriString();
HttpHeaders httpHeaders = new HttpHeaders();
if (headers != null && !headers.isEmpty()) {
httpHeaders.setAll(headers);
}
httpHeaders.remove("Content-Type");
HttpEntity requestEntity = new HttpEntity<>(httpHeaders);
RestTemplate timeoutRestTemplate = createRestTemplateWithTimeout(timeout);
return timeoutRestTemplate.exchange(
finalUrl,
HttpMethod.GET,
requestEntity,
String.class
).getBody();
}
/**
* 发送 GET 请求(带 Query 参数),直接返回解析后的 Java 对象
* @param url 请求地址
* @param params Query 参数
* @param headers 请求头
* @param responseType 响应体要转换的目标类(如:OssSignatureDTO.class)
* @param 目标类型
* @return 解析后的 Java 对象
*/
public static T getForObject(String url, Map params, Map headers,
int timeout, Class responseType) {
// 1. 同样构建带 Query 参数的 URL
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);
if (params != null && !params.isEmpty()) {
for (Map.Entry entry : params.entrySet()) {
uriBuilder.queryParam(entry.getKey(), entry.getValue());
}
}
String finalUrl = uriBuilder.toUriString();
// 2. 构建请求头
HttpHeaders httpHeaders = new HttpHeaders();
if (headers != null && !headers.isEmpty()) {
headers.forEach(httpHeaders::add);
}
// 3. 构建请求实体
HttpEntity requestEntity = new HttpEntity<>(httpHeaders);
// 4. 发送请求并自动解析为目标对象
RestTemplate timeoutRestTemplate = createRestTemplateWithTimeout(timeout);
return timeoutRestTemplate.getForObject(finalUrl, responseType, requestEntity);
}
// 可选:配置超时时间(需要自定义 RestTemplate 的 RequestFactory)
public static RestTemplate createRestTemplateWithTimeout(int timeout) {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(timeout); // 连接超时
requestFactory.setReadTimeout(timeout); // 读取超时
return new RestTemplate(requestFactory);
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.15</version>
</dependency>
直接使用我们的settings.xml文件
通过本指南快速设置仓库凭证,并完成制品文件的拉取。 本方法适用于本地没有配置过settings.xml可以通过我们提供给您的示例settings.xml文件完成设置。若您在本地进行过 Maven 配置,请参考下方**修改已有的settings.xml文件 ** (修改方式)。
下载示例配置文件settings.xml并将其存放至$HOME/.m2/文件目录下。 示例文件settings.xml中的username和password为凭证。 示例settings.xml中已为你自动填写username和password,可以直接使用,无须手动修改
settings
.xml
修改已有的settings.xml文件
通过本指南快速设置仓库凭证,并完成制品文件的拉取。 本方法适用于本地进行过settings.xml的配置,需要在您的settings.xml文件中修改配置完成操作。若您在本地没有进行过 Maven 配置,可参考 拉取(覆盖方式)
添加账户及仓库
请在settings.xml文件中添加对应的仓库及仓库的访问凭证,通常settings.xml在$HOME/.m2/文件目录下。
<servers>
<server>
<id>rdc-releases</id>
<username>63aa8d60c8605436e801b00e</username>
<password>1kS1yEeu_IQU</password>
</server>
<server>
<id>rdc-snapshots</id>
<username>63aa8d60c8605436e801b00e</username>
<password>1kS1yEeu_IQU</password>
</server>
</servers>
<repositories>
<repository>
<id>rdc-releases</id>
<url>https://packages.aliyun.com/maven/repository/2314917-release-Rur2IA/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>rdc-snapshots</id>
<url>https://packages.aliyun.com/maven/repository/2314917-snapshot-WqFvpI/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
下方gateway-sdk-commons为必须依赖的基础包
<dependency>
<groupId>{请根据实际业务替换}</groupId>
<artifactId>{请根据实际业务替换}</artifactId>
<version>{请根据实际业务替换}</version>
</dependency>
<dependency>
<groupId>com.metac.gateway</groupId>
<artifactId>gateway-sdk-commons</artifactId>
<version>1.0.0</version>
</dependency>
调⽤示例
import com.metac.gateway.sdk.commons.models.Config;
import com.metac.gateway.sdk.commons.models.RuntimeOptions;
import com.metac.trend.Client;
import com.metac.trend.models.*;
public static void main(String[] args) throws Exception {
// 配置客户端
Config config = new Config();
config.setAccessKeyId("ak"); //这⾥替换你的ak
config.setAccessKeySecret("sk"); //这⾥替换你的sk
config.setEndpoint("open.metac-inc.com");
Client client = new Client(config);
//获取图片上传签名,主要给前端直传使用,有公网图片地址可忽略这一步交互
SasOssGetOssSecretFiletypeRequest sasOssGetOssSecretFiletypeRequest = new SasOssGetOssSecretFiletypeRequest();
sasOssGetOssSecretFiletypeRequest.setFileType(1);
SasOssGetOssSecretFiletypeResponse sasOssGetOssSecretFiletypeResponse = client.sasOssGetOssSecretFiletypeResponse(sasOssGetOssSecretFiletypeRequest);
//调用算法功能,此处以文生图功能为例。除明确标记为同步的接口,其他服务都为异步模式,提交后返回调用ID,需要通过ID获取调用结果
SasAlgorithmTextToImageRequest request = new SasAlgorithmTextToImageRequest();
request.setRootCategory("WOMAN");
request.setText("a red dress with a v-neck");
request.setBatch_size(1);
SasAlgorithmTextToImageResponse sasAlgorithmTextToImageResponse = client.sasAlgorithmTextToImageResponse(request);
Long id = (Long)sasAlgorithmTextToImageResponse.getBody().getData();
//通过调用ID获取结果
SasMyCreationQueryOneIdRequest sasMyCreationQueryOneIdRequest = new SasMyCreationQueryOneIdRequest();
sasMyCreationQueryOneIdRequest.setId(id);// 提交任务接口返回的任务id
SasMyCreationQueryOneIdResponse sasMyCreationQueryOneIdResponse = client.sasMyCreationQueryOneIdResponse(sasMyCreationQueryOneIdRequest);
}
import hashlib
import time
import uuid
from urllib.parse import urlencode
import requests
class ApiClient(object):
def __init__(self, app_key: str, access_key_id: str, access_key_secret: str, endpoint: str):
self.app_key = app_key
self.access_key_id = access_key_id
self.access_key_secret = access_key_secret
self.endpoint = endpoint
self.base_url = 'https://' + self.endpoint + '/api'
self.timeout = 8000
self.session = requests.Session()
self.session.headers.update(
{
"Content-Type": "application/json;charset=utf-8",
"accessKey": self.access_key_id,
"appKey": self.app_key}
)
def send_get(self, headers=None, params=None):
if headers is None:
headers = {}
if params is None:
params = {}
args = self.cleanNoneValue(
{
"url": self.base_url,
"headers": self._prepare_headers(headers),
"params": self._prepare_params(params),
"timeout": self.timeout}
)
response = self._dispatch_request("GET")(**args)
self._handle_exception(response)
try:
data = response.json()
except ValueError:
data = response.text
return data
def send_post(self, headers=None, params=None):
if headers is None:
headers = {}
if params is None:
params = {}
args = self.cleanNoneValue(
{
"url": self.base_url,
"headers": self._prepare_headers(headers),
"json": params,
"timeout": self.timeout}
)
print(args)
response = self._dispatch_request("POST")(**args)
self._handle_exception(response)
try:
data = response.json()
except ValueError:
data = response.text
return data
def _prepare_headers(self, headers):
headers['requestId'] = str(uuid.uuid1())
timestamp = int(round(time.time() * 1000))
headers['timestamp'] = str(timestamp)
headers['sign'] = self._get_sign(timestamp)
return headers
def _prepare_params(self, params):
return self.encoded_string(self.cleanNoneValue(params))
def _get_sign(self, timestamp):
sign_str = f"{self.app_key}{self.access_key_id}{timestamp}{self.access_key_secret}"
m = hashlib.md5()
m.update(sign_str.encode('utf-8'))
return m.hexdigest()
def _dispatch_request(self, http_method):
return {
"GET": self.session.get,
"DELETE": self.session.delete,
"PUT": self.session.put,
"POST": self.session.post,
}.get(http_method, "GET")
def _handle_exception(self, response):
status_code = response.status_code
if status_code < 400:
return
raise Exception(response.text)
def encoded_string(self, query):
return urlencode(query, True).replace("%40", "@")
def cleanNoneValue(self, d) -> dict:
out = {}
for k in d.keys():
if d[k] is not None:
out[k] = d[k]
return out
if __name__ == "__main__":
# 创建api客户端,ak,sk请替换为自己的账号
client = ApiClient('marketing-server', 'ak_xxx',
'sk_xxx',
'open.metac-inc.com')
headers = {
'apiName': 'marketing_algorithm_human_seg'
}
params = {
'image': 'https://metac-tmp.oss-cn-hangzhou.aliyuncs.com/human_seg.png?OSSAccessKeyId=LTAI5tC14UqFaXidfeRSTfwF&Expires=1753204791&Signature=T%2BGgv88w08E%2FFn6mhetXXC%2B9uXo%3D',
'return_view_image': True
}
# 同步接口直接返回结果
task_result = client.send_post(headers, params)
print(task_result)
# 异步接口返回任务ID,再通过任务ID查询结果
# task_id = task_result['data']
# time.sleep(50)
# headers = {
# 'apiName': 'marketing_model_task_fetchWithMarketingModelTaskOutputPO_id'
# }
# params = {
# 'id': 2420259
# }
# print(client.send_get(headers, params)['data'])
| 码值 | 英文描述 | 中文描述 |
|---|---|---|
| 200 | Success | 成功 |
| 400 | Bad Request | 参数格式错误,请检查入参。比如:数字类型的参数传入了字符串 |
| 401 | Unauthorized | 鉴权不通过,请检查入参密钥ak、sk、MD5加密鉴权串 |
| 403 | Forbidden | 一般是命中了接口限流 |
| 404 | Not Found | 一般是请求没有命中,请检查appName |
| 415 | Unsupported Media Type | 请求方式错误,请注意区分接口post、get请求方式 |
| 500 | Internal Server Error | 服务异常,请联系业务接口人 |
| 码值 | 英文描述 | 中文描述 |
|---|---|---|
| 2000 | success | 请求处理成功 |
| 5000 | request process failure | 请求处理失败 |
| 5003 | request param constrains not satisfied | 请求参数约束不满足 |
| 5005 | user authentication error | 用户认证错误 一般是没有相应接口的权限 |
| 5007 | app authentication error | 应用认证错误 |
| 5008 | api authentication error | API 认证错误 |
| 5009 | data authentication error | 数据认证错误 |
| 5011 | account exception | 账户异常 |
| 5012 | account unaudited | 账户未审核 |
| 5013 | account review fail | 账户审核失败 |
| 5014 | illegal uri | 非法 URI |
| 5016 | remote server error | 远程服务器错误 |