https://a.storyblok.com/f/270183/1368x665/6d6d34327e/26jan_dev-blog_devfest.jpg

Construire un jeu d'aventure fantastique avec Rails et RCS

Publié le January 22, 2026

Temps de lecture : 27 minutes

C'est la fin de l'automne au pays de la messagerie. Alors que la température baisse et que les feuilles changent de couleur, vous partez pour une nouvelle quête avec votre fidèle compagnon, Vonage, armé de la magie du RCS...

En octobre de l'année dernière, j'ai assisté au DevFest Nantes en France. Chaque année, cet événement a un thème spécifique et le thème de cette année était "le monde magique des légendes et des contes".

Banner image for DevFest Nantes 2025, with the tagline ‘This year step into the magical world of legends and tales!’”Banner image for DevFest Nantes 2025, with the tagline ‘This year step into the magical world of legends and tales!’Vonage a sponsorisé l'événement et nous avions un stand sur place. Lorsque je discute avec des développeurs à notre stand, j'aime toujours avoir une sorte d'application de démonstration qui montre nos produits. La messagerie professionnelle RCS a pris un essor considérable ces derniers temps, et j'ai donc voulu avoir une démo qui utilise le canal canal RCS de notre Messages API. En tant qu'équipe, nous voulions également nous imprégner du thème de l'événement, et l'application de démonstration était une excellente occasion de montrer certaines des fonctionnalités géniales de la messagerie RCS tout en créant un jeu amusant et engageant qui s'inspire du thème de l'événement. C'est ainsi qu'est né le jeu RCS Fantasy Adventure !

Screen recording of the game being played showing the initial set-up via the web-app and then the first two RCS messages being received and responded to.Screen recording of the game being played.

Bien que l'application ait été conçue comme une démonstration de stand, la même approche pourrait être utilisée pour divers cas d'utilisation professionnels tels que les messages de vente et de marketing. Dans cet article, nous allons passer en revue la mise en œuvre de l'application. Avant d'aborder les détails de la mise en œuvre, nous allons brièvement couvrir le canal RCS de l'API Messages de Vonage, en particulier le canal Carte riche et Réponse suggérée qui ont été utilisées dans l'application.

TL;DR Si vous êtes le genre de développeur qui préfère plonger directement dans le code, n'hésitez pas à consulter le dépôt de l'application de démonstration sur l'espace de travail GitHub de la Communauté. Je ferai également référence à des parties spécifiques de ce dépôt à différents moments de cet article.

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.

Messages API RCS Channel

Une chose m'a frappé lorsque j'ai discuté avec des développeurs au DevFest : même si beaucoup d'entre eux avaient déjà entendu parler de la messagerie RCS, la plupart la considéraient simplement comme une "nouvelle version de SMS" et n'étaient pas conscients de l'ensemble de ses fonctionnalités et de ses capacités.

Nous n'allons pas couvrir tout ce que que RCS peut faire dans ce billet de blog, alors n'hésitez pas à consulter notre documentation pour plus d'informations. Ce que nous allons couvrir, ce sont deux fonctionnalités spécifiques de RCS Messaging que j'ai utilisées dans l'application de démonstration : Les cartes riches et les réponses suggérées.

Qu'est-ce qu'une carte riche ?

Les Rich Cards sont des éléments d'interface utilisateur de la messagerie RCS qui vous permettent de combiner du texte, des médias (tels que des images ou des vidéos) et des puces de suggestion (telles que des suggestions de réponses ou d'actions) dans un seul message.

La mise en page d'une carte peut être ajustée de différentes manières, par exemple en spécifiant une mise en page verticale ou horizontale, et en ajustant la hauteur ou l'alignement du support.

La carte ci-dessous (tirée de notre jeu) est en orientation verticale avec une grande hauteur de média, et contient un titre, une image, un texte de contenu et trois puces de réponse suggérées (boutons).

A screenshot of an example RCS message from the adventure game showing an RCS Rich Card with an image (an adventurer wandering in a tangled forest), a title (Into the Wilds), some text describing the scene (You begin your journey with Lira the unicorn and Tharos the dragon. You reach a fork in the road. Left: Through the Silver Forest, where illusions trick travelers. Right: Over the Windblown Cliffs, where storms never cease.Straight ahead: Across the Misty Marshes, said to hide secret paths), and three button options (Silver Forest, Windblown Cliffs, Misty Marshes)A screenshot of an example RCS message from the adventure game

Pour envoyer cette carte, la charge utile JSON de la demande à l'API Messages ressemblerait à ceci :

{
   "to": "447700900000",
   "from": "Vonage",
   "channel": "rcs",
   "message_type": "card",
   "card": {
      "title": "An answer is needed",
      "text": "Queen Elira looks at you solemnly. The fate of Eldrathia rests in your hands. Will you accept this quest?",
      "media_url": "https://example.com//img/message-media/step-zero.png",
      "media_height": "TALL",
      "media_force_refresh": false,
      "suggestions": [
         {
            "type": "reply",
            "text": "Accept the quest",
            "postback_data": "en-step_one"
         },
         {
            "type": "reply",
            "text": "Ask for more time",
            "postback_data": "en-step_twelve"
         },
         {
            "type": "reply",
            "text": "Refuse the quest",
            "postback_data": "en-step_two"
         }
      ]
   },
   "rcs": {
      "card_orientation": "VERTICAL",
      "image_alignment": "RIGHT"
   }
}

Vous pouvez en savoir plus sur RCS Cartes richesmais il y a quelques points importants à noter ici :

  • La valeur de media_url doit être une URL publiquement accessible pour un fichier d'un type de média pris en charge. Le fichier accessible dans cette URL sera utilisé pour afficher le média (dans le cas de notre application de démonstration, l'image) dans le message de la carte reçu par le lecteur.

  • La valeur de postback_data la propriété de chacun des objets de la base de données suggestions est utilisée par notre application pour déterminer le contenu de la carte qui sera ensuite envoyée à l'utilisateur. Nous y reviendrons plus en détail dans la section suivante.

