You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 15:20:46