https://a.storyblok.com/f/270183/34410/fd65f9eeae/2fa_swift-vaporasync-1.png

Como enviar mensagens SMS com Swift e Vapor usando Async/Await

Publicado em November 19, 2021

Tempo de leitura: 4 minutos

O Swift 5.5 introduz o recurso de linguagem async/await para ajudar a melhorar a legibilidade do código Swift concorrente, eliminando a necessidade de manipuladores de conclusão. Este post será muito semelhante a “Como enviar mensagens SMS com Swift, Vapor e Vonage” em nosso blog. Este post utilizará a Messages API V1 em vez da SMS API, mas será uma boa maneira de ilustrar as melhorias decorrentes do uso de async/await.

Se você já conhece a postagem original do blog, pode pular diretamente para a seção “Enviar o SMS”.

Pré-requisitos

  • Xcode 13 e Swift 5.5 ou versão posterior.

  • A Vapor Toolbox instalada no seu computador.

Criar um projeto de vapor

Você pode criar um projeto Vapor usando o comando “novo projeto” vapor new AsyncTextMessage no seu terminal. Primeiro, ele perguntará se você deseja usar o Fluent (pressione n para pular) e, em seguida, se você deseja usar o Leaf. O Leaf é uma linguagem de modelos que você usará para gerar páginas HTML dinâmicas; portanto, pressione y para incluí-la. Assim que o comando for concluído, mude para a pasta que foi criada para você usando cd AsyncTextMessage.

Você também precisará criar um .env arquivo para armazenar as credenciais da sua conta da API da Vonage. No seu terminal, use o comando a seguir para criar o arquivo, substituindo X e Y pela sua chave de API e seu segredo, respectivamente:

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

Agora você pode abrir o projeto no Xcode usando o vapor xcode comando. Assim que o Xcode abrir, ele começará a baixar as dependências do Vapor usando o Swift Package Manager (SPM). Para visualizar as dependências, você pode abrir o Package.swift arquivo.

Por padrão, o Xcode executa seu aplicativo a partir de um diretório local aleatório. Como você carregará recursos locais, é necessário definir um diretório de trabalho personalizado. Vá até Produto > Esquema > Editar Esquema... e defina o diretório de trabalho como a pasta raiz do seu projeto.

Setting custom working directory

Pressione CMD+R para compilar e executar. Quando terminar, acesse sua página da web em localhost:8080.

Criar uma página da Web

Agora que seu projeto está configurado, você vai criar uma interface para inserir um número de telefone e uma mensagem para o SMS. Abra o index.leaf arquivo em Resources/Views e atualize-o:

<!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>

O código acima adiciona um formulário com campos para um número de telefone e uma mensagem; assim que o formulário for enviado, ele enviará uma POST solicitação para /send. Observe o bloco Leaf que começa com #if(messageId):. Ele verifica se há um valor para a messageId variável e, se houver, adicionará o texto à página. Se você compilar e executar (CMD + R), verá agora sua página atualizada.

Criar as estruturas do modelo

Uma vantagem de usar o Vapor é que você pode contar com a segurança de tipos da linguagem Swift. Você pode modelar entradas e saídas para o seu servidor de forma que estejam em conformidade com o Codable protocolo; o Vapor possui um Content protocolo para isso.

Crie uma estrutura chamada Input que esteja em conformidade com Content na parte inferior do routes.swift arquivo:

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"
    }
}

A API do Vonage Messages espera que os campos estejam no formato “snake case”; por isso, as estruturas possuem a enumeração `CodingKeys` para mapear os nomes de suas propriedades para seus equivalentes no formato “snake case”. Abaixo da estrutura `Input`, crie outra estrutura para a resposta esperada da Messages API:

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

Enviar o SMS

Para enviar o SMS, é necessário fazer uma chamada à Messages API do Vonage. Para isso, é preciso definir a /send rota usada pelo formulário da web, analisar os dados do formulário e, em seguida, fazer a solicitação. Comece definindo a nova rota na routes função:

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

Observe como o método usa req async throws -> View in. Isso significa que a função é assíncrona e pode gerar erros. Por isso, o do bloco interno, que está decodificando os campos do formulário da web em uma Input estrutura. O closure retorna um View. Isso difere do que acontecia anteriormente, quando era necessário retornar um future que, eventualmente, seria resolvido em um View.

Em seguida, você utilizará o Vapor's API do Cliente , que permite que você faça chamadas HTTP externas, para chamar a Messages API. Adicione a chamada à rota de envio:

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)"]
        )
    }
}

O código acima aguardará o resultado da chamada à Messages API, que utiliza as credenciais da API para autorização; em seguida, clientResponse será preenchido com o resultado. Isso permite que você escreva código como se fosse síncrono. Além disso, como o código está em um do bloco, se houver um erro, ele simplesmente será lançado e tratado automaticamente; ou você pode adicionar um catch para tratá-los você mesmo.

A linha a seguir decodifica a resposta da Messages API e, por fim, essa resposta é usada para renderizar a página. Mais uma vez, isso utiliza try await; portanto, quando req.view.render for concluída, ela retornará uma View ou lançará um erro.

Experimente

Compile e execute (CMD + R) o projeto, abra localhost:8080 no seu navegador e, em seguida, preencha um número de telefone e uma mensagem.

Sending a message via the web page

Ao clicar no botão “Enviar”, os dados serão enviados para a rota que você definiu anteriormente, será feita a chamada para a Messages API do Vonage e, se for bem-sucedida, o ID da mensagem será exibido.

The web page showing a successful message ID

E agora?

Você pode encontrar o projeto concluído no GitHub.

Você pode fazer muito mais com a Messages API, como enviar mensagens no WhatsApp e no Facebook Messenger. Saiba mais sobre isso em nossa plataforma para desenvolvedores.

Compartilhar:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiEx-funcionário da Vonage

Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia