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

时间:2017-02-04 00:35:59

标签: python twilio voip

我在Heroku上使用python部署跟踪Redux Thunk,并且能够正常拨打电话。这是我遇到问题的接收。我没有为TVOIncomingCall实例或PKPushRegistry修改任何init或委托逻辑。事实上,当我编译时,日志显示"pushRegistry:didUpdatePushCredentials:forType""Successfully registered for VoIP push notifications."这使我认为我的server.py上的传入处理程序是问题所在。

我的问题是:在python中,启动VoIP推送通知以通知用户来电的正确方法是什么?我在我的应用中启用了VoIP服务并生成了一个VoIP服务证书(.p12)并收到了有效的PUSH_CREDENTIAL_SID我的努力,但该怎么办?

Quickstart说要点击我服务器的'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值显然是错误的。我认为它需要以某种方式等于对app实例的引用。在快速入门python示例中,IDENTITY = 'voice_test'此外,PUSH_CREDENTIAL_SID在哪里发挥作用?

提前致谢。

UPDATE
______

根据@ 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. 嵌套在client动词的dial名词

2 个答案:

答案 0 :(得分:1)

Twilio开发者传道者在这里。

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

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

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

让我知道这是否有帮助。

<强>更新

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

@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)

答案 1 :(得分:0)

使用新的推送凭据SID更新应用程序服务器的ax2.autoscale()文件中的import numpy as np import matplotlib.pylab as plt import copy # Creating the two figures x = np.random.rand(20) fig1, ax1 = plt.subplots() fig2, ax2 = plt.subplots() nr = 0 for color, ax in zip(("red", "blue"), (ax1, ax2)): x = np.random.rand(20) + nr ax.hist(x, color=color) nr += 0.5 # Copying from ax1 to ax2 for patch in ax1.patches: patch_cpy = copy.copy(patch) # cut the umbilical cord the hard way patch_cpy.axes = None patch_cpy.figure = None patch_cpy.set_transform(ax2.transData) ax2.add_patch(patch_cpy) ax2.autoscale() plt.show() 值。它在文件顶部使用以下常量:

PUSH_CREDENTIAL_SID

server.py函数中:

ACCOUNT_SID = 'AC***'
API_KEY = 'SK***'
API_KEY_SECRET = '***'
PUSH_CREDENTIAL_SID = 'CR***'
APP_SID = 'AP***'

您似乎也错过了上面的placeCalldef 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) 是对TwiML app的引用,其中包含一些调用说明。