Laravel ve Nexmo ile Etkileşimli Sesli Yanıt Sistemi Oluşturma
Laravel uygulamasını aramak ve sizinle konuşmasını ister misiniz? Laravel ve Nexmo ile "telefon menüsü" olan gerçekten basit bir IVR (etkileşimli sesli yanıt) oluşturma konusuna hızlı bir göz atalım. İşiniz bittiğinde, cep telefonunuzu alıp bir telefon numarası arayıp Laravel uygulamasının duyduğunuz şeyleri kontrol edebileceksiniz.
Düşündüğünüzden muhtemelen daha kolaydır, başlayalım!
Kurulum
İlk önce, Composer'ı kullanarak standart Laravel kurulumuyla kurulum alacağız. Laradock kullanarak bunları bir araya getiriyorum , bu yüzden öncelikle konteynerlerdenbash
birinde çalışmak için bir işleme başlamalıyım:
$docker-compose exec --user=laradock workspace bash
Bu beni proje dizinime götürür, bu yüzden burada yeni bir Laravel projesi oluşturacağım. workspace
Konteyner besteci zaten yüklüdür. Laradock kullanmıyorsanız, geliştirme sisteminize besteci yüklemeniz gerekir:
$composer create-project laravel/laravel laravel-hotline
Oldukça güzel bir vanilidir, ancak bu noktada kodu inceleyebilirsiniz . Orada çok şey göremiyorum, bu yüzden Nexmo paketlerini ekleyelim:
$composer require nexmo/laravel
Ve bu nedenle telefon hattımız ilginç bir şeyler yapabilir, iki bağımlılık daha ekleyeceğiz. SimplePie, RSS yayınlarını ve bir Twitter istemcisini çözümleyebiliyoruz, böylece bir Tweet çekebiliyoruz.
$composer require simplepie/simplepie
$composer require thujohn/twitter
Tüm kütüphaneler kurulduktan sonra servis sağlayıcıları konfigürasyonumuza ekleyebiliriz. Bu iki satırı aşağıdaki providers
bölümün içine yerleştirin config/app.php
:
'providers' => [
//...
Nexmo\Laravel\NexmoServiceProvider::class,
Thujohn\Twitter\TwitterServiceProvider::class,
],
Ayrıca iki Facade takma adını aynı dosyaya ekleyebiliriz:
'aliases' => [
//...
'Nexmo' => Nexmo\Laravel\Facade\Nexmo::class,
'Twitter' => Thujohn\Twitter\Facades\Twitter::class,
]
Son adım yapılandırma dosyalarını üretmek ve düzenlemektir. Nexmo ve Twitter için yapılandırma dosyaları oluşturmak için, projenin kökünden şu komutu çalıştırın:
$php artisan vendor:publish
Sonra config/nexmo.php
Nexmo anahtarınızı ve sırrınızı düzenleyip ekleyin. Elinde yok mu? Nexmo.com adresinden ücretsiz üye olabilirsiniz . Kimlik bilgilerini config/ttwitter.php
de eklemek zorunda kalacaksınız . O yoksa, sından Twitter'ın uygulama yönetimi sayfasına ve yeni bir uygulama oluşturun.
Yapılandırma dosyalarını düzenlemek yerine, yalnızca kimlik bilgilerini dosyanıza ekleyebilirsiniz .env
. Ayrıntılar için Nexmo ve Twitter istemci readmes bölümüne göz atın.
İsterseniz, kurulumu atlayabilir ve bu noktada kodu kaldırabilirsiniz.
Bir Nexmo Uygulaması Oluşturma
Web isteğini uygulamanıza yönlendirmek gibi, sunucumuzun IP adresini gösteren bir alan adı gerektirir; yönlendirme telefonları, kodumuzun dışındaki bazı yapılandırmaları gerektirir. Nexmo, bu yapılandırmayı 'Uygulamalar' için bir API ile yönetir .
Bir Uygulama, bir dizi web kancası tanımlamamıza, bir telefon numarası eklememize ve kimlik bilgilerini saklamamıza izin veren yapılandırma için bir kapsayıcıdır. Webhook'lar, bir şey olduğunda, Nexmo'nun gelen bir telefon çağrısı gibi istekte bulunabileceği belirli URL'lerdir. Telefon numaraları Nexmo'dan gelir ve hesabımızda bir tane bulduktan sonra onu uygulamaya ekleyebiliriz.
Bir uygulama oluşturup bir telefon numarası eklediğinizde, sık gerçekleşen veya bir web isteği tarafından tetiklenmesi gereken görevler değildir (en azından uygulamalarımız için), bir Esnaf komutası için mükemmel hedeflerdir .
AppCreate Komutu
Yeni komutumuzun yapısını oluşturmak için mevcut Artisan komutunu kullanacağız :
php artisan make:command AppCreate
Temel yapı oluşturulduktan sonra (onu buluruz /app/Console/Commands/AppCreate.php
) yapıcıyı, daha önce besteci ile birlikte dahil ettiğimiz Nexmo PHP İstemcisini vermek üzere güncelleştirebiliriz .
<?php
namespace App\Console\Commands;
use Nexmo\Client;
//...
protected $client;
public function __construct(Client $client)
{
$this->client = $client;
parent::__construct();
}
Komutların açıklamasını da güncellememiz gerekiyor ve imzası var. Bu, --help
yararlı olmasını sağlayacak ve komutun verileceğini beklediğimiz argümanları tanımlayacaktır. $description
Oldukça nettir:
protected $description = 'Create a new Nexmo Application';
protected $signature = 'nexmo:app:create {name} {answer_url} {event_url} {--type=voice} {--answer_method} {--event_method} {--keyfile=nexmo.key}';
Bu $signature
biraz daha karmaşık. Biz o tanımlayarak işe başlamak nexmo:app:create
biz komut diyoruz nasıl olacak. Sonra bir uygulama bekleyeceğiz {name}
. Bundan sonra, iki web kancasına ihtiyacımız var. Yeni gelen bir çağrı answer_url
olduğunda kullanılacak web kancası, adlı olarak adlandırılır ve herhangi bir çağrı ile ilgili olay için (asılan bir çağrı gibi) kullanılacak web kancasıdır event_url
.
İsteğe bağlı olarak, bir uygulamanın ayarlanmasına izin vereceğiz --type
(ancak şu anda API, yalnızca voice
uygulamaları desteklemektedir) ve web kanca HTTP yöntemlerinin ayarlanmasına izin veriyoruz. Varsayılan olarak, kullanılan yöntem answer_url
, bir olduğunu GET
ve kullandığı yöntem event_url
bir olduğunu POST
.
Son olarak, bir uygulama oluşturulduğunda API yanıtında özel bir anahtar gönderilir. Bu sadece bir uygulamanın oluşturulması için sağlanır, bu nedenle bir yere kaydedilmesi gerekir. --keyfile
Nerede olduğunu belirtmeme izin vereceğiz; Ancak, varsayılan olarak içinde saklanır nexmo.key
.
Bu bağımsız değişken kümesi ve sırası , yalnızca bir uygulama oluşturmaktan çok daha fazlasını yapan Nexmo CLI aracındaki aynı komutun koşulu ve sırasını izler . Açıkçası, bir Esnaf komutunun yerine kullanılabilir, ancak bu bize PHP İstemcisi'ni kullanarak yeni bir Uygulama oluşturmak ne kadar kolay olduğunu görmek için bir şans verir.
Komutumuzu tanımladıkça, kodu handle()
komuta yazalım . PHP İstemcisi akıcı bir şekilde bir Uygulama oluşturmamıza izin verir, ancak netlik uğruna bunu birkaç satırlık kodla oluşturacağız. Yeni Application
bir VoiceConfig
tane oluşturacağız ve webhooks'la yeni bir tane geçeceğiz:
<?php
namespace App\Console\Commands;
use Nexmo\Client;
use Nexmo\Application\Application;
use Nexmo\Application\VoiceConfig;
//...
public function handle()
{
$application = new Application();
$application->setName($this->argument('name'));
$config = new VoiceConfig();
$config->setWebhook(VoiceConfig::ANSWER, $this->argument('answer_url'), $this->option('answer_method'));
$config->setWebhook(VoiceConfig::EVENT, $this->argument('event_url'), $this->option('event_method'));
$application->setVoiceConfig($config);
//...
Uygulama yapılandırıldıktan sonra handle()
yöntemi bitirip API yapabiliriz . API çağrısı başarısız olabileceğinden (geçersiz kimlik bilgileri, kötü bir ağ bağlantısı, vb.), Aramayı bir try
blokta sararız . Ayrıca, ilerlememizi kullanıcıya bildireceğiz ve başarıyla, Başvuruya atıf yapmak için daha sonra kullanılabilecek olan Uygulama Kimliği'ni sağlayacağız.
//...
try {
$this->info('Making API Request');
$application = $this->client->applications()->post($application);
file_put_contents($this->option('keyfile'), $application->getPrivateKey());
$this->info('Key Saved To: ' . realpath($this->option('keyfile')));
$this->info('Created Application: ' . $application->getId());
} catch (\Exception $e) {
$this->error('Request Failed: ' . $e->getMessage());
$this->error($e->getTraceAsString(), \Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG);
}
} //end of handle()
API isteği başarısız olursa, kullanıcıyı bilgilendiririz ve istekte bulunsalar - yığın izlemeyi ekleyin.
Komut işlemi yapılırken onu $commands
dizindeki dizine eklemeliyiz app/Console/Kernel.php
.
protected $commands = [
//...
\App\Console\Commands\AppCreate::class
];
Şimdi tek yapmamız gereken buyruğu çalıştırıp uygulamanızı yaratmaktır:
$php artisan nexmo:app:create Laravel-Hotline \
http://tjlytle.ngrok.io/nexmo/answer \
http://tjlytle.ngrok.io/nexmo/event
Making API Request
Key Saved To: /var/www/nexmo.key
Created Application: e2de8f00-0400-4475-89c9-a9c4fde5f40d
Bu noktada
localhost
, uygulamanın çalıştığı yerin muhtemel olmasına rağmen, web kuyruklarında referans olmadığımızı fark edeceksiniz. Nexmo'nun gelen çağrı web kancasını uygulamaya göndermek için URL'nin harici olarak erişilebilir olması gerekir. Daha önce kullanmadıysanız , ngrok , halka açık internet ortamında yerel bir geliştirme ortamı erişilebilir kılmak için mükemmel bir çözümdür.
Bağlantı Uygulama Komutu
Şimdi, Laravel Yardım Hattına işaret eden web kuyruklu bir Nexmo Uygulamamız var, ancak bu Uygulama telefon numarası olmadan çağrılamıyor. Numaralar Nexmo gösterge tablosunu kullanarak, Nexmo CLI aracıyla veya bir API çağrısıyla edinilebilir.
Yeni bir Nexmo hesabı oluşturduysanız, kontrol panelinizde bir test numarası olabilir. Değilse, giriş yapın ve birini bulun .
Numaralarınızdan birini, Uygulama Kimliği'ni kullanarak yeni Başvurunuza bağlayabilirsiniz; Bununla birlikte, API ile bağlayabilirsiniz, bu yüzden bunu yapmak için başka bir Artisan komutu oluşturalım:
php artisan make:command LinkApp
CreateApp
Komut gibi, komutun kurucusunu Nexmo PHP İstemcisini enjekte edecek şekilde güncelleyeceğiz. $signature
Bu sefer çok daha basittir ve benzeri CreateApp
o Nexmo CLI aracında kardeş komutu ile aynı formatı aşağıdaki gibidir:
protected $description = 'Link a Number to an Application';
protected $signature = 'nexmo:link:app {number} {app}';
Komut, yalnızca iki bağımsız değişkeni, telefon numarasının bağlanmasını ve bağlantılandırılması gereken uygulamayı beklemektedir. handle()
İlişkiyi kurmak için yöntemin birkaç satırını ekleyeceğiz:
<?php
namespace App\Console\Commands;
use Nexmo\Client;
use Nexmo\Application\Application;
use Nexmo\Numbers\Number;
//...
public function handle()
{
$application = new Application($this->argument('app'));
$number = new Number($this->argument('number'));
$number->setVoiceDestination($application);
//...
Gördüğünüz gibi, bir Application
uygulama kimliğiyle oluşturulabilir ve bu API eşleştirme Uygulamasını başvurmak gerekir. Aynı şey a Number
için de geçerlidir, eğer telefon numarası bir kimlik numarası ile oluşturulduysa, Nexmo hesabınızda aynı numaraya referans verecektir.
İki kaynağı bulduktan sonra, numarayı herhangi bir sesli çağrı için uygulamayı kullanacak şekilde yapılandırabiliriz.
Gibi CreateApp
bir API çağrısı sarmak edeceğiz try
bloğun yüzden hataları yakalamak ve kullanıcıyı bilgilendirebilir:
//...
try{
$this->info('Making API Request');
$this->client->numbers()->update($number);
$this->info('Linked Number to Application');
} catch (\Exception $e) {
$this->error('Request Failed: ' . $e->getMessage());
$this->error($e->getTraceAsString(), \Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG);
}
} //end of handle()
Ekleyerek komutu Kayıt $commands
yanında dizideki AppCreate
içinde app/Console/Kernel.php
.
protected $commands = [
//...
\App\Console\Commands\AppCreate::class,
\App\Console\Commands\LinkApp::class
];
Sonra bir spin verin (elbette Nexmo numaranızla birlikte):
$php artisan -vvv nexmo:link:app 14045559404 e2de8f00-0400-4475-89c9-a9c4fde5f40d
Making API Request
Linked Number to Application
Certianly hepsi Nexmo CLI aracı birkaç komutları ile yapılmış olabilir; Bununla birlikte, SaaS benzeri bir ürün oluşturuyorsanız, uygulamalarınızı otomatik olarak sağlama ve numaraları bağlama, uygulamanızda yapmak istediğiniz bir şeydir. Birkaç kod satırı ile yapmak kolaydır.
Sadece okuyor musun? Sen edebilirsiniz kodunu görmek de bu noktada.
Telefon Almak
Telefonunuzun kilidini açmadan ve uygulamanızı aramadan önce, tanımladığımız web kancalarının arkasına bazı kodlar koymamız gerekir.
Webhooks Hakkında Biraz
Uygulama numaramıza bir çağrı yapıldığında Nexmo, bir HTTP isteği yapacak /nexmo/answer
ve HTTP yanıtının geçerli bir NCCO (Nexmo çağrı kontrolü nesnesi) yığınının JSON yapısı olacağını bekleyecektir. Bu yığın, aramada neler olacağını tanımlar. Örneğin, "Laravel Yardım Hattı'na hoş geldiniz" diyerek veya kullanıcının telefonunda bir numaraya basarak yakalamasını söyleyerek.
Bir NCCO, hangi URL'nin sonraki web kancasını alması gerektiğini de tanımlayabilir. Bir input
kullanıcının tuşlarını NCCO kullanarak yakaladığımızda, HTML'nin olduğu gibi , verilerin gönderildiği URL'yi de tanımlıyoruz <form>
.
Nexmo Belgeleri, NCCO'lar hakkında bilmeniz gereken her şeye sahiptir .
Tanımladığımız diğer web kancasıydı /nexmo/event
. Nexmo, bir çağrı değiştiğinde her URL'ye bir HTTP isteği yapacaktır. Örneğin, uygulamanızın numarasına gelen bir çağrı, çağrı olduğunda bir web kancasına, çağrı başvurumuza göre ringing
başka bir çağrıya neden answered
olur. Bu web kuyrukları, arama durumunu izlememizi sağlar.
Rotaları Yapılandırma
Varsayılan olarak, Laravel normal rota için CSRF katmanını ekler (iyi bir şey). Defaul tarafından Nexmo, bir NCCO'ya herhangi bir kullanıcı girdisinin yanı sıra etkinlik webhook'larını POST
da (iyi bir şey olarak) gönderir .
CSFR katmanını düzenlemeyle kaldırabiliriz app/Http/Kernel.php
, ancak hem web arayüzü hem de sesli arayüzü olan bir uygulama oluşturuyorsak bunu yapmamamız gerekir.
Ayrıca katman yazılımının kendisine bir URI istisnası da ekleyebiliriz ve bu URL'lerin tümünün öneki /nexmo
olarak yalnızca bir satır alacağız:
protected $except = [
'nexmo/*',
];
Bunun yerine, tüm Nexmo rotaları için yeni bir katman grubu oluşturalım. Burada app/Providers/RouteServiceProvider.php
mevcut API eşleme yöntemine benzeyen bir yöntem ekleyeceğiz:
protected function mapNexmoRoutes()
{
Route::prefix('nexmo')
->middleware('bindings')
->namespace($this->namespace)
->group(base_path('routes/nexmo.php'));
}
Ve bu yöntemi şu adresten arayın map()
:
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
$this->mapNexmoRoutes();
}
Şimdi bulunan herhangi bir routes/nexmo.php
güzergahta CSRF katmanının yanı sıra diğer weble ilgili katmanlar da olmayacaktır. Ve tanımlanan herhangi rotalar routes/nexmo.php
tarafından öneki /nexmo
böylece işlemek için, /nexmo/answer
webhook, sadece bir rota tanımlamak /answer
.
En yaratalım routes/nexmo.php
ve basit bir yol tanımlar:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
//simple hello world
Route::get('/answer', function (Request $request) {
return [
[
'action' => 'talk',
'text' => 'Welcome to the Laravel Hotline'
]
];
});
//just log the events so we can inspect the data
Route::post('/event', function (Request $request) {
error_log($request->getContent());
return;
});
Kadar basit! Laravel, bir dizi json_encode
veri döndürdüğümüzü göreceğiz ve verileri doğru ayarladık content/type
. Devam edin, arayın ve kendiniz görün.
Uygulamayı oluştururken belirttiğimiz gibi, Nexmo için webhook'ları yapacak
/nexmo/answer
ve/nexmo/event
uygulama, uygulama oluştururken kullanılan alan adında kamuya açık internette erişilebilir olmalıdır. Bu web kancalarını güncellemeniz gerekiyorsa , API çağrısı veya Nexmo CLI komutu kadar kolaydır .
Bu noktada kodu kontrol ederek bir dönme için bunu alın .
Bir Kontrol Ünitesi Yapmak
routes/nexmo.php
NCCO'nun sağına koymak, her şeyin harekete geçtiğini görmek için hızlı bir yol olmakla birlikte, sesli isteklerimizi yerine getirmek için uygun bir IVR kontrolörü oluşturmamız gerekir. Rotamızı bir denetleyiciye işaret edecek şekilde güncelleyelim:
Route::get ('/answer', 'IvrController@answer')->name('ivr.answer');
Route::post('/menu', 'IvrController@menu' )->name('ivr.menu');
/menu
Tebrikten sonra kullanıcı girdilerini işlemek için yeni bir rota ekledik . Ayrıca, daha sonra URL'ler üretebilmemiz için rotaları adlandırdık. Artisan'ı yeni bir kontrolör oluşturmak için kullanalım:
$php artisan make:controller IvrController
Açacağız /app/Http/Controllers/IvrController.php
ve answer
gelen aramaları cevaplayacak yöntemi ekleyeceğiz. Bu, bir selamlama olarak daha önce kullandığımız basit NCCO'yı alacak ve yığına iki tane daha NCCO ekleyecek:
public function answer(Request $request)
{
return [
[
'action' => 'talk',
'text' => 'Welcome to the Laravel Hotline'
],
[
'action' => 'talk',
'text' => "Press 1 to hear Taylor's latest tweet. Press 2 to listen to the latest Laravel Podcast",
'bargeIn' => true
],
[
'action' => 'input',
'eventUrl' => [route('ivr.menu')],
'maxDigits' => 1
]
];
}
İlk NCCO tam olarak daha önce kullandığımız şey. İkincisi de bir talk
, ama bargeIn
çağrıda bulunulan kişinin herhangi bir zamanda basamağa basmasını sağlayan bayrak ekledik . İlk beri talk
yok bargeIn
, metin kullanıcı bir tuşa basıldığında bile oynamaya devam edecektir.
Son NCCO kullanıcı girdisini yakalar ve sonuçları bir ivr.menu
route ( /nexmo/menu
) olarak a olarak gönderir POST
. Şimdi bu basit yöntemi oluşturalım ( menu()
şimdi:
public function menu(Request $request)
{
switch ($request->json('dtmf')){
case '1';
return $this->tweet($request);
case '2':
return $this->podcast($request);
default:
return $this->answer($request);
}
}
Bu basit switch
, geçerli seçenekler arar ve hiçbiri bulunmazsa menü tekrarlanır. Kullanıcı bir çevirdiğinde 1
NCCO tarafından oluşturulan her türlü biz dönüşünü tweet()
ve için 2
biz NCCO tarafından oluşturulan kullanın podcast()
.
Bizim tweet()
yöntem en son tweet getirir @taylorotwell (bireysel tweet almak için kullanılır dereferencing diziyi dikkat edin):
public function tweet()
{
$tweet = \Twitter::getUserTimeline(['screen_name' => 'taylorotwell', 'count' => 1, 'format' => 'array'])[0];
$text = $tweet['text'];
//...
Makul bir şans olduğundan, bir bağlantı tweetledi ve Nexmo TTS t.co
kısaltılmış bir URL okumak, tüm bu bilgilendirici değil, URL'yi alan adına bir referansla değiştirebiliriz (en azından, bunun için bazı içerik ekleyeceğiz) Çağırın):
//...
foreach($tweet['entities']['urls'] as $link){
$domain = parse_url($link['expanded_url'], PHP_URL_HOST);
$text = substr($text, 0, $link['indices'][0]) .
'and a link to ' . $domain .
substr($text, $link['indices'][1]);
}
//....
Cıvata biraz daha okunaklı hale talk
getirildiğinde basit bir NCCO iade edeceğiz :
//...
return [
[
'action' => 'talk',
'text' => \Twitter::ago($tweet['created_at']) . ' he tweeted ' . $text
]
];
} // end of tweet()
Devam edin, deneyin - yardım hattınızı arayın ve tuşuna basın 1
.
Şimdi ikinci seçeneği bitirelim. Bunun için, Laravel Podcast için RSS akışını alıp en yeni ses dosyasını bulacağız. Yapılandırmayı basit tutmak için önbelleği devre dışı bırakacağız:
public function podcast()
{
$rss = new \SimplePie();
$rss->enable_cache(false);
$rss->set_feed_url('https://rss.simplecast.com/podcasts/351/rss');
$rss->init();
$item = $rss->get_item(0);
//...
talk
Ayrıştırılan RSS özet akışıyla ve ilk öğe bulunursa, bölüm tanımını okur ve a stream
da ses dosyasını çalar. Bu , NCCO yığınını döndürür :
//...
return [
[
'action' => 'talk',
'text' => $item->get_description()
],
[
'action' => 'stream',
'streamUrl' => [$item->get_enclosure(0)->get_link()]
]
];
} //end of podcast()
Şimdi telefon hattını ararsanız, sadece bir düğmeye basarak en yeni Laravel Podcast'i dinleyebilirsiniz.
Nexmo ve Laravel ile başka ne yapabilirsiniz? Bir dahaki sefere Laravel Hotline uygulamamıza ses yongası ekleyeceğiz. Arkadaşlarınızı arayabilir ve konuşma sırasında en sevdiğiniz Laravel ses bitlerini konuşmaya enjekte edebilirsiniz.
Ve tabii ki, Laravel Hotline uygulamasının kaynağını tamamlanmış haliyle kapabilirsiniz.
I love looking through a post that can make people think. Also, thank you for allowing for me to comment!
Just want to say your article is as surprising. The clearness in your submit is simply great and i could suppose you're knowledgeable in this subject. Fine with your permission allow me to snatch your feed to stay updated with drawing close post. Thanks one million and please continue the enjoyable work.