Que sont les réponses suggérées ?

Les réponses suggérées sont un type de suggestion qui peut être inclus dans les messages RCS Texte, Carte et Carrousel. Elles vous permettent de définir des réponses spécifiques que le destinataire du message peut choisir plutôt que d'utiliser un texte libre.

Si vous regardez l'exemple JSON dans la section Cartes riches ci-dessus, vous verrez que les objets Réponse suggérée contiennent trois propriétés :

  • typedont la valeur est toujours réponse

  • textequi définit le texte affiché sur la puce de suggestion

  • postback_dataqui sont les données incluses dans le message entrant

{
  "type": "reply",
  "text": "Accept the quest",
  "postback_data": "en-step_one"
}

Lorsque le destinataire clique sur une puce de réponse suggérée dans son application de messagerie, cela déclenche une réponse à partir duquel vous pouvez identifier la réponse sélectionnée.

La demande de message entrant sera envoyée à l'adresse du webhook que vous avez spécifiée dans les paramètres de votre application Vonage. La charge utile JSON de cette demande ressemblera à ceci :

{
   "message_uuid": "aaaaaaaa-bbbb-4ccc-8ddd-0123456789ab",
   "timestamp": "2025-02-03T12:14:25Z",
   "to": "Vonage",
   "from": "447700900001",
   "channel": "rcs",
   "message_type": "reply",
   "reply": {
      "id": "en-step_one",
      "title": "Accept the quest"
   }
}

Notez que la valeur de l'attribut titre provient de la propriété text de la réponse sélectionnée. La valeur de la propriété id provient de la propriété postback_data de la réponse sélectionnée.

Plus tard, nous verrons comment la relation entre l'élément postback_data de la réponse suggérée et l'élément id de la réponse créent un flux de travail de messagerie, qui constitue la mécanique de la partie principale du jeu.

Mécanismes de jeu

Commençons par examiner les mécanismes généraux du jeu et le déroulement des opérations.

La configuration initiale du jeu s'effectue via une application web, le jeu proprement dit se déroulant via la messagerie RCS. La raison en est que, bien que le canal de messagerie RCS de l'API Messages prenne en charge les messages sortants et entrants, dans la mise en œuvre actuelle de l'API, la conversation doit être initiée par l'entreprise (c.-à-d. qu'un message sortant doit être envoyé d'abord).

Mécanismes du jeu : Configuration initiale du jeu

La configuration initiale du jeu se fait en plusieurs étapes :

Créer un lecteur

Le point de départ du jeu est un formulaire où l'utilisateur peut créer son joueur en entrant un nom. Pour une mise en œuvre réelle, vous devriez capturer le numéro de téléphone de l'utilisateur à ce stade, mais pour l'application de démonstration, j'utilisais un agent RCS de test avec un numéro de test prédéfini pour l'appareil que nous utilisions sur le stand. Le numéro de cet appareil était défini dans l'environnement, il n'était donc pas nécessaire de capturer le numéro de l'utilisateur à cette étape.

A screenshot of the New Player view from the web application for the adventure game showing a heading (Get ready for a new quest!), some paragraph text (You are about to embark on an exciting adventure! Using the magic of RCS messaging via the Vonage Messages API, you will go on a quest in the kingdom of Eldrathia. Please enter a name to create a new player:), and a form with a ‘Name’ input and a ‘Create Player’ buttonA screenshot of the New Player view from the web application for the adventure gameUne fois le formulaire envoyé, l'application web redirige vers la page Créer un jeu.

Créer un jeu

Cette page affiche un texte initial ainsi qu'un bouton pour démarrer le jeu.

A screenshot of the New Game view from the web application for the adventure game showing some paragraph text (You are a young wizard apprentice in the mystical kingdom of Eldrathia. The Heartfire, source of life and magic in the land, has been extinguished by the evil sorcerer Varnak. Queen Elira calls upon you, a unicorn named Lira, and a dragon named Tharos to recover the Flame Crystal, hidden in the Echoing Peaks. Will you restore the Heartfire — or will darkness consume Eldrathia?), and a ‘Start Quest’ buttonA screenshot of the New Game view from the web application for the adventure gameUne fois le bouton cliqué, l'application web redirige vers une page expliquant que le jeu a commencé et que le destinataire recevra un message RCS sous peu.

A screenshot of the Show Game view from the web application for the adventure game showing a heading (Your quest has begun!) some paragraph text (You will receive a secret message shortly with your first challenge. Good luck, brave adventurer!)A screenshot of the Show Game view from the web application for the adventure gameLe reste du déroulement du jeu se fait alors entièrement par le biais de la messagerie RCS.

Mécanismes de jeu : Flux de messagerie RCS

Le jeu commence à chaque fois par le même message initial, qui invite le joueur à accepter la quête. À partir de ce moment, le message que le joueur reçoit ensuite dépend du choix qu'il a fait (c'est-à-dire de la réponse suggérée qu'il a sélectionnée) dans le message précédent.

