Skip to content

接口签名

接口签名可以验证请求的合法性,防止请求被篡改或伪造。

签名规则

请求时需携带以下自定义请求头:

请求头字段说明示例值
x-user-id用户 ID100
x-timestamp时间戳(秒级)1723786112
x-nonce随机字符串3f8b7c1a92e4d5ff
x-signature生成的签名5e884898da28047151d0e56f8dc62927...

x-signature 生成规则

  1. 拼接字符串

请求方法 + 请求路径 + 用户ID + 秒级时间戳 + 随机字符串

如:GET + /openapi/account + 100 + 1723786112 + 3f8b7c1a92e4d5ff

  1. 生成签名

使用 HMAC-SHA256 算法,以 apiKey 作为密钥,对签名字符串进行哈希运算,结果转换为十六进制字符串。

js
const signature = crypto.createHmac('sha256', apiKey)
    .update(signString)
    .digest('hex')
  1. 请求接口携带签名请求头
js
fetch('/openapi/account', {
    method: 'GET',
    headers: {
        'x-user-id': '100',
        'x-timestamp': '1723786112',
        'x-nonce': '3f8b7c1a92e4d5ff',
        'x-signature': signature,
    },
}).then(res => res.json())

代码示例

Python 示例

python
import time
import hmac
import hashlib
import secrets
import requests

def get_accounts():
    method = "GET"
    path = "/openapi/account"
    userId = "100"
    apiKey = "AK-MAD9F4GXPO2PBW0"
    timestamp = str(int(time.time()))
    nonce = secrets.token_hex(8)  # 16位随机十六进制字符串

    # 拼接签名字符串
    sign_string = method.upper() + path + userId + timestamp + nonce

    # 生成签名
    signature = hmac.new(apiKey.encode(), sign_string.encode(), hashlib.sha256).hexdigest()

    # 发送 GET 请求
    url = "https://applo.cc/api" + path  # 替换为实际 API 域名
    headers = {
        "x-user-id": userId,
        "x-timestamp": timestamp,
        "x-nonce": nonce,
        "x-signature": signature,
    }

    response = requests.get(url, headers=headers)
    data = response.json()
    return data.get("data")

if __name__ == "__main__":
    result = get_accounts()
    print(result)

PHP 示例

php
// 获取账号列表
function getAccounts() {
    $method   = 'GET';
    $path     = '/openapi/account';
    $userId   = '100';
    $apiKey   = 'AK-MAD9F4GXPO2PBW0';
    $timestamp = (string) time();
    $nonce     = bin2hex(random_bytes(8)); // 16位随机十六进制字符串

    // 拼接签名字符串
    $signString = strtoupper($method) . $path . $userId . $timestamp . $nonce;

    // 生成签名
    $signature = hash_hmac('sha256', $signString, $apiKey);

    // 发起 GET 请求
    $url = 'https://applo.cc/api' . $path; // 替换为实际 API 域名
    $headers = [
        "x-user-id: $userId",
        "x-timestamp: $timestamp",
        "x-nonce: $nonce",
        "x-signature: $signature",
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $response = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($response, true);
    return $data['data'] ?? null;
}

// 调用示例
$result = getAccounts();
print_r($result);

Java 示例

java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

public class ApiClient {

    public static String hmacSha256(String key, String data) throws Exception {
        Mac sha256Hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        sha256Hmac.init(secretKey);
        byte[] hash = sha256Hmac.doFinal(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte b : hash) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static String getAccounts() throws Exception {
        String method = "GET";
        String path = "/openapi/account";
        String userId = "100";
        String apiKey = "AK-MAD9F4GXPO2PBW0";
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonce = javax.xml.bind.DatatypeConverter.printHexBinary(java.security.SecureRandom.getSeed(8)).toLowerCase();

        String signString = method.toUpperCase() + path + userId + timestamp + nonce;
        String signature = hmacSha256(apiKey, signString);

        String urlStr = "https://applo.cc/api" + path; // 替换为实际 API 域名
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("x-user-id", userId);
        conn.setRequestProperty("x-timestamp", timestamp);
        conn.setRequestProperty("x-nonce", nonce);
        conn.setRequestProperty("x-signature", signature);

        Scanner scanner = new Scanner(conn.getInputStream());
        StringBuilder response = new StringBuilder();
        while (scanner.hasNext()) {
            response.append(scanner.nextLine());
        }
        scanner.close();
        return response.toString();
    }

    public static void main(String[] args) throws Exception {
        String result = getAccounts();
        System.out.println(result);
    }
}

Nodejs 示例

js
const crypto = require('crypto');

// 获取账号列表
const getAccounts = async () => {
    const method = 'GET';
    const path = `/openapi/account`;
    const userId = '100';
    const apiKey = 'AK-MAD9F4GXPO2PBW0';
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const nonce = crypto.randomBytes(8).toString('hex');

    const signString = `${method.toUpperCase()}${path}${userId}${timestamp}${nonce}`;
    const signature = crypto.createHmac('sha256', apiKey)
        .update(signString)
        .digest('hex');

    const url = 'https://applo.cc/api' + path;
    const res = await fetch(url, {
        method: 'GET',
        headers: {
            'x-user-id': userId,
            'x-timestamp': timestamp,
            'x-nonce': nonce,
            'x-signature': signature,
        },
    }).then(res => res.json())

    return res.data;
}

// 调用示例
getAccounts().then(result => {
    console.log(result);
});

Go 示例

go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"time"
	"math/rand"
)

func getAccounts() (string, error) {
	method := "GET"
	path := "/openapi/account"
	userId := "100"
	apiKey := "AK-MAD9F4GXPO2PBW0"
	timestamp := fmt.Sprintf("%d", time.Now().Unix())

	// 生成16位随机十六进制字符串
	nonceBytes := make([]byte, 8)
	rand.Read(nonceBytes)
	nonce := hex.EncodeToString(nonceBytes)

	// 拼接签名字符串
	signString := method + path + userId + timestamp + nonce

	// 生成签名
	h := hmac.New(sha256.New, []byte(apiKey))
	h.Write([]byte(signString))
	signature := hex.EncodeToString(h.Sum(nil))

	// 发起 GET 请求
	url := "https://applo.cc/api" + path // 替换为实际 API 域名
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("x-user-id", userId)
	req.Header.Set("x-timestamp", timestamp)
	req.Header.Set("x-nonce", nonce)
	req.Header.Set("x-signature", signature)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	return string(body), nil
}

func main() {
	result, err := getAccounts()
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}