[PYTHON] Verständnis anhand des Mechanismus Twilio # 3-1 --AWS API Gateway + Lambda-Implementierung Walkthrough (Teil 1)

Dieser Artikel ist eine Fortsetzung des folgenden Artikels. Wir empfehlen Ihnen, dies zuerst zu lesen. Verständnis aus dem Mechanismus Twilio # 1 - Einführung Twilio # 2 - Den Mechanismus verstehen

Anruf vom Twilio Client tätigen / Wir implementieren eine Anwendung, um den Twilio Client anzurufen. Da der Betrag groß sein wird, werden wir ihn in zwei Teile teilen. Der folgende Inhalt richtet sich an Personen mit Erfahrung in der Entwicklung von AWS, insbesondere an Personen, die APIs durch Kombination von AWS Lambda und API Gateway entwickelt und veröffentlicht haben. Wenn Sie keine Erfahrung haben, empfehlen wir Ihnen, beide zu kombinieren, um eine API zu erstellen und zu veröffentlichen, um ein Gefühl dafür zu bekommen.

―― 1. Einführung ―― 1. Definition der Grundstruktur und der Begriffe bei Verwendung von Twilio ―― 2. Die Umgebung wurde diesmal überprüft ―― 2. Kommunikationsflussdatenstruktur ―― 1. Authentifizierung / Capability Token-Übertragung ―― 2. Anruf (eingehender Anruf) von einem externen Telefon zu einem Twilio-Client ―― 3. Anruf vom Twilio-Client zum externen Telefon (OutgoingCall) --3-1. ** Walkthrough zur Implementierung von AWS API Gateway + Lambda (Teil 1) ** ** ← Jetzt hier **

Exemplarische Vorgehensweise

Lassen Sie uns die Spezifikationen des Twilio-Clients erneut bestätigen, die dieses Mal realisiert werden.

--Was du tun kannst

Es wird angenommen, dass die Parameter wie die Telefonnummer wie folgt sind.

Parameter Wert Erklärung / Bemerkungen
Twilio Telefonnummer 050-3123-4567 Die dem Twilio-Client zugewiesene Telefonnummer. Bitte kaufen Sie im Voraus über die Twilio-Konsole.
Client Name DeviceId_0001 Ein Name zum Identifizieren und Steuern des Twilio-Clients innerhalb des Twilio-Servers.
Externes Telefon 090-5987-6543 Telefon außerhalb von Twilio. Bitte benutzen Sie Ihr eigenes Handy.

Lassen Sie uns die diesmal realisierte Konfiguration erneut bestätigen. TwilioDiagrams_Fig1-1.png

Implementieren Sie jede API mit AWS Lambda und erstellen Sie sie so, dass sie über API Gateway verwendet werden kann. Der API-Name, der Lambda-Funktionsname und der API-Gateway-Ressourcenname entsprechen wie folgt.

API-Name Name der AWS Lambda-Funktion Ressourcenname
Capability Token-Erfassungs-API TwilioRetrieveCapabilityToken /twilio/retrieve_capability_token
TwiML-Rückgabe-API für eingehende Anrufe TwilioRetieveTwimlCallIncoming /twilio/retrieve_twiml/call_incoming
TwiML-Rückgabe-API für ausgehende Anrufe TwilioRetieveTwimlCallOutgoing /twilio/retrieve_twiml/call_outgoing

Jede API wird in der Produktphase von API Gateway bereitgestellt. Daher wird API Server möglicherweise die folgende URL bereitstellen.

Der in JavaScript implementierte Twilio-Client hat den folgenden Bildschirm. In diesem Bildschirm können Sie ein normales Telefon anrufen und einen normalen Anruf erhalten. twilio_client_webbrowser.png