A screenshot of an example RCS message from the adventure game showing an RCS Rich Card with an image (Queen Elira), a title (An Answer is Needed), some text describing the scene (Queen Elira looks at you solemnly. The fate of Eldrathia rests in your hands. Will you accept this quest? Accept the quest and travel with Lira and Tharos to the Echoing Peaks. Ask for more time to prepare before leaving. Refuse the quest — it's too dangerous), and three button options (Accept the quest, Ask for more time, Refuse the Quest)A screenshot of an example RCS message from the adventure gameLe joueur peut emprunter plusieurs itinéraires dans le jeu, avec diverses quêtes secondaires, et quelques fins possibles.

Le flux de messages est cependant le même à chaque fois. Le joueur reçoit une carte RCS avec des propositions de réponses. avec des propositions de réponses, il choisit une option de réponse et reçoit un autre message avec d'autres propositions de réponses, et ainsi de suite jusqu'à la fin du jeu où il recevra un dernier message sans aucune proposition de réponse.

Mise en œuvre

Maintenant que nous avons une compréhension générale des cartes RCS et des réponses suggérées, ainsi qu'un aperçu des mécanismes du jeu, il est temps de se plonger dans la mise en œuvre réelle de l'application.

L'application est construite en utilisant Ruby on Rails 8 et le SDK Ruby de Vonagemais vous pouvez suivre la même approche de base avec n'importe quelle technologie de votre choix.

Mise en œuvre : Configuration initiale du jeu

L'implémentation de la configuration initiale du jeu se résume à du code Rails standard. Nous allons l'aborder brièvement maintenant, en commençant par les routes.

Itinéraires

Rails.application.routes.draw do
  scope "/:locale" do
    resources :players, only: %i[new create] do
      resources :games, only: %i[new create show]
    end
  end
  resources :inbound_messages, only: %i[create]
  resources :status_messages, only: %i[create]

  root to: redirect("/#{I18n.default_locale}/players/new")
end

L'application utilise le routage de Rails pour définir les itinéraires. pour définir les itinéraires. Nous définissons nouveau, créer et montrer itinéraires pour jeu et nouveau et créer itinéraires pour joueur. Le jeu sont imbriqués dans les itinéraires joueur et nous examinerons la relation entre ces deux éléments lorsque nous aborderons les modèles.

Des routes sont également définies pour messages_entrant et les messages_étatque nous aborderons lorsque nous étudierons la mise en œuvre de l'intégration RCS.

Une dernière chose à noter est que l'option racine est redirigé vers le chemin nouveau_joueur dans la locale par défaut.

Internationalisation

De même que l'utilisation de default_locale dans la redirection de la page racine vous avez peut-être aussi remarqué que le chemin d'accès au player et jeu mentionnés ci-dessus sont définis en fonction d'un paramètre :locale paramètre de chemin. DevFest Nantes, l'événement pour lequel l'application de démonstration a été construite, s'est déroulé en France et j'ai donc décidé de donner le choix entre le français et l'anglais lors de l'interaction avec le jeu. Le choix des langues a été mis en œuvre en utilisant la fonctionnalité i18n (internationalisation) intégrée à Rails. Si vous souhaitez approfondir la question de l'internationalisation, je vous recommande le Guide Rails. Les fichiers pertinents dans l'application de démonstration pour l'implémentation i18n sont :

Notez que l'internationalisation des messages RCS est gérée séparément de l'internationalisation intégrée à Rails, et sera traitée dans la section sur l'intégration de la messagerie RCS.

Modèles

Il existe des modèles très basiques pour joueur et Jeuavec comme a_beaucoup / appartient_à définie entre eux.

class Player < ApplicationRecord
  has_many :games, dependent: :destroy
end

class Game < ApplicationRecord
  belongs_to :player
end

Le Joueur a un nom que l'on peut voir dans le fichier migration.

Contrôleurs

Les deux contrôleurs pertinents pour la configuration initiale du jeu sont les suivants :

  • Contrôleur de joueurs

  • Contrôleur de jeux

Contrôleur de joueurs

class PlayersController < ApplicationController
  def new
    @player = Player.new
  end

  def create
    @player = Player.new(player_params)
    if @player.save
      redirect_to new_player_game_path(@player)
    else
      render "new"
    end
  end

  private

  def player_params
    params.require(:player).permit(:name)
  end
end

Le Contrôleur de joueurs définit deux actions :

  • A nouvelle qui rend simplement l'action joueurs/nouveaux vue.

  • A créer qui crée un nouveau lecteur l'enregistre dans la base de données, puis redirige vers l'objet chemin_jeu_nouveau_joueur pour ce joueur qui renvoie au chemin Contrôleur de jeux#new action

Contrôleur de jeux

class GamesController < ApplicationController
  def show
    @player = Player.find(params[:player_id])
    @game = Game.find(params[:id])
  end

  def new
    @player = Player.find(params[:player_id])
    @game = @player.games.new
  end

  def create
    @player = Player.find(params[:player_id])
    @game = @player.games.new
    if @game.save
      message = MessagesCreator.new("#{I18n.locale}-step_zero").create_message
      begin
        Vonage.messaging.send(
          from: ENV["RCS_SENDER_ID"],
          to: ENV["MESSAGES_TO_NUMBER"],
          **message
        )
      rescue StandardError => e
        Rails.logger.error("Failed to send message: #{e.message}")
        render "new" and return
      end
      redirect_to player_game_path(@player, @game)
    else
      render "new"
    end
  end
end

Le GamesController définit trois actions :

  • A nouvelle qui rend simplement l'action jeux/nouveau vue.

  • A créer qui crée un nouveau jeu associé au joueurl'enregistre dans la base de données, puis tente d'envoyer un message RCS. Nous allons voir en détail ce que fait le MessageCreator et ce qui se passe dans les étapes begin/rescue lorsque nous nous pencherons sur l'intégration de la messagerie RCS. En termes de configuration initiale du jeu, la partie pertinente de cette action est le fait que si le message est envoyé avec succès, il redirige vers la page chemin_du_jeu_du_joueur pour le joueur et Jeu qui renvoient à l'objet #show .

  • A spectacle qui rend l'action games/show pour le jeu nouvellement créé.

Points de vue

Trois modèles d'affichage sont utilisés lors de la configuration initiale du jeu :

  • A vue joueurs/nouveauxqui contient un texte d'introduction et le formulaire de création d'un nouveau lecteur.

  • A jeux/nouvelle vuequi contient une image et du texte ainsi que le formulaire de création d'un nouveau jeu.

  • A games/show viewqui contient le texte expliquant que le jeu a commencé et que le joueur va recevoir un message RCS.

Les modèles de vue utilisent tous l'API i18n de Rails, en particulier la fonction t de l'alias translate pour interpoler le contenu textuel de la locale définie dans la vue. Par exemple, le modèle games/show appelle la méthode deux fois : une fois pour afficher le message quest_started et une fois pour afficher le texte de l'en-tête intro_paragraph_html de l'intro_paragraph_html.

<h1><%= t "show_game.quest_started" %></h1>
<p><%= @player.name %>, <%= t "show_game.intro_paragraph_html" %></p>

Notez que par défaut, l'API i18n de Rails échappe tout HTML dans les chaînes de texte. L'utilisation de html ajouté à l'élément intro_paragraph_html signifie que le HTML dans ces chaînes de caractères particulières ne ne sera pas échappé. Voir le Guide Rails pour plus d'informations sur cette fonctionnalité.

Mise en œuvre : Flux de messagerie RCS

Jusqu'à présent, nous avons examiné le code MVC standard de Ruby on Rails. Nous allons maintenant explorer le fonctionnement de la messagerie RCS avec l'API Messages de Vonage.

Configuration de l'application

Cette application utilise le SDK Ruby de Vonagede Vonage, en particulier l'initialisateur Vonage Rails Initializerpour s'intégrer à l'API Messages. Nous ne couvrirons pas l'installation ici, voir le README pour des instructions complètes.

Remarque : Vous souhaitez utiliser une autre technologie ? Nous proposons également des SDK dans d'autres langues.

Pour envoyer des messages via l'API Messages, le SDK utilise l'authentification JWT, qui nécessite un identifiant d'application et une clé privée de votre application Vonage.

  • Pour créer une application, allez à la page Créer une application sur le tableau de bord de Vonage, et définissez un nom pour votre application.

  • Si vous avez l'intention d'utiliser une API qui utilise des Webhooks, vous aurez besoin d'une clé privée. Cliquez sur "Générer une clé publique et privée", votre téléchargement devrait démarrer automatiquement. Conservez-la en lieu sûr ; cette clé ne peut pas être retéléchargée si elle est perdue. Elle suivra la convention de nommage suivante private_<votre identifiant d'application>.key. Cette clé peut maintenant être utilisée pour authentifier les appels à l'API. Remarque : votre clé ne fonctionnera pas tant que votre application n'aura pas été sauvegardée.

  • Choisissez les fonctionnalités dont vous avez besoin (par exemple, Voice, Messages, RTC, etc.) et fournissez les webhooks requis (par exemple, URL d'événement, URL de réponse ou URL de message entrant). Ces éléments seront décrits dans le tutoriel.

  • Pour sauvegarder et déployer, cliquez sur "Générer une nouvelle application" pour finaliser la configuration. Votre application est maintenant prête à être utilisée avec les API de Vonage.

Lors de la configuration de votre Applications Vonage :

  • Activer l'API Messages.

  • Définissez les URL des webhooks Inbound et Status à l'URL de base de votre application (ou à l'URL de Ngrok en cas de développement local), suivie de /inbound_messages et de /status_messages respectivement.

L'initialisateur Rails utilise soit des variables d'environnement ou les informations d'identification Rails pour charger vos informations d'identification. Pour cette démo, nous avons utilisé les variables d'environnement :

VONAGE_APPLICATION_ID=your-app-id
VONAGE_PRIVATE_KEY=path/to/private.key

En cas d'exécution locale, placez la clé privée dans le répertoire racine. Pour la production, utilisez une méthode sécurisée adaptée à votre plateforme de déploiement.

Si vous regardez le fichier .env-example du référentiel, vous verrez que trois autres variables d'environnement y sont définies :

  • RCS_SENDER_ID. Il s'agit de l'identifiant de l'expéditeur ( sender_id de l'agent RCS Agent que vous utilisez pour envoyer les messages

  • NOMBRE_DE_MESSAGES. Il s'agit du numéro auquel les messages sont envoyés.

  • BASE_URL. Il s'agit de l'URL de base de l'application. Il peut s'agir d'une URL locale/de test (par exemple, une URL de l'application ngrok tunnel) ou une URL de production.

