本文主要提供 生成腾讯云智能数智人 aPaas 平台接口调用URL 的方式,以及常见编程语言 demo,语言类型包括 Golang、Java、C++、Python、JavaScript。
一、必要参数获取
二、公共参数
参数 | 类型 | 必须 | 说明 |
appkey | string | 是 | 根据各接口文档提供的方式获取到的 appkey。 |
timestamp | string | 是 | 请求时间戳,单位:秒。时间戳需要和当前时间的差异不过能超过五分钟,否则会鉴权失败。 |
requestid | string | 否 | 只有部分接口(如交互数智人的创建长链接通道)需要该参数。获取方式请参考对应接口文档。 |
signature | string | 是 |
注意:
三、签名方法
在调用 aPaas 任一接口时,都需在 URL 中以 QueryString 形式携带请求签名(signature)等公共参数。
请求参数签名步骤如下:
1. signature 签名规则如下,这里以下为例说明(示例为伪代码仅供参考):
appkey = example_appkeyaccesstoken = example_accesstoken域名路由 = https://api.example.com/v2/ivh/example_uri
2. 根据对应接口文档,对除 signature 之外的所有需要的参数按字典序进行排序,作为签名原文,用于生成签名。示例中仅使用 appkey 和 timestamp 两个参数(各个接口需要的参数请在相关文档中确认), 排序拼接后的字符串示例为:
appkey=example_appkey×tamp=1717639699
3. 对签名原文使用 accesstoken 进行 HmacSha256 加密,之后再进行 base64 编码:
hashBytes = HmacSha256("appkey=example_appkey×tamp=1717639699","example_accesstoken")signature = Base64Encode(hashBytes)
4. 得到 signature 签名值为:
aCNWYzZdplxWVo+JsqzZc9+J9XrwWWITfX3eQpsLVno=
5. 将 signature 值进行 urlencode(必须进行 URL 编码,否则将导致鉴权失败)后拼接得到最终请求 URL 为:
https://api.example.com/v2/ivh/example_uri?appkey=example_appkey×tamp=1717639699&signature=aCNWYzZdplxWVo%2BJsqzZc9%2BJ9XrwWWITfX3eQpsLVno%3D
四、签名生成 Demo
用户只需要将访问对应接口需要的除 signature 以外所有公共参数填入 demo 中相应位置,即可生成请求签名并拼接成访问接口的完整 URL 。
package main import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "fmt" "net/url" "sort" "strconv" "time" ) func GenSignature(signingContent string, accessToken string) string { // 计算 HMAC-SHA256 值 h := hmac.New(sha256.New, []byte(accessToken)) h.Write([]byte(signingContent)) // 将 HMAC-SHA256 值进行 Base64 编码 hashInBase64 := base64.StdEncoding.EncodeToString(h.Sum(nil)) // URL encode encodeSign := url.QueryEscape(hashInBase64) // 拼接签名 signature := "&signature=" + encodeSign return signature } func GenReqURL(parameter map[string]string, accessToken string, baseURL string) string { // 按字典序拼接待计算签名的字符串 signingContent := "" pathKey := make([]string, 0, len(parameter)) for k := range parameter { pathKey = append(pathKey, k) } sort.Strings(pathKey) for _, k := range pathKey { if signingContent != "" { signingContent += "&" } signingContent += k + "=" + parameter[k] } // 计算签名 signature := GenSignature(signingContent, accessToken) // 拼接访问接口的完整URL return baseURL + "?" + signingContent + signature } func main() { baseUrl := "https://api.example.com/v2/ivh/example_uri" accesstoken := "example_accesstoken" wssUrl := "wss://api.example.com/v2/ws/ivh/example_uri" // 示例一(访问需要提供 appkey 和 timestamp 参数的接口): // 用户按需填入生成签名所需的公共参数 parameter := map[string]string{ "appkey": "example_appkey", // 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟 // 示例时间戳: // "timestamp": "1717639699", // 推荐使用下面的语句生成当前时间戳: "timestamp": strconv.FormatInt(time.Now().Unix(), 10), } url1 := GenReqURL(parameter, accesstoken, baseUrl) // 使用示例时间戳输出应当如下: // Example 1:https://api.example.com/v2/ivh/example_uri?appkey=example_appkey×tamp=1717639699&signature=aCNWYzZdplxWVo%2BJsqzZc9%2BJ9XrwWWITfX3eQpsLVno%3D fmt.Println("Example 1:" + url1) // 示例二(访问需要提供 appkey, requestID 和 timestamp 参数的接口): // 用户按需填入生成签名所需的公共参数 parameter = map[string]string{ "appkey": "example_appkey", "requestid": "example_requestid", // 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟 // 示例时间戳: // "timestamp": "1717639699", // 用户若自己提供时间戳应保证单位为秒且与当前时间相差不得超过五分钟 "timestamp": strconv.FormatInt(time.Now().Unix(), 10), } url2 := GenReqURL(parameter, accesstoken, wssUrl) // 使用示例时间戳输出应当如下: // Example 2:wss://api.example.com/v2/ws/ivh/example_uri?appkey=example_appkey&requestid=example_requestid×tamp=1717639699&signature=QVenICk0VHtHGYZKXM6IC%2BW1CjZC1joSr%2Fx0gfKKYT4%3D fmt.Println("Example 2:" + url2) }
import java.util.*; import java.util.stream.Collectors; import java.time.Instant; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; public class Presigned { public static String GenSignature(String signingContent, String accessToken) { try { // 计算 HMAC-SHA256 值 Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(accessToken.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256_HMAC.init(secret_key); String hashInBase64 = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(signingContent.getBytes(StandardCharsets.UTF_8))); // URL encode String encodeSign = URLEncoder.encode(hashInBase64, StandardCharsets.UTF_8.toString()); // 拼接签名 String signature = "&signature=" + encodeSign; return signature; } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) { e.printStackTrace(); return null; } } public static String GenReqURL(Map<String, String> parameter, String accessToken, String baseURL) { // 按字典序拼接待计算签名的字符串 String signingContent = parameter.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .map(entry -> entry.getKey() + "=" + entry.getValue()) .collect(Collectors.joining("&")); // 计算签名 String signature = GenSignature(signingContent, accessToken); // 拼接访问接口的完整URL return baseURL + "?" + signingContent + signature; } public static void main(String[] args) { String baseUrl = "https://api.example.com/v2/ivh/example_uri"; String accesstoken = "example_accesstoken"; String wssUrl = "wss://api.example.com/v2/ws/ivh/example_uri"; // 示例一(访问需要提供 appkey 和 timestamp 参数的接口): // 用户按需填入生成签名所需的公共参数 Map<String, String> parameter = new TreeMap<>(); parameter.put("appkey", "example_appkey"); // 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟 // 示例时间戳: // parameter.put("timestamp", "1717639699"); // 推荐使用下面的语句生成当前时间戳: parameter.put("timestamp", String.valueOf(Instant.now().getEpochSecond())); String url = GenReqURL(parameter, accesstoken, baseUrl); // 使用示例时间戳输出应当如下: // Example 1:https://api.example.com/v2/ivh/example_uri?appkey=example_appkey×tamp=1717639699&signature=aCNWYzZdplxWVo%2BJsqzZc9%2BJ9XrwWWITfX3eQpsLVno%3D System.out.println("Example 1:" + url); // 示例二(访问需要提供 appkey, requestID 和 timestamp 参数的接口): parameter.clear(); parameter.put("appkey", "example_appkey"); parameter.put("requestid", "example_requestid"); // 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟 // 示例时间戳: // parameter.put("timestamp", "1717639699"); // 推荐使用下面的语句生成当前时间戳: parameter.put("timestamp", String.valueOf(Instant.now().getEpochSecond())); url = GenReqURL(parameter, accesstoken, wssUrl); // 使用示例时间戳输出应当如下: // Example 2:wss://api.example.com/v2/ws/ivh/example_uri?appkey=example_appkey&requestid=example_requestid×tamp=1717639699&signature=QVenICk0VHtHGYZKXM6IC%2BW1CjZC1joSr%2Fx0gfKKYT4%3D System.out.println("Example 2:" + url); } }
#include<iostream>#include <map>#include<string>#include<vector>#include<algorithm>#include <ctime>#include <iomanip>#include <sstream>#include<openssl/hmac.h>#include<openssl/sha.h>using namespace std;static const string base64_chars ="ABCDEFGHIJKLMNOPQRSTUVWXYZ""abcdefghijklmnopqrstuvwxyz""0123456789+/";string url_encode(const string &value) {ostringstream escaped;escaped.fill('0');escaped<< hex;for (size_t i = 0; i< value.length(); ++i) {char c = value[i];if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {escaped << c;} else {escaped<< uppercase;escaped << '%'<< setw(2)<< int((unsigned char) c);escaped<< nouppercase;}}return escaped.str();}string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {string ret;int i = 0;int j = 0;unsigned char char_array_3[3];unsigned char char_array_4[4];while (in_len--) {char_array_3[i++] = *(bytes_to_encode++);if (i == 3) {char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);char_array_4[3] = char_array_3[2] & 0x3f;for(i = 0; (i <4) ; i++)ret += base64_chars[char_array_4[i]];i = 0;}}if (i){for(j = i; j < 3; j++)char_array_3[j] = '\\0';char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);char_array_4[3] = char_array_3[2] & 0x3f;for (j = 0; (j < i + 1); j++)ret += base64_chars[char_array_4[j]];while((i++ < 3))ret += '=';}return ret;}string GenSignature(const string& signingContent, const string& accessToken) {// 计算 HMAC-SHA256 值unsigned char hash[EVP_MAX_MD_SIZE];unsigned int hashLength;HMAC(EVP_sha256(), accessToken.c_str(), accessToken.length(), (unsigned char *) signingContent.c_str(), signingContent.length(), hash, &hashLength);// 将 HMAC-SHA256 值进行 Base64 编码string hashInBase64 = base64_encode(hash, hashLength);// URL encodestring encodeSign = url_encode(hashInBase64);// 拼接签名string signature = "&signature=" + encodeSign;return signature;}string GenReqURL(const map<string, string>& parameter, const string& accessToken, const string& baseURL) {// 按字典序拼接待计算签名的字符串string signingContent;vector<string> pathKey;for (const auto& p : parameter) {pathKey.push_back(p.first);}sort(pathKey.begin(), pathKey.end());for (const auto& k : pathKey) {if (!signingContent.empty()) {signingContent += "&";}signingContent += k + "=" + parameter.at(k);}// 计算签名string signature = GenSignature(signingContent, accessToken);// 拼接访问接口的完整URLreturn baseURL + "?" + signingContent + signature;}// 编译时需要链接到OpenSSL库, 可以使用下面的命令:// g++ presigned.cpp -o presigned -lcryptoint main() {string baseUrl = "https://api.example.com/v2/ivh/example_uri";string accesstoken = "example_accesstoken";string wssUrl = "wss://api.example.com/v2/ws/ivh/example_uri";// 示例一(访问需要提供 appkey 和 timestamp 参数的接口):// 用户按需填入生成签名所需的公共参数map<string, string> parameter1 = {{"appkey", "example_appkey"},// 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟// 示例时间戳:// {"timestamp" , "1717639699"},// 推荐使用下面的语句生成当前时间戳:{"timestamp", to_string(time(NULL))}};string url = GenReqURL(parameter1, accesstoken, baseUrl);// 使用示例时间戳输出应当如下:// Example 1:https://api.example.com/v2/ivh/example_uri?appkey=example_appkey×tamp=1717639699&signature=aCNWYzZdplxWVo%2BJsqzZc9%2BJ9XrwWWITfX3eQpsLVno%3Dcout << "Example 1:"<< url<< endl;// 示例二(访问需要提供 appkey, requestID 和 timestamp 参数的接口):// 用户按需填入生成签名所需的公共参数map<string, string> parameter2 = {{"appkey", "example_appkey"},{"requestid", "example_requestid"},// 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟// 示例时间戳:// {"timestamp" , "1717639699"},// 推荐使用下面的语句生成当前时间戳:{"timestamp", to_string(time(NULL))}};url = GenReqURL(parameter2, accesstoken, wssUrl);// 使用示例时间戳输出应当如下:// Example 2:wss://api.example.com/v2/ws/ivh/example_uri?appkey=example_appkey&requestid=example_requestid×tamp=1717639699&signature=QVenICk0VHtHGYZKXM6IC%2BW1CjZC1joSr%2Fx0gfKKYT4%3Dcout << "Example 2:"<< url<< endl;return 0;}
import hmacimport hashlibimport timeimport base64from urllib.parse import quote# 用户可以在函数内部生成时间戳, 只需要传入appkey和accessToken即可获取访问接口所需的公共参数和签名def GenSignature(signing_content, access_token):# 计算 HMAC-SHA256 值h = hmac.new(access_token.encode(), signing_content.encode(), hashlib.sha256)# 将 HMAC-SHA256 值进行 Base64 编码hash_in_base64 = base64.b64encode(h.digest()).decode()# URL encodeencode_sign = quote(hash_in_base64)# 拼接签名signature = f"&signature={encode_sign}"return signaturedef GenReqURL(parameter, access_token, base_url):# 按字典序拼接待计算签名的字符串signing_content = '&'.join(f'{k}={parameter[k]}' for k in sorted(parameter.keys()))# 计算签名signature = GenSignature(signing_content, access_token)# 拼接访问接口的完整 URLreturn f'{base_url}?{signing_content}{signature}'def main():base_url = 'https://api.example.com/v2/ivh/example_uri'access_token = 'example_accesstoken'wss_url = 'wss://api.example.com/v2/ws/ivh/example_uri'# 示例一(访问需要提供 appkey 和 timestamp 参数的接口):# 用户按需填入生成签名所需的公共参数parameter1 = {'appkey': 'example_appkey',# 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟# 示例时间戳:# 'timestamp': '1717639699'# 推荐使用下面的语句生成当前时间戳:'timestamp': int(time.time()) # 使用当前时间戳(单位:秒)}url1 = GenReqURL(parameter1, access_token, base_url)# 使用示例时间戳输出应当如下:# Example 1:https://api.example.com/v2/ivh/example_uri?appkey=example_appkey×tamp=1717639699&signature=aCNWYzZdplxWVo%2BJsqzZc9%2BJ9XrwWWITfX3eQpsLVno%3Dprint('Example 1:', url1)# 示例二(访问需要提供 appkey, requestID 和 timestamp 参数的接口):# 用户按需填入生成签名所需的公共参数parameter2 = {'appkey': 'example_appkey','requestid': 'example_requestid',# 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟# 示例时间戳:# 'timestamp': '1717639699'# 推荐使用下面的语句生成当前时间戳:'timestamp': int(time.time()) # 使用当前时间戳(单位:秒)}url2 = GenReqURL(parameter2, access_token, wss_url)# 使用示例时间戳输出应当如下:# Example 2:wss://api.example.com/v2/ws/ivh/example_uri?appkey=example_appkey&requestid=example_requestid×tamp=1717639699&signature=QVenICk0VHtHGYZKXM6IC%2BW1CjZC1joSr%2Fx0gfKKYT4%3Dprint('Example 2:', url2)if __name__ == '__main__':main()
const crypto = require('crypto');// 用户可以在函数内部生成时间戳, 只需要传入appkey和accessToken即可获取访问接口所需的公共参数和签名function GenSignature(signingContent, accessToken) {// 计算 HMAC-SHA256 值const hmac = crypto.createHmac('sha256', accessToken);hmac.update(signingContent);// 将 HMAC-SHA256 值进行 Base64 编码const hashInBase64 = hmac.digest('base64');// URL encodeconst encodeSign = encodeURIComponent(hashInBase64);// 拼接签名const signature = `&signature=${encodeSign}`;return signature;}function GenReqURL(parameter, accessToken, baseURL) {// 按字典序拼接待计算签名的字符串let signingContent = '';const pathKey = Object.keys(parameter).sort();for (const k of pathKey) {if (signingContent !== '') {signingContent += '&';}signingContent += `${k}=${parameter[k]}`;}// 计算签名const signature = GenSignature(signingContent, accessToken);// 拼接访问接口的完整URLreturn `${baseURL}?${signingContent}${signature}`;}function main() {const baseUrl = 'https://api.example.com/v2/ivh/example_uri';const accesstoken = 'example_accesstoken';const wssUrl = 'wss://api.example.com/v2/ws/ivh/example_uri';// 示例一(访问需要提供 appkey 和 timestamp 参数的接口):// 用户按需填入生成签名所需的公共参数const parameter1 = {appkey: 'example_appkey',// 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟// 示例时间戳:// timestamp: '1717639699',// 推荐使用下面的语句生成当前时间戳:timestamp: Math.floor(Date.now() / 1000), // 使用当前时间戳(单位:秒)};const url1 = GenReqURL(parameter1, accesstoken, baseUrl);// 使用示例时间戳输出应当如下:// Example 1:https://api.example.com/v2/ivh/example_uri?appkey=example_appkey×tamp=1717639699&signature=aCNWYzZdplxWVo%2BJsqzZc9%2BJ9XrwWWITfX3eQpsLVno%3Dconsole.log('Example 1:', url1);// 示例二(访问需要提供 appkey, requestID 和 timestamp 参数的接口):const parameter2 = {appkey: 'example_appkey',requestid: 'example_requestid',// 用户提供的时间戳应保证单位为秒且与当前时间相差不得超过五分钟// 示例时间戳:// timestamp: '1717639699',// 推荐使用下面的语句生成当前时间戳:timestamp: Math.floor(Date.now() / 1000), // 使用当前时间戳(单位:秒)};const url2 = GenReqURL(parameter2, accesstoken, wssUrl);// 使用示例时间戳输出应当如下:// Example 2:wss://api.example.com/v2/ws/ivh/example_uri?appkey=example_appkey&requestid=example_requestid×tamp=1717639699&signature=QVenICk0VHtHGYZKXM6IC%2BW1CjZC1joSr%2Fx0gfKKYT4%3Dconsole.log('Example 2:', url2);}main();
五、接口调用注意事项
发送请求调用数智人相关接口时,请求体都要求有 header 和 payload 参数,请注意不要把这里的 header 理解为请求头,它也是请求体的一个参数。
以下为请求体的正确写法示例:
{"Header": {},"Payload": {"ReqId": "d7aa08da33dd4a662ad5be508c5b77cf","paramKey1": "paramValue1""paramKey2": "paramValue2"}}
以下为请求体的错误写法示例:
{"ReqId": "d7aa08da33dd4a662ad5be508c5b77cf","paramKey1": "paramValue1""paramKey2": "paramValue2"}