DEV Community

Cover image for Elixir and SMS tutorial
Byron Salty
Byron Salty

Posted on • Updated on

Elixir and SMS tutorial

This tutorial will use the TextBelt SMS service. Sign up and get an API key in order to make this fully work.

Create Project and go into that directory

mix phx.new sms_demo --no-ecto
cd sms_demo
Enter fullscreen mode Exit fullscreen mode

Add HTTPoison and Poison dependencies to the project

#Path mix.exs

defp deps do
    [
        ...
        {:poison, "~> 4.0"},
        {:httpoison, "~> 1.8"},
        ...
Enter fullscreen mode Exit fullscreen mode

Get dependencies again

mix deps.get
Enter fullscreen mode Exit fullscreen mode

Create Handler for SMS sending / receiving

# Path: lib/sms_demo/sms_handler.ex

defmodule SmsDemo.SmsHandler do
    use GenServer

    def send_message(to_phone, message) do
        GenServer.cast(SmsDemo.SmsHandler, {:send, {to_phone, message}})
    end

    def receive_message(from_phone, message) do
        GenServer.cast(SmsDemo.SmsHandler, {:receive, {from_phone, message}})
    end

    def start_link(_) do
        GenServer.start_link(__MODULE__, [], name: __MODULE__)
    end

    def init([]) do
        {:ok, %{}}
    end

    def handle_cast({:send, {phone, message}}, state) do
        textbelt_url = "https://textbelt.com/text"
        textbelt_key = Application.get_env(:sms_demo, :textbelt_key)
        replyWebhookUrl = Application.get_env(:sms_demo, :webhook_url)

        params = %{
            phone: phone,
            message: message,
            key: textbelt_key,
            replyWebhookUrl: replyWebhookUrl
        }

        HTTPoison.post(textbelt_url,
            Poison.encode!(params),
            [{"Content-type", "application/json"}])

        {:noreply, state}
    end

    def handle_cast({:receive, {phone, message}}, state) do
        # TODO: Do something with the message

        {:noreply, state}
    end
end
Enter fullscreen mode Exit fullscreen mode

Update Application defintion to spawn the above Handler

# Path: lib/sms_demo/application.ex

def start(_type, _args) do
    children = [
        ...
        SmsDemo.SmsHandler,
        ... 
Enter fullscreen mode Exit fullscreen mode

Add WebHook Controller

# Path: lib/sms_demo_web/controllers/webhook_controller.ex
defmodule SmsDemoWeb.WebhookController do
  alias SmsDemo.SmsHandler
  use SmsDemoWeb, :controller

  def hook(conn, params) do
    SmsHandler.receive_message(params["fromNumber"], params["text"])

    json(conn, %{status: "ok"})
  end
end

Enter fullscreen mode Exit fullscreen mode

Uncomment the /api scope in Router and add our hook

# Path: lib/sms_demo_web/router.ex
scope "/api", SmsDemoWeb do
    pipe_through :api

    post "/hook", WebhookController, :hook
end
Enter fullscreen mode Exit fullscreen mode

Test Webhook locally

$ mix phx.server

$ curl -X POST http://localhost:4000/api/hook \
       -H 'Content-Type: application/json' \
       -d '{"fromNumber": "+1555123456", "text": "Here is my reply"}'

Enter fullscreen mode Exit fullscreen mode

That's all the plumbing. Now we can make a little joke telling interaction in which we want to:

1. Hit a web endpoint api and pass in a phone number to tell a joke to
2. Send via SMS the first part of the joke
3. Expect an SMS response of "Why?"
4. Send via SMS the second part of the joke
Enter fullscreen mode Exit fullscreen mode

Check out the finished project on github at
https://github.com/byronsalty/sms_demo

Top comments (0)