Skip to main content
 首页 » 编程设计

python之使用 Twilio 可编程语音 SDK 接听电话

2025年02月15日30shihaiming

我正在关注 Quickstart Guide在 Heroku 上使用 python 部署,并且能够很好地调用电话。这是我遇到问题的接收。我没有为 TVOIncomingCall 实例或 PKPushRegistry 修改任何初始化或委托(delegate)逻辑。事实上,当我编译时,日志显示 "pushRegistry:didUpdatePushCredentials:forType" 和 "Successfully registered for VoIP push notifications." 这让我觉得我的传入处理程序在我的server.py 是问题所在。

我的问题是:在 python 中,触发 VoIP 推送通知以通知用户有来电的正确方法是什么?我在我的应用程序中启用了 VoIP 服务并生成一个 VoIP 服务证书 (.p12) 并收到一个有效的 PUSH_CREDENTIAL_SID 作为我的努力,但如何处理它呢?

快速入门说要点击我服务器的“placeCall”端点,因此我更新了我的 Twilio 号码的传入路径并在仪表板中相应地指向它,但这会导致每当有人调用我的 Twilio 号码时都会出现“发生应用程序错误”响应。

这是我的 server.py 中的相关代码:

import os 
from flask import Flask, request 
from twilio.jwt.access_token import AccessToken, VoiceGrant 
from twilio.rest import Client 
import twilio.twiml 
 
ACCOUNT_SID = 'ACxxxxxxxx' 
API_KEY = 'SKxxxxxxxxxxxxxxxx' 
API_KEY_SECRET = 'xxxxxxxxxxxxxxxx' 
PUSH_CREDENTIAL_SID = 'CRxxxxxxxxxxxxxxxx' 
APP_SID = 'APxxxxxxxxxxxxxxxx' 
ACCOUNT_AUTH = 'xxxxxxxxxxxxxxxx' 
 
IDENTITY = 'MyApp' #not literally 
 
app = Flask(__name__) 
 
@app.route('/accessToken') 
def token(): 
  account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID) 
  api_key = os.environ.get("API_KEY", API_KEY) 
  api_key_secret = os.environ.get("API_KEY_SECRET", API_KEY_SECRET) 
  push_credential_sid = os.environ.get("PUSH_CREDENTIAL_SID", PUSH_CREDENTIAL_SID) 
  app_sid = os.environ.get("APP_SID", APP_SID) 
 
  grant = VoiceGrant( 
    push_credential_sid = push_credential_sid, 
    outgoing_application_sid = app_sid 
  ) 
 
  token = AccessToken(account_sid, api_key, api_key_secret, IDENTITY) 
  token.add_grant(grant) 
 
  return str(token) 
 
 
@app.route('/placeCall', methods=['GET', 'POST']) 
def placeCall(): 
    account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID) 
    api_key = os.environ.get("API_KEY", API_KEY) 
    api_key_secret = os.environ.get("API_KEY_SECRET", API_KEY_SECRET) 
    push_credential_sid = os.environ.get("PUSH_CREDENTIAL_SID", PUSH_CREDENTIAL_SID) 
    app_sid = os.environ.get("APP_SID", APP_SID) 
 
    CALLER_ID = request.values.get('From') 
    IDENTITY = request.values.get('To') 
 
    #client = Client(api_key, api_key_secret, account_sid) 
    client = Client(api_key, api_key_secret, account_sid, app_sid, push_credential_sid) 
    call = client.calls.create(to='client:' + IDENTITY, from_= 'client:' + CALLER_ID) 
    return str(call.sid) 

我的 Identity 值显然是错误的。我认为它需要以某种方式等于对应用程序实例的引用。在 quickstart python 示例中,IDENTITY = 'voice_test' 另外,PUSH_CREDENTIAL_SID 在哪里发挥作用?

提前致谢。

更新
______

根据@philnash 的评论,我将client 名词嵌套在dial 动词中。这是我的新 /incoming 端点:

@app.route('/incoming', methods=['GET', 'POST']) 
def incoming(): 
    CALLER_ID = request.values.get('From') 
    resp = twilio.twiml.Response() 
    resp.dial(client = IDENTITY, callerId = CALLER_ID, record = "record-from-answer-dual") 
    return str(resp) 

这现在会导致调试器中出现“架构验证警告”,指出“未知或意外的嵌套元素”是可能的原因。我是否错误地注册了客户端?旧的 SDK 允许您显式传入您的 clientName 作为参数。

我的 server.py 中的 IDENTITY 字符串是:

  1. 在任何方法范围之外定义。
  2. 用于生成 accessToken
  3. 嵌套在dial动词的client名词中。

请您参考如下方法:

此处为 Twilio 开发人员布道师。

/placeCall端点不适用于您的 Twilio 号码的来电 webhook。在示例中,它用于简单地生成对您的客户端的调用。

相反,您的来电 webhook 应该指向一个端点,该端点将返回一些 TwiML指示 Twilio 调用您的客户端。 TwiML 只是 XML 的一个子集,您需要的元素是 <Dial> 嵌套 <Client> .您的端点应返回类似以下内容:

<Response> 
  <Dial> 
    <Client>YOUR_CLIENT_NAME</Client> 
  </Dial> 
</Response> 

如果这有帮助,请告诉我。

更新

根据问题的更新,我们现在需要在 Python 中生成这个 TwiML。你可以nest TwiML与 Twilio Python helper library使用 Python 的 with句法。我相信这应该有效:

@app.route('/incoming', methods=['GET', 'POST']) 
def incoming(): 
    CALLER_ID = request.values.get('From') 
    resp = twilio.twiml.Response() 
    with resp.dial(callerId = CALLER_ID, record = "record-from-answer-dual") as dial: 
        dial.client(IDENTITY) 
    return str(resp)