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

树莓派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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:10:29