Création et envoi de messages

API Messages Vonage

L'API Messages attend un formulaire POST avec une charge utile JSON qui décrit le type et le contenu du message à envoyer. Par exemple, la charge utile pour l'envoi d'un message texte RCS ressemblerait à ceci :

{
   "to": "447700900000",
   "from": "Vonage",
   "channel": "rcs",
   "message_type": "text",
   "text": "Hello from Vonage!"
}

Fonctionnalité de messagerie du SDK Ruby de Vonage

Le SDK Ruby de Vonage définit une fonction de messagerie qui renvoie un fichier messagerie qui, à son tour, définit un objet envoyer qui définit à son tour une méthode "send". Cette méthode prend des arguments de type mot-clé, les convertit en JSON et les envoie en tant que charge utile d'un message de type POST à l'API Messages, en ajoutant l'en-tête nécessaire pour l'authentification, etc.

Vous pouvez simplement passer toutes les propriétés JSON comme arguments de mot-clé, bien que le SDK fournisse également des méthodes de commodité pour chaque canal qui prend un sous-ensemble d'arguments et renvoie un hachage qui correspond à la structure attendue. Par exemple, pour créer le message texte RCS ci-dessus, vous pouvez utiliser la méthode rcs comme suit :

message = Vonage.messaging.rcs(
  type: "text',
  message: "Hello from Vonage!"
)

Ce hachage peut ensuite être transmis en tant qu'arguments de mots-clés à la fonction send via la déstructuration :

Vonage.messaging.send(
   to: "447700900000",
   from: "Vonage",
   **message
)

Cette approche peut sembler peu utile pour un message de base tel qu'un message texte, mais pour des types de messages plus complexes tels que RCS card la définition du contenu du message dans un hachage séparé comme celui-ci peut simplifier le flux de travail global.

Notez que les méthodes de commodité prennent également un paramètre opts pour définir les paramètres JSON en dehors du contenu principal du message. Nous y reviendrons un peu plus loin dans cet article.

La classe MessagesCreator

Lorsque nous avons abordé la méthode GamesController#create nous avons brièvement mentionné la classe MessagesCreator. Dans cette section, nous allons détailler l'objectif de cette classe et la manière dont elle est mise en œuvre.

