簽名
Webull SDK 已經封裝了簽名流程,所以如果您使用 Webull SDK,無需另外處理。
本文將詳細說明簽名值的生成方式。
概述
API 請求簽名是利用請求內容和密鑰,透過特定簽名演算法所產生的值。這種加密技術可確保 API 請求資料的完整性與真實性,防止傳輸過程遭到竄改,並驗證請求發起者的身份。為確保雙方溝通的安全性,當您使用 OpenAPI 時,Webull 會對每個 API 請求進行簽名安全驗證。 無論您是透過 HTTP 或 HTTPS 發送請求,都必須依下方範例,在request header中帶入簽名值:
x-signature: signature_value
內容構成
簽名內容包含四個部分:
-
HTTP request path
-
HTTP request query params
-
HTTP request body
-
HTTP request headers
-
被簽名的內容不需要進行 URL 編碼
-
針對 HTTP POST 請求,
Content-Type必須設為application/json。
簽名相關的 headers 如下:
| 名稱 | 說明 |
|---|---|
| x-app-key | App Key |
| x-signature-algorithm | Signature algorithm,預設為 HMAC-SHA1 |
| x-signature-version | Signature algorithm version, 預設為 1.0 |
| x-signature-nonce | Signature nonce, 每個請求都需重新產生 |
| x-timestamp | RFC-3339 的請求時間戳,格式為:YYYY-MM-DDThh:mm:ssZ,例如 2023-07-16T19:23:51Z,僅支援 UTC 時區 |
| host | 請求的 Host,格式為 host:port,例如 api.webull.com:8080 或 api.webull.com |
簽名規則
參與簽名的內容
1. HTTP request path
2. HTTP request query params
3. HTTP request body
4. HTTP request headers: x-app-key、x-signature-algorithm、x-signature-version、x-signature-nonce、x-timestamp、host
構建簽名內容
-
將所有參數名稱(包含請求參數及標頭)依字母升冪順序排序
-
依序將參數名稱與參數值以
name1=v1&name2=v2的格式拼接,產生一個新的字串稱為 str1 -
使用 MD5 對 Body 參數產生 128 位元(16 字節)的雜湊值,並轉換為大寫:
toUpper(MD5(body)),此字串稱為 str2 -
依序連接
path,&,str1,&,str2,組成一個新字串,命名為 str3 -
對 str3 進行 URL 編碼,得到 encoded_string
-
body 參數的鍵和值之間不能有空格
-
如果 body 為空,則 str3 = path + "&" + str1
構建金鑰
將字元 & 加到你的 App Secret 結尾以取得 app_secret
如需瞭解如何取得你的 App Secret,請參考API 申請
產生簽名
生成簽名值的演算法:
signature = base64(HMAC-SHA1(app_secret, encoded_string))
範例
請求內容
請求路徑:
/trade/place_order
請求查詢參數:
| 名稱 | 範例數值 | 備註 |
|---|---|---|
| a1 | webull | 不需進行URL編碼 |
| a2 | 123 | 不需進行URL編碼 |
| a3 | xxx | 不需進行URL編碼 |
| q1 | yyy | 不需進行URL編碼 |
Request Headers:
| 名稱 | 範例數值 | 備註 |
|---|---|---|
| x-app-key | 776da210ab4a452795d74e726ebd74b6 | 不需進行URL編碼 |
| x-timestamp | 2022-01-04T03:55:31Z | 不需進行URL編碼 |
| x-signature-version | 1.0 | 不需進行URL編碼 |
| x-signature-algorithm | HMAC-SHA1 | 不需進行URL編碼 |
| x-signature-nonce | 48ef5afed43d4d91ae514aaeafbc29ba | 不需進行URL編碼 |
| host | api.webull.com | 不需進行URL編碼 |
Request Body:
{"k1":123,"k2":"this is the api request body","k3":true,"k4":{"foo":[1,2]}}
App Secret:
0f50a2e853334a9aae1a783bee120c1f
構建請求內容
-
將所有參數名稱按字串升冪順序排序,結果為:
Parameter name: a1, value: webull
Parameter name: a2, value: 123
Parameter name: a3, value: xxx
Header name: host, value: api.webull.com
Parameter name: q1, value: yyy
Header name: x-app-key, value: 776da210ab4a452795d74e726ebd74b6
Header name: x-signature-algorithm, value: HMAC-SHA1
Header name: x-signature-nonce, value: 48ef5afed43d4d91ae514aaeafbc29ba
Header name: x-signature-version, value: 1.0
Header name: x-timestamp, value: 2022-01-04T03:55:31Z -
依序連接參數名稱和值,以取得**
str1**:# str1
str1 = "a1=webull&a2=123&a3=xxx&host=api.webull.com&q1=yyy&x-app-key=776da210ab4a452795d74e726ebd74b6&x-signature-algorithm=HMAC-SHA1&x-signature-nonce=48ef5afed43d4d91ae514aaeafbc29ba&x-signature-version=1.0&x-timestamp=2022-01-04T03:55:31Z" -
使用 MD5 對 Body 參數產生 128 位元(16 字節)的雜湊值,並轉換為大寫:
toUpper(MD5(body)),此字串稱為str2:Body Parameter{"k1":123,"k2":"this is the api request body","k3":true,"k4":{"foo":[1,2]}}# str2
str2 = "E296C96787E1A309691CEF3692F5EEDD" -
依序連接
path,&,str1,&,str2,組成一個新字串,命名為str3# str3
str3 = "/trade/place_order&a1=webull&a2=123&a3=xxx&host=api.webull.com&q1=yyy&x-app-key=776da210ab4a452795d74e726ebd74b6&x-signature-algorithm=HMAC-SHA1&x-signature-nonce=48ef5afed43d4d91ae514aaeafbc29ba&x-signature-version=1.0&x-timestamp=2022-01-04T03:55:31Z&E296C96787E1A309691CEF3692F5EEDD" -
對 str3 進行 URL 編碼,得到
encoded_string# encoded_string
encoded_string = "%2Ftrade%2Fplace_order%26a1%3Dwebull%26a2%3D123%26a3%3Dxxx%26host%3Dapi.webull.com%26q1%3Dyyy%26x-app-key%3D776da210ab4a452795d74e726ebd74b6%26x-signature-algorithm%3DHMAC-SHA1%26x-signature-nonce%3D48ef5afed43d4d91ae514aaeafbc29ba%26x-signature-version%3D1.0%26x-timestamp%3D2022-01-04T03%3A55%3A31Z%26E296C96787E1A309691CEF3692F5EEDD"
構建金鑰
將字元 & 加到你的 App Secret 結尾以取得 app_secret:
# app_secret
app_secret = "0f50a2e853334a9aae1a783bee120c1f&"
產生簽名
生成簽名值的演算法:
signature = base64(HMAC-SHA1(app_secret, encoded_string))
-
使用
HMAC-SHA1加密演算法,並以app_secret為金鑰加密encoded_string -
接著,使用 Base64 對加密結果進行編碼
-
最終簽名字串為:kvlS6opdZDhEBo5jq40nHYXaLvM=
補充說明
-
如果請求中含有多個同名參數,請將所有數值按升冪排序後,使用 & 連接在一起。例如:
url?k1=v1&k1=v2&k1=v3如果請求中有多個同名參數,請將所有數值按升冪排序,然後使用 & 將它們連接起來。例如:
k1 = v1&v2&v3 -
在
Golang中,json.Marshal預設會將escapeHtml設為true,這會將<、>和&進行跳脫。此時你需要將跳脫後的內容還原為原始字元,如下所示:func trans(data []byte) []byte {
data = bytes.Replace(data, []byte("\\u0026"), []byte("&"), -1)
data = bytes.Replace(data, []byte("\\u003c"), []byte("<"), -1)
data = bytes.Replace(data, []byte("\\u003e"), []byte(">"), -1)
return data
}