Como enviar um SMS em massa

A ferramenta de SMS da Zenvia te ajuda na automatização dos processos de comunicação. Venha saber como utilizá-la para encaminhar SMS em massa

primeiro SMS foi encaminhado em 3 de dezembro de 1992, por um engenheiro chamado Neil Papworth. Completando quase 30 anos de existência, o SMS é até hoje um dos melhores e mais eficientes meios de impactar através de entregas imediatas, por baixo custo e com taxa de abertura de até 98% – conforme mostra pesquisa feita por Daniel Rowles, da Mobile Marketing.

De acordo com os dados coletados, “é possível impactar 100% dos usuários mobile com mensagens de texto de até 160 caracteres”, sendo que 90% são lidas em até 3 minutos. Quando equiparada a outras formas de comunicação, como por exemplo o e-mail, que possui uma taxa de abertura entre 17 e 22%, a probabilidade do SMS ser aberto é muito superior.

SMS Marketing

O SMS Marketing é o encaminhamento de uma mensagem de texto para uma base de clientes com números pré-cadastrados, ou seja, vários contatos irão receber em um único disparo o mesmo SMS. Além da praticidade, instantaneidade e uma maior garantia de leitura, o SMS em massa também é econômico quando comparado a outras estratégias de comunicação.

No caso de uma empresa que atua como veículo de imprensa, o SMS em massa pode ser utilizado para informar a publicação de uma nova edição de uma revista. No caso de uma empresa de telecomunicações, é possível encaminhar uma nova proposta de pacote para vários clientes ao mesmo tempo.

Ao contrário do e-mail Marketing, que depende do uso de internet, o SMS em massa atinge o consumidor via mensagem de texto e pode servir tanto para divulgação e oferta de melhores condições de serviços, como para lembrar o cliente de uma fatura para vencer ou até mesmo realizar cobranças. Assim sendo, a ferramenta de SMS da Zenvia ajuda na automatização dos processos de comunicação que necessitam do envio de SMS.

Pensando nisso, fizemos um tutorial utilizando a API de SMS da Zenvia e dando a ela o propósito de encaminhar SMS em massa. Com isso, aqui você encontrará:

1- Tutorial: aprenda a mandar um SMS em massa;

2- Criando a aplicação Node.js;

3- Criando e populando o banco de dados;

4- Voltando para a nossa aplicação;

Tutorial: aprenda a mandar um SMS em massa

O projeto final criado neste tutorial está disponível no nosso repositório do github.

Iremos construir uma aplicação com base no banco de dados de uma empresa fictícia de telecomunicações, a TelenetCompany, que possui planos de internet fixa, móvel e telefonia fixa. A aplicação será capaz de consultar no banco de dados quais clientes que não possuem o plano mais caro contratado e enviará uma proposta de upgrade com desconto.

1- Vamos começar criando uma conta: basta acessar este site, clicar em “CRIAR UMA CONTA” no canto superior direito e preencher os campos.

2- Após criar a conta, siga o seguinte fluxo para configurarmos a Sandbox para fazermos os nossos testes com a Zenvia:

Menu superior > Produtos > Desenvolvedores > Sandbox > Criar novo > Escolha o canal "SMS" > Próximo

3- Agora você precisa configurar o seu número de celular para realizar os teste. Para isso, basta ler o QR CODE que aparece na tela e enviar a mensagem previamente escrita pelo QR CODE que a Zenvia realiza automaticamente a configuração. Caso você não consiga ler QR CODE, envie um SMS para o número indicado na tela e com a keyword como mensagem

4- Depois disso, seu número estará vinculado ao ambiente de testes e você poderá usar.

5- Faça um teste, selecionando o seu número e enviando uma mensagem de teste.

6- Na mesma tela de envio de mensagens, é possível perceber algumas informações importantes, armazene o API-TOKEN e a KEYWORD, pois precisaremos deles mais tarde na hora de construirmos nossa aplicação e realizar as chamadas para a API.

Criando a aplicação Node.js

1- Instale o Node.js no seu computador (de preferência a versão LTS);

1.1- opcional – Instale o yarn. O Node.js possui um gerenciador de pacotes padrão chamado npm (Node Package Manager), porém existe um gerenciador diferente chamado yarn. No restante deste artigo, haverão as opções de instalação para ambos gerenciadores de pacote como no passo a seguir.

2- Inicie o projeto criando o package.json com o seguinte comando no terminal:

npm init -y

yarn init -y

3- Instale o ts-nodets-node-dev e o typescript como dependências de desenvolvimento:

npm i ts-node ts-node-dev typescript -D

yarn add ts-node ts-node-dev typescript -D

3.1 – Instale o arquivo de configuração do typescript:

npx typescript --init

4- Crie um arquivo src/server.ts para testarmos a aplicação:

console.log('Hello World!')

5- Abra o arquivo package.json e insira o script para iniciar o servidor assim como na área grifada em cinza:

{
  "name": "zenvia-sms-massive",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "ts-node-dev --transpile-only --ignore-watch node_modules --respawn src/server.ts"
  },
  "devDependencies": {
    "ts-node": "^9.1.1",
    "ts-node-d": "^1.1.1",
    "typescript": "^4.1.3"
  }
}

5.1- Sempre que você quiser executar a aplicação basta executar no terminal:

npm run dev

yarn dev

Criando e populando o banco de dados

1- Vamos começar criando o nosso banco que dados que armazenará as informações dos inadimplentes. Para fins didáticos, vamos utilizar o banco de dados SQLite, pois ele não necessita de instalação e o banco fica salvo em apenas um arquivo. Para manusear o banco de dados vamos utilizar o Prisma, ORM (Object Relational Mapper) para Node.js e Typescript muito útil e prático, permitindo que alteremos o banco de dados mudando apenas uma linha de código. Instale as dependências do prisma @prisma/cli e @prisma/client e inicialize o prisma:

npm install prisma @prisma/client && npx prisma init

yarn add prisma @prisma/client && npx prisma init

A inicialização do prisma irá gerar um arquivo prisma/schema.prisma é nele que iremos esquematizar nosso banco de dados.

2- Arquitete o banco de dados no arquivo prisma/schema.prisma:

datasource db {
 provider = "sqlite"
 url   = "file:./dev.db"
}

generator client {
 provider = "prisma-client-js"
}

model Pessoa {
 id      Int      @id @default(autoincrement())
 nome    String
 celular String
 Divida  Divida[]
}

model Divida {
 id             Int         @id @default(autoincrement())
 dataVencimento DateTime
 dividendo      Pessoa      @relation(fields: [dividendoId], references: [id])
 dividendoId    Int
 valor          Float
}  

3- Execute a criação do banco de dados:

npx prisma migrate dev --name init --preview-feature

Assim, o arquivo do seu banco de dados será criado prisma/dev.db.

4- Para testar a aplicação, crie o arquivo prisma/seed.ts para popular o banco de dados, troque os números de celular pelo seu para receber os torpedos de voz e troque as datas das dívidas para que esteja de acordo com os períodos explicados no início do tutorial:

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

const main = async () => {
 // Inserção dos benefícios
 await prisma.benefit.create({
  data: { id: 1, name: '5GB de Internet Móvel', value: 19.99 },
 })
 await prisma.benefit.create({
  data: { id: 2, name: '10GB de Internet Móvel', value: 29.99 },
 })
 await prisma.benefit.create({
  data: { id: 3, name: '30GB de Internet Móvel', value: 49.99 },
 })

 await prisma.benefit.create({
  data: { id: 4, name: '60 minutos telefone fixo por mês', value: 9.99 },
 })
 await prisma.benefit.create({
  data: { id: 5, name: '120 minutos telefone fixo por mês', value: 19.99 },
 })
 await prisma.benefit.create({
  data: { id: 6, name: 'Minutos ilimitados telefone fixo', value: 30.99 },
 })

 await prisma.benefit.create({
  data: { id: 7, name: '40 megas internet fixa', value: 39.99 },
 })
 await prisma.benefit.create({
  data: { id: 8, name: '100 megas internet fixa', value: 89.99 },
 })
 await prisma.benefit.create({
  data: { id: 9, name: '300 megas internet fixa', value: 129.99 },
 })

 console.log('Benefícios criados.')

 // Inserção dos planos
 await prisma.plan.create({
  data: {
   id: 1,
   name: 'Básico',
   discount: 0,
   benefits: { connect: [{ id: 1 }, { id: 4 }, { id: 7 }] },
  },
 })
 await prisma.plan.create({
  data: {
   id: 2,
   name: 'Padrão',
   discount: 0.1,
   benefits: { connect: [{ id: 2 }, { id: 5 }, { id: 8 }] },
  },
 })
 await prisma.plan.create({
  data: {
   id: 3,
   name: 'Avançado',
   discount: 0.25,
   benefits: { connect: [{ id: 3 }, { id: 6 }, { id: 9 }] },
  },
 })

 console.log('Planos criados.')

 // Inserção das pessoas
 await prisma.person.create({
  data: { name: 'Pessoa Teste', phone: '5511999999999', planId: 2 },
 })

 console.log('Pessoas criadas.')
}