Das Festlegen von Arbeiten im Zusammenhang mit Twilio ist [Eröffnen und Vorbereiten eines Twilio-Kontos](http://qiita.com/tmiki/items/ac28b6f6ad745f3e1b2e#twilio%E3%82%A2%E3%82%AB%E3%82%A6%E3% 83% B3% E3% 83% 88% E3% 81% AE% E9% 96% 8B% E8% A8% AD% E6% BA% 96% E5% 82% 99).

Die spezifischen Arbeiten in Bezug auf AWS sind wie folgt. Es wird davon ausgegangen, dass Sie bereits ein AWS-Konto eröffnet haben.

―― 1. Implementierung der API Server-Verarbeitung (Python unter AWS Lambda) --1-1. Implementieren und Bereitstellen der CapabilityToken-Erfassungs-API als Lambda-Funktion --1-2. Implementieren und Bereitstellen der TwiML-Rückgabe-API für eingehende Anrufe als Lambda-Funktion --1-3. Implementieren und Bereitstellen der TwiML-Rückgabe-API für ausgehende Anrufe als Lambda-Funktion. --2 API-Gateway-Einstellungen --2-1. Erstellen Sie eine API über das Amazon API Gateway-Menü in der AWS Management Console ―― 2-2. Definieren Sie die Ressource für jede API --2-3. CORS einstellen --2-4. Methode für CapabilityToken-Erfassungs-API definieren (/ twilio / retrieve_capability_token) --2-5. Definieren Sie die Methode für die TwiML-Rückgabe-API (/ twilio / retrieve_twiml / call_incoming) für eingehende Anrufe --2-6. Definieren Sie die Methode für die TwiML-Rückgabe-API (/ twilio / retrieve_twiml / call_outgoing) für ausgehende Anrufe ―― 2-7. Prod Erstellen Sie eine Bühne und stellen Sie sie bereit ―― 2-8. Überprüfen Sie den Betrieb jeder API ―― 3. Implementierung und Bereitstellung von Twilio Client --3-1. Twilio Client mit JavaScirpt implementieren --3-2. Erstellen Sie einen S3-Bucket und aktivieren Sie das statische Website-Hosting --3-3. Auf S3-Eimer stellen ―― 4. Funktionsprüfung! --4-1. Zugriff auf den Twilio Client auf S3 mit einem Webbrowser über HTTPS --4-2. Rufen Sie den Twilio Client von einer verifizierten Telefonnummer aus an ―― 4-3. Rufen Sie eine bestätigte Telefonnummer vom Twilio Client an

Schauen wir uns jeden der folgenden Punkte an.

1. Implementierung der API Server-Verarbeitung (Python unter AWS Lambda)

Die bei dieser Überprüfung erstellte API ist in Python unter AWS Lambda implementiert. Wenn Sie Lambda noch nicht kennen, sollten Sie die Schritte in der folgenden Dokumentation befolgen, um ein Gefühl dafür zu bekommen, wie es ist.

AWS Lambda Developer Guide - Erste Schritte https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/getting-started.html

Wie Sie sehen können, ist JSON am einfachsten als Eingabe- / Ausgabeformat der Lambda-Funktion zu verwenden. Daher verwendet die diesmal implementierte Funktion auch so viel JSON wie möglich.

1-1. Implementieren Sie die CapabilityToken-Erfassungs-API als Lambda-Funktion

Schnittstelle (Eingabe / Ausgabe)

Bestimmen Sie zunächst die Eingangs- und Ausgangsstrukturen dieser Lambda-Funktion. Wie in [Übertragung von Zertifizierungs- / Fähigkeitstoken] definiert (http://qiita.com/tmiki/items/fad1a22ba1fe14d32e34#%E8%AA%8D%E8%A8%BCcapabilitytoken%E6%8E%88%E5%8F%97) Machen wir es zur Struktur von.

Input


{"twilioPhoneNumber": "+81-50-1234-9876"}

Der Twilio-Client geht davon aus, dass ihm im Quellcode eine Twilio-Telefonnummer zugeordnet ist. Diese API authentifiziert sich, indem sie nur prüft, ob die unter Eingabe angegebene Twilio-Telefonnummer registriert ist.

Output


{"capabilityToken": capabilityToken, "success": true}

Wenn die Authentifizierung erfolgreich ist, generiert diese API ein Capability Token. Es gibt auch den Erfolg oder Misserfolg des Prozesses zurück.

Implementierung

Schreiben wir nun die Lambda-Funktion.

TwilioRetrieveCapabilityToken.py


from __future__ import print_function
from twilio.util import TwilioCapability

print('Loading function')


class UnregisteredPhoneNumberException(Exception):
    def __init__(self,value):
        self.value = value


def get_client_name_by_phone_number (phone_number):
    ''' This function returns a valid clientName.
        If the parameter "phone_number" is not registered, this function raise an "UnregisteredPhoneNumberException".
    '''

    # regularize the input string "phone_number" to match registered phone numbers.
    phone_number_wo_hyphen = phone_number.replace('-','')

    # match and get the correct clientName
    if (phone_number_wo_hyphen == "+8150312345678"):
        clientName= "DeviceId_0001"

    else:
        raise UnregisteredPhoneNumberException('Unregistered phone number "' + phone_number + '"')

    return clientName


def lambda_handler(event, context):
    ''' Creates and responds a Twilio Capability Token.
    This function will be received a json formatted string like below.
    {"twilioPhoneNumber": "+81-50-1234-9876"}

    This function will return a json formatted string like below.
    If this function succeed, the parameter "success" will be set as true.
    {"capabilityToken": capabilityToken, "success": true}
    '''

    # configure parameters belong to Twilio
    twilio_account_sid = "{{twilio_accound_sid}}"
    twilio_auth_token = "{{twilio_account_auth_token}}"
    twilio_app_sid = "{{twilio_app_sid}}"
    expiration_time_for_capability_token = 3600


    # get necessary parameter from "event" and "context"
    twilio_phone_number = event.get("twilioPhoneNumber")


    # Create a Capability token with twilio_account_sid and its twilio_auth_token
    # It enables a Twilio client to receive an incoming call and to make an outgoing call.
    try:
        capability = TwilioCapability(twilio_account_sid, twilio_auth_token)
        capability.allow_client_incoming(get_client_name_by_phone_number(twilio_phone_number))
        capability.allow_client_outgoing(twilio_app_sid)
        capabilityToken = capability.generate(expiration_time_for_capability_token)
        res = {"capabilityToken": capabilityToken, "success": True}

    except UnregisteredPhoneNumberException:
        res = {"capabilityToken": None, "success": False}

    return res

Werfen wir einen Blick auf die von uns erstellte Lambda-Funktion.

Erstens gibt es die folgenden Elemente als Werte, die von der Umgebung abhängen. Bitte lesen Sie entsprechend Ihrer Umgebung.

    # configure parameters belong to Twilio
    twilio_account_sid = "{{twilio_accound_sid}}"
    twilio_auth_token = "{{twilio_account_auth_token}}"
    twilio_app_sid = "{{twilio_app_sid}}"
    expiration_time_for_capability_token = 3600

Zu Beginn der Funktion werden die Twilio-Konto-SID, das damit verbundene Auth-Token und die zuvor erstellte App-SID angegeben. Ändern Sie sie daher entsprechend Ihrer Umgebung. Das Ablaufdatum des Capability-Tokens ist hier auf 3600 Sekunden festgelegt. Bitte ändern Sie dies jedoch entsprechend.

--In der Funktion get_client_name_by_phone_number

    # match and get the correct clientName
    if (phone_number_wo_hyphen == "+815012349876"):
        clientName = "DeviceId_0001"

Bitte geben Sie die Twilio-Telefonnummer an, die Sie beim Einrichten Ihres Twilio-Kontos erhalten haben. Ändern Sie den Kundennamen nach Ihren Wünschen. Diese Funktion hat derzeit eine Verbindung zwischen der Twilio-Telefonnummer und dem Client-Namen im Quellcode. In Zukunft wird jedoch davon ausgegangen, dass eine DB-Verbindung hergestellt und die Verbindungsinformationen aus der DB abgerufen werden.

Der Verarbeitungsablauf ist wie folgt.

Bereitstellen

Diese Lambda-Funktion erfordert das Paket twilio.util. Daher funktioniert es nicht, nur den obigen Quellcode aus dem Inline-Editor von AWS Management Console einzufügen. Sie müssen ein Bereitstellungspaket erstellen und hochladen. Führen Sie die folgenden Schritte aus, um ein Bereitstellungspaket (Zip-Datei) zu erstellen.

Erstellen eines Bereitstellungspakets (Python) https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html

Melden Sie sich bei einem geeigneten Linux-Server an und führen Sie die folgenden Schritte aus. Platzieren Sie den Quellcode und alle erforderlichen Bibliotheken im aktuellen Verzeichnis und komprimieren Sie dieses Verzeichnis.

#Klonen Sie den Twilio Client-Schnellstart für Python, um Informationen zur Abhängigkeit der Twilio-Bibliothek abzurufen
#Alles was Sie brauchen sind Anforderungen.Da es nur txt ist, können Sie dies manuell bringen
$ git clone https://github.com/TwilioDevEd/client-quickstart-python

#Erstellen Sie ein Arbeitsverzeichnis
$ mkdir ./twilio_on_aws
$ cd ./twilio_on_aws

#Erstellen Sie den Quellcode. Kopieren Sie die obige Quelle und fügen Sie sie ein.
$ vi TwilioRetrieveCapabilityToken.py

#Installieren Sie verwandte Bibliotheken in Ihrem Arbeitsverzeichnis
$ pip install -r ../client-quickstart-python/requirements.txt -t ./

#Komprimieren Sie den Quellcode und die zugehörigen Bibliotheken in eine Zip-Datei und erstellen Sie ein Bereitstellungspaket
$ zip -r ../TwilioRetrieveCapabilityToken.zip ./

Laden Sie das oben genannte Bereitstellungspaket von der AWS Management Console hoch. LambdaFunction_TwilioRetrieveCapabilityToken_1.png

Ich denke, dass es standardmäßig kein Problem mit der Konfiguration gibt, solange die Handler-Einstellungen korrekt sind. Diese Lambda-Funktion verwendet keine anderen AWS-Services, daher kann die IAM-Rolle lambda_basic_execution sein. LambdaFunction_TwilioRetrieveCapabilityToken_2.png

Damit ist die Implementierung und Bereitstellung der CapabilityToken-Erfassungs-API abgeschlossen.

1-2. Implementieren Sie die TwiML-Rückgabe-API für eingehende Anrufe als Lambda-Funktion

Schnittstelle (Eingabe / Ausgabe)

Details der Schnittstelle zwischen Twilio Server und API Server sind unten zusammengefasst. [Anruf vom externen Telefon an den Twilio-Client (eingehender Anruf)](http://qiita.com/tmiki/items/fad1a22ba1fe14d32e34#%E5%A4%96%E9%83%A8%E9%9B%BB%E8%A9 % B1% E3% 81% 8B% E3% 82% 89twilio% E3% 82% AF% E3% 83% A9% E3% 82% A4% E3% 82% A2% E3% 83% B3% E3% 83% 88 % E3% 81% B8% E3% 81% AEcall eingehender Anruf)

Die von Twilio Server als Eingabe übergebenen Parameter entsprechen in etwa der Struktur der HTTP-GET-Parameter, und die Ausgabe muss XML zurückgeben, sodass beide eine schlechte Affinität zu JSON zu haben scheinen. Es ist möglich, eine Datenstrukturkonvertierungsverarbeitung innerhalb der Lambda-Funktion durchzuführen, es ist jedoch architektonisch nicht vorzuziehen, eine nicht wesentliche Verarbeitung zu beschreiben. Das Festhalten an JSON ist jedoch auch Zeitverschwendung. Lassen Sie daher API Gateway den Konvertierungsprozess nur für die Eingabe ausführen. Die Eingabe wird vom API-Gateway in das JSON-Format konvertiert. Die Ausgabe generiert XML mit der Lambda-Funktion und gibt es so zurück, wie es ist.

Lassen Sie API Gateway die HTTP-POST-Anforderung von Twilio Server übersetzen, und diese API erwartet den folgenden JSON.

Input


{
    "AccountSid": "AC3exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "ApiVersion": "2010-04-01",
    "Called": "+815031234567",
    "CalledCountry": "JP",
    "CalledVia": "815031234567",
    "Caller": "+819059876543",
    "CallerCountry": "JP",
    "CallSid": "CA1fnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
    "CallStatus": "ringing",
    "Direction": "inbound",
    "ForwardedFrom": "815031234567",
    "From": "+819059876543",
    "FromCountry": "JP",
    "To": "+815031234567",
    "ToCountry": "JP"
}

Ich werde TwiML so wie es ist zurückgeben.

Output


<?xml version="1.0\" encoding="UTF-8"?><Response><Dial timeout="60"><Client>DeviceId_0001</Client></Dial></Response>

Implementierung

Schreiben wir nun die Lambda-Funktion.

TwilioRetrieveTwimlCallIncoming.py


from __future__ import print_function
import json

print('Loading function')

def get_client_name_by_phone_number(phone_number):
    # regularize the input string "phone_number" to match registered phone numbers.
    phone_number_wo_hyphen = phone_number.replace('-','')

    # match and get the correct clientName
    if (phone_number_wo_hyphen == "+815031234567"):
        clientName = "DeviceId_0001"

    else:
        clientName = None

    return clientName

def lambda_handler(event, context):
    ''' Returns a TwiML to enable a real phone to call a Twilio device.
    This function will be received the following parameters.

    {
        "Caller": "+819012345678",
        "To": "+815098765432"
    }
    '''

    call_incoming_phone_number = event.get("To")
    client_name = get_client_name_by_phone_number(call_incoming_phone_number)

    if (client_name is None):
        res = '<?xml version="1.0" encoding="UTF-8"?><Response><Say language="en-US" loop="0">An error occurred. Your Twilio phone number {CallIncomingPhoneNumber} is invalid.</Say></Response>'
    else:
        res = '<?xml version="1.0\" encoding="UTF-8"?><Response><Dial timeout="60"><Client>{ClientName}</Client></Dial></Response>'


    strfmt = {"ClientName": client_name, "CallIncomingPhoneNumber": call_incoming_phone_number}

    return res.format(**strfmt)

Werfen wir einen Blick auf die von uns erstellte Lambda-Funktion.

Erstens gibt es die folgenden Elemente als Werte, die von der Umgebung abhängen. Schreiben Sie sie also neu.

def get_client_name_by_phone_number(phone_number):
    #Unterlassung

    if (phone_number_wo_hyphen == "+815031234567"):
        clientName = "DeviceId_0001"

Bitte geben Sie die Twilio-Telefonnummer an, die Sie beim Einrichten Ihres Twilio-Kontos erhalten haben. Ändern Sie den Kundennamen nach Ihren Wünschen. Es wird erwartet, dass diese Funktion get_client_name_by_phone_number in Zukunft eine DB-Verbindung herstellt und die Zuordnungsinformationen aus der DB abruft. Der Einfachheit halber haben wir derzeit eine Verknüpfung zwischen der Twilio-Telefonnummer und dem Kundennamen im Quellcode.

Der Verarbeitungsablauf ist wie folgt.

Bereitstellen

Diese Lambda-Funktion erfordert keine externe Bibliothek und kann über den Inline-Editor der AWS Management Console bereitgestellt werden. LambdaFunction_TwilioRetrieveTwimlCallIncoming_1.png

Ich denke, dass es standardmäßig kein Problem mit der Konfiguration gibt, solange die Handler-Einstellungen korrekt sind. Diese Lambda-Funktion verwendet keine anderen AWS-Services, daher kann die IAM-Rolle lambda_basic_execution sein. LambdaFunction_TwilioRetrieveTwimlCallIncoming_2.png

1-3. Implementieren Sie die TwiML-Rückgabe-API für ausgehende Anrufe als Lambda-Funktion

Schnittstelle (Eingabe / Ausgabe)

Details der Schnittstelle zwischen Twilio Server und API Server sind unten zusammengefasst. [Anruf vom Twilio-Client zum externen Telefon (ausgehender Anruf)](http://qiita.com/tmiki/items/fad1a22ba1fe14d32e34#twilio%E3%82%AF%E3%83%A9%E3%82%A4%E3% 82% A2% E3% 83% B3% E3% 83% 88% E3% 81% 8B% E3% 82% 89% E5% A4% 96% E9% 83% A8% E9% 9B% BB% E8% A9% B1% E3% 81% B8% E3% 81% AEcall ausgehend)

Ähnlich wie bei der TwiML-Rückgabe-API für eingehende Anrufe ist dies auch eine Methode zum Konvertieren von Eingaben in API-Gateway und zur Eingabe in die Lambda-Funktion sowie zum Zurückgeben von TwiML direkt von der Lambda-Funktion.

Lassen Sie API Gateway die HTTP-POST-Anforderung von Twilio Server übersetzen, und diese API erwartet den folgenden JSON.

Input


{
    "Direction": "inbound",
    "CallSid": "CA48nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
    "From": "client:DeviceId_0001",
    "Caller": "client:DeviceId_0001",
    "ApiVersion": "2010-04-01",
    "ApplicationSid": "APf7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "AccountSid": "AC3exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "CallStatus": "ringing",
    "callerPhoneNumber": "+81-50-3123-4567",
    "callOutgoingPhoneNumber": "+81-90-5987-6543"
}

Ich werde TwiML so wie es ist zurückgeben.

Output


<?xml version="1.0" encoding="UTF-8"?><Response><Dial timeout="60" callerId="+81-50-3123-4567"><Number>+81-90-5987-6543</Number></Dial></Response>

Implementierung

Schreiben wir nun die Lambda-Funktion.

TwilioRetrieveTwimlCallOutgoing.py


from __future__ import print_function
import json

print('Loading function')

def lambda_handler(event, context):
    ''' Returns a TwiML to enable a Twilio device to call a real phone.
    This function will be received the following parameters.

    {
        "callerPhoneNumber": "+81-50-3123-4567",
        "callOutgoingPhoneNumber": "+81-90-59876543"
    }
    '''

    print ("event: " + json.dumps(event))
    caller_phone_number = event.get("callerPhoneNumber")
    call_outgoing_phone_number = event.get("callOutgoingPhoneNumber")


    res = '<?xml version="1.0" encoding="UTF-8"?><Response><Dial timeout="60" callerId="{callerId}"><Number>{callOutgoingPhoneNumber}</Number></Dial></Response>'
    strfmt = {"callerId": caller_phone_number, "callOutgoingPhoneNumber": call_outgoing_phone_number}

    return res.format(**strfmt)

Diese Lambda-Funktion ist nur ein Prozess zum Generieren von TwiML basierend auf den als Eingabe übergebenen Parametern. Daher gibt es keinen Teil, der von der Umgebung abhängt.

Der Verarbeitungsablauf ist wie folgt.

Bereitstellen

Diese Lambda-Funktion erfordert keine externe Bibliothek und kann über den Inline-Editor der AWS Management Console bereitgestellt werden. LambdaFunction_TwilioRetrieveTwimlCallOutgoing_1.png

Ich denke, dass es standardmäßig kein Problem mit der Konfiguration gibt, solange die Handler-Einstellungen korrekt sind. Diese Lambda-Funktion verwendet keine anderen AWS-Services, daher kann die IAM-Rolle lambda_basic_execution sein. LambdaFunction_TwilioRetrieveTwimlCallOutgoing_2.png

Zusammenfassung

Die Implementierung der erforderlichen API ist oben abgeschlossen. Geben Sie die erforderlichen Parameter in JSON ein und überprüfen Sie, ob das beabsichtigte Ergebnis zurückgegeben wird. Sie können den Vorgang einfach über die AWS Management Console überprüfen. Das Format der Eingabe / Ausgabe wird zusammengefasst.

API-Name Input Output
Capability Token-Erfassungs-API JSON JSON
TwiML-Rückgabe-API für eingehende Anrufe JSON XML
TwiML-Rückgabe-API für ausgehende Anrufe JSON XML

2. API-Gateway-Einstellungen

2-1. Bei Verwendung von API Gateway

Das API-Gateway von AWS bietet nützliche Funktionen zum Implementieren von RESTful-APIs. Es gibt ein einzigartiges Konzept, also lasst es uns im Voraus unterdrücken.

Amazon API Gateway-Konzept https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-basic-concept.html

Die wichtigen Konzepte in dieser exemplarischen Vorgehensweise lauten wie folgt.

Ich glaube nicht, dass das obige Konzept nur durch das Lesen der Dokumentation in den Sinn kommt. Probieren Sie die folgenden Tutorials aus, um ein Gefühl für API Gateway zu bekommen und die Konzepte zu verstehen.

Beginnen Sie mit Amazon API Gateway https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/getting-started-intro.html

2-1. Erstellen Sie eine API über das Amazon API Gateway-Menü in der AWS Management Console

Öffnen Sie in der AWS Management Console die Amazon API Gateway Console (https://ap-northeast-1.console.aws.amazon.com/apigateway/home?region=ap-northeast-1#/apis).

Klicken Sie auf die Schaltfläche "APIs erstellen", um eine neue API-Gateway-API zu erstellen. Erstellen Sie es hier mit dem Namen "twilio_on_aws". Nach der Erstellung wird die API-Gateway-API zur Liste "APIs" hinzugefügt. APIGateway_Create_4.png

2-2. Definieren Sie Ressourcen für jede API

API-Gateway Sobald die API erstellt wurde, fügen wir die erforderlichen Ressourcen hinzu. Sie können sich das als Bestandteil der API Path of Resource ≒ vorstellen.

Erstellen Sie zunächst eine Ressource mit dem Namen "/ twilio". Wir werden die erforderlichen Ressourcen darunter hinzufügen, damit wir endlich die folgenden Pfade konfigurieren können. Der Ressourcenname und der Ressourcenpfad werden separat angegeben, aber ich glaube nicht, dass es sinnvoll ist, sie separat anzugeben. Machen Sie sie also gleich. Standardmäßig ist das Ressourcenpfadtrennzeichen "-", dies sollte jedoch "_" sein.

/twilio/retrieve_capability_token /twilio/retrieve_twiml/call_incoming /twilio/retrieve_twiml/call_outgoing

APIGateway_Resources_1.png

2-3. Methode für die CapabilityToken-Erfassungs-API definieren (/ twilio / retrieve_capability_token)

Wählen Sie / twilio / retrieve_capability_token und dann Aktionen> Methode erstellen. Wählen Sie "POST" als Methode. Da der Bildschirm zur Auswahl der Art der Implementierung angezeigt wird, mit der diese Methode verbunden werden soll, stellen Sie den Wert wie unten gezeigt ein und verknüpfen Sie ihn mit der zuvor erstellten Lambda-Funktion.

Artikelname Wert einstellen
Integration Type Lambda Function
Lambda Region ap-northeast-1
Lambda Function TwilioRetrieveCapabilityToken

APIGateway_retrieve_capability_token_1.png

Wenn Sie auf die Schaltfläche "Speichern" klicken, wird das Popup "Berechtigung zur Lambda-Funktion hinzufügen" angezeigt. Drücken Sie "OK". APIGateway_retrieve_capability_token_2.png

Dies bedeutet, dass die für jede Lambda-Funktion festgelegte "Lambda-Funktionsrichtlinie" geändert wurde. Die Berechtigung zum Ausführen der Lambda-Funktion "TwilioRetrieveCapabilityToken" wird von der Ressource "/ twilio / retrieve_capability_token" erteilt. Weitere Informationen zu Lambda-Funktionsrichtlinien finden Sie in den folgenden Dokumenten.

Verwenden Sie ressourcenbasierte Richtlinien mit AWS Lambda (Lambda-Funktionsrichtlinien). https://docs.aws.amazon.com/{ja_jp/lambda/latest/dg/access-control-resource-based.html

Damit ist die Implementierung der CapabilityToken-Erfassungs-API abgeschlossen.

Sie können die erstellten API-Gateway- und Lambda-Funktionen unter "TEST" testen. Führen Sie also die API aus, indem Sie die Standardeingabe angeben und bestätigen, dass das beabsichtigte Ergebnis zurückgegeben wird.

RequestBody


{
  "twilioPhoneNumber": "+81-50-1234-9876"
}

ResponseBody


{
  "success": true,
  "capabilityToken": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ...."
}

Zu diesem Zeitpunkt kann es nicht von anderen Hosts als RESTful-API aufgerufen werden. Die später beschriebene Bereitstellungsarbeit ist erforderlich.

2-4. Definieren Sie die Methode für die TwiML-Rückgabe-API (/ twilio / retrieve_twiml / call_incoming) für eingehende Anrufe

Wählen Sie / twilio / retrieve_twiml / call_incoming und wählen Sie Aktionen> Methode erstellen. Wählen Sie "POST" als Methode. Da der Bildschirm zur Auswahl der Art der Implementierung angezeigt wird, mit der diese Methode verbunden werden soll, stellen Sie den Wert wie unten gezeigt ein und verknüpfen Sie ihn mit der zuvor erstellten Lambda-Funktion.

Artikelname Wert einstellen
Integration Type Lambda Function
Lambda Region ap-northeast-1
Lambda Function TwilioRetrieveTwimlCallIncoming

APIGateway_retrieve_twiml_call_incoming_1.png

Wenn Sie auf die Schaltfläche "Speichern" klicken, wird das Popup "Berechtigung zur Lambda-Funktion hinzufügen" angezeigt. Drücken Sie "OK". Dies ändert auch die "Lambda-Funktionsrichtlinie" APIGateway_retrieve_twiml_call_incoming_2.png

Nachdem Sie die Ressource / Methode festgelegt haben, testen wir sie. Sie können von "TEST" testen. Geben Sie den folgenden JSON in Request Body an und testen Sie, ob das beabsichtigte TwiML zurückgegeben wird.

RequestBody


{
    "Caller": "+819059876543",
    "From": "+819059876543",
    "Called": "+815031234567",
    "To": "+815031234567"
}

ResponseBody


"<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response><Dial timeout=\"60\"><Client>DeviceId_0001</Client></Dial></Response>"

Zusätzlich zu der oben genannten Arbeit muss die diesmal erstellte API die folgenden zwei Dinge realisieren.

Stoppen Sie das Entkommen der automatischen Reaktion

Stoppen Sie zunächst die automatische Escape-Verarbeitung der Antwort. Dies wird in "Integrationsantwort" eingestellt. Öffnen Sie "Integrationsantwort", erweitern Sie "Methodenantwortstatus" auf 200 Zeilen und dann "Body Mapping-Vorlagen". Standardmäßig ist "application / json" angegeben. Drücken Sie daher die Taste "-", um es zu entfernen. APIGateway_retrieve_twiml_call_incoming_3.png

Klicken Sie anschließend auf die Schaltfläche "+" unter "Zuordnungsvorlage hinzufügen" und fügen Sie "application / xml" als Inhaltstyp hinzu. Gleichzeitig können Sie den Inhalt von "Body Mapping-Vorlagen" angeben. Geben Sie also eine Zeile darunter an und klicken Sie auf die Schaltfläche "Speichern".

$input.path('$')

APIGateway_retrieve_twiml_call_incoming_4.png

Testen wir die Methode mit derselben Anforderung wie zuvor und überprüfen den Inhalt der Antwort. Das "" "wurde entfernt, um ein wohlgeformtes XML zu erstellen.

ResponseBody


<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial timeout="60"><Client>DeviceId_0001</Client></Dial>
</Response>

Eingabe in API konvertieren (Schlüssel konvertieren = Wertepaar durch "&" in JSON getrennt)

Die von Twilio Server übergebenen Parameter sind nicht JSON, sondern Schlüssel = Wert-Paare wie GET-Parameter. Um dies zu konvertieren, muss in "Integrationsanforderung" "Body Mapping Template" definiert werden.

Öffnen Sie die Integrationsanforderung und erweitern Sie Body Mapping-Vorlagen. Aktivieren Sie "Wir wissen, dass keine Vorlagen definiert sind (empfohlen)" unter "Textdurchgang anfordern". Klicken Sie auf die Schaltfläche "+" unter "Zuordnungsvorlage hinzufügen", um "application / x-www-form-urlencoded" hinzuzufügen. APIGateway_retrieve_twiml_call_incoming_6.png

Fügen Sie den folgenden Inhalt als "Body Mapping-Vorlage" ein und klicken Sie auf "Speichern".

#set($raw_input = $input.path("$"))

{
  #foreach( $kvpairs in $raw_input.split( '&' ) )
    #set( $kvpair = $kvpairs.split( '=' ) )
      #if($kvpair.length == 2)
        "$kvpair[0]" : "$kvpair[1]"#if( $foreach.hasNext ),#end
      #end
  #end
}

APIGateway_retrieve_twiml_call_incoming_7.png

Die Details der Zuordnungsvorlage werden im folgenden Artikel zusammengefasst. Bitte beziehen Sie sich bei Bedarf darauf.

Konvertieren von Zeichenfolgen wie GET-Abfrageparametern in JSON mit API Gateway Mapping Template

Ich möchte nach dem Einstellen testen, kann aber die Anforderungsparameter nicht angeben und es scheint, dass ich nicht gut testen kann. APIGateway_retrieve_twiml_call_incoming_8.png

Überprüfen Sie daher den Vorgang nach der Bereitstellung. Führen Sie vor dem Erstellen der TwiML-Rückgabe-API für ausgehende Anrufe die Aufgaben 2-7 und 2-8 aus und überprüfen Sie den Vorgang.

2-5. Definieren Sie die Methode für die TwiML-Rückgabe-API (/ twilio / retrieve_twiml / call_outgoing) für ausgehende Anrufe

Wählen Sie twilio / retrieve_twiml / call_outgoing und wählen Sie Aktionen> Methode erstellen. Wählen Sie "POST" als Methode. Da der Bildschirm zur Auswahl der Art der Implementierung angezeigt wird, mit der diese Methode verbunden werden soll, stellen Sie den Wert wie unten gezeigt ein und verknüpfen Sie ihn mit der zuvor erstellten Lambda-Funktion. APIGateway_retrieve_twiml_call_outgoing_2.png

Artikelname Wert einstellen
Integration Type Lambda Function
Lambda Region ap-northeast-1
Lambda Function TwilioRetrieveTwimlCallOutgoing

Wenn Sie auf die Schaltfläche "Speichern" klicken, wird das Popup "Berechtigung zur Lambda-Funktion hinzufügen" angezeigt. Drücken Sie "OK". Dies ändert auch die "Lambda-Funktionsrichtlinie" APIGateway_retrieve_twiml_call_outgoing_2.png

Nachdem Sie die Ressource / Methode festgelegt haben, testen wir sie. Sie können von "TEST" testen. Geben Sie den folgenden JSON in Request Body an und testen Sie, ob das beabsichtigte TwiML zurückgegeben wird.

RequestBody


{
    "callerPhoneNumber": "+81-50-3123-4567",
    "callOutgoingPhoneNumber": "+81-90-5987-6543"
}

ResponseBody


"<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response><Dial timeout=\"60\" callerId=\"+81-50-3123-4567\"><Number>+81-90-5987-6543</Number></Dial></Response>"

Ähnlich wie die TwiML-Rückgabe-API für eingehende Anrufe muss diese API zusätzlich zu der oben genannten Arbeit die folgenden zwei Dinge erreichen.

Stoppen Sie das Entkommen der automatischen Reaktion

Stoppen Sie zunächst die automatische Escape-Verarbeitung der Antwort. Dies wird in "Integrationsantwort" eingestellt. Öffnen Sie "Integrationsantwort", erweitern Sie "Methodenantwortstatus" auf 200 Zeilen und dann "Body Mapping-Vorlagen". Standardmäßig ist "application / json" angegeben. Drücken Sie daher die Taste "-", um es zu entfernen. APIGateway_retrieve_twiml_call_outgoing_3.png

Klicken Sie anschließend auf die Schaltfläche "+" unter "Zuordnungsvorlage hinzufügen" und fügen Sie "application / xml" als Inhaltstyp hinzu. Gleichzeitig können Sie den Inhalt von "Body Mapping-Vorlagen" angeben. Geben Sie also eine Zeile darunter an und klicken Sie auf die Schaltfläche "Speichern".

$input.path('$')

APIGateway_retrieve_twiml_call_outgoing_4.png

Testen wir die Methode mit derselben Anforderung wie zuvor und überprüfen den Inhalt der Antwort. Das "" "wurde entfernt, um ein wohlgeformtes XML zu erstellen.

ResponseBody


<?xml version="1.0" encoding="UTF-8"?><Response><Dial timeout="60" callerId="+81-50-3123-4567"><Number>+81-90-5987-6543</Number></Dial></Response>

Eingabe in API konvertieren (Schlüssel konvertieren = Wertepaar durch "&" in JSON getrennt)

Die von Twilio Server übergebenen Parameter sind nicht JSON, sondern Schlüssel = Wert-Paare wie GET-Parameter. Um dies zu konvertieren, muss in "Integrationsanforderung" "Body Mapping Template" definiert werden.

Öffnen Sie die Integrationsanforderung und erweitern Sie Body Mapping-Vorlagen. Aktivieren Sie "Wir wissen, dass keine Vorlagen definiert sind (empfohlen)" unter "Textdurchgang anfordern". Klicken Sie auf die Schaltfläche "+" unter "Zuordnungsvorlage hinzufügen", um "application / x-www-form-urlencoded" hinzuzufügen. APIGateway_retrieve_twiml_call_outgoing_6.png

Fügen Sie den folgenden Inhalt als "Body Mapping-Vorlage" ein und klicken Sie auf "Speichern".

#set($raw_input = $input.path("$"))

{
  #foreach( $kvpairs in $raw_input.split( '&' ) )
    #set( $kvpair = $kvpairs.split( '=' ) )
      #if($kvpair.length == 2)
        "$kvpair[0]" : "$kvpair[1]"#if( $foreach.hasNext ),#end
      #end
  #end
}

APIGateway_retrieve_twiml_call_outgoing_7.png

Die Details der Zuordnungsvorlage werden im folgenden Artikel zusammengefasst. Bitte beziehen Sie sich bei Bedarf darauf.

Konvertieren von Zeichenfolgen wie GET-Abfrageparametern in JSON mit API Gateway Mapping Template

Ich möchte nach dem Einstellen testen, kann aber die Anforderungsparameter nicht angeben und es scheint, dass ich nicht gut testen kann. APIGateway_retrieve_twiml_call_outgoing_8.png

Überprüfen Sie daher den Vorgang nach der Bereitstellung. Führen Sie zuerst die Schritte 2-7 und 2-8 aus, um den Betrieb zu überprüfen.

2-6 CORS einstellen

Stellen Sie nach dem Erstellen der Methode jede Ressource so ein, dass CORS (Cross Origin Resource Sharing) zulässig ist. Dies ist eine Spezifikation, die auf in JavaScript implementierte Webbrowser-Apps angewendet wird und API-Aufrufe domänenübergreifend zulässt / verweigert. Der diesmal implementierte Twilio-Client wird von https://twilio-on-aws-us.s3.amazonaws.com bereitgestellt, der Domäne von S3 in HTML. Die API wird jedoch in der Domäne für das API-Gateway bereitgestellt, z. B. https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/. Daher muss die API, die Sie gerade erstellen, mit CORS konfiguriert werden, um API-Aufrufe aus dem Inhalt der S3-Domäne zuzulassen.

Auf den folgenden Websites finden Sie eine ausführliche Erläuterung von CORS.

HTTP-Zugriffskontrolle (CORS) https://developer.mozilla.org/ja/docs/Web/HTTP/HTTP_access_control

Ursprünglich ist es erforderlich, einen einzelnen Domänennamen anzugeben, von dem aus Domäneninhalte die API aufrufen können. Diese exemplarische Vorgehensweise steuert jedoch nicht so viel und ermöglicht API-Aufrufe von allen Domänen.

Die Einstellung ist in diesem Fall einfach. Wählen Sie bei ausgewählter Zielressource unter "Aktionen" "CORS aktivieren" aus. Sie können die hinzuzufügenden Header anpassen, klicken Sie jedoch einfach auf die Schaltfläche "CORS aktivieren und vorhandene CORS-Header ersetzen". APIGateway_CORS_1.png

Ein Bestätigungsfenster wird angezeigt. Klicken Sie einfach auf die Schaltfläche "Ja, vorhandene Werte ersetzen". APIGateway_CORS_2.png

"OPTIONEN" wurde zur Methode hinzugefügt. Wenn Sie die Einstellungen "Integrationsantwort" und "Methodenantwort" überprüfen, können Sie sehen, dass die CORS-Einstellungen hinzugefügt wurden.

APIGateway_CORS_3.png APIGateway_CORS_4.png

Nehmen Sie für alle Ressourcen, die die API bereitstellen, dieselben Einstellungen vor.

2-7. Prod Erstellen Sie eine Bühne und stellen Sie sie bereit

Stellen Sie die erforderliche Ressource / Methode nach dem Definieren bereit, damit sie von außen aufgerufen werden kann. Wählen Sie zunächst "API bereitstellen" unter "Aktionen" aus. Anfangs ist Stage nicht definiert. Wählen Sie unter [Bereitstellungsphase] die Option [Neue Phase]. Stellen Sie jeden Wert wie unten gezeigt ein und klicken Sie auf die Schaltfläche "Bereitstellen".

Artikelname Wert einstellen
Stage name* prod
Stage description ※Irgendein. Hier heißt es Produktionsumgebung.
Deployment description ※Irgendein. Hier heißt es Erstveröffentlichung.

APIGateway_Deploy_1.png

Nach der Bereitstellung können Sie die erstellte Phase unter "APIs" -> "API-Name" -> "Stufen" im linken Bereich überprüfen. "URL aufrufen" ist die URL, die von außen verwendet werden kann. APIGateway_Deploy_2.png

Wenn Sie den Stufennamen erweitern, können Sie sehen, dass die bisher erstellten Ressourcen / Methoden so zugeordnet sind, wie sie sind. Es ist notwendig, den Vorgang zu überprüfen. Überprüfen wir daher die spezifische Aufruf-URL jeder API. APIGateway_Deploy_3.png

2-8 Überprüfen Sie den Betrieb jeder API

Überprüfen Sie die Funktion mit Curl. Lassen Sie uns im Voraus eine Linux-Instanz erstellen. Beachten Sie, dass Curl detaillierte Informationen ausgeben kann, indem Sie die Option "-v" angeben. Wenn es nicht funktioniert, verwenden Sie die Option "-v" zur Fehlerbehebung.

Capability Token-Erfassungs-API

Führen Sie den folgenden Befehl unter Linux aus.

$ curl -v -H "Content-type: application/json" -X POST -d '{"twilioPhoneNumber": "+81-50-3123-4567"}' https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/twilio/retrieve_capability_token

#Bestätigen Sie, dass die Standardantwort zurückgegeben wird.
{"success": true, "capabilityToken": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9....."}

TwiML-Rückgabe-API für eingehende Anrufe

Führen Sie den folgenden Befehl unter Linux aus. Der Hauptteil der POST-Anforderung ist [HTTP-POST-Anforderung von Twilio Server während eines eingehenden Anrufs](http://qiita.com/tmiki/items/fad1a22ba1fe14d32e34#twilio-server%E3%81%8B%E3%82%89% E3% 81% AE http-post% E3% 83% AA% E3% 82% AF% E3% 82% A8% E3% 82% B9% E3% 83% 88) Geben Sie den gleichen Inhalt an.

curl -v -H "Content-type: application/x-www-form-urlencoded; charset=UTF-8" -X POST -d 'ApplicationSid=AP75zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz&ApiVersion=2010-04-01&Called=&Caller=%2B819059876543&CallStatus=ringing&CallSid=CCA86nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn&To=%2B815031234567&From=%2B819059876543&Direction=inbound&AccountSid=AC3exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/twilio/retrieve_twiml/call_incoming

#Bestätigen Sie, dass die Standardantwort zurückgegeben wird.
<?xml version="1.0" encoding="UTF-8"?><Response><Dial timeout="60"><Client>DeviceId_0001</Client></Dial></Response>

TwiML-Rückgabe-API für ausgehende Anrufe

Führen Sie den folgenden Befehl unter Linux aus. Der Hauptteil der POST-Anforderung ist HTTP-POST-Anforderung von Twilio Server während eines ausgehenden Anrufs E3% 81% AE http-post% E3% 83% AA% E3% 82% AF% E3% 82% A8% E3% 82% B9% E3% 83% 88-1) Geben Sie den gleichen Inhalt an.

curl -v -H "Content-type: application/x-www-form-urlencoded; charset=UTF-8" -X POST -d 'AccountSid=AC3exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&ApiVersion=2010-04-01&ApplicationSid=AP75zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz&Called=&Caller=client%3ADeviceId_0001&CallSid=CA06nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn&CallStatus=ringing&Direction=inbound&From=client%3ADeviceId_0001&To=&callerPhoneNumber=%2B81-50-3123-4567&callOutgoingPhoneNumber=%2B81-90-5987-6543' https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/twilio/retrieve_twiml/call_outgoing

#Bestätigen Sie, dass die Standardantwort zurückgegeben wird.
<?xml version="1.0" encoding="UTF-8"?><Response><Dial timeout="60" callerId="+81-50-3123-4567"><Number>+81-90-5987-6543</Number></Dial></Response>

Damit ist die Implementierung auf der API-Serverseite abgeschlossen. Wir werden den Twilio Client ab dem nächsten implementieren.

Recommended Posts

Verständnis anhand des Mechanismus Twilio # 3-1 --AWS API Gateway + Lambda-Implementierung Walkthrough (Teil 1)
Die einfachste AWS Lambda-Implementierung
[AWS] API mit API Gateway + Lambda erstellen
[AWS SAM] Erstellen Sie eine API mit DynamoDB + Lambda + API Gateway
LINE BOT mit Python + AWS Lambda + API Gateway
[AWS] Versuchen Sie, API Gateway + Lambda mit X-Ray zu verfolgen
Amazon API Gateway und AWS Lambda Python-Version
Tweet von AWS Lambda
Erstellen Sie mit AWS SAM schnell eine API mit Python, Lambda und API Gateway
AWS CDK-Lambda + API-Gateway (Python)
Senden Sie mit ESP32-WROOM-32 aufgenommene Bilder an AWS (API Gateway → Lambda → S3).
[Python] Ich habe eine REST-API mit AWS API Gateway und Lambda geschrieben.