Python 使用Twilio可编程语音SDK接收呼叫

Python 使用Twilio可编程语音SDK接收呼叫,python,twilio,voip,Python,Twilio,Voip,我正在Heroku上使用python部署,并且能够很好地进行调用。这是我遇到的问题接收。我没有修改TVOIncomingCall实例或PKPushRegistry的任何init或委托逻辑。事实上,当我编译时,日志上写着“pushRegistry:didUpdatePushCredentials:forType”和“已成功注册VoIP推送通知。”这让我认为我的服务器上的传入处理程序是问题所在 我的问题是:在python中,发出VoIP推送通知以通知用户来电的正确方法是什么?我已经在我的应用程序中启

我正在Heroku上使用python部署,并且能够很好地进行调用。这是我遇到的问题接收。我没有修改
TVOIncomingCall
实例或
PKPushRegistry
的任何init或委托逻辑。事实上,当我编译时,日志上写着
“pushRegistry:didUpdatePushCredentials:forType”
“已成功注册VoIP推送通知。”
这让我认为我的服务器上的传入处理程序是问题所在

我的问题是:在python中,发出VoIP推送通知以通知用户来电的正确方法是什么?我已经在我的应用程序中启用了VoIP服务,生成了VoIP服务证书(.p12),并收到了有效的
推送凭证\u SID
,但如何处理它呢

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

以下是my 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
值显然是错误的。我认为它需要以某种方式等同于对应用程序实例的引用。在快速启动python示例中,
IDENTITY='voice\u test'
还有,
PUSH\u凭证\u 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作为参数传入

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

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

  • 使用新的推送凭据SID更新应用程序服务器的
    server.py
    文件中的
    PUSH\u CREDENTIAL\u SID
    值。它在文件顶部带有以下常量:

    ACCOUNT_SID = 'AC***'
    API_KEY = 'SK***'
    API_KEY_SECRET = '***'
    PUSH_CREDENTIAL_SID = 'CR***'
    APP_SID = 'AP***'
    
    在您的
    placeCall
    功能中:

    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)
    

    您似乎还缺少上面的
    APP_SID
    ,它是包含一些调用指令的引用

    这里是Twilio开发者福音传道者

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

    相反,您的传入呼叫webhook应该指向一个端点,该端点将返回一些指示Twilio来拨打您的客户端。TwiML只是XML的一个子集,您需要的元素是嵌套的。您的端点应该返回如下内容:

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

    谢谢你的回复,梅根!从一开始我就应该分享更多的代码,但事实上,您告诉我的大部分内容都已经在我的server.py中了。我没有在“placeCall”函数中包含最后两行。然而,它现在就在那里,但是拨打我的Twilio号码仍然会导致可怕的“应用程序错误已发生”响应消息。感谢您的回复!我已经更新了我原来的问题。请参阅更新部分中的注释。:)谢谢你的更新。我不认为你做的嵌套正确,检查我的更新答案。好的!现在我们有进展了!根据您的建议更新了服务器,我现在收到“错误-52134-无效的APNs设备令牌”。我将重新生成并上载新的VoIP服务证书,并更新推送凭据SID。谢谢你,菲尔。
    @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)