API 授權與驗證
快代理 API 會對每個訪問請求進行身份驗證,即每個請求都需要包含簽名信息(signature參數)以驗證請求者身份。 簽名信息由API密鑰生成,密鑰包括 SecretId 和 SecretKey;每個訂單都有對應的API密鑰,API密鑰相當于調用API的密碼,一定要嚴格保密謹防泄露。
必須使用https調用接口
https加密傳輸可讓API調用信息不被第三方監聽和截獲,更加安全。使用https只需保證API鏈接以https://開頭。
簽名驗證方式
我們提供兩種簽名方式供您選擇:
- 密鑰令牌驗證(默認)
- 數字簽名驗證
您可以根據自己的業務需要選擇合適的簽名驗證方式。下面是對兩種驗證方式的詳細說明。
密鑰令牌驗證
參數設置:sign_type=token
密鑰令牌驗證即提前調用get_secret_token接口獲取密鑰令牌(secret_token),將獲取到的secret_token直接用作簽名(signature)。
此驗證方式非常簡單,適合希望快速接入,不需要防篡改、防重放的開發者(需要防篡改、防重放請使用數字簽名驗證)。
關于令牌有效期
密鑰令牌默認有效期為60分鐘,您可以在會員中心-API設置里修改。
開發建議:
- 您不必每次調用接口前都獲取令牌,建議您本地保存獲取到的secret_token,在合適的時候調用get_secret_token接口再次獲取密鑰令牌。
- 您可以隨時調用check_secret_token接口檢查token有效性。
簽名參數示例
signature=oxf0n0g59h7wcdyvz2uo68ph2s
使用示例:
以調用獲取訂單到期時間接口為例,當用戶調用這一接口時,其請求參數可能如下:
| 參數 | 參數說明 | 參數值 |
|---|---|---|
| secret_id | 訂單SecretId | o1fjh1re9o28876h7c08 |
| sign_type | 鑒權方式 | token |
-
調用get_secret_token接口獲取密鑰令牌:
secret_token: oxf0n0g59h7wcdyvz2uo68ph2s
-
直接將獲取到的secret_token作為簽名(signature)參數生成api鏈接:
https://dev.kdlapi.com/api/getorderexpiretime? sign_type=token&secret_id=o1fjh1re9o28876h7c08×tamp=1555080775&signature=oxf0n0g59h7wcdyvz2uo68ph2s
數字簽名驗證
參數設置:sign_type=hmacsha1
數字簽名驗證方式通過將調用參數+時間戳+隨機數(可選)用SecretKey計算出簽名進行驗證,具有安全性好,防篡改、防重放的特點。
簽名參數示例
sign_type=hmacsha1×tamp=1555080775&signature=ooCUlI6XTxoPS5PG8gNMT37YVl4%3D
我們采用HMAC-SHA1方式進行數字簽名,接下來對生成簽名參數的步驟做一個詳細介紹。
1. 生成簽名串
以下是生成簽名串的詳細過程:
會員中心API密鑰管理頁得到訂單的SecretId和SecretKey:
- SecretId:
o1fjh1re9o28876h7c08 - SecretKey:
jd1gzm6ant2u7pojhbtl0bam0xpzsm1c
注意: 上述取值只是示例,請根據您實際的 SecretId 和 SecretKey 進行后續操作!
以調用獲取訂單到期時間接口為例,當用戶調用這一接口時,其請求參數可能如下:
| 參數 | 參數說明 | 參數值 |
|---|---|---|
| secret_id | 訂單SecretId | o1fjh1re9o28876h7c08 |
| sign_type | 鑒權方式 | hmacsha1 |
| timestamp | 當前時間戳 | 1555064362 |
1.1 對參數排序
首先對所有請求參數按參數名的字典序( ASCII 碼)升序排序。注意:
1)只按參數名進行排序,參數值保持對應即可,不參與比大小;
2)按 ASCII 碼比大小,不是按字母表,也不是按數值。用戶可以借助編程語言中的相關排序函數來實現這一功能,如 php 中的 ksort 函數。
上述示例參數的排序結果如下:
{
"secret_id": "o1fjh1re9o28876h7c08",
"sign_type": "hmacsha1",
"timestamp": 1555064362,
}
使用其它程序設計語言開發時,可對上面示例中的參數進行排序,得到的結果一致即可。
1.2 拼接請求字符串
此步驟生成請求字符串。 將把上一步排序好的請求參數格式化成“參數名稱”=“參數值”的形式,如對 SecretId 參數,其參數名稱為 "secret_id" ,參數值為 "o1fjh1re9o28876h7c08" ,因此格式化后就為 secret_id=o1fjh1re9o28876h7c08 。
注意: “參數值”為原始值而非url編碼后的值。
然后將格式化后的各個參數用"&"拼接在一起,最終生成的請求字符串為:
secret_id=o1fjh1re9o28876h7c08&sign_type=hmacsha1×tamp=1555069980
1.3 拼接簽名原文字符串
此步驟生成簽名原文字符串。 簽名原文字符串由以下幾個參數構成:
- 請求方法: 支持 POST 和 GET 方式,這里使用 GET 請求,注意方法為全大寫。
- 請求路徑: 例如獲取訂單到期時間的請求路徑為:
/api/getorderexpiretime。實際的請求路徑根據接口的不同而不同,詳見各接口描述。 - 請求字符串: 即上一步生成的請求字符串。
簽名原文串的拼接規則為: 請求方法 + 請求路徑 + ? + 請求字符串
示例的拼接結果為:
GET/api/getorderexpiretime?secret_id=o1fjh1re9o28876h7c08&sign_type=hmacsha1×tamp=1555069980
1.4 生成簽名串
此步驟生成簽名串。首先使用 HMAC-SHA1 算法對上一步中獲得的簽名原文字符串進行簽名,然后將生成的簽名串使用 Base64 進行編碼,即可獲得最終的簽名串。
具體代碼如下,以 PHP 語言為例:
<?php
$secretKey = 'jd1gzm6ant2u7pojhbtl0bam0xpzsm1c';
$rawStr = 'GET/api/getorderexpiretime?secret_id=o1fjh1re9o28876h7c08&sign_type=hmacsha1×tamp=1555069980';
$signStr = base64_encode(hash_hmac('sha1', $rawStr, $secretKey, true));
echo $signStr;
最終得到的簽名串為:
ooCUlI6XTxoPS5PG8gNMT37YVl4=
使用其它程序設計語言開發時,可用上面示例中的原文進行簽名驗證,得到的簽名串與例子中的一致即可。
1.5 簽名串編碼
生成的簽名串并不能直接作為請求參數,需要對其進行 URL 編碼。
如上一步生成的簽名串為ooCUlI6XTxoPS5PG8gNMT37YVl4=,最終得到的簽名串請求參數(signature)為 ooCUlI6XTxoPS5PG8gNMT37YVl4%3D, 它將用于生成最終的api鏈接。
提示
-
如果用戶的請求方法是 GET,或者請求方法為 POST 同時 Content-Type 為 application/x-www-form-urlencoded,則發送請求時所有請求參數的值均需要做 URL 編碼,參數鍵和=符號不需要編碼。非 ASCII 字符在 URL 編碼前需要先以 UTF-8 進行編碼。
-
有些編程語言的 http 庫會自動為所有參數進行 urlencode,在這種情況下,就不需要對簽名串進行 URL 編碼了,否則兩次 URL 編碼會導致簽名失敗。
-
其他參數值也需要進行編碼,編碼采用 RFC 3986。使用 %XY 對特殊字符例如漢字進行百分比編碼,其中“X”和“Y”為十六進制字符(0-9 和大寫字母 A-F),使用小寫將引發錯誤。
1.6 生成api鏈接示例
以getorderexpiretime接口為例,最終輸出api鏈接為:
https://dev.kdlapi.com/api/getorderexpiretime?
sign_type=hmacsha1&secret_id=o1fjh1re9o28876h7c08×tamp=1555080775&signature=ooCUlI6XTxoPS5PG8gNMT37YVl4%3D
溫馨提示
由于示例中的密鑰是虛構的,時間戳也不是系統當前時間。為了得到一個可以正常返回的 url ,需要修改示例中的 secret_id 和 secret_key 為真實訂單的密鑰信息,并使用系統當前時間戳作為 timestamp 。
在實際調用 API 時,推薦使用配套的SDK,SDK 封裝了簽名的過程,開發時只關注產品提供的具體接口即可。詳細信息參見 SDK中心。
2. 代碼示例
提示
- 在下面的示例中,不同編程語言,甚至同一語言每次執行得到的 url 可能都有所不同,表現為參數的順序不同,但這并不影響正確性。只要所有參數都在,且簽名計算正確即可。
- 其他語言示例請參考 代碼樣例-數字簽名 (sdk_hmacsha1)
Python示例
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import time
import base64
import hashlib
import hmac
import requests
class Auth:
"""用于保存用戶secret_id、secret_key,以及計算簽名的對象。"""
def __init__(self, secret_id, secret_key):
self.secret_id = secret_id
self.secret_key = secret_key
@classmethod
def get_string_to_sign(cls, method, endpoint, params):
""" 生成簽名原文字符串 """
s = method + endpoint.split('.com')[1] + '?'
query_str = '&'.join("%s=%s" % (k, params[k]) for k in sorted(params))
return s + query_str
def sign_str(self, raw_str, method=hashlib.sha1):
""" 生成簽名串 """
try:
hmac_str = hmac.new(self.secret_key.encode('utf8'), raw_str.encode('utf8'), method).digest()
except UnicodeDecodeError as e:
hmac_str = hmac.new(self.secret_key.encode('utf8'), raw_str, method).digest()
return base64.b64encode(hmac_str)
def _get_base_res(method, endpoint, params):
"""處理基礎請求,
若響應為json格式則返回請求結果dict
否則直接返回原格式
"""
try:
r = None
if method == "GET":
r = requests.get("https://" + endpoint, params=params)
elif method == "POST":
r = requests.post("https://" + endpoint, data=params)
if r.status_code != 200:
return 'HTTP Status Code: %s' % r.status_code
try:
return json.loads(r.content.decode('utf8'))
except ValueError as e: # 返回結果不是json格式, 直接返回
return r.content.decode('utf8')
except Exception as e:
print(str(e))
if __name__ == '__main__':
secret_id = 'o1fjh1re9o28876h7c08'
secret_key = 'jd1gzm6ant2u7pojhbtl0bam0xpzsm1c'
method = 'GET' # 請求方式
endpoint = 'dev.kdlapi.com/api/getorderexpiretime'
# 除signature外的所有參數都放入params
params = {
'secret_id': secret_id,
'sign_type': 'hmacsha1',
'timestamp': int(time.time()),
}
auth = Auth(secret_id, secret_key)
raw_str = auth.get_string_to_sign(method, endpoint, params)
params['signature'] = auth.sign_str(raw_str)
res = _get_base_res(method, endpoint, params)
print(res)
3. SDK下載
通過sdk封裝了簽名計算過程,讓您免去了這部分的編程工作,配置好apikey即可調用。