התראות (Dialogflow)

אפשרויות נוספות ב-Dialogflow

אפשר ללחוץ על המשך כדי לייבא את דוגמת ההתראות מ-Dialogflow. לאחר מכן, מבצעים את הפעולות הבאות כדי לפרוס את הדוגמה ולבדוק אותה:

  1. צריך להזין שם נציג וליצור נציג חדש ב-Dialogflow לדוגמה.
  2. כשמסיימים לייבא את הנציג, לוחצים על מעבר לנציג.
  3. מתפריט הניווט הראשי, עוברים אל מילוי הזמנה.
  4. מפעילים את עורך מוטבע ולוחצים על פריסה. העורך מכיל את הקוד לדוגמה.
  5. בתפריט הניווט הראשי, נכנסים אל Integrations (שילובים) ולוחצים על Google Assistant.
  6. בחלון החלון הקופץ, מפעילים את האפשרות שינויים בתצוגה מקדימה אוטומטית ולוחצים על בדיקה כדי לפתוח את סימולטור הפעולות.
  7. בסימולטור, מזינים Talk to my test app כדי לבדוק את הטעימה!
המשך

הפעולה יכולה לשלוח התראות למשתמשים בכל פעם שהדבר רלוונטי, למשל שליחת תזכורת כשתאריך היעד של המשימה מתקרב.

במדריך הזה אנחנו משתמשים בדוגמה לטיפים בנושא פעולות ב-Google כדי להראות לכם איך להגדיר התראות על פעולה מסוימת. כשהמשתמשים מפעילים את הפעולה, השאלה אם הם רוצים לשמוע טיפ על פיתוח פעולה משלהם. המשתמשים יכולים לבחור לטיפ קטגוריה ספציפית או אקראית, או לשמוע את הטיפ העדכני ביותר.

פלטפורמות נתמכות

ההתראות זמינות במכשירי Android ו-iOS (כדי לקבל התראות, אפליקציית Assistant צריכה להיות מותקנת במכשירי iOS). הם לא נתמכים כרגע ברמקולים עם הפעלה קולית, במסכים חכמים או בפלטפורמות אחרות.

דרישות מוקדמות

צריך להגדיר לפחות אחת מהפעולות בפרויקט הפעולות כ-Intent הפעלה, שיופעל כשהמשתמש יקיש על התראה שמתקבלת מ-Assistant.

לא ניתן להגדיר את הפעולות כך שיפעילו את Intent קבלת הפנים שמוגדר כברירת מחדל מהתראה.

הגדרת מסוף

כדי להוסיף לפעולה תמיכה בהתראות:

  1. נכנסים ל-Actions Console ולוחצים על Build > Actions (בנייה > פעולות).

  2. לוחצים על הפעולה שתואמת ל-Intent הטריגר הנוסף שעבורו רוצים להפעיל התראות.

    כדי לראות את הדוגמה לטיפים של Actions on Google, עליך לבחור באפשרות "tell_minute_tip".

  3. גוללים למטה לקטע User engagement ומפעילים את האפשרות רוצה לשלוח התראות?.

  4. מזינים את שם התוכן.

    בדוגמה של הטיפים ל-Actions on Google, הכותרת יכולה להיות "נוסף טיפ חדש".

  5. לוחצים על שמירה.

יבוא

לצורך הסעיפים הבאים, צריך להצהיר על פעולות הייבוא הבאות בקוד ההפצה:

Dialogflow
const {
  dialogflow,
  UpdatePermission,
  Suggestions,
} = require('actions-on-google');
Actions SDK
const {
  actionssdk,
  UpdatePermission,
  Suggestions,
} = require('actions-on-google');

צירוף משתמשים

לפני שתוכלו לשלוח התראות למשתמשים, עליכם לבקש מהם להביע הסכמה. כדי לעשות את זה, אפשר להציג להם צ'יפ של הצעה ולבקש את רשותם. כשהוא מעניק הרשאה, אתם מקבלים מזהה משתמש מעודכן לשליחת התראות למשתמש הזה.

