https://d226lax1qjow5r.cloudfront.net/blog/blogposts/how-to-send-sms-messages-with-swift-and-vapor-using-async-await/2fa_swift-vaporasync-1.png

Cómo enviar mensajes SMS con Swift y Vapor usando Async/Await

Publicado el November 19, 2021

Tiempo de lectura: 4 minutos

Swift 5.5 introduce la característica de lenguaje async/await para ayudar a mejorar la legibilidad del código Swift concurrente eliminando la necesidad de manejadores de finalización. Este post será muy similar a Cómo enviar mensajes SMS con Swift, Vapor y Vonage en nuestro blog. Este post utilizará la Messages API V1 en lugar de la SMS API, pero será una buena manera de ilustrar las mejoras de la utilización de async/await.

Si ya conoces la entrada original del blog, puedes pasar a la sección "Enviar el SMS".

Requisitos previos

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Crear un proyecto Vapor

Puede crear un proyecto Vapor utilizando el comando nuevo proyecto vapor new AsyncTextMessage en su terminal. Primero le preguntará si desea utilizar Fluent (pulse n para omitir), y luego si desea utilizar Leaf. Leaf es un lenguaje de plantillas que utilizará para generar páginas HTML dinámicas, así que pulse y para incluirlo. Una vez que el comando haya terminado, cambie el directorio a la carpeta que creó para usted usando cd AsyncTextMessage.

También deberás crear un archivo .env para almacenar las credenciales de tu cuenta API de Vonage. En tu terminal, utiliza el siguiente comando para crear el archivo reemplazando X y Y por tu clave y secreto de API, respectivamente:

echo "APIKEY=X \nAPISECRET=Y" > .env

Ahora puede abrir el proyecto en Xcode utilizando el comando vapor xcode comando. Una vez abierto Xcode, empezará a descargar las dependencias de Vapor usando Swift Package Manager (SPM). Para ver las dependencias, puede abrir el archivo Package.swift archivo.

Por defecto, Xcode ejecuta su aplicación desde un directorio local aleatorio. Dado que vas a cargar recursos locales, necesitas establecer un directorio de trabajo personalizado. Vaya a Producto > Esquema > Editar esquema... y establezca el directorio de trabajo en la carpeta raíz de su proyecto.

Setting custom working directory

Pulsa CMD+R para compilar y ejecutar. Una vez completado, busque su página web en localhost:8080.

Crear una página web

Ahora que tu proyecto está configurado, vas a crear una interfaz para introducir un número de teléfono y un mensaje para el SMS. Abra el archivo index.leaf en Recursos/Vistas y actualízalo:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Send a text message</title>
  </head>

  <body>
    <h1>Send a text message using the Vonage Messages API</h1>

    #if(messageId):
      <p> Successful SMS ID: #(messageId)</p>
    #endif

    <form action="/send" method="post">
        <p>
        <label>Phone number E.g. 447000000000</label><br>
        <input type="text" name="to">
        </p>

        <p>
        <label>Text message</label><br>
        <textarea name="text"> </textarea>
        </p>
        <button type="submit">Send text</button>
    </form>
  </body>
</html>

El código anterior añade un formulario con entradas para un número de teléfono y un mensaje, y una vez enviado el formulario, enviará una solicitud POST solicitud a /send. Fíjate en el bloque Leaf que empieza por #if(messageId):. Busca un valor para la variable messageId y, si lo tiene, añadirá el texto a la página. Si construyes y ejecutas (CMD + R), verás tu página actualizada.

Creación de estructuras modelo

Una ventaja de usar Vapor es que puedes apoyarte en la seguridad de tipos del lenguaje Swift. Puedes modelar las entradas y salidas a tu servidor usando que se ajusten al protocolo Codable Vapor tiene un protocolo Content para esto.

Crear una estructura llamada Input que se ajuste a Content en la parte inferior del routes.swift archivo:

struct Input: Content {
    let to: String
    let text: String
    let from = "SwiftText"
    let channel = "sms"
    let messageType = "text"

    private enum CodingKeys: String, CodingKey {
        case to
        case text
        case from
        case channel
        case messageType = "message_type"
    }
}

La API de Messages API de Vonage espera campos en mayúsculas y minúsculas, por lo que los structs tienen el enum CodingKeys para asignar sus nombres de propiedades a su equivalente en mayúsculas y minúsculas. Debajo de la estructura Input, crea otra estructura para la respuesta que se espera de la API de Messages:

struct Response: Content {
    let messageId: String
    
    private enum CodingKeys: String, CodingKey {
        case messageId = "message_uuid"
    }
}

Enviar el SMS

Para enviar el SMS, debes realizar una llamada a Messages API de Vonage. Para ello, debes definir la ruta /send utilizada por el formulario web, analizar los datos del formulario y realizar la solicitud. Comienza definiendo la nueva ruta en la función routes función:

app.post("send") { req async throws -> View in
    do {
        let input = try req.content.decode(Input.self)
    }
}

Observe cómo el método utiliza req async throws -> View in. Esto significa que la función es asíncrona y podría arrojar errores. De ahí el bloque do que decodifica los campos del formulario web en una estructura Input struct. El cierre devuelve un archivo View. Esto difiere de lo que ocurría anteriormente, cuando había que devolver un futuro que finalmente se habría resuelto en un . View.

A continuación, utilizará Vapor Cliente API de Vapor, que permite realizar llamadas HTTP externas, para llamar a la Messages API. Añade la llamada a la ruta de envío:

app.post("send") { req async throws -> View in
    do {
        let input = try req.content.decode(Input.self)
        
        let clientResponse = try await req.client.post("https://api.nexmo.com/v1/messages") { req in
            try req.content.encode(input, as: .json)
            let auth = BasicAuthorization(
                username: Environment.get("APIKEY")!,
                password: Environment.get("APISECRET")!
            )
            req.headers.basicAuthorization = auth
        }
        
        let messageResponse = try clientResponse.content.decode(Response.self)
        
        return try await req.view.render(
            "index",
            ["messageId": "\(messageResponse.messageId)"]
        )
    }
}

El código anterior esperará el resultado de la llamada a la Messages API, que utiliza las credenciales de la API para la autorización, luego clientResponse se establecerá con el resultado. Esto permite escribir código como si fuera síncrono. Además, como el código está en un bloque do si se produce un error, se lanzará y se gestionará automáticamente, o puedes añadir un bloque catch para manejarlo tú mismo.

La siguiente línea decodifica la respuesta del Messages API, y finalmente se usa para renderizar la página. De nuevo se utiliza try awaitpor lo que cuando req.view.render devuelva una instancia View o lanzará un error.

Pruébelo

Construye y ejecuta (CMD + R) el proyecto, abre localhost:8080 en tu navegador y, a continuación, introduce un número de teléfono y un mensaje.

Sending a message via the web page

Al hacer clic en el botón enviar, se enviarán los datos a la ruta que definiste anteriormente, se realizará la llamada a la API de Messages de Vonage y, si tiene éxito, se mostrará el ID del mensaje.

The web page showing a successful message ID

¿Y ahora qué?

Puede encontrar el proyecto completo en GitHub.

Puedes hacer más cosas con la Messages API, como enviar mensajes en Whatsapp y Facebook Messenger. Infórmate en nuestra plataforma para desarrolladores.

Compartir:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiVonage Antiguo miembro del equipo

Abdul es desarrollador de Vonage. Ha trabajado en productos de consumo como ingeniero de iOS. En su tiempo libre, le gusta andar en bicicleta, escuchar música y asesorar a aquellos que están comenzando su viaje en la tecnología.