树莓派Zero W(MicroPython)用urequests向Twilio发POST请求拨打电话遇错求助
解决MicroPython(树莓派Zero W)调用Twilio拨打电话API的问题
问题核心
Twilio的Calls API要求请求体使用application/x-www-form-urlencoded格式,但你的代码用了json=body参数,这会将请求头设为application/json,导致Twilio无法解析To、From等参数,从而返回21201错误。此外,你还缺少了Twilio API必需的Url参数(用于指定TwiML指令)。
解决方案
以下是基于MicroPython标准库的修正代码,核心是手动构造符合要求的表单编码请求体,并设置正确的请求头:
方法1:使用urllib.parse.urlencode(推荐,若你的MicroPython环境包含该模块)
import urequests import urllib.parse # 替换为你的Twilio账号信息和号码 TWILIO_USER = "你的Twilio Account SID" TWILIO_KEY = "你的Twilio Auth Token" CALLING_NUMBER = "+目标号码(E.164格式)" CALLER_NUMBER = "+你的Twilio号码(E.164格式)" url = f"https://api.twilio.com/2010-04-01/Accounts/{TWILIO_USER}/Calls.json" def call() -> None: # 必须包含Url参数,用于返回TwiML指令(示例使用Twilio的演示TwiML) body = { "To": CALLING_NUMBER, "From": CALLER_NUMBER, "Url": "http://demo.twilio.com/docs/voice.xml" } # 将字典编码为x-www-form-urlencoded格式的字符串 encoded_body = urllib.parse.urlencode(body) # 设置正确的Content-Type请求头 headers = {"Content-Type": "application/x-www-form-urlencoded"} # 使用data参数传递编码后的请求体,同时传入认证信息 response = urequests.post(url, data=encoded_body, headers=headers, auth=(TWILIO_USER, TWILIO_KEY)) print("Status Code", response.status_code) print("Response Text", response.text)
方法2:手动编码表单数据(若环境无urllib.parse)
如果你的MicroPython环境没有urllib.parse模块,可以手动实现简单的URL编码:
import urequests # 替换为你的Twilio账号信息和号码 TWILIO_USER = "你的Twilio Account SID" TWILIO_KEY = "你的Twilio Auth Token" CALLING_NUMBER = "+目标号码(E.164格式)" CALLER_NUMBER = "+你的Twilio号码(E.164格式)" url = f"https://api.twilio.com/2010-04-01/Accounts/{TWILIO_USER}/Calls.json" def simple_urlencode(data): """手动将字典转换为x-www-form-urlencoded格式字符串""" encoded_pairs = [] for key, value in data.items(): # 基础编码:替换空格,若有特殊字符可扩展处理 encoded_key = key.replace(" ", "%20") encoded_value = str(value).replace(" ", "%20") encoded_pairs.append(f"{encoded_key}={encoded_value}") return "&".join(encoded_pairs) def call() -> None: body = { "To": CALLING_NUMBER, "From": CALLER_NUMBER, "Url": "http://demo.twilio.com/docs/voice.xml" } encoded_body = simple_urlencode(body) headers = {"Content-Type": "application/x-www-form-urlencoded"} response = urequests.post(url, data=encoded_body, headers=headers, auth=(TWILIO_USER, TWILIO_KEY)) print("Status Code", response.status_code) print("Response Text", response.text)
关键注意事项
- 请求格式:必须使用
data参数传递编码后的字符串,而非json参数;同时显式设置Content-Type请求头 - 必填参数:Twilio Calls API要求
Url参数,用于返回TwiML指令(比如播放语音、接通通话),缺少该参数会导致额外错误 - 号码格式:
To和From号码必须使用E.164标准格式(如+1234567890),确保是Twilio认可的有效号码
内容的提问来源于stack exchange,提问作者Kile Alkuri
相关产品推荐
相关产品推荐