Voyons d'abord ce qui se passe dans l'action action de création dans son intégralité.

  • Nous commençons par récupérer un Joueur de la base de données à l'aide de l'objet player_id fourni dans les paramètres de la requête, et en l'affectant à un objet @joueur variable d'instance

  • Nous créons ensuite un nouveau jeu pour ce joueur et attribuons ce jeu à un objet @gmae une variable d'instance

  • Nous tentons ensuite de sauver cette Jeu dans la base de données.

    • Si la sauvegarde n'est pas réussie, nous rendons le fichier jeux/nouveau .

    • Si la sauvegarde est réussie, nous :

      • Créer un nouveau message à l'aide de la fonction Créateur de messages classe

      • Saisir un début/sauvetage dans lequel nous tentons d'envoyer le message à l'aide de la fonction Messagerie#envoyer du SDK Ruby de Vonage et enregistrer les erreurs si l'appel API renvoie une réponse d'erreur.

      • Rediriger vers la page GamesController#show action

La plupart des étapes ci-dessus sont du code Rails standard, et la fonction Messagerie#envoyer du SDK Ruby de Vonage que nous avons abordé dans une section précédente. Ce que nous n'avons pas encore exploré, c'est cette ligne de code :

message = MessagesCreator.new("#{I18n.locale}-step_zero").create_message

C'est ce que nous allons faire maintenant.

Nous appelons nouveau au créateur de MessagesCreator en passant un argument de type chaîne qui est la valeur locale actuellement définie, interpolée dans la chaîne de caractères '-step_zero'de sorte que la chaîne résultante sera fr-step_zero ou en-step_zero.

L'appel à nouveau instancie un nouveau MessagesCreator sur lequel nous appelons ensuite la fonction create_message en assignant la valeur de retour de cette méthode à un objet message variable locale.

Mais qu'est-ce que c'est exactement ? MessagesCreator, et que fait la fonction create_message fait-elle ?

La classe classe MessagesCreator est une classe personnalisée créée spécifiquement pour cette application de démonstration et est définie dans le fichier app/services/messages_creator.rb .

L'objectif de cette classe est de fournir un moyen de créer la charge utile JSON qui définit la structure et le contenu d'une carte RCS sur la base d'une valeur d'entrée spécifique. en fonction d'une valeur d'entrée spécifique. Par exemple, l'entrée renverra la structure et le contenu de la version française du message étape_zéro (qui est la première carte RCS envoyé au joueur). envoyé au joueur). Si cela n'est pas encore tout à fait logique, cela devrait devenir plus clair au fur et à mesure que nous décomposons l'implémentation de cette classe.

La classe définit une fonction initialiser qui définit la valeur transmise en tant que paramètre data_id (par exemple 'fr-step_zero') à une valeur @data_id . Elle définit également une variable d'instance @data_id Il définit également une variable data_id pour accéder à la valeur de cette variable d'instance.

La classe définit également une fonction create_message et la méthode suivante méthodes suivantes :

  • contenu du message

  • contenu de la carte

  • paramètres_standard

  • message_opts

  • parse_yaml

  • set_base_url_for_media_params

Voyons ce que font toutes ces méthodes.

La méthode create_message

def create_message
  Vonage.messaging.rcs(
    type: "card",
    message: message_content,
    opts: message_opts
  )
end

Cette méthode fait appel à la fonction Messagerie#rcs du SDK Ruby de Vonage dont nous avons parlé plus haut. Elle transmet ici la valeur de type : comme 'carte', la valeur de message : comme valeur de retour de l'appel à la fonction message_content et la valeur de opts : comme valeur de retour de l'appel à la méthode message_opts .

Cette méthode renvoie un hachage qui définit la structure et le contenu du message RCS, qui peut ensuite être utilisé comme partie de la charge utile JSON dans la demande envoyée à l'API Messages de Vonage.

La méthode message_content

def message_content
  content = card_content
  set_base_url_for_media_params(content)
  content.merge(standard_params)
end

Cette méthode appelle la fonction contenu_carte de la méthode card_content. Comme nous le verrons prochainement, la méthode card_content renvoie un hachage de clés et de valeurs qui définissent une partie de la structure et du contenu de la charge utile JSON de la demande d'API de carte RCS. Le retour de cet appel de méthode est assigné à un fichier contenu variable locale.

L'option set_base_url_for_media_params est ensuite appelée, en passant le paramètre contenu comme argument. Cette méthode met à jour la valeur du champ media_url dans la clé contenu pour inclure ce qui a été défini comme BASE_URL dans nos variables d'environnement. Ainsi, l'URL fournie à l'API Messages est l'URL publique complète requise pour accéder à l'image spécifique.

Le contenu est ensuite fusionné avec le hash retourné par l'appel à la fonction standard_params et le hachage fusionné qui en résulte est renvoyé par la méthode message_content .

La méthode card_content

Cette méthode renvoie un hachage contenant la majorité des propriétés et des valeurs requises pour le message RCS carte dans la charge utile JSON de la demande à l'API Messages.

def card_content
  content_lang = data_id.split("-").first
  content_step = data_id.split("-").last
  parse_yaml("message_content.yml")[content_lang][content_step]
end

Afin de renvoyer le contenu correct de la carte, la méthode utilise la valeur attribuée à l'élément data_id lorsque la méthode MessagesCreator a été instancié. La variable data_id est scindée sur le trait d'union, la première partie de la scission étant affectée à une variable d'instance content_lang et la seconde partie à une variable content_step à une variable content_step. La fonction parse_yaml est ensuite appelée. Cette méthode renvoie les données YAML d'un fichier spécifié sous la forme d'un hachage Ruby. Les valeurs de la variable content_lang et de content_step sont alors utilisées comme clés pour accéder à une partie spécifique des données de ce hachage.

Le fichier message_content.yml est structuré comme suit :