הצגת צ'יפים של הצעות להצטרפות

כדי שהמשתמשים יוכלו לקבל התראות מהפעולה, עליכם להציג להם צ'יפ הצעה שבאמצעותו הם יוכלו להביע הסכמה לקבלת התראות.

קטע הקוד הבא שולח למשתמש את צ'יפ ההצעות 'התרעה על טיפים חדשים' לצד תשובת טקסט.

Dialogflow Node.js
conv.ask('I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
Actions SDK Node.js
conv.ask(' I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
Dialogflow Java
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
Actions SDK Java
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
Dialogflow JSON

שימו לב: קובץ ה-JSON שמוצג בהמשך מתאר תגובה של תגובה לפעולה מאתר אחר (webhook).

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "Hi! Welcome to Push Notifications!"
            }
          },
          {
            "simpleResponse": {
              "textToSpeech": "I can send you push notifications. Would you like that?"
            }
          }
        ],
        "suggestions": [
          {
            "title": "Send notifications"
          }
        ]
      }
    }
  }
}
Actions SDK JSON

שימו לב: קובץ ה-JSON שמוצג בהמשך מתאר תגובה של תגובה לפעולה מאתר אחר (webhook).

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ],
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "Hi! Welcome to Push Notifications!"
              }
            },
            {
              "simpleResponse": {
                "textToSpeech": " I can send you push notifications. Would you like that?"
              }
            }
          ],
          "suggestions": [
            {
              "title": "Send notifications"
            }
          ]
        }
      }
    }
  ]
}

אחרי שהמשתמש מקיש על הצ'יפ, עליך לבקש את ההרשאה UPDATE. כאן מוסבר איך לעשות זאת באמצעות הפונקציה askForUpdatePermission בספריית הלקוח של Node.js.

Dialogflow Node.js
  1. פותחים את הנציג במסוף Dialogflow ובוחרים את הכוונה שרוצים להגדיר לעדכונים.
  2. גוללים למטה אל תגובה ופותחים את הכרטיסייה Google Assistant.
  3. לוחצים על הוספת תוכן ההודעה ובוחרים באפשרות צ'יפים של הצעות.
  4. מגדירים את הטקסט של הצ'יפ לטקסט שמזמין את המשתמש להביע הסכמה. בדוגמת הטיפים של Actions on Google, הגדרנו את הצ'יפ אני רוצה לקבל התראות על טיפים חדשים.
  5. אפשר להוסיף עוד Intent ב-Dialogflow, שנקרא לדוגמה setup_push, ולהגדיר פעולה תואמת, כמו setup.push. הביטוי של Intent זה חייב להיות זהה לטקסט של צ'יפ ההסכמה, בדוגמה שלנו בנושא התראת אזהרה לגבי טיפים חדשים.
קטע הקוד הבא מראה איך לבקש את ההרשאה באמצעות ספריית הלקוח Actions on Google עבור Node.js:
app.intent('Subscribe to Notifications', (conv) => {
  conv.ask(new UpdatePermission({
    intent: 'Notification',
  }));
});
Actions SDK Node.js

צריך להגדיר את הפתרון של NLU כך שיפעיל פונקציה שמבקשת את ההרשאה אם ביטוי המשתמש תואם לערך של בקשת ההצטרפות להתראות שנשלחות מהאפליקציה. לפניכם דוגמה בסיסית מאוד המבוססת על התאמת מחרוזות:

conv.ask(new UpdatePermission({
  intent: 'Notification',
}));
Dialogflow Java
  1. פותחים את הנציג במסוף Dialogflow ובוחרים את הכוונה שרוצים להגדיר לעדכונים.
  2. גוללים למטה אל תגובה ופותחים את הכרטיסייה Google Assistant.
  3. לוחצים על הוספת תוכן ההודעה ובוחרים באפשרות צ'יפים של הצעות.
  4. מגדירים את הטקסט של הצ'יפ לטקסט שמזמין את המשתמש להביע הסכמה. בדוגמת הטיפים של Actions on Google, הגדרנו את הצ'יפ אני רוצה לקבל התראות על טיפים חדשים.
  5. אפשר להוסיף עוד Intent ב-Dialogflow, שנקרא לדוגמה setup_push, ולהגדיר פעולה תואמת, כמו setup.push. הביטוי של Intent זה חייב להיות זהה לטקסט של צ'יפ ההסכמה, בדוגמה שלנו בנושא התראת אזהרה לגבי טיפים חדשים.
קטע הקוד הבא מראה איך לבקש את ההרשאה באמצעות ספריית הלקוח Actions on Google Java/Kotlin:
@ForIntent("Subscribe to Notifications")
public ActionResponse subscribeToNotifications(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  responseBuilder.add(new UpdatePermission().setIntent("Notification"));
  return responseBuilder.build();
}
Actions SDK Java

צריך להגדיר את הפתרון של NLU כך שיפעיל פונקציה שמבקשת את ההרשאה אם ביטוי המשתמש תואם לערך של בקשת ההצטרפות להתראות שנשלחות מהאפליקציה. לפניכם דוגמה בסיסית מאוד המבוססת על התאמת מחרוזות:

ResponseBuilder responseBuilder = getResponseBuilder(request);
responseBuilder.add(new UpdatePermission().setIntent("Notification"));
return responseBuilder.build();
Dialogflow JSON

הערה: בקובץ ה-JSON שמוצג בהמשך מתוארת תגובה של תגובה לפעולה מאתר אחר (webhook) באמצעות Dialogflow.

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.PERMISSION",
        "data": {
          "@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
          "permissions": [
            "UPDATE"
          ],
          "updatePermissionValueSpec": {
            "intent": "tell_latest_tip"
          }
        }
      }
    }
  }
}
Actions SDK JSON

הערה: קובץ ה-JSON שמוצג בהמשך מתאר תגובה של תגובה לפעולה מאתר אחר (webhook) באמצעות Actions SDK.

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.PERMISSION",
          "inputValueData": {
            "@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
            "permissions": [
              "UPDATE"
            ],
            "updatePermissionValueSpec": {
              "intent": "tell_latest_tip"
            }
          }
        }
      ]
    }
  ]
}

סיום המינוי

כדי לסיים את ההרשמה ל-Node.js webhook, צריך לשמור את מזהה ההתראות של המשתמש ואת הכוונה שהוא בחר. שניהם מועברים כארגומנטים אם המשתמש מעניק את ההרשאה.

אם הפעולה נוצרה באמצעות Dialogflow, צריך:

  • יש להוסיף Intent שמטפל ב-actions_intent_PERMISSION.
  • צריך לציין את שם ה-Action של ה-Intent בשביל משהו שהתגובה לפעולה מאתר אחר (webhook) יכולה לסנן אותו למועד מאוחר יותר.

בקוד הבא מוסבר איך מטפלים באובייקטים מסוג Intent ב-Dialogflow עם אובייקט בשם finish_push_setup, עם שם הפעולה finish.push.setup:

Dialogflow Node.js
app.intent('Confirm Notifications Subscription', (conv) => {
  if (conv.arguments.get('PERMISSION')) {
    const updatesUserId = conv.arguments.get('UPDATES_USER_ID');
    // Store user ID in database for later use
    conv.close(`Ok, I'll start alerting you.`);
  } else {
    conv.close(`Ok, I won't alert you.`);
  }
});
Actions SDK Node.js
app.intent('actions.intent.PERMISSION', (conv) => {
  if (conv.arguments.get('PERMISSION')) {
    const updatesUserId = conv.arguments.get('UPDATES_USER_ID');
    // Store user ID in database for later use
    conv.close(`Ok, I'll start alerting you.`);
  } else {
    conv.close(`Ok, I won't alert you.`);
  }
});
Dialogflow Java
@ForIntent("Confirm Notifications Subscription")
public ActionResponse confirmNotificationsSubscription(ActionRequest request) {
  // Verify the user has subscribed for push notifications
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isPermissionGranted()) {
    Argument userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
    if (userId != null) {
      // Store the user's ID in the database
    }
    responseBuilder.add("Ok, I'll start alerting you.");
  } else {
    responseBuilder.add("Ok, I won't alert you.");
  }
  responseBuilder.endConversation();
  return responseBuilder.build();
}
Actions SDK Java
@ForIntent("actions.intent.PERMISSION")
public ActionResponse confirmNotificationsSubscription(ActionRequest request) {
  // Verify the user has subscribed for push notifications
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isPermissionGranted()) {
    Argument userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
    if (userId != null) {
      // Store the user's ID in the database
    }
    responseBuilder.add("Ok, I'll start alerting you.");
  } else {
    responseBuilder.add("Ok, I won't alert you.");
  }
  responseBuilder.endConversation();
  return responseBuilder.build();
}
Dialogflow JSON

הערה: בקובץ ה-JSON שבהמשך מתוארת בקשה ל-webhook.

{
  "responseId": "ee9e7ed5-fa1a-48c6-aac7-f9fbe94f1f58-712767ed",
  "queryResult": {
    "queryText": "actions_intent_PERMISSION",
    "action": "confirm.subscription",
    "parameters": {},
    "allRequiredParamsPresent": true,
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            ""
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_screen_output"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_account_linking"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_media_response_audio"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_audio_output"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_web_browser"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/google_assistant_input_type_keyboard"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_intent_permission",
        "parameters": {
          "PERMISSION": true,
          "text": "yes",
          "UPDATES_USER_ID": "ABwppHHssyPbvEBF1mgN7Ddwb7mkhiVohW9PZ--I_svqy7zFElA4DHkf9pn04UBd5gwZo26_RfXCQ8otcztyIfe6MCQ"
        }
      }
    ],
    "intent": {
      "name": "projects/PROJECT_ID/agent/intents/c7f7b30b-5b88-4bb5-b0b8-1cd0862d1dd2",
      "displayName": "Confirm Notifications Subscription"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en"
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "user": {
        "permissions": [
          "UPDATE"
        ],
        "locale": "en-US",
        "userVerificationStatus": "VERIFIED"
      },
      "conversation": {
        "conversationId": "ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k",
        "type": "ACTIVE",
        "conversationToken": "[]"
      },
      "inputs": [
        {
          "intent": "actions.intent.PERMISSION",
          "rawInputs": [
            {
              "inputType": "KEYBOARD",
              "query": "yes"
            }
          ],
          "arguments": [
            {
              "name": "PERMISSION",
              "boolValue": true,
              "textValue": "true"
            },
            {
              "name": "text",
              "rawText": "yes",
              "textValue": "yes"
            },
            {
              "name": "UPDATES_USER_ID",
              "textValue": "ABwppHHssyPbvEBF1mgN7Ddwb7mkhiVohW9PZ--I_svqy7zFElA4DHkf9pn04UBd5gwZo26_RfXCQ8otcztyIfe6MCQ"
            }
          ]
        }
      ],
      "surface": {
        "capabilities": [
          {
            "name": "actions.capability.SCREEN_OUTPUT"
          },
          {
            "name": "actions.capability.ACCOUNT_LINKING"
          },
          {
            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
          },
          {
            "name": "actions.capability.AUDIO_OUTPUT"
          },
          {
            "name": "actions.capability.WEB_BROWSER"
          }
        ]
      },
      "availableSurfaces": [
        {
          "capabilities": [
            {
              "name": "actions.capability.AUDIO_OUTPUT"
            },
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            },
            {
              "name": "actions.capability.WEB_BROWSER"
            }
          ]
        }
      ]
    }
  },
  "session": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k"
}
Actions SDK JSON

הערה: בקובץ ה-JSON שבהמשך מתוארת בקשה ל-webhook.

{
  "user": {
    "permissions": [
      "UPDATE"
    ],
    "locale": "en-US",
    "userVerificationStatus": "VERIFIED"
  },
  "conversation": {
    "conversationId": "ABwppHEP6OAFZHkSGEiZ5HYM9qrlk8YtIH1DQmJ52cxXELSPvM-kSc_tMJ_5O6ITbgVJlY9i2FIsKWjE_HXLke48",
    "type": "NEW"
  },
  "inputs": [
    {
      "intent": "actions.intent.PERMISSION",
      "rawInputs": [
        {
          "inputType": "KEYBOARD",
          "query": "yes"
        }
      ],
      "arguments": [
        {
          "name": "PERMISSION",
          "boolValue": true,
          "textValue": "true"
        },
        {
          "name": "text",
          "rawText": "yes",
          "textValue": "yes"
        },
        {
          "name": "UPDATES_USER_ID",
          "textValue": "ABwppHFvBKC-tMYUsUjJkm3YECgZvd6A3sOc7KuQvO4ZdQX3bGLmyoQ41dh4Zmtlzv_kaOKBt1Sf6eRpNbayynrl"
        }
      ]
    }
  ],
  "surface": {
    "capabilities": [
      {
        "name": "actions.capability.AUDIO_OUTPUT"
      },
      {
        "name": "actions.capability.WEB_BROWSER"
      },
      {
        "name": "actions.capability.SCREEN_OUTPUT"
      },
      {
        "name": "actions.capability.ACCOUNT_LINKING"
      },
      {
        "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
      }
    ]
  },
  "availableSurfaces": [
    {
      "capabilities": [
        {
          "name": "actions.capability.AUDIO_OUTPUT"
        },
        {
          "name": "actions.capability.SCREEN_OUTPUT"
        },
        {
          "name": "actions.capability.WEB_BROWSER"
        }
      ]
    }
  ]
}

שליחת התראות

אפשר לשלוח התראות למשתמשים באמצעות Actions API. כדי להשתמש ב-API הזה, צריך להפעיל את ה-API בפרויקט ב-Google Cloud, להגדיר ולהוריד מפתח חשבון שירות מסוג JSON. אתם יכולים לעיין בשלב 8 בהוראות שמפורטות כאן בדוגמת הקוד.

לאחר מכן תוכלו להשתמש בספריית הלקוח של Google OAuth2 כדי להמיר את המפתח של חשבון השירות באסימון גישה, ולהשתמש באסימון כדי לאמת את הבקשות שלכם ל-Actions API.

קבלת מפתח לחשבון שירות

  1. עוברים לכתובת ה-URL הזו ומחליפים את "example-project-1" במזהה הפרויקט במסוף Actions: https://console.developers.google.com/apis/api/actions.googleapis.com/overview?project=example-project-1
  2. אם מופיע הלחצן הפעלה, לוחצים עליו. אם לא, ממשיכים לשלב 3.
  3. עוברים לכתובת ה-URL הזו ומחליפים את "example-project-1" במזהה הפרויקט במסוף Actions: https://console.developers.google.com/apis/credentials?project=example-project-1
  4. לוחצים על Create credentials > Service Account Key.
  5. לוחצים על התיבה Select בקטע Service Account ולוחצים על New Service Account.
  6. נותנים לחשבון השירות שם כמו "התראות" והתפקיד של בעלי הפרויקט.
  7. בוחרים את סוג המפתח של JSON ולוחצים על יצירה. מורידים למחשב המקומי מפתח של חשבון שירות מסוג JSON.

להחליף את המפתח באסימון גישה ולשלוח התראה

כדי לשלוח התראה דרך Actions API, צריך להמיר את המפתח של חשבון השירות באסימון גישה. לשם כך מומלץ להשתמש בספריית לקוח של Google API. בסדרת קטעי הקוד שלאחר מכן, אנחנו משתמשים בספריית הלקוח של Google API Node.js.

  1. מתקינים את ספריית הלקוח של Google API ומבקשים: npm install googleapis request --save
  2. תוכלו להשתמש בקוד הבא כדי לקבל אסימון גישה מהמפתח של חשבון השירות ולשלוח התראה:
Dialogflow Node.js
const {google} = require('googleapis');
const request = require('request');

const jwtClient = new google.auth.JWT(
  serviceAccount.client_email, null, serviceAccount.private_key,
  ['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
  null
);

jwtClient.authorize((err, tokens) => {
  if (!err) {
    request.post('https://actions.googleapis.com/v2/conversations:send', {
      auth: {
        bearer: tokens.access_token,
      },
      json: true,
      body: {
        customPushMessage: {
          userNotification: {
            title: 'Push Notification Title',
          },
          target: {
            userId: '<UPDATES_USER_ID>',
            intent: 'Notification Intent',
          },
        },
        isInSandbox: true,
      },
    }, (err, httpResponse, body) => {
      console.log(`${httpResponse.statusCode}: ${httpResponse.statusMessage}`);
    });
  }
});
Actions SDK Node.js
const {google} = require('googleapis');
const request = require('request');

const jwtClient = new google.auth.JWT(
  serviceAccount.client_email, null, serviceAccount.private_key,
  ['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
  null
);

jwtClient.authorize((err, tokens) => {
  if (!err) {
    request.post('https://actions.googleapis.com/v2/conversations:send', {
      auth: {
        bearer: tokens.access_token,
      },
      json: true,
      body: {
        customPushMessage: {
          userNotification: {
            title: 'Push Notification Title',
          },
          target: {
            userId: '<UPDATES_ORDER_ID>',
            intent: 'Notification Intent',
          },
        },
        isInSandbox: true,
      },
    }, (err, httpResponse, body) => {
      console.log(`${httpResponse.statusCode}: ${httpResponse.statusMessage}`);
    });
  }
});
Dialogflow Java
final class Notification {

  private final String title;

  Notification(String title) {
    this.title = title;
  }

  String getTitle() {
    return title;
  }
}

final class Target {

  private final String userId;
  private final String intent;
  private final String locale;

  Target(String userId, String intent, String locale) {
    this.userId = userId;
    this.intent = intent;
    this.locale = locale;
  }

  String getUserId() {
    return userId;
  }

  String getIntent() {
    return intent;
  }

  String getLocale() {
    return locale;
  }
}

final class PushMessage {

  private final Notification userNotification;
  private final Target target;

  PushMessage(Notification userNotification, Target target) {
    this.userNotification = userNotification;
    this.target = target;
  }

  Notification getUserNotification() {
    return userNotification;
  }

  Target getTarget() {
    return target;
  }
}

final class PushNotification {

  private final PushMessage customPushMessage;
  private boolean isInSandbox;

  PushNotification(PushMessage customPushMessage, boolean isInSandbox) {
    this.customPushMessage = customPushMessage;
    this.isInSandbox = isInSandbox;
  }

  PushMessage getCustomPushMessage() {
    return customPushMessage;
  }

  boolean getIsInSandbox() {
    return isInSandbox;
  }
}

private PushNotification createNotification(String title, String userId, String intent, String locale) {
  Notification notification = new Notification(title);
  Target target = new Target(userId, intent, locale);
  PushMessage message = new PushMessage(notification, target);
  boolean isInSandbox = true;
  return new PushNotification(message, isInSandbox);
}

private ServiceAccountCredentials loadCredentials() throws IOException {
  String actionsApiServiceAccountFile =
      this.getClass().getClassLoader().getResource("service-account.json").getFile();
  InputStream actionsApiServiceAccount = new FileInputStream(actionsApiServiceAccountFile);
  ServiceAccountCredentials serviceAccountCredentials =
      ServiceAccountCredentials.fromStream(actionsApiServiceAccount);
  return (ServiceAccountCredentials)
      serviceAccountCredentials.createScoped(
          Collections.singleton(
              "https://www.googleapis.com/auth/actions.fulfillment.conversation"));
}

private String getAccessToken() throws IOException {
  AccessToken token = loadCredentials().refreshAccessToken();
  return token.getTokenValue();
}

public void sendNotification(String title, String userId, String intent, String locale) throws IOException {
  Preconditions.checkNotNull(title, "title cannot be null.");
  Preconditions.checkNotNull(userId, "userId cannot be null.");
  Preconditions.checkNotNull(intent, "intent cannot be null.");
  Preconditions.checkNotNull(locale, "locale cannot be null");
  PushNotification notification = createNotification(title, userId, intent, locale);

  HttpPost request = new HttpPost("https://actions.googleapis.com/v2/conversations:send");

  String token = getAccessToken();

  request.setHeader("Content-type", "application/json");
  request.setHeader("Authorization", "Bearer " + token);

  StringEntity entity = new StringEntity(new Gson().toJson(notification));
  entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
  request.setEntity(entity);
  HttpClient httpClient = HttpClientBuilder.create().build();
  httpClient.execute(request);
}
Actions SDK Java
final class Notification {

  private final String title;

  Notification(String title) {
    this.title = title;
  }

  String getTitle() {
    return title;
  }
}

final class Target {

  private final String userId;
  private final String intent;

  Target(String userId, String intent) {
    this.userId = userId;
    this.intent = intent;
  }

  String getUserId() {
    return userId;
  }

  String getIntent() {
    return intent;
  }
}

final class PushMessage {

  private final Notification userNotification;
  private final Target target;

  PushMessage(Notification userNotification, Target target) {
    this.userNotification = userNotification;
    this.target = target;
  }

  Notification getUserNotification() {
    return userNotification;
  }

  Target getTarget() {
    return target;
  }
}

final class PushNotification {

  private final PushMessage customPushMessage;
  private boolean isInSandbox;

  PushNotification(PushMessage customPushMessage, boolean isInSandbox) {
    this.customPushMessage = customPushMessage;
    this.isInSandbox = isInSandbox;
  }

  PushMessage getCustomPushMessage() {
    return customPushMessage;
  }

  boolean getIsInSandbox() {
    return isInSandbox;
  }
}

private PushNotification createNotification(String title, String userId, String intent) {
  Notification notification = new Notification(title);
  Target target = new Target(userId, intent);
  PushMessage message = new PushMessage(notification, target);
  boolean isInSandbox = true;
  return new PushNotification(message, isInSandbox);
}

private ServiceAccountCredentials loadCredentials() throws IOException {
  String actionsApiServiceAccountFile =
      this.getClass().getClassLoader().getResource("service-account.json").getFile();
  InputStream actionsApiServiceAccount = new FileInputStream(actionsApiServiceAccountFile);
  ServiceAccountCredentials serviceAccountCredentials =
      ServiceAccountCredentials.fromStream(actionsApiServiceAccount);
  return (ServiceAccountCredentials)
      serviceAccountCredentials.createScoped(
          Collections.singleton(
              "https://www.googleapis.com/auth/actions.fulfillment.conversation"));
}

private String getAccessToken() throws IOException {
  AccessToken token = loadCredentials().refreshAccessToken();
  return token.getTokenValue();
}

public void sendNotification(String title, String userId, String intent) throws IOException {
  Preconditions.checkNotNull(title, "title cannot be null.");
  Preconditions.checkNotNull(userId, "userId cannot be null.");
  Preconditions.checkNotNull(intent, "intent cannot be null.");
  PushNotification notification = createNotification(title, userId, intent);

  HttpPost request = new HttpPost("https://actions.googleapis.com/v2/conversations:send");

  String token = getAccessToken();

  request.setHeader("Content-type", "application/json");
  request.setHeader("Authorization", "Bearer " + token);

  StringEntity entity = new StringEntity(new Gson().toJson(notification));
  entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
  request.setEntity(entity);
  HttpClient httpClient = HttpClientBuilder.create().build();
  httpClient.execute(request);
}