1. 程式人生 > >騰訊AI開放平臺的簽名演算法(Python)

騰訊AI開放平臺的簽名演算法(Python)

前幾天老師佈置了一個作業,要求使用python進行語音合成,實現班級點名的功能。後來使用了pyttsx庫,發現這個庫合成的語音聽起來不清晰,於是果斷拋棄。然後就想起了使用騰訊的語音合成api,發現騰訊優圖的語音合成還是比較清晰的。本來騰訊ai開放平臺的api使用起來不難,但就是計算 “sign” 這個簽名時有些不好理解。這裡只對這個簽名的演算法進行講解。

官方提供的介紹如下:

下面分步介紹:

# 在執行這一步時首先要保證parms裡的所有必須引數(sign除外)都已經完整
# 我的params如下:
params = {
            'app_id' : self.APP_ID,
            'time_stamp' : time_stamp,
            'nonce_str' : nonce_str,
            'text' : self.TEXT,
            'model_type' : self.model_type, # 語音 0~2。0:女。1:女英文。2:男
            'speed' : self.speed, # 語速 -2:0.6,-1:0.8, 0:正常, 1:1.2倍,2:1.5倍
        };
# 其中的time_stamp和nonce_str需要實時計算。方法如下:
 
 time_stamp = int(time.time());   # 獲得時間戳(秒級),防止請求重放
 
 nonce_str = ''.join(random.sample(string.ascii_letters + string.digits, 10)); # 獲得隨機字串,保證簽名不被預測。

"""將<key, value>請求引數對按key進行字典升序排序,得到有序的引數對列表N
   將列表N中的引數對按URL鍵值對的格式拼接成字串,得到字串T(如:key1=value1&key2=value2),URL鍵值拼接過程value部分需要URL編碼,URL編碼演算法用大寫字母,例如%E8,而不是小寫%e8"""

# 獲得sign對應的值
  before_sign = '';
        # 對key排序拼接
        for key in sorted(params):
            before_sign += f'{key}={quote(str(params[key]).encode("utf8"))}&';

# 將應用祕鑰以app_key為鍵名,拼接到before_sign的末尾
 
before_sign += f"app_key={self.APP_KEY}";

 # 對獲得的before_sign進行MD5加密(結果大寫),得到藉口請求籤名

   sign = hashlib.md5(before_sign.encode("utf-8")).hexdigest().upper();

  # 將請求籤名新增進引數字典

   params["sign"] = sign;

最後附上完整程式碼:

        # 獲得時間戳(秒級),防止請求重放
        time_stamp = int(time.time());
        # 獲得隨機字串,保證簽名不被預測
        nonce_str = ''.join(random.sample(string.ascii_letters + string.digits, 10))
        # 組合引數(缺少sign,其值要根據以下獲得)
        params = {
            'app_id' : self.APP_ID,
            'time_stamp' : time_stamp,
            'nonce_str' : nonce_str,
            'text' : self.TEXT,
            'model_type' : self.model_type, # 語音 0~2。0:女。1:女英文。2:男
            'speed' : self.speed, # 語速 -2:0.6,-1:0.8, 0:正常, 1:1.2倍,2:1.5倍
        };
        # 獲得sign對應的值
        before_sign = '';
        # 對key排序拼接
        for key in sorted(params):
            before_sign += f'{key}={quote(str(params[key]).encode("utf8"))}&';
        # 將應用祕鑰以app_key為鍵名,拼接到before_sign的末尾
        before_sign += f"app_key={self.APP_KEY}";
        # 對獲得的before_sign進行MD5加密(結果大寫),得到藉口請求籤名
        sign = hashlib.md5(before_sign.encode("utf-8")).hexdigest().upper();
        # 將請求籤名新增進引數字典
        params["sign"] = sign;