en:
  step_zero:
    title: "An answer is needed"
    text: |
      Queen Elira looks at you solemnly. The fate of Eldrathia rests in your hands. Will you accept this quest?
      • Accept the quest and travel with Lira and Tharos to the Echoing Peaks
      • Ask for more time to prepare before leaving
      • Refuse the quest — it's too dangerous
    media_url: '/img/message-media/step-zero.png'
    suggestions:
      - type: "reply"
        text: "Accept the quest"
        postback_data: "en-step_one"
      - type: "reply"
        text: "Ask for more time"
        postback_data: "en-step_twelve"
      - type: "reply"
        text: "Refuse the quest"
        postback_data: "en-step_two"
  step_one:
    title: "Into the Wilds"
    text: |
      You begin your journey with Lira the unicorn and Tharos the dragon. You reach a fork in the road.
      • Left: Through the Silver Forest, where illusions trick travelers.
      • Right: Over the Windblown Cliffs, where storms never cease.
      • Straight ahead: Across the Misty Marshes, said to hide secret paths.
    media_url: '/img/message-media/step-one.jpg'
    suggestions:
      - type: "reply"
        text: "Silver Forest"
        postback_data: "en-step_three"
      - type: "reply"
        text: "Windblown Cliffs"
        postback_data: "en-step_four"
      - type: "reply"
        text: "Misty Marshes"
        postback_data: "en-step_thirteen"
# rest of YAML data

Vous pouvez consulter l'intégralité du fichier data/messages_content.yml dans son intégralité.

Ainsi, par exemple, si la valeur de content_lang était et en la valeur de content_step était étape_unpuis l'appel de méthode suivant :

parse_yaml("message_content.yml")[content_lang][content_step]

renverrait les données YAML suivantes :

title: "Into the Wilds"
text: |
   You begin your journey with Lira the unicorn and Tharos the dragon. You reach a fork in the road.
   • Left: Through the Silver Forest, where illusions trick travelers.
   • Right: Over the Windblown Cliffs, where storms never cease.
   • Straight ahead: Across the Misty Marshes, said to hide secret paths.
media_url: '/img/message-media/step-one.jpg'
suggestions:
  - type: "reply"
    text: "Silver Forest"
    postback_data: "en-step_three"
  - type: "reply"
    text: "Windblown Cliffs"
    postback_data: "en-step_four"
  - type: "reply"
    text: "Misty Marshes"
    postback_data: "en-step_thirteen"

Sous la forme d'un hash Ruby comme celui-ci :

{
  title: "Into the Wilds",
  text: "You begin your journey with Lira the unicorn and Tharos the dragon. You reach a fork in the road.\n• Left: Through the Silver Forest, where illusions trick travelers.\n• Right: Over the Windblown Cliffs, where storms never cease.\n• Straight ahead: Across the Misty Marshes, said to hide secret paths.",
media_url: "/img/message-media/step-one.jpg",
suggestions: [
  {
    type: "reply",
    text: "Silver Forest",
    postback_data: "en-step_three"
  },
  {
    type: "reply",
    text: "Windblown Cliffs",
    postback_data: "en-step_four"
  },
  {
    type: "reply",
    text: "Misty Marshes",
    postback_data: "en-step_thirteen"
  }
 ]
}

La méthode standard_params

def standard_params
  parse_yaml("message_settings.yml")["standard_params"]
end

Cette méthode est similaire à la méthode contenu_carte en ce sens qu'elle appelle parse_yaml afin d'accéder aux données d'un fichier YAML (messages_settings.yml) et d'accéder à certaines données de ce fichier sous la forme d'un hachage Ruby. La différence est que l'on accède à chaque fois aux mêmes données, à savoir celles qui se trouvent dans le fichier standard_params . Les données YAML définies sont les suivantes :

media_height: "TALL"
media_force_refresh: false

La raison pour laquelle cet ensemble standard de propriétés a été défini est qu'il sera le même pour chaque carte dans la charge utile JSON envoyée à l'API Messages, et le fait de les extraire de cette manière permet d'éviter les répétitions dans le fichier messages_content.yml et les extraire de cette manière permet de supprimer les répétitions dans le fichier messages_content.yml.

La méthode message_opts

def message_opts
  parse_yaml("message_settings.yml")["card_opts"]
end

Cette méthode est pratiquement identique à la méthode standard_params mais elle renvoie un hachage permettant de définir les options du message en dehors de la méthode carte . Les données YAML définies auxquelles accède cette méthode sont les suivantes :

rcs:
  card_orientation: "VERTICAL"
  image_alignment: "RIGHT"

Il est utilisé pour définir l'option rcs dans la charge utile JSON de la demande à l'API Messages, et sera le même pour chaque demande.

La méthode parse_yaml

def parse_yaml(filename)
  YAML.load_file(Rails.root.join("data", filename))
end

C'est cette méthode qui est utilisée dans le card_content, standard_paramset message_opts sont utilisées. Il appelle la méthode load_file de la méthode YAML (qui fait partie de la bibliothèque standard de Ruby). Cette méthode lit le YAML à partir du fichier spécifié et le désérialise en un objet Ruby approprié à la façon dont le fichier est structuré (dans le cas de nos fichiers, un Hash).

La méthode set_base_url_for_media_params

def set_base_url_for_media_params(content)
  if content.key?("media_url")
    content["media_url"] = "#{ENV['BASE_URL']}#{content['media_url']}"
  end
end

Cette méthode est appelée dans le champ contenu_du_message du message. L'objectif de cette méthode est de mettre à jour la valeur de l'élément media_url dans le hachage Ruby renvoyé par l'analyse du fichier message_content.yml en Ruby. Les différentes cartes du fichier YAML ont leur clé media_url est définie comme le chemin d'accès au fichier multimédia situé à la racine de l'application Rails, par exemple /img/message-media/step-zero.png. Cependant, pour que l'image soit affichée dans le message RCS, le fichier image doit être accessible via une URL complète. Cette méthode met donc à jour la valeur de la variable media_url en y ajoutant la valeur de la clé BASE_URL de la variable d'environnement BASE_URL. Par exemple, si BASE_URL a pour valeur https://example.com alors media_url dans ce cas serait mis à jour à https://example.com/img/message-media/step-zero.png.

