Python调用Yealink管理云API出现TypeError错误,求解决方案
修复Yealink API脚本的TypeError问题
错误原因
buildHeaders函数存在逻辑缺陷:仅当传入的body参数不为空时,才会构建并返回headers字典;当body为空(比如你发起的GET请求场景),函数无显式返回值,默认返回None。在doRequest函数中尝试给None类型的headers添加Content-Type字段,直接触发TypeError: 'NoneType' object does not support item assignment错误。
修复方案
1. 修正buildHeaders函数逻辑
确保无论body是否为空,函数都返回有效的headers字典,并适配无body场景的签名生成逻辑。
2. 适配GET请求签名规则
保证GET请求(无body)时能正确生成符合Yealink API要求的签名头。
修改后的完整代码
# -*- coding: utf-8 -*- import hmac import hashlib import base64 import time import uuid import requests from hashlib import md5 import json from urllib3 import encode_multipart_formdata requests.packages.urllib3.disable_warnings() accesskeyId = "f8517322d648ffa7ff758ccd17" accesskeySecret = "11e47ef340e698eec4d5ea3" base_url = 'https://api-dm.yealink.com:8445/' def doRequest(method, uri, query, body, isForm): url = base_url + uri if not isForm: headers = buildHeaders(method, uri, query, body) headers['Content-Type'] = "application/json;charset=UTF-8" else: headers = buildHeaders(method, uri, {}, {}) print(headers) if method == 'GET' and len(query) > 0: parameter = getQueries(query) r = requests.get(url, headers=headers, params=parameter, verify=False) print(r.text, r.status_code) if method == 'POST': if not isForm: jsonBody = json.dumps(body) r = requests.post(url, headers=headers, data=jsonBody, verify=False) print(r.text, r.status_code) else: encode_data = encode_multipart_formdata(body) body = encode_data[0] headers['Content-Type'] = encode_data[1] r = requests.post(url, headers=headers, data=body, verify=False) print(r.text, r.status_code) def buildHeaders(method, uri, query, body): headers = {} # 基础认证头无论body是否为空都需添加 headers['X-Ca-Key'] = str(accesskeyId) headers['X-Ca-Nonce'] = str(''.join(str(uuid.uuid4()).split('-'))) headers['X-Ca-Timestamp'] = str(int(round(time.time() * 1000))) # 仅当body不为空时添加Content-MD5 if len(body) > 0: headers['Content-MD5'] = str(base64.b64encode(md5(json.dumps(body).encode("utf-8")).digest()).decode("utf-8")) # 统一生成签名并返回完整headers headers['X-Ca-Signature'] = str(base64.b64encode(hmac.new(accesskeySecret.encode("utf-8"), sign(method, uri, query, body , headers).encode("utf-8"), digestmod=hashlib.sha256).digest()).decode('utf8')) return headers def getQueries(query): formattedQueryString = "" paramIndex = 0 for p in query: formattedQueryString += f"{str(p)}={str(query[p])}" paramIndex += 1 if paramIndex != len(query): formattedQueryString += "&" return formattedQueryString def buildHeaderString(headers): header_string = "" for key,value in headers.items(): if len(value) == 0: continue if len(header_string) > 0: header_string += "\n" header_string += f"{key}:{value}" return header_string def sign(method, uri, query, body , header): header_string = buildHeaderString(header) stringToSign = f"{method}\n{header_string}\n{uri}" if len(query) > 0: stringToSign += f"\n{getQueries(query)}" return stringToSign # Get data print("GET the Details:") doRequest('GET','api/open/v1/manager/mvc/MVCInfo/get', {"id": "805061D10004477"},{},False)
额外说明
- 修正后的
buildHeaders函数先初始化基础API认证头,再根据body是否为空决定是否添加Content-MD5,最后统一生成签名并返回完整字典,彻底避免None类型问题。 - 用f-string优化了字符串拼接逻辑,提升代码可读性,不影响原有功能。
内容的提问来源于stack exchange,提问作者lionx
相关产品推荐
相关产品推荐

