HTTPS
协议、JSON
或FORM
数据格式、UTF-8
编码。30QPS/s
。授权对象ISV
即服务商、应用开发者。
授权对象APP
即开放应用/配送应用,由服务商进行管理、开发的应用。
ApiKey
是服务商ISV
调用API的唯一身份标识,ApiSecret
是对应的API密钥。
AppId
是开放应用/配送应用APP
的唯一身份标识,AppSecret
是对应的应用的密钥。
HTTP Header | 描述 |
---|---|
Authorization | 用于验证请求合法性的认证信息。请严格按照签名格式进行填充,否则会返回401 HTTP状态码。 |
Content-Type | 请求或响应内容的 MIME 类型。例如Content-Type : application/json;charset=UTF-8 或application/x-www-form-urlencoded 。 |
User-Agent | 每次请求中此HTTP Header 会标识自己,若没有此信息将会拒绝请求。 |
X-APPID | ApiKey 或者AppId 。 |
X-Source | ISV 或者APP 。 |
X-Expiration | 请求时间,请使用Unix时间戳。 |
X-Host | 服务器域名。例如X-Host : https://api.boolc.cn 。 |
通过API请求,响应头部信息包括:
2xx
、3xx
、4xx
、5xx
的HTTP状态码Content-Type
: application/json;charset=UTF-8
HTTP状态码为2xx
,接口状态码为2xxxx
,API执行后将返回一个JSON
格式的信息对象。具体格式如下:
{
"code": <Code int>,
"data": <Data interface{}>,
"msg": "<Msg string>"
}
Key | 描述 |
---|---|
code | 接口状态码,该状态码不同于HTTP状态码,是接口定义的状态码。 |
data | 接口返回的数据,详见对应接口的响应数据。 |
msg | 正确/错误返回信息提示。 |
状态码 | 描述 |
---|---|
20000 | 接口请求成功。 |
40001 | 参数方面的异常状态,如参数格式错误、参数长度错误等。 |
40003 | 鉴权失败,若在网关鉴权错误HTTP状态码为2xx ,若在服务内部鉴权错误HTTP状态码为401 。 |
40005 | 系统维护、更新等状态产生的问题。 |
40008 | 未经授权的系统,和40003 区别在于系统鉴权问题,将会记录黑名单。 |
50000 | 系统错误,请将请求头、参数、签名等信息截图交由技术协调处理。 |
50001 | 未知错误,请将请求头、参数、签名等信息截图交由技术协调处理。 |
50008 | Token非法、失效等情况返回的状态码。 |
API通过验证签名来保证请求的真实性和数据的完整性。
请使用ApiKey/ApiSecret
或AppId/AppSecret
对API HOST、Body等关键数据的组合进行HmacSHA256签名。请求签名通过HTTP Header Authorization
传递,具体说明请见下方说明。没有携带签名或者签名验证不通过的请求,都不会被执行,并返回401 Unauthorized。
X-APPID
、X-Expiration
、X-Host
、X-Source
填充后,将四个HTTP Headers(Key通过ASCII排序)以及RequestMethod、RequestURI、Body用&
进行拼接,即:
<HTTP Headers Key string>=<HTTP Headers Value string>&<RequestMethod string>&<RequestURI string>&<Body string>
例如:
X-APPID=GV5CD2hnRfRv47Ju&X-Expiration=1625481243&X-Host=https://api.boolc.cn&X-Source=ISV&POST&/open/app/app&{"channel":"BOOL"}
将ApiSecret
或AppSecret
与X-Expiration
拼接
<ApiSecret/AppSecret string><X-Expiration string>
将上方两步生成的签名字符串、签名密钥,使用HmacSHA256算法计算签名,然后进行Base64 encode,得到最终的签名(需要使用UTF-8字符集),将计算的签名放入Headers的Authorization
中。
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"net/http"
"sort"
"strconv"
"strings"
"time"
)
func sign() error {
expiration := strconv.Itoa(int(time.Now().Unix()))
params := map[string]string{
"channel": "BOOL",
}
body, err := json.Marshal(params)
if err != nil {
return err
}
conn, err := http.NewRequest("POST", "<BoolApiURL string>", strings.NewReader(string(body)))
if err != nil {
return err
}
client := &http.Client{}
// 设置请求头
conn.Header.Set("X-APPID", <ApiKey string>)
conn.Header.Set("X-Expiration", expiration)
conn.Header.Set("X-Host", <ApiHost string>)
conn.Header.Set("X-Source", <Source string>)
// 拼接签名密钥
secret := "<ApiSecret string>" + expiration
var keys []string
for k := range conn.Header {
keys = append(keys, k)
}
sort.Strings(keys)
var pList = make([]string, 0, 0)
for _, key := range keys {
pList = append(pList, key+"="+conn.Header.Get(key))
}
pList = append(pList, conn.Method)
if conn.URL.RawQuery != "" {
pList = append(pList, conn.URL.Path+"?"+conn.URL.RawQuery)
} else {
pList = append(pList, conn.URL.Path)
}
pList = append(pList, string(body))
// 生成签名字符串
var content = strings.Join(pList, "&")
// 加签并发送请求
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(content))
sha := hex.EncodeToString(h.Sum(nil))
conn.Header.Set("Content-Type", "application/json")
conn.Header.Set("Authorization", base64.StdEncoding.EncodeToString([]byte(sha)))
resp, err := client.Do(conn)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
#python 3.8
import time
import hmac
import hashlib
import base64
import httplib
import urllib
expiration = str(time.time())
params = '{"channel": "BOOL"}'
headers = { "X-APPID": "ApiKey", "X-Expiration": expiration, "X-Host": "API HOST", "X-Source": "Source" }
secret = "ApiSecret"+expiration
secret_enc = secret.encode('utf-8')
string_to_sign = ""
for key in sorted(headers):
string_to_sign += "{}={}&".format(key, headers[key])
string_to_sign += "POST"
string_to_sign += "&"
string_to_sign += "/"
string_to_sign += "&"
string_to_sign += params
string_to_sign_enc = string_to_sign.encode("utf-8")
# 加签并发送请求
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = base64.b64encode(hmac_code)
headers["Content-Type"] = "application/json"
headers["Authorization"] = sign
conn = httplib.HTTPConnection("BOOL API URL")
conn.request("POST", "/", params, headers)
response = conn.getresponse()
data = response.read()
conn.close()
其中X-APPID=app_id,X-Expiration=expiration,X-Host=host,X-Source=APP,Body为空,将四个参数(Key通过ASCII排序)以及RequestMethod、RequestURI、Body用&进行拼接,即:
X-APPID=app_id&X-Expiration=expiration&X-Host=host&X-Source=APP&RequestMethod&RequestURI&Body
例如:
X-APPID=1&X-Expiration=1683957868&X-Host=https://api.99make.com&X-Source=APP&GET&/pages/open/auth?app_id=1&callback_scene=20&callback_url=https://api.boolcms.cn&expiration=1683957868&host=https://api.99make.com&source=APP&GET&/pages/open/auth?app_id=1&callback_scene=20&callback_url=https://api.boolcms.cn&expiration=1683957868&host=https://api.99make.com&source=APP&
将ApiSecret
或AppSecret
与X-Expiration
拼接
<ApiSecret/AppSecret string><X-Expiration string>
将上方两步生成的签名字符串、签名密钥,使用HmacSHA256算法计算签名,然后进行Base64 encode,得到最终的签名,将计算的签名放入URl中。
https://h5.kkpaotui.com/#/pages/open/auth?app_id=1&callback_scene=20&callback_url=https://api.boolcms.cn&expiration=1683957868&host=https://api.99make.com&source=APP&sign=W0KDlhe%20OnY3do7gKYyPnPBVc2g88zR0mEDwG0ncP24%3D