Twilioで電話したらSMSを送るアプリをHerokuで作る



Twilioで電話をしたらその電話へSMSメッセージを送るサンプルアプリを作っていこうと思います。
サーバーサイドはHerokuで作ろう。言語はrubyです。フレームワークはsinatraで。(Ruby on Railsがまだ覚えられてない。。）

# 実行環境
* ruby 2.1.3p242 
* OSX Yosemite 10.10.5
* sinatra 1.4.6


# 目次
1. Herokuでアプリを作る
2. Twilioで電話番号を購入&設定
3. 2の電話番号に電話してSMSのメッセージがくるのを確認

## Herokuでアプリを作る
### 初期設定
どこでもいいので、作業ディレクトリを作ってgit,Gemfileを作ります

```bash
# フォルダ作成＆移動
mkdir sample-app && cd sample-app
 
# Gitリポジトリにする
git init

# Gemfile の生成
bundle init

```

### Gemのインストール

```bash
vim Gemfile
```

Gemfileを編集します。

```vim
# A sample Gemfile
source "https://rubygems.org"

# gem "rails"
gem 'sinatra'
gem 'sinatra-contrib', '~> 1.4.2'

# twilio
gem 'twilio-ruby', '~> 3.12'

# Unicorn
gem 'unicorn'
gem 'faraday'

group :development, :test do
  # Foreman
  gem 'foreman'

end

group :production do

end

```

Gemfileが終わったらインストールします。

```bash
bundle install --path vendor/bundle --without production

```

###アプリの作成
今回はsinatraでアプリケーションを作っていきます
アプリケーションの本体となる```main.rb```を作ります。

```bash
vim main.rb

```

**main.rb**でとりあえず、動くHerokuアプリを作ります。

```ruby:main.rb
require 'sinatra'
require 'sinatra/base'
 
class MainApp < Sinatra::Base
  get '/' do
    'Hello, World!'
  end
end

```

`MainApp`というクラスにgetでHello,worldを出すだけです。
次にHerokuの実行環境に必要なconfig.ru と unicorn.rb と Procfileを作ります。

config.ruを作ります。

```bash
vim config.ru
```

```ru:config.ru
require './main.rb'
run MainApp.new
```

unicorn.rbを作ります。

```bash
mkdir config && vim config/unicorn.rb
```

```ruby:config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true
 
before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end
 
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end
 
after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end
 
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

```

Procfileを作ります。

```bash
vim Procfile
```

```Procfile
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
```

アプリを起動してみます。GemfileにForemanを入れているので起動してみます。

```bash
foreman start
```

`http://0.0.0.0:5000`にアクセスして`Hello, World!`が表示されていたらとりあえず成功です。

### Herokuアプリの作成
Herokuのアプリも作ってしまいましょう

```bash
heroku create TWILIO_APP_NAME
git add .
git commit -m 'first commit.'
git push heroku master

```

うまく成功すれば、`http://TWILIO_APP_NAME.herokuapp.com`でも`Hello, World!`が表示されるはずです。

### Twilioアプリを作る
ここまでは、準備段階。いよいよ、電話をしたらSMSメッセージが送られるTwilioサンプルを作っていきます。

`main.rb`を編集します。


```ruby:main.rb
require 'sinatra'
require 'sinatra/base'
require 'twilio-ruby'
require 'rubygems'
require 'net/http'
require 'uri'
require 'faraday'

class MainApp < Sinatra::Base

    before do
		@rootPath = 'https://TWILIO_APP_NAME.herokuapp.com'

    end
    
end
```

必要なライブラリーをrequireで指定して、 beforeでインスタンス変数`@rootPath`を作成しました。Herokuのパスを他でも使えるようにしています。


###電話着信の処理
```ruby:main.rb
	post '/call' do
		content_type "text/xml"

		#かかってきた電話番号
        fromNumber = params[:From]
		Twilio::TwiML::Response.new do |r|
			r.Say "Twilioのエスエムエスサンプルです。この後強制的にあなたのエスエムエスにメッセージを送ります。ごめんね", language: 'ja-JP', voice: 'alice', loop: '3'
			r.Pause
			r.Redirect "#{@rootPath}/postsms/#{fromNumber}" , method: 'post'
		end.text
   end

```

誰かからTwilioの電話番号へ電話がかかってきた時のTwilioの応答処理を実装していきます。
`post '/call' do`でhttps://TWILIO_APP_NAME.herokuapp.com/callにpostでリクエスト来た時に応答するようにします。
これはあとで、Twilioの電話番号にも指定するので覚えておきます。

`content_type "text/xml"`
デバックがしやすいようにcontent_typeをxmlにします。

```ruby
		#かかってきた電話番号
        fromNumber = params[:From]
```

かかってきた電話番号はパラメーターで`From`の中に入っています。
他に取得できるパラメーターは以下で確認できます。

[TwiMLTMメッセージ : Twilioのリクエスト](https://jp.twilio.com/docs/api/twiml/sms/twilio_request)

さて、Twilioの自動音声を実装します。

```ruby
		Twilio::TwiML::Response.new do |r|
			r.Say "Twilioのエスエムエスサンプルです。この後強制的にあなたのエスエムエスにメッセージを送ります。ごめんね", language: 'ja-JP', voice: 'alice', loop: '3'
			r.Pause
			r.Redirect "#{@rootPath}/postsms/#{fromNumber}" , method: 'post'
		end.text

```

`r.Say`でTwilioの自動音声させる文章や、言語、声の種類、ループ回数を指定しています。
`r.Pause`でちょっと待機させて、`r.Redirect`でSMSを処理するリクエストを投げる処理へ移動させます。

(/callのこの部分で、SMSをポストすることもできたんですが、それだと電話中にSMSが送られてしまいました。なので、r.Redirectでリダイレクトさせて、ほかのURLでSMSのポストをすることにしました。)


###電話を終了させる

```ruby:main.rb
   post '/postsms/:fromNumber' do
		content_type "text/xml"
		#かかってきた電話番号
        fromNumber = params[:fromNumber]

		Twilio::TwiML::Response.new do |r|
				conn = Faraday.new(:url =>  @rootPath) do |faraday|
					faraday.request  :url_encoded             # form-encode POST params
					faraday.response :logger                  # log requests to STDOUT
					faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
				end
				conn.post "/sendsms/#{fromNumber}"

			#hangupで終了させないとだめ
			r.Hangup
		end.text

   end

```
SMSの処理です。この処理に来た時点ではまだTwilioとの電話は継続しています。SMSへのpostリクエストを送ってから、電話を終了させます。
Twilioの処理としては、`r.Hangup`電話を終了させているだけです。

```
		Twilio::TwiML::Response.new do |r|
			#hangupで終了させないとだめ
			r.Hangup
		end.text
		
		
```

電話を終了させる前に、rubyのHTTP クライアントライブラリ Faraday でpostリクエストを投げます。

Faradayの詳しい説明は[こちら](https://gist.github.com/mitukiii/2775321)

```ruby:main.rb
				conn = Faraday.new(:url =>  @rootPath) do |faraday|
					faraday.request  :url_encoded             # form-encode POST params
					faraday.response :logger                  # log requests to STDOUT
					faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
				end
				conn.post "/sendsms/#{fromNumber}"
				
```

###SMS送信
SMSを送信する処理です。

```ruby:main.rb

	post '/sendsms/:postPhoneNumber' do
		content_type "text/xml"
		
		postPhoneNumber = params[:postPhoneNumber]

		if postPhoneNumber != nil
			#先頭の0を国際番号+81に入れ替える
			postPhoneNumber = postPhoneNumber.gsub(/\A0/, "+81")

			#アカウント
			account_sid = "ACxxxxxxxxxxxxxxxxxxxxxx"
			auth_token = "yyyyyyyyyyyyyyyyyyyyyy"

			client = Twilio::REST::Client.new account_sid, auth_token

			# Your Twilio number
			from = "+1xxxxxxxxxx" 
					 
			client.account.messages.create(
			:from => from,
			:to => postPhoneNumber,
			:body => "smsメッセージをtwilioで送りました・ω・"
			)

		end
		
   end

```

SMS送信する処理は以下です。

```ruby:main.rb
			#アカウント
			account_sid = "ACxxxxxxxxxxxxxxxxxxxxxx"
			auth_token = "yyyyyyyyyyyyyyyyyyyyyy"

			client = Twilio::REST::Client.new account_sid, auth_token

			# Your Twilio number
			from = "+1xxxxxxxxxx" 
					 
			client.account.messages.create(
			:from => from,
			:to => postPhoneNumber,
			:body => "smsメッセージをtwilioで送りました・ω・"
			)

```

アカウントの`account_sid `と`auth_token `は自分のTwilioのアカウントを指定します。
ここにTwilioに[ログインして](https://jp.twilio.com/user/account/voice/getting-started)
プログラマブルVOICE > はじめよう >  APIクレデンシャルを表示する
で確認ができます。

![スクリーンショット 2015-12-20 12.40.53.png](https://qiita-image-store.s3.amazonaws.com/0/31587/ea8a3c6a-e590-4b55-4e97-095d19fa0d81.png "スクリーンショット 2015-12-20 12.40.53.png")


```ruby:main.rb
# Your Twilio number
from = "+1xxxxxxxxxx" 
```


ここはあとで電話番号を買うのでその番号を指定します。

コードは以上です。

### Herokuにデプロイする
ここまで作ったらHerokuにデプロイしましょう

```bash
git add .
git commit -m 'twilio sms app commit.'
git push heroku master

```

## Twilioで電話番号を購入&設定
Twilioで電話を買います。
SMS送信できる電話番号はアメリカの番号です。
なのでアメリカの番号を買いましょう

Twilioログイン後、プログラマブルVOICE　> 電話番号 に移動します。
https://jp.twilio.com/user/account/voice/phone-numbers

**Buy a Number**ボタンを押します。

国をアメリカに指定して検索

![スクリーンショット 2015-12-20 12.46.36.png](https://qiita-image-store.s3.amazonaws.com/0/31587/1512bc83-7a2c-8333-da4c-363238c89446.png "スクリーンショット 2015-12-20 12.46.36.png")

好きな電話番号を選んで購入します。
![スクリーンショット 2015-12-20 12.46.57.png](https://qiita-image-store.s3.amazonaws.com/0/31587/00eea854-6cea-0d14-40a0-6b766a2b99ba.png "スクリーンショット 2015-12-20 12.46.57.png")


購入が終わったら
プログラマブルVOICE　> 電話番号 に戻り、電話番号に紐づくURLを登録します。HerokuアプリのURLになります。

![スクリーンショット 2015-12-20 12.54.03.png](https://qiita-image-store.s3.amazonaws.com/0/31587/fa154311-105c-f382-9159-1a8b6f26346d.png "スクリーンショット 2015-12-20 12.54.03.png")

今回はアクセスが/callにアプリで作っているので
http://TWILIO_APP_NAME.herokuapp.com/callのURLを指定します。

main.rbの電話番号を買った電話番号に更新しましょう


```ruby:main.rb
# Your Twilio number
from = "+1xxxxxxxxxx" 
```


そしてHerokuにデプロイします。


```bash
git add .
git commit -m 'add phone number.'
git push heroku master

```


## 2の電話番号に電話してSMSのメッセージがくるのを確認
ここまでくれば購入した電話番号に電話をすればSMSが来るはずです。
が、国際電話になるので、ちょっと戸惑いました。。

私のキャリアがSoftbankのiPhoneを使っているのですが、国際電話には
010 > 国番号 > 相手先電話番号
または
+ > 国番号 > 相手先電話番号
をしないと電話がかけられないみたいです。
http://www.softbank.jp/mobile/service/global/outgoing/call/support/setting-method/iphone/


アメリカの国番号は1です。

なので仮にTwilioで+1 123-456-7890という電話番号を購入したのなら

キーパッドで010 1 1234567890と入力すれば電話がかけられるようになります。

上手く行けば電話が終わったあとにSMSにメッセージが来るはずです！

![IMG_3710.PNG](https://qiita-image-store.s3.amazonaws.com/0/31587/37d0236b-0c57-357c-7f0b-fa18ceb602f2.png "IMG_3710.PNG")



#最後に
TwilioでHerokuのアプリを作って電話購入までをまとめました。
国際電話のかけかたとか、プログラムではないところでつまづいたので、参考になれば幸いです。

## 参考
* http://dev.classmethod.jp/server-side/ruby-on-rails/sinatra-postgresql-unicorn-on-heroku/
* https://gist.github.com/mitukiii/2775321
* http://qiita.com/srockstyle/items/111d25f44ef2cc51d9ac
* http://dev.classmethod.jp/server-side/twilio/twilio-sms/
* https://jp.twilio.com/docs/quickstart/ruby/sms/sending-via-rest