接口介绍
1. 接口调用
所有接口调用根路径为 https://api.tecmz.com/open_api/ ,调用方式为 POST
。
鉴权方式有两种,一种是标准鉴权,一种是简单鉴权,选择其中一种即可。
2. 鉴权方式(标准)
2.1 请求公共参数
参数 | 错误说明 |
---|---|
app_id | AppId |
timestamp | 时间戳,从1970年01月01日到现在的秒数,误差不超过1800秒 |
sign | 请求签名,计算方式见 签名生成方法 |
2.2. 签名生成方法
1) 对参数按照 key=value 的格式,并按照参数名 ASCII 字典序排序如下
param = "app_id=xxxxxxxxxx&body=test×tamp=1365773829";
一定要注意需要将参数按照参数名 ASCII 码进行排序
2) 拼接API密钥
paramWithSecret = param + "&app_secret=xxxxxxxxxxxxxx"
sign = md5( paramWithSecret )
其中 xxxxxxxxxxxxxx 为 AppSecret , sign 为计算的签名
3) 拼接上签名
param = param + "&sign=" + sign
2.3 示例代码
PHP 参考代码
function generateSign($params, $appSecret)
{
ksort($params, SORT_STRING);
$str = [];
foreach ($params as $k => $v) {
$str [] = $k . '=' . $v;
}
$str[] = 'app_secret=' . $appSecret;
$str = join('&', $str);
return md5($str);
}
$appId = 'xxxxxxxxxx';
$appSecret = 'xxxxxxxxxx';
$url = 'https://api.tecmz.com/open_api/xxxx';
$param = [
'body' => 'test',
'aaa' => 'aaa',
'bbb' => 'bbb'
];
$param['app_id'] = $appId;
$param['timestamp'] = time();
$param['sign'] = generateSign($param, $appSecret);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$result = curl_exec($ch);
curl_close($ch);
var_dump($result);
Java 参考代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class SignExample {
public static void main(String[] args) {
String appId = "xxxxxxxxxx";
String appSecret = "xxxxxxxxxx";
String url = "https://api.tecmz.com/open_api/xxxx";
Map<String, String> params = new HashMap<>();
params.put("body", "test");
params.put("aaa", "aaa");
params.put("bbb", "bbb");
params.put("app_id", appId);
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
String sign = generateSign(params, appSecret);
params.put("sign", sign);
String result = makeRequest(url, params);
System.out.println("Response: " + result);
}
private static String generateSign(Map<String, String> params, String appSecret) {
String[] sortedKeys = params.keySet().toArray(new String[0]);
Arrays.sort(sortedKeys);
StringBuilder stringBuilder = new StringBuilder();
for (String key : sortedKeys) {
stringBuilder.append(key).append("=").append(params.get(key)).append("&");
}
stringBuilder.append("app_secret=").append(appSecret);
String str = stringBuilder.toString();
return md5(str);
}
private static String md5(String input) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] hash = messageDigest.digest(input.getBytes());
StringBuilder stringBuilder = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(b & 0xff);
if (hex.length() == 1) {
stringBuilder.append('0');
}
stringBuilder.append(hex);
}
return stringBuilder.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
private static String makeRequest(String url, Map<String, String> params) {
try {
URL apiUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
StringBuilder requestBody = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
String encodedKey = URLEncoder.encode(key, "UTF-8");
String encodedValue = URLEncoder.encode(value, "UTF-8");
requestBody.append(encodedKey).append("=").append(encodedValue).append("&");
}
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody.toString().getBytes());
outputStream.flush();
outputStream.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
connection.disconnect();
return response.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
python参考代码
import hashlib
import time
import requests
def generate_sign(params, app_secret):
sorted_params = sorted(params.items(), key=lambda x: x[0])
str_list = [f"{k}={v}" for k, v in sorted_params]
str_list.append(f"app_secret={app_secret}")
sign_str = "&".join(str_list)
return hashlib.md5(sign_str.encode('utf-8')).hexdigest()
app_id = "xxxxxxxxxx"
app_secret = "xxxxxxxxxx"
url = "https://api.tecmz.com/open_api/xxxx"
param = {
"body": "test",
"aaa": "aaa",
"bbb": "bbb",
"app_id": app_id,
"timestamp": int(time.time()),
}
param["sign"] = generate_sign(param, app_secret)
response = requests.post(url, data=param, verify=False, timeout=30)
print(response.text)
golang参考代码
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
)
func generateSign(params map[string]string, appSecret string) string {
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
var strList []string
for _, k := range keys {
strList = append(strList, fmt.Sprintf("%s=%s", k, params[k]))
}
strList = append(strList, fmt.Sprintf("app_secret=%s", appSecret))
str := strings.Join(strList, "&")
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}
func main() {
appID := "xxxxxxxxxx"
appSecret := "xxxxxxxxxx"
urlStr := "https://api.tecmz.com/open_api/xxxx"
params := map[string]string{
"body": "test",
"aaa": "aaa",
"bbb": "bbb",
"app_id": appID,
"timestamp": fmt.Sprintf("%d", time.Now().Unix()),
}
params["sign"] = generateSign(params, appSecret)
data := url.Values{}
for k, v := range params {
data.Set(k, v)
}
resp, err := http.PostForm(urlStr, data)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
var responseBody strings.Builder
_, err = responseBody.ReadFrom(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}
fmt.Println(responseBody.String())
}
nodejs参考代码
const crypto = require('crypto');
const axios = require('axios');
function generateSign(params, appSecret) {
const sortedKeys = Object.keys(params).sort();
const strList = sortedKeys.map(key => `${key}=${params[key]}`);
strList.push(`app_secret=${appSecret}`);
const signStr = strList.join('&');
return crypto.createHash('md5').update(signStr, 'utf8').digest('hex');
}
const appId = "xxxxxxxxxx";
const appSecret = "xxxxxxxxxx";
const url = "https://api.tecmz.com/open_api/xxxx";
const params = {
body: "test",
aaa: "aaa",
bbb: "bbb",
app_id: appId,
timestamp: Math.floor(Date.now() / 1000)
};
params.sign = generateSign(params, appSecret);
axios.post(url, new URLSearchParams(params))
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error("Error:", error);
});
3. 鉴权方式(简单)
使用这种方式需要在 接口管理→接口信息→开启简单授权,配置Key。
后续请求时,只需要在请求头中添加 Authorization
参数即可,值为 Bearer KEY
即可。
Authorization: Bearer KEY
4. 统一返回封装
调用成功
{
"code": 0,
"msg": "ok",
"data": {
"xxx": "xxx"
}
}
其中 data 中为业务数据
调用失败
{
"code": "<错误码>",
"msg": "<错误原因>"
}
5. 错误码
错误码 | 错误说明 |
---|---|
0 | 业务处理成功 |
-1 | 业务处理出现错误 |