Résumé

Pour résumer brièvement ce que le MessagesCreator fait :

  • Vous instanciez un nouveau Créateur de messages en lui passant un data_id telle que en-step_zero

  • Appel create_message sur cet objet :

    • Lit le contenu YAML du fichier message_content.yml correspondant à l'objet data_id

    • Met à jour l'adresse media_url pour inclure la valeur BASE_URL

    • Fusionne le contenu du message spécifique avec les paramètres_standard

    • Définir le hachage fusionné comme valeur de l'élément message dans une invocation de la méthode Messagerie#rcs du SDK Ruby de Vonage

    • Lit le contenu YAML du fichier message_settings.yml et définit la valeur désérialisée de la variable card_opts en tant que valeur de l'élément opts dans l'invocation de la commande Messagerie#rcs du SDK Ruby de Vonage

    • Retourne un hash Ruby représentant toutes les cartes RCS card pour l'étape spécifiée. Il peut ensuite être déstructuré en mots-clés paramétrés lors d'une invocation de la commande Messagerie#envoyer du SDK Ruby de Vonage.

Nous avons déjà vu ce processus en action dans le contexte de la commande GamesController#create nous allons maintenant l'examiner dans le contexte d'une action de réponse dans l'action InboundMessagesController#create dans l'action InboundMessagesController#create.

Le contrôleur de messages entrants

Comme indiqué brièvement plus haut, lorsque le joueur qui a reçu un message de carte RCS tape sur l'une des options de réponse suggérée, cela déclenche une réponse RCS à l'expéditeur du message initial (dans ce cas, notre agent de test RCS). à l'expéditeur du message initial (dans ce cas, notre agent de test RCS).

Ce message entrant est envoyé par l'API Messages de Vonage à l'URL que vous avez spécifiée comme votre webhook entrant lorsque vous avez configuré votre application Vonage. Dans notre application Rails, nous avons une URL /inbound_messages et ce chemin, ainsi que l'URL de base de notre application, est défini en tant que webhook entrant. Tous les messages entrants provenant de l'In-App Messaging API seront donc envoyés à cette route dans notre application, et puisque ces demandes de messages entrants sont des POST l'application Rails les acheminera automatiquement vers une page d'accueil créer dans le contrôleur associé à notre route, dans ce cas le contrôleur InboundMessagesController.

Le contrôleur Contrôleur de messages entrants est est assez simple. Elle appelle une action skip_before_action et définit également la méthode créer et définit également l'action de création. Avant d'examiner l'action créer nous verrons brièvement ce qu'est l'action skip_before_action fait ici.

La méthode skip_before_action

skip_before_action :verify_authenticity_token

L'action skip_before_action est une méthode intégrée au framework Ruby on Rails qui vous permet d'ignorer l'exécution de certains callbacks. Par défaut, chaque fois qu'une action de contrôleur est invoquée dans une application Ruby on Rails, Rails invoque un certain nombre de méthodes de rappel. L'une de ces méthodes de rappel par défaut est verify_authenticity_token. Il s'agit de l'une des nombreuses méthodes utilisées par Numbers pour se protéger contre les attaques de type Cross-Site Request Forgery (CSRF). Vous pouvez en savoir plus à ce sujet dans la documentation Ruby on Rails APImais en résumé, cette méthode permet de vérifier que la requête HTTP acheminée vers l'action de votre contrôleur provient de Origine qui est l'application elle-même.

Dans le cas de notre demande de message entrant, elle provient de l'API Messages de Vonage et devrait donc normalement être bloquée par l'option verify_authenticity_token . En appelant l'action skip_before_action et en passant la méthode :verify_authenticity_token comme argument, la méthode verify_authenticity_token est ignorée et la requête n'est donc pas bloquée.

L'action Créer

def create
  reply_id = params[:reply][:id].to_s
  message = MessagesCreator.new(reply_id).create_message

  Vonage.messaging.send(
    from: ENV["RCS_SENDER_ID"],
    to: ENV["MESSAGES_TO_NUMBER"],
    **message
  )
  head :ok
end

La charge utile JSON pour le RCS entrant entrant entrant acheminé vers le contrôleur InboundMessagesController#create ressemblera à ceci :

{
   "message_uuid": "aaaaaaaa-bbbb-4ccc-8ddd-0123456789ab",
   "timestamp": "2025-02-03T12:14:25Z",
   "to": "Vonage",
   "from": "447700900001",
   "channel": "rcs",
   "message_type": "reply",
   "reply": {
      "id": "en-step_one",
      "title": "Accept the quest"
   }
}

Ruby on Rails fournit cette charge utile à la fonction créer sous la forme d'un paramètre params (hachage). La partie de la charge utile JSON qui nous intéresse dans le contexte du flux de travail de notre application est le paramètre reply.id à laquelle on accède dans l'action du contrôleur de la manière suivante :

reply_id = params[:reply][:id].to_s

La valeur de l'élément reply.id est ensuite transmise à la fonction MessagesCreator.new . Comme nous l'avons vu dans la section sur la méthode MessagesCreator cette méthode instancie une classe MessagesCreator avec un objet data_id assignée à la valeur de la variable d'instance inbound reply.id de la réponse entrante.

Le créer_message est ensuite appelée sur la méthode MessagesCreator et renvoie un hachage Ruby représentant la structure et le contenu d'une carte RCS card . Ce hachage est ensuite déstructuré en mots-clés paramétrés dans une invocation de la méthode Ce hachage est ensuite déstructuré en mots-clés paramétrés lors de l'invocation de la méthode Messagerie#envoyer du SDK Ruby de Vonage, avec la méthode de et to paramètres.

 Vonage.messaging.send(
    from: ENV["RCS_SENDER_ID"],
    to: ENV["MESSAGES_TO_NUMBER"],
    **message
  )

