Open hklchung opened 1 year ago
Hello @hklchung Can you please refer this end-end test link? Let me know if this helps.
@hklchung did you use this guide ?
Hi @charan678 this is the guide I have been following. I have also double checked to ensure the Twilio webhook URL starts with http://
since I am using Ngrok.
I tried to run test_url() but unfortunately all returned with a response code 404.
Any advice on how to proceed would be highly appreciated
.
hello @hklchung It's working for me. Following are the steps followed by me
setup ngrok
open active phone number page and add ngrok http url to webhook for both messaging and voice
I used this code below to test and export TWILIO_AUTH_TOKEN before running in local env
from flask import Flask, request, abort
from twilio.twiml.voice_response import VoiceResponse
from twilio.twiml.messaging_response import MessagingResponse
from twilio.request_validator import RequestValidator
from functools import wraps
import os
app = Flask(__name__)
def validate_twilio_request(f):
"""Validates that incoming requests genuinely originated from Twilio"""
@wraps(f)
def decorated_function(*args, **kwargs):
# Create an instance of the RequestValidator class
validator = RequestValidator(os.environ.get('TWILIO_AUTH_TOKEN'))
# Validate the request using its URL, POST data,
# and X-TWILIO-SIGNATURE header
request_valid = validator.validate(
request.url,
request.form,
request.headers.get('X-TWILIO-SIGNATURE', ''))
print("Request valid = ", request_valid)
# Continue processing the request if it's valid, return a 403 error if
# it's not
if request_valid:
return f(*args, **kwargs)
else:
return abort(403)
return decorated_function
@app.route('/voice', methods=['POST'])
@validate_twilio_request
def incoming_call():
"""Twilio Voice URL - receives incoming calls from Twilio"""
# Create a new TwiML response
resp = VoiceResponse()
# <Say> a message to the caller
from_number = request.values['From']
body = """
Thanks for calling!
Your phone number is {0}. I got your call because of Twilio's webhook.
Goodbye!""".format(' '.join(from_number))
resp.say(body)
# Return the TwiML
return str(resp)
#
@app.route('/message', methods=['POST'])
@validate_twilio_request
def incoming_message():
"""Twilio Messaging URL - receives incoming messages from Twilio"""
# Create a new TwiML response
resp = MessagingResponse()
# <Message> a text back to the person who texted us
body = "Your text to me was {0} characters long. Webhooks are neat :)" \
.format(len(request.values['Body']))
resp.message(body)
# Return the TwiML
return str(resp)
@app.route('/health', methods=['GET'])
def healthcheck():
return str("received")
if __name__ == '__main__':
app.run(debug=True)
twilio-python = 8.1.0 python version = 3.8.8 os = mac os Test phone number location = us ( +1 XXX ) Flask version = 2.2.2
How to Use Ngrok to Send Automatic Textback SMS Using POST & GET API Requests how-to-secure-your-flask-app-by-validating-incoming-twilio-requests
Thanks @charan678, your answer provided me new direction to test in a more granular level. I found a working solution.
The webhook on the Twilio console must first be set to http://
, Ngrok tunnels can have both http://
and https://
(no need to change anything here). But the tricky part is when the request comes through to the app, the request URL is of course a http://
, this needs to be manually changed back to https://
before sending into the RequestValidator().
Would you know why this change is required, considering the webhook URL set in the console is http://
and not a https://
?
Please check out my solution that I introduced issues, This was super frustrating in having to debug
Issue Summary
I am developing a Python (Flask) voice app on a local machine and using Ngrok tunnel to allow Twilio access the app via a webhook (all set up according to the Twilio guide). I need to add a step to check the requests are coming from Twilio and am using the RequestValidator from the Twilio Python SDK. However, this step always returns false, but should be true as I am the one initiating the request during testing.
Steps to Reproduce
Code Snippet
In your Python Flask test voice application, set up a /call app route, then inside the call() test the following
Technical details: