Configurer et recevoir des notifications push

Vous pouvez utiliser les méthodes de la collection Points d'observation pour recevoir des notifications lorsque des données changent dans des formulaires. Cette page fournit une présentation conceptuelle et des instructions pour configurer et recevoir des notifications push.

Présentation

La fonctionnalité de notifications push de l'API Google Forms permet aux applications de s'abonner aux notifications lorsque des données changent dans les formulaires. Les notifications sont généralement transmises à un sujet Cloud Pub/Sub dans les minutes qui suivent la modification.

Pour recevoir des notifications push, vous devez configurer un sujet Cloud Pub/Sub et fournir le nom de ce sujet lorsque vous créez une surveillance pour le type d'événement approprié.

Vous trouverez ci-dessous les définitions des concepts clés utilisés dans cette documentation:

  • Une cible est un emplacement où des notifications sont envoyées. La seule cible compatible est un sujet Cloud Pub/Sub.
  • Un type d'événement est une catégorie de notifications à laquelle une application tierce peut s'abonner.
  • Une montre est une instruction destinée à l'API Forms, qui permet d'envoyer à une cible des notifications pour un type d'événement particulier sur un formulaire donné.

Une fois que vous avez créé une surveillance pour un type d'événement sur un formulaire particulier, sa cible (à savoir un sujet Cloud Pub/Sub) reçoit les notifications de ces événements sur ce formulaire jusqu'à ce que la montre expire. Votre montre dure une semaine, mais vous pouvez la prolonger à tout moment avant qu'elle n'expire en envoyant une requête à watches.renew().

Votre sujet Cloud Pub/Sub ne reçoit que des notifications concernant les formulaires que vous pouvez afficher avec les identifiants que vous fournissez. Par exemple, si l'utilisateur révoque l'autorisation de votre application ou perd l'accès en modification à un formulaire surveillé, les notifications ne sont plus envoyées.

Types d'événements disponibles

L'API Google Forms propose actuellement deux catégories d'événements:

  • EventType.SCHEMA, qui avertit les modifications apportées au contenu et aux paramètres d'un formulaire.
  • EventType.RESPONSES, qui avertit l'envoi des réponses au formulaire (nouvelles et mises à jour).

Réponses aux notifications

Les notifications sont encodées au format JSON et contiennent les éléments suivants:

  • ID du formulaire de déclenchement
  • ID de la montre qui déclenche le déclenchement
  • Type d'événement ayant déclenché la notification
  • Autres champs définis par Cloud Pub/Sub, tels que messageId et publishTime

Les notifications ne contiennent pas de données détaillées sur le formulaire ni sur les réponses. Après chaque notification reçue, un appel d'API distinct est nécessaire pour récupérer les nouvelles données. Pour savoir comment procéder, consultez la section Utilisation suggérée.

L'extrait de code suivant illustre un exemple de notification pour une modification de schéma:

{
  "attributes": {
    "eventType": "SCHEMA",
    "formId": "18Xgmr4XQb-l0ypfCNGQoHAw2o82foMr8J0HPHdagS6g",
    "watchId": "892515d1-a902-444f-a2fe-42b718fe8159"
  },
  "messageId": "767437830649",
  "publishTime": "2021-03-31T01:34:08.053Z"
}

L'extrait de code suivant illustre un exemple de notification pour une nouvelle réponse:

{
  "attributes": {
    "eventType": "RESPONSES",
    "formId": "18Xgmr4XQb-l0ypfCNGQoHAw2o82foMr8J0HPHdagS6g",
    "watchId": "5d7e5690-b1ff-41ce-8afb-b469912efd7d"
  },
  "messageId": "767467004397",
  "publishTime": "2021-03-31T01:43:57.285Z"
}

Configurer un sujet Cloud Pub/Sub

Les notifications sont envoyées aux sujets Cloud Pub/Sub. Depuis Cloud Pub/Sub, vous pouvez recevoir des notifications via un hook Web ou en interrogeant un point de terminaison d'abonnement.

Pour configurer un sujet Cloud Pub/Sub, procédez comme suit:

  1. Remplissez les conditions préalables à l'utilisation de Cloud Pub/Sub.
  2. Configurez un client Cloud Pub/Sub.
  3. Consultez la tarification de Cloud Pub/Sub et activez la facturation pour votre projet de la console développeur.
  4. Créez un sujet Cloud Pub/Sub de l'une des trois manières suivantes:

  5. Créez un abonnement dans Cloud Pub/Sub pour indiquer à Cloud Pub/Sub comment envoyer vos notifications.

  6. Enfin, avant de créer des montres qui ciblent votre sujet, vous devez accorder l'autorisation au compte de service des notifications Forms (forms-notifications@system.gserviceaccount.com) de publier sur votre sujet.

Créer une montre

Une fois que le compte de service des notifications push de l'API Forms peut publier un sujet sur un sujet, vous pouvez créer des notifications à l'aide de la méthode watches.create(). Cette méthode vérifie que le sujet Cloud Pub/Sub fourni peut être atteint par le compte de service des notifications push et échoue s'il ne peut pas atteindre le sujet, par exemple si le sujet n'existe pas ou si vous ne lui avez pas accordé l'autorisation de publication sur ce sujet.

Python

forms/snippets/create_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secret.json", SCOPES)
  creds = tools.run_flow(flow, store)

service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

watch = {
    "watch": {
        "target": {"topic": {"topicName": "<YOUR_TOPIC_PATH>"}},
        "eventType": "RESPONSES",
    }
}

form_id = "<YOUR_FORM_ID>"

# Print JSON response after form watch creation
result = service.forms().watches().create(formId=form_id, body=watch).execute()
print(result)

Node.js

forms/snippets/create_watch.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';

async function runSample(query) {
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const forms = google.forms({
    version: 'v1',
    auth: authClient,
  });
  const watchRequest = {
    watch: {
      target: {
        topic: {
          topicName: 'projects/<YOUR_TOPIC_PATH>',
        },
      },
      eventType: 'RESPONSES',
    },
  };
  const res = await forms.forms.watches.create({
    formId: formID,
    requestBody: watchRequest,
  });
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Supprimer une montre

Python

forms/snippets/delete_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secret.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"
watch_id = "<YOUR_WATCH_ID>"

# Print JSON response after deleting a form watch
result = (
    service.forms().watches().delete(formId=form_id, watchId=watch_id).execute()
)
print(result)

Node.js

formulaires/extraits/delete_watch.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';
const watchID = '<YOUR_FORMS_WATCH_ID>';

async function runSample(query) {
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const forms = google.forms({
    version: 'v1',
    auth: authClient,
  });
  const res = await forms.forms.watches.delete({
    formId: formID,
    watchId: watchID,
  });
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Autorisation

Comme tous les appels à l'API Forms, les appels à watches.create() doivent être autorisés à l'aide d'un jeton d'autorisation. Le jeton doit inclure un champ d'application qui accorde un accès en lecture aux données sur lesquelles des notifications sont envoyées.

Pour que les notifications soient envoyées, l'application doit conserver une autorisation OAuth de l'utilisateur autorisé avec les champs d'application requis. Si l'utilisateur déconnecte l'application, les notifications cessent et la montre peut être suspendue avec une erreur. Pour reprendre les notifications après avoir récupéré l'autorisation, consultez Renouveler une montre.

Lister les cadrans d'un formulaire

Python

form/snippets/list_watches.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secrets.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"

# Print JSON list of form watches
result = service.forms().watches().list(formId=form_id).execute()
print(result)

Node.js

formulaires/extraits/list_watches.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';

async function runSample(query) {
  const auth = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/forms.responses.readonly',
  });
  const forms = google.forms({
    version: 'v1',
    auth: auth,
  });
  const res = await forms.forms.watches.list({formId: formID});
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Renouveler une montre

Python

forms/snippets/renew_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secrets.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"
watch_id = "<YOUR_WATCH_ID>"

# Print JSON response after renewing a form watch
result = (
    service.forms().watches().renew(formId=form_id, watchId=watch_id).execute()
)
print(result)

Node.js

Forms/snippets/renew_watch.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';
const watchID = '<YOUR_FORMS_WATCH_ID>';

async function runSample(query) {
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const forms = google.forms({
    version: 'v1',
    auth: authClient,
  });
  const res = await forms.forms.watches.renew({
    formId: formID,
    watchId: watchID,
  });
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Limitations

Les notifications sont limitées : chaque montre peut recevoir au maximum une notification toutes les 30 secondes. Ce seuil de fréquence est susceptible d'être modifié.

En raison d'une limitation, une seule notification peut correspondre à plusieurs événements. En d'autres termes, une notification indique qu'un ou plusieurs événements se sont produits depuis la dernière notification.

Limites

À tout moment, pour un formulaire et un type d'événement donnés, chaque projet Cloud Console peut avoir:

  • jusqu'à 20 visionnages au total
  • jusqu'à une montre par utilisateur final

De plus, à tout moment, chaque formulaire est limité à 50 observations par type d'événement au total sur l'ensemble des projets Cloud Console.

Une montre est associée à un utilisateur final lorsqu'elle est créée ou renouvelée avec les identifiants de cet utilisateur. Une montre est suspendue si l'utilisateur final associé perd l'accès au formulaire ou révoque l'accès de l'application au formulaire.

Fiabilité

Chaque montre est informée au moins une fois après chaque événement dans toutes les circonstances, sauf exceptionnelles. Dans la grande majorité des cas, les notifications sont délivrées dans les minutes qui suivent un événement.

Erreurs

Si l'envoi des notifications d'une montre échoue continuellement, l'état de la montre passe à SUSPENDED et le champ errorType de la montre est défini. Pour réinitialiser l'état d'une montre suspendue sur ACTIVE et réactiver les notifications, consultez Renouveler une montre.

Utilisation suggérée

  • Utiliser un seul sujet Cloud Pub/Sub comme cible de nombreuses activités d'observation.
  • Lorsque vous recevez une notification sur un sujet, l'ID du formulaire est inclus dans la charge utile de la notification. Utilisez-la avec le type d'événement pour savoir quelles données récupérer et sous quel formulaire.
  • Pour récupérer les données mises à jour après une notification avec EventType.RESPONSES, appelez forms.responses.list().
    • Définissez le filtre de la requête sur timestamp > timestamp_of_the_last_response_you_fetched.
  • Pour récupérer les données mises à jour après une notification avec EventType.SCHEMA, appelez forms.get().