main().catch((e) => console.error(e))  

5- Adicione o script seed no arquivo package.json:

{
 "name": "zenvia-sms-massive",
 "version": "1.0.0",
 "main": "index.js",
 "license": "MIT",
 "scripts": {
  "dev": "ts-node-dev --transpile-only --ignore-watch node_modules --respawn src/server.ts",
  "seed": "ts-node prisma/seed.ts"
 },
 "devDependencies": {
  "ts-node": "^9.1.1",
  "ts-node-dev": "^1.1.6",
  "typescript": "^4.2.2"
 },
 "dependencies": {
  "@prisma/cli": "^2.18.0",
  "@prisma/client": "^2.18.0",
 }
}

6- Execute o script seed:

npm run seed

yarn seed

Agora, com o banco de dados criado e populado, podemos começar a desenvolver a lógica da nossa aplicação.

Voltando para nossa aplicação

1- Instale o express, body-parser e o dotenv para criarmos nossa aplicação:

npm i express body-parser dotenv && npm i --save-dev @types/express

yarn add express body-parser dotenv  && yarn add @types/express-D

2- Instale o Axios para realizarmos as requisições http:

npm i axios

yarn add axios

3- Vamos começar criando o arquivo de configuração do Axios para chamarmos a API de voz da Zenvia services/api.ts:

import axios from 'axios'

export const api= axios.create({
   baseURL: 'https://api.zenvia.com/v2',
})

4- Crie um arquivo chamado .env, nele conterá seu token de acesso em uma variável de ambiente, coloque seu APITOKEN e sua KEYWORD logo após o sinal de =adquiridos no momento do envio da mensagem de testes:

API_TOKEN=
KEYWORD=

5- Volte para o arquivo src/server.ts, ele será o nosso arquivo de configuração do servidor para criarmos nossa API:

import express from 'express'
import bodyParser from 'body-parser'
import routes from './routes'

// Inicialização do servidor express
const app = express()

// Indica para o servidor usar o body parser
app.use(bodyParser.json())

// Indica para o servidor usar as rotas do arquivo routes.ts
app.use(routes)

// Indica para o servidor ouvir a porta 4000
app.listen(4000, () => console.log('Servidor rodando na porta 4000'))    

6- Crie o arquivo src/routes.ts que terá a rota da nossa aplicação:

import express from 'express'
import { sendPlanUpgradeController } from './UseCases/SendPlanUpgrade/index'

// Inicialização do Router do express
const routes = express.Router()

// Declaração da rota GET /sendPlanUpgrade que iniciara o processo de envio de SMS em massa
routes.get('/sendPlanUpgrade', sendPlanUpgradeController.handle)

export default routes         

sendPlanUpgradeController será criado a seguir, mas antes, vamos criar alguns arquivos que ele depende.

7- Crie os arquivos de tipagem Benefit.ts, Person.ts e Plan.ts na pasta src/entities:

Benefit.ts

import { IPlan } from './Plan'

export interface IBenefit {
 id: number
 name: string
 value: number
 Plan?: IPlan
 planId?: string
}

 Person.ts 

import { IPlanWithTotal } from './../repositories/PlanRepository'

export interface IPerson {
 id: number
 name: string
 phone: string
 planId?: number | null
 Plan?: IPlanWithTotal
}                 

Plan.ts

import { Benefit } from '@prisma/client'

export interface IPlan {
 id: number
 name: string
 benefits: Benefit[]
 discount: number
}  

8- Agora, crie o repositório dos planos com os arquivos src/repositories/PlanRepository.ts e src/repositories/implementations/PlanRepository.ts:

src/repositories/PlanRepository.ts 

import { Benefit } from '@prisma/client'
import { IPlan } from '../entities/Plan'

export interface IPlanWithTotal extends Omit {
 total: number
 benefits?: Benefit[]
}

export interface IPlanRepository {
 findAllWithTotal(): Promise
 findMostExpensivePlan(): Promise
} 

src/repositories/implementations/PlanRepository.ts

import { PrismaClient } from '@prisma/client'
import { IPlanWithTotal } from './../PlanRepository'
import { IPlanRepository } from '../PlanRepository'

const prisma = new PrismaClient()

export class PlanRepository implements IPlanRepository {
 async findAllWithTotal(): Promise {
  // Busca todos os planos no banco de dados
  const allPlans = await prisma.plan.findMany()

  // Adiciona o valor total da soma dos benefícios deste plano e retorna
  const plansWithTotal = await allPlans.map(async (plan) => {
   return {
    ...plan,
    total: (
     await prisma.benefit.aggregate({
      sum: { value: true },
      where: { planId: plan.id },
     })
    ).sum.value,
   }
  })

  // Retorna os planos com os totais
  return Promise.all(plansWithTotal).then(function (results) {
   return results
  })
 }
 async findMostExpensivePlan(): Promise {
  // Busca todos os planos no banco de dados
  const allPlans = await prisma.plan.findMany()

  // Adiciona o valor total da soma dos benefícios deste plano
  const finalPlans = allPlans.map(async (plan) => {
   return {
    ...plan,
    total: (
     await prisma.benefit.aggregate({
      sum: { value: true },
      where: { planId: plan.id },
     })
    ).sum.value,
   }
  })

  // Retorna o plano mais caro
  return await Promise.all(finalPlans).then(function (results) {
   const higherTotal = Math.max.apply(
    Math,
    results.map(function (o) {
     return o.total
    })
   )
   return results.filter((result) => result.total === higherTotal)[0]
  })
 }
}            

9- Agora, crie o repositório das pessoascom os arquivos src/repositories/PersonRepository.ts e src/repositories/implementations/PersonRepository.ts:

src/repositories/PersonRepository.ts

import { IPlanWithTotal } from './PlanRepository'
import { IPerson } from '../entities/Person'

export interface IPersonRepository {
 findPeopleWithCheapestPlansByMostExpensivePlan(
  mostExpensivePlan: IPlanWithTotal
 ): Promise
}     

src/repositories/implementations/PersonRepository.ts

import { planRepository } from './../index'
import { PrismaClient } from '@prisma/client'
import { IPerson } from './../../entities/Person'
import { IPlanWithTotal } from './../PlanRepository'
import { IPersonRepository } from '../PersonRepository'

const prisma = new PrismaClient() // Inicialização do PrismaClient

export class PersonRepository implements IPersonRepository {
 async findPeopleWithCheapestPlansByMostExpensivePlan(
  mostExpensivePlan: IPlanWithTotal
 ): Promise {
  // Busca e todas as pessoas que não possuem o plano mais caro
  const people = await prisma.person.findMany({
   where: { planId: { not: mostExpensivePlan.id } },
  })

  // Busca todos os planos com seus respectivos valores totais
  const allPlansWithTotal = await planRepository.findAllWithTotal()

  // Retorna as pessoas e seus respectivos planos
  return await people.map((person) => {
   return {
    ...person,
    Plan: allPlansWithTotal.filter((plan) => plan.id === person.planId)[0],
   }
  })
 }
}          

10- Crie o arquivo de inicialização e exportação dos repositórios src/repositories/index.ts:

