
Compartilhar:
Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.
Crie uma experiência RCS interativa em tempo real com Node.js e Vonage
Tempo de leitura: 7 minutos
Serviços de Comunicação Enriquecida (RCS) estão mudando a forma como as marcas interagem com fãs e clientes. Seja para organizar um evento esportivo global, um festival de música ou simplesmente para criar conversas mais ricas e interativas, o RCS oferece recursos inovadores de mensagens para manter seu público envolvido.
Neste tutorial, vamos combinar o RCS respostas sugeridas, rich cards independentese carrosséis de rich cards em uma única jornada de usuário integrada, que você pode adaptar para esportes, música ou qualquer experiência de usuário em tempo real. Tudo isso usando a API de Mensagens da Vonage Messages API!
>> Resumo: Confira o projeto completo no GitHub
Por que criar experiências interativas em tempo real?
O RCS permite que você vá muito além do SMS. Com mídia rica, botões interativos e feedback em tempo real, você pode:
Aumente o engajamento e as conversões
Forneça conteúdo personalizado instantaneamente
Crie experiências memoráveis e alinhadas à marca diretamente no aplicativo de mensagens padrão do usuário
Hoje, você vai criar um aplicativo que orienta os usuários por uma experiência dinâmica, com várias etapas. Esse exemplo é perfeito para eventos ao vivo, votações de fãs ou ofertas exclusivas.
Nossa missão: do “Jogador do Jogo” aos produtos oficiais
Veja como funciona a jornada do usuário:
O usuário recebe: “Quem vai ganhar?” (Brasil, Alemanha, Empate)
O usuário seleciona “Brasil” → recebe um cartão de votação para o “Melhor Jogador da Partida” (Ronaldinho, Ronaldo, Pelé)
O usuário toca em “Ronaldinho” → vê um carrossel de produtos do Ronaldinho
Você pode facilmente adaptar esse fluxo para eventos musicais, lançamentos de produtos ou qualquer experiência em tempo real.
Pré-requisitos
Antes de começar, você vai precisar de:
Node.js instalado no seu computador
O ngrok está instalado para disponibilizar seu servidor local
Um account da API da Vonage
Um agente registrado do RCS Business Messaging (RBM)
Um celular compatível com RCS para testes
>> Observação: O RCS via Vonage requer uma conta gerenciada. Entre em contato com seu gerente de contas da Vonage para obter acesso ao Modo Desenvolvedor. Por favor, entre em contato com nossa equipe de vendas se você não tiver um Account gerenciado.
Configuração do projeto
Sua aplicação Node será relativamente simples, com uma organização um pouco modular para manter o código organizado e alinhado às melhores práticas modernas. Mas, antes de criar sua aplicação Node, comece criando uma aplicação Vonage para usar a Messages API e executando nossa dependência ngrok.
Exponha seu servidor com o ngrok
Para receber webhooks da Vonage, seu servidor local precisa estar acessível pela internet. Use o ngrok para expor seu servidor. No terminal, execute:
ngrok http 3000Anote a URL HTTPS fornecida pelo ngrok:
por exemplo https://your-ngrok-subdomain.ngrok.io
Você pode ler mais sobre testes com o ngrok nas ferramentas do nosso portal para desenvolvedores.
Crie e configure seu aplicativo da Vonage
Agora, crie seu aplicativo Vonage no Painel do Vonage. Dê um nome ao aplicativo e ative o recurso “Mensagens”.
Creating a new Vonage Messages API application for an RCS-based interactive football experience
Nas configurações do seu aplicativo Vonage:
Defina a URL de entrada como
https://YOUR_NGROK_URL/inbound.Defina a URL de status como
https://example.com/rcs_status.
** Os status das mensagens serão abordados em um artigo futuro.Gere uma chave pública e uma chave privada clicando no botão. Certifique-se de mover seu
private.keyarquivo para o diretório raiz do projeto (rcs-interactive-football) na próxima seção.Salve as alterações.
Em seguida, vincule seu RCS Agent clicando na guia “Vincular contas externas”:
Dashboard view showing the Vonage-Node-RCS application linked to the Vonage RoR RCS external account, with voice and message capabilities enabled.
Crie seu aplicativo Node
Estamos mantendo nosso aplicativo simples e com uma estrutura plana. Você pode conferir o repositório do GitHub para ver o código um pouco mais limpo e organizado.
Sua estrutura de arquivos ficará assim:
rcs-interactive-football/
├── index.js
├── config.js
├── messageTemplates.js
├── messagingService.js
├── .env
├── package.json
└── private.key
Então, vá em frente e crie um novo diretório e inicialize um projeto Node.js:
mkdir rcs-interactive-football
cd rcs-interactive-football
npm init -yInstale os pacotes necessários do Node com Node Package Manager:
npm install express dotenv @vonage/server-sdkexpress: Cria o servidor web.dotenv: Carrega variáveis de ambiente com segurança.@vonage/server-sdk: O SDK do Vonage Node para interagir com a Messages API
E crie os arquivos do seu projeto:
touch index.js config.js messageTemplates.js messagingService.js .envAgora você pode mover sua arquivo private.key que você baixou do painel da Vonage e colocá-lo na raiz do seu projeto.
Configure seu ambiente
No arquivo arquivo .env , adicione suas credenciais e configuração da Vonage:
VONAGE_APPLICATION_ID=your_application_id
VONAGE_API_SIGNATURE_SECRET=your_api_secret
VONAGE_PRIVATE_KEY=./private.key
RCS_SENDER_ID=your_rbm_agent_id
PORT=3000VONAGE_APPLICATION_ID: Seu ID de aplicativo da Vonage, que pode ser encontrado no painel da API.VONAGE_API_SIGNATURE_SECRET= Sua senha exclusiva da Vonage. Encontrada em configurações da conta.VONAGE_PRIVATE_KEY: Seu arquivo de chave privada.RCS_SENDER_ID: Seu SenderID do RBM (o nome da marca). O SenderID deve seguir uma formatação específica, como, por exemplo, não conter espaços. Se tiver dúvidas, consulte seu gerente de Account.PORT: Número da porta do servidor Express.
Crie seu aplicativo de nó RCS
Passo 1: Configure seu cliente Vonage
Este aplicativo centraliza todos os valores configuráveis (variáveis de ambiente, URLs de imagens e links externos) em um único arquivo config.js. Isso cria uma separação clara entre conteúdo e lógica. Essa abordagem oferece uma única fonte de referência para valores que possam sofrer alterações. Essa organização permite que você troque rapidamente recursos de mídia ou atualize links de produtos, mantendo intacto o fluxo central de mensagens.
// config.js
require('dotenv').config();
module.exports = {
port: process.env.PORT || 3000,
vonage: {
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKey: process.env.VONAGE_PRIVATE_KEY,
signatureSecret: process.env.VONAGE_API_SIGNATURE_SECRET,
},
rcsSenderId: process.env.RCS_SENDER_ID,
images: {
footballMatch: "https://github.com/Vonage-Community/tutorial-messages-node-rcs_realtime_football/blob/main/public/football_match.png?raw=true",
manOfMatch: "https://github.com/Vonage-Community/tutorial-messages-node-rcs_realtime_football/blob/main/public/man_of_match.png?raw=true",
jersey: "https://github.com/Vonage-Community/tutorial-messages-node-rcs_realtime_football/blob/main/public/ronaldinho_jersey.png?raw=true",
photo: "https://github.com/Vonage-Community/tutorial-messages-node-rcs_realtime_football/blob/main/public/ronaldinho_photo.png?raw=true",
tshirt: "https://github.com/Vonage-Community/tutorial-messages-node-rcs_realtime_football/blob/main/public/ronaldinho_shirt.png?raw=true",
},
merchLinks: {
jersey: "https://www.ebay.com/b/Ronaldinho-International-Club-Soccer-Fan-Jerseys/2887/bn_16948843",
photo: "https://www.ebay.com/shop/ronaldinho-signed-photo?_nkw=ronaldinho+signed+photo",
tshirt: "https://www.ebay.com/itm/236003366810?_skw=ronaldinho+tshirt",
}
}; Etapa 2: Defina seus modelos de mensagem RCS
A seguir, vamos preencher nosso arquivo messageTemplate.js . O módulo `messageTemplates.js` encapsula todas as estruturas de mensagens RCS em funções organizadas e reutilizáveis, que separam a apresentação da lógica de negócios.
Cada função de modelo (respostas sugeridas, rich cards independentes ou carrosséis de rich cards) segue o mesmo padrão. Ela aceita um parâmetro de número de telefone, obtém a mídia e os URLs apropriados do nosso módulo de configuração e, em seguida, retorna um objeto de mensagem RCS devidamente formatado, pronto para a API da Vonage.
Essa abordagem modular torna nosso fluxo interativo fácil de entender e modificar, permitindo que os desenvolvedores adaptem rapidamente os modelos aos seus próprios cenários de interação em tempo real, sem precisar se debruçar sobre uma lógica complexa de mensagens.
Assim, por exemplo, na documentação do Messages, você pode ver o exemplo resposta sugerida:
vonage.messages.send({
messageType: 'custom',
channel: Channels.RCS,
custom: {
contentMessage: {
text: 'What do you think of Vonage APIs?',
suggestions: [
{
reply: {
text: 'They\''re great!',
postbackData: 'suggestion_1',
},
},
{
reply: {
text: 'They\'re awesome!',
postbackData: 'suggestion_2',
},
},
],
},
},
to: MESSAGES_TO_NUMBER,
from: RCS_SENDER_ID,
})
Da mesma forma, você pode criar uma initialMessage função no seu messagesTemplate.js . Essa versão modularizada abstrai o destinatário e o SenderID:
// messageTemplates.js
const config = require('./config');
module.exports = {
// Initial Suggested Reply Message to Kick-off
initialMessage: (to) => ({
to,
from: config.rcsSenderId,
channel: 'rcs',
message_type: 'custom',
custom: {
contentMessage: {
text: "Who will win?",
suggestions: [
{ reply: { text: "Brazil", postbackData: "brazil" }},
{ reply: { text: "Germany", postbackData: "germany" }},
{ reply: { text: "Draw", postbackData: "draw" }},
]
}
}
})
};Continue adicionando os modelos para o RCS Standalone Rich Card e o RCS Rich Card Carousel. Além disso, eles abstraem a mídia, que obtemos do nosso módulo de configuração. Primeiro, o Standalone Card, que permite que os usuários votem no jogador do jogo:
// Standalone Rich Card for voting on Man of the Match
manOfTheMatchMessage: (to) => ({
to,
from: config.rcsSenderId,
channel: 'rcs',
message_type: 'custom',
custom: {
contentMessage: {
richCard: {
standaloneCard: {
thumbnailImageAlignment: "RIGHT",
cardOrientation: "VERTICAL",
cardContent: {
title: "Vote Now!",
description: "Who was the man of the match?",
media: {
height: "TALL",
contentInfo: {
fileUrl: config.images.manOfMatch,
forceRefresh: true
}
},
suggestions: [
{ reply: { text: "Ronaldinho", postbackData: "ronaldinho" } },
{ reply: { text: "Ronaldo", postbackData: "ronaldo" } },
{ reply: { text: "Pele", postbackData: "pele" } }
]
}
}
}
}
}
})E, por fim, crie o modelo de mensagem para o carrossel do RCS, que mostra aos usuários os produtos que eles podem comprar.
// RCS Rich Card Carousel for Player Merch to Present
playerMerchCarousel: (to) => ({
to,
from: config.rcsSenderId,
channel: 'rcs',
message_type: 'custom',
custom: {
contentMessage: {
richCard: {
carouselCard: {
cardWidth: "MEDIUM",
cardContents: [
{
title: "Ronaldinho Jersey",
description: "Authentic gameworn kit.",
media: {
height: "TALL",
contentInfo: {
fileUrl: config.images.jersey,
forceRefresh: true
}
},
suggestions: [
{
action: {
text: "Buy now",
postbackData: "buy_now_jersey",
openUrlAction: {
url: config.merchLinks.jersey
}
}
}
]
},
{
title: "Autographed Photo",
description: "Timeless photo signed by Ronaldinho himself.",
media: {
height: "TALL",
contentInfo: {
fileUrl: config.images.photo,
forceRefresh: true
}
},
suggestions: [
{
action: {
text: "Buy now",
postbackData: "buy_now_photo",
openUrlAction: {
url: config.merchLinks.photo
}
}
}
]
},
{
title: "Fan T-shirt",
description: "100% Cotton, 100% Passion.",
media: {
height: "TALL",
contentInfo: {
fileUrl: config.images.tshirt,
forceRefresh: true
}
},
suggestions: [
{
action: {
text: "Buy now",
postbackData: "buy_now_shirt",
openUrlAction: {
url: config.merchLinks.tshirt
}
}
}
]
}
]
}
}
}
}
})>> Você pode ver o arquivo arquivo messagesTemplate.js
Etapa 3: Criação de um serviço de mensagens
Agora que já temos nossa configuração e nossos modelos de mensagem definidos, vamos criar um serviço de mensagens que abstraia as interações com a API da Vonage. O módulo messagingService.js utiliza esses modelos de mensagem que já criamos e adiciona a funcionalidade necessária para enviar efetivamente a mensagem por meio da API.
Primeiro, vamos inicializar o cliente Vonage usando nossa configuração:
// messagingService.js
const { Vonage } = require('@vonage/server-sdk');
const config = require('./config');
const messageTemplates = require('./messageTemplates');
// Initialize the Vonage client with our application credentials
const vonage = new Vonage({
applicationId: config.vonage.applicationId,
privateKey: require('fs').readFileSync(config.vonage.privateKey)
});Agora que nosso vonage cliente está pronto, podemos criar a sendInitialMessage funcionalidade, enviando a mensagem com o número de telefone para o cliente:
module.exports = {
sendInitialMessage: async (to) => {
try {
const msg = messageTemplates.initialMessage(to);
const response = await vonage.messages.send(msg);
console.log(`Initial message sent successfully`);
return response;
} catch (error) {
console.error('Error sending initial message:', error);
throw error;
}
}
}Vamos criar mais duas funções ( sendManOfTheMatchMessage e sendPlayerMerchCarousel ) para corresponder às nossas outras duas mensagens:
sendManOfTheMatchMessage: async (to) => {
try {
const msg = messageTemplates.manOfTheMatchMessage(to);
const response = await vonage.messages.send(msg);
console.log(`Man of the Match message sent successfully`);
return response;
} catch (error) {
console.error('Error sending Man of the Match message:', error);
throw error;
}
},
sendPlayerMerchCarousel: async (to) => {
try {
const msg = messageTemplates.playerMerchCarousel(to);
const response = await vonage.messages.send(msg);
console.log(`Merchandise carousel sent successfully`);
return response;
} catch (error) {
console.error('Error sending merchandise carousel:', error);
throw error;
}
}
>> Você pode ver o arquivo arquivo messagesService.js
Etapa 4: Implementar a lógica principal do aplicativo
Agora é hora de reunir tudo em nosso index.js arquivo. É aqui que vamos criar nosso servidor Express, configurar nossas rotas e implementar a lógica de fluxo interativa que torna nossa experiência com o RCS dinâmica e envolvente.
Configurar o servidor Express
Primeiro, vamos configurar o Express e definir o middleware básico para que possamos lidar com solicitações em JSON e codificadas por URL:
// index.js
const express = require('express');
const { verifySignature } = require('@vonage/jwt');
const config = require('./config');
const messagingService = require('./messagingService');
// Initialize Express app
const app = express();
app.use(express.json());
app.use(express.urlencoded());
// Constants
const PORT = config.port;
const VONAGE_API_SIGNATURE_SECRET = config.vonage.signatureSecret;
// Simple home route to confirm server is running
app.get('/', (req, res) => {
res.send('RCS Interactive Football Demo - Server is running!');
}); Acionar a primeira mensagem
Essa rota nos permite iniciar manualmente a conversa com um usuário. Você pode acessá-la usando o Postman ou o cURL para enviar a mensagem inicial “Quem vai ganhar?”.
app.post('/send-initial-message', async (req, res) => {
const toNumber = req.body.to;
try {
await messagingService.sendInitialMessage(toNumber);
res.status(200).json({ message: 'Initial message sent successfully.' });
} catch (error) {
console.error('Error in /send-initial-message:', error);
res.status(500).json({ error: 'Internal server error.' });
}
}); Tratar webhooks de entrada
Agora, a parte mais importante: o manipulador de webhooks que processa as respostas dos usuários e cria nosso fluxo interativo.
A Vonage envia callbacks de webhook quando um usuário interage com sua mensagem RCS. Por isso, verificamos o tipo de canal e o tipo de mensagem:
if (inboundMessage.channel === 'rcs' && inboundMessage.message_type === 'reply')E esperamos que essa interação venha de uma resposta sugerida, de um botão em um cartão ou de um item do carrossel. Os cartões avançados utilizam o postbackData , mas, para respostas sugeridas, precisamos recorrer a um id:
const userSelection = inboundMessage.reply?.postbackData || inboundMessage.reply?.id;
Resumindo, seu inbound webhook fica assim:
app.post('/inbound', async (req, res) => {
// Verify the message signature for security
const token = req.headers.authorization?.split(' ')[1];
if (!token || !verifySignature(token, VONAGE_API_SIGNATURE_SECRET)) {
console.error('Invalid signature');
return res.status(401).json({ error: 'Invalid signature' });
}
const inboundMessage = req.body;
// Only process RCS reply messages
if (inboundMessage.channel === 'rcs' && inboundMessage.message_type === 'reply') {
// Retrieve the postbackData for RCS Cards, id for Suggested Replies
const userSelection = inboundMessage.reply?.postbackData || inboundMessage.reply?.id;
const userNumber = inboundMessage.from;
// Log the inbound message for debugging
console.log(`User ${userNumber} selected: ${userSelection}`);
try {
// Handle different user selections based on our interactive flow
switch (userSelection) {
case 'brazil':
// User selected Brazil - send man of the match voting
console.log(`Sending man of the match message to ${userNumber}`);
await messagingService.sendManOfTheMatchMessage(userNumber);
break;
case 'ronaldinho':
// User selected Ronaldinho - send merchandise carousel
console.log(`Sending player merchandise carousel to ${userNumber}`);
await messagingService.sendPlayerMerchCarousel(userNumber);
break;
default:
// For any other selection, log a confirmation message to the service
console.log(`Sending confirmation for ${userSelection} to ${userNumber}`);
}
// Always return 200 OK to Vonage
res.status(200).end();
} catch (error) {
console.error('Error processing inbound message:', error);
res.status(500).json({ error: 'Internal server error' });
}
} else {
// Not an RCS reply message
console.log('Received non-RCS reply message');
res.status(200).end();
}
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
console.log('RCS Interactive Football Demo is ready!');
});
>> Você pode ver o arquivo arquivo index.js
Como testar seu aplicativo Node RCS
Abra uma nova aba do terminal, separada da aba do ngrok, e inicie seu servidor Express:
node index.jsUse uma ferramenta como o Postman ou o cURL para enviar uma solicitação POST ao seu /send-initial-message ponto de extremidade com o número de telefone do destinatário:
curl -X POST https://YOUR_NGROK_URL/send-initial-message \
-H "Content-Type: application/json" \
-d '{"to": "YOUR_RCS_TEST_NUMBER"}'Veja o fluxo interativo se desenrolar no seu dispositivo!
Example of an RCS Rich Card showcasing a Ronaldinho jersey as part of an interactive football campaign
Conclusão
Ótimo trabalho! Você acabou de criar uma experiência RCS em tempo real e com várias etapas usando o Node.js e a Messages API do Vonage. Ela é modular e fácil de reutilizar. Esse padrão funciona muito bem para esportes, música, varejo ou qualquer evento em que sejam necessárias interações rápidas e engajamento real.
Dito isso, desenvolvemos apenas um ramo do fluxo. Se o usuário escolher a Alemanha ou achar que a partida terminará em um empate, nada acontece… por enquanto! Esses são seus próximos passos. Você já tem os modelos e a arquitetura prontos, então adicionar esses caminhos deve ser bem simples.
Mas não pare por aí!
Experimente combinar isso com a nova API de Localização de Dispositivosda Vonage. Se você souber que um usuário está no estádio ou assistindo ao jogo em um bar, poderá acionar esse fluxo RCS interativo exatamente no momento em que ele tiver maior impacto.
Se você desenvolver o restante do fluxo ou integrar isso ao seu próprio aplicativo de eventos, nos avise. Adoraríamos ver o resultado. Marque VonageDev no X ou dê uma passada na Slack da Comunidade de Desenvolvedores da Vonage e mostre o que você está desenvolvendo.
Compartilhar:
Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.