Les envoyer demande à l'API Messages de Vonage d'envoyer la carte RCS au destinataire. au destinataire. Le joueur reçoit alors ce message RCS carte sélectionne une option de réponse suggérée et le processus se répète.

La dernière chose à mentionner à propos de la commande InboundMessagesController#create est qu'elle renvoie un message 200 sans corps. En effet, si le webhook de Vonage ne reçoit pas de code d'état 200 il réessayera d'envoyer la demande périodiquement pendant les 24 heures suivantes.

Le StatusMessagesController

Le dernier élément de mise en œuvre à mentionner en ce qui concerne le flux de messagerie RCS est le contrôleur StatusMessagesController classe. Lorsque nous avons configuré l'Application Vonage, ainsi que le webhook des messages entrants, nous avons également défini l'URL pour le webhook de l'état des messages. Comme pour le webhook des messages entrants, avec le webhook du Message Status webhook a POST envoyée par l'API Messages de Vonage à une URL prédéfinie. Cependant, au lieu d'être déclenché par un message entrant, il est déclenché par les changements d'état d'un message sortant. Par exemple, si vous envoyez un message RCS sortant via l'API Messages de Vonage et que ce message est rejeté, délivréou luces changements d'état déclencheront un message d'état vers l'URL de votre webhook d'état.

Dans notre application Rails, nous avons défini une route qui transmet ces demandes à notre StatusMessagesController#create pour qu'elles soient traitées.

def create
  p "Status message received: " + params.to_unsafe_h.to_s
  head :ok
end

Notre créer ne fait rien d'autre avec la demande d'état du message que d'envoyer la charge utile à la console. Dans une application réelle, cependant, une certaine logique pourrait être mise en œuvre pour effectuer différentes actions en fonction des différents états. Nous aborderons brièvement cette question, ainsi que d'autres considérations, dans la section suivante.

Les seules autres choses à mentionner à propos du StatusMessagesController sont les suivantes :

  • Il appelle skip_before_action :verify_authenticity_token de la même manière, et pour la même raison, que le contrôleur InboundMessagesController et pour la même raison.

  • Les créer renvoie une valeur de 200 de la même manière, et pour la même raison, que la méthode InboundMessagesController#create.

Mise en œuvre dans le monde réel

Cette application a été conçue comme une démonstration unique pour un événement spécifique. Elle n'est pas destinée à être de qualité production, et la mise en œuvre reflète ce fait. La même approche fondamentale pourrait être utilisée pour une application réelle, mais il y a certains aspects de la mise en œuvre que vous pourriez vouloir aborder différemment.

Stockage des données des messages

Dans notre application, les messages que nous avons envoyés et reçus étaient éphémères - nous n'avons pas conservé d'enregistrement de quelque manière que ce soit. De plus, bien que nous ayons créé Joueur et Jeu dans notre base de données, ces enregistrements ne sont pas utilisés au-delà de la configuration initiale du jeu. Dans un contexte réel, vous pourriez vouloir stocker des enregistrements de messages envoyés et/ou de réponses de destinataires dans une base de données, et relier ces messages à la base de données du jeu et/ou joueur et/ou du joueur.

Transmission des messages de non-réponse

Les créer du contrôleur InboundMessagesController est définie de telle sorte qu'elle s'attend à ce que le message entrant ait un type_de_message de réponse. Nous nous attendons à ce que le destinataire réponde en sélectionnant l'une des options de réponse suggérées, mais dans une situation réelle, il existe de nombreux types de messages RCS que le destinataire pourrait envoyer en réponse. Dans une application de qualité, vous voudrez probablement ajouter une logique conditionnelle à l'action du contrôleur pour gérer les différents types de messages entrants.

Gestion des statuts

Comme indiqué dans la section sur le StatusMessagesController nous ne faisons pas grand-chose avec les données reçues via notre webhook Message Status. Il y a un certain nombre de choses que vous pourriez vouloir considérer dans une application réelle en termes d'ajout de fonctionnalités supplémentaires autour de l'état des messages, par exemple :

  • Si vous conservez les données des messages sortants dans une base de données, vous pouvez utiliser les données d'état pour mettre à jour ces enregistrements.

  • Vous pourriez mettre en œuvre une certaine logique pour réessayer d'envoyer les messages qui ont reçu un message rejeté a été rejeté.

Base de données au lieu de YAML

Étant donné que cette application de démonstration n'était destinée à être utilisée qu'une seule fois, avec un ensemble prédéfini de messages qui n'avaient pas besoin d'être modifiés, l'utilisation de YAML pour définir la structure et le contenu des messages était un choix raisonnable, car il nécessitait moins de frais généraux de développement en termes d'implémentation initiale.

Dans un contexte réel, vous pourriez être amené à créer ou mettre à jour régulièrement plusieurs flux de messagerie, utiliser YAML pour définir les messages pourrait devenir fastidieux et source d'erreurs. Une solution plus robuste pourrait être de stocker les données pour définir les messages RCS dans une base de données, et d'implémenter une sorte d'interface d'administration pour créer et maintenir les objets de message.

Prochaines étapes

Si cet article de blog vous a donné envie de commencer à construire avec les API de Vonage, vous pouvez vous inscrire pour un Account gratuit, consulter notre documentation et nos outils, et vous impliquer dans notre communauté de développeurs !

S'inscrire

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.

Vous avez une question ou souhaitez partager ce que vous construisez ?

Restez connecté et tenez-vous au courant des dernières nouvelles, astuces et événements concernant les développeurs.

Liens utiles

Documentation

Outillage

Communauté

Partager:

https://a.storyblok.com/f/270183/373x376/e8d3211236/karl-lingiah.png
Karl LingiahDéveloppeur Ruby Advocate

Karl est un défenseur des développeurs pour Vonage, qui se concentre sur la maintenance de nos SDK de serveur Ruby et sur l'amélioration de l'expérience des développeurs pour notre communauté. Il aime apprendre, fabriquer des objets, partager ses connaissances et tout ce qui a trait à la technologie du web.