import { PersonRepository } from './implementations/PersonRepository'
import { PlanRepository } from './implementations/PlanRepository'

// Inicialiazção e exportação dos repositórios
export const planRepository = new PlanRepository()
export const personRepository = new PersonRepository()  

11- Crie agora o caso de uso SendPlanUpgrade que irá conter o Controller. Crie os arquivos src/UseCases/SendPlanUpgrade/SendPlanUpgradeController.ts e src/UseCases/SendPlanUpgrade/index.ts

import { Request, Response } from 'express'
import { config } from 'dotenv'
import { api } from './../../services/api'
import { planRepository, personRepository } from './../../repositories/index'
import { transformMoney } from './../../../utils/transformMoney'

config() // Inicialização do dotenv

export class SendPlanUpgradeController {
 async handle(request: Request, response: Response): Promise {
  // Tente
  try {
   // Busca no banco de dados o plano mais caro
   const mostExpensivePlan = await planRepository.findMostExpensivePlan()

   // Busca no banco de dados as pessoas que não possuem o plano mais caro
   const peopleToSendMessage = await personRepository.findPeopleWithCheapestPlansByMostExpensivePlan(
    mostExpensivePlan
   )

   // Enviar um SMS para todas essas pessoas, oferecendo uma atualização no plano com desconto
   peopleToSendMessage.forEach((people) => {
    api
     .post(
      '/channels/sms/messages',
      {
       from: `${process.env.KEYWORD}`,
       to: people.phone,
       contents: [
        {
         type: 'text',
         text: `Olá ${
          people.name
         }, tudo bem? Somos da sua provedora de telefonia e internet TelenetCopany e estamos aqui para oferecer um upgrade no seu plano. Seu Plano é o ${
          people.Plan?.name
         } e você paga ${transformMoney(
          people.Plan?.total
         )}. Você pode atualizar ele para o Plano ${
          mostExpensivePlan.name
         }, onde os seus benefícios avulsos saem por um total de ${transformMoney(
          mostExpensivePlan.total
         )} e com o plano sai por apenas ${transformMoney(
          parseFloat(
           (
            mostExpensivePlan.total -
            mostExpensivePlan.total * mostExpensivePlan.discount
           ).toFixed(2)
          )
         )}. Entre em contato conosco respondendo este SMS para prosseguir com o upgrade de plano.`,
        },
       ],
      },
      {
       headers: {
        'X-API-TOKEN': `${process.env.API_TOKEN}`,
       },
      }
     )
     .then((res) => console.log('\nSucesso:\n', res.data))
     .catch((error) => console.log('\nFalha:\n', error.response.data))
   })

   return response.status(200).send()
  } catch (error) {
   return response.status(400).send(error)
  }
 }
}             
import { SendPlanUpgradeController } from './SendPlanUpgradeController'

export const sendPlanUpgradeController = new SendPlanUpgradeController()         

12- O SendPlanUpgradeController precisa da função transformMoney, crie no arquivo src/utils/transformMoney.ts:

export const transformMoney = (value?: number) => {
 if (!value) {
  return ''
 }
 const money = value.toString().split('.')
 return `R$ ${money[0]},${money[1]}`
}                                         

Sua aplicação está pronta. Sevocê já cumpriu com todos os passos anteriores, para testá-la, basta executar o script dev. Após a inicialização da aplicação, o servidor ouvirá a porta 4000. Você pode fazer uma requisição GET ao URL http://localhost:4000/sendPlanUpgrade. Abrindo este URL no seu navegador, a aplicação fará uma busca ao banco de dados e irá procurar quem não tem o plano mais caro para enviar a estas pessoas uma proposta de upgrade via SMS.

Lembre-se que para usar a API de Voz Zenvia, após criar sua conta na plataforma, é preciso utilizar o API-TOKEN gerado pela Zenvia. Você pode acessar o projeto final da aplicação produzida neste tutorial no nosso repositório do github.

Categorias:
Escrito por

Vitor Pereira

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Leia também

Fique por dentro e confira as nossas dicas sobre o mercado mobile e interação digital.