Credentials
tab. Click the create credentials
dropdown button and then click service account key
. Provide a service account name, select the owner
role, and leave the JSON radio button checked. When you click Create
a JSON file will be downloaded. Leave it in the download folder for now, we will use it later.Create credentials
dropdown button again. Select API key. An API key will be generated and we will get it later. That’s all we need to do on our Google project console.Twilio-Autopilot
. In the directory, add two files to it:webhook.php
to listen to a POST request from Autopilot (more on this to follow). The .env
file is used to store sensitive credentials.GOOGLE_API_KEY='ENTER THE API KEY WE CREATED IN THE PREVIOUS STEP' GOOGLE_APPLICATION_CREDENTIALS=./credentials.json
GOOGLE_API_KEY
is the API key we created in our Google Project. The second environment variable makes reference to a file in our project’s root directory called credentials.json
. Since that doesn’t exist yet, let’s go ahead and create it. Copy the file that was downloaded when we created a service account key on Google to the root directory of our project. Make sure you rename it credentials.json
.$ composer require vlucas/phpdotenv google/apiclient
webhook.php
file to be accessible through a public URL. To do this we will use ngrok. From your terminal run the command:$ php -S localhost:3000
$ ./ngrok http 3000
appointment-booking
.v0.1
. Once the build is complete, go to WhatsApp and type the word “Hi”. Did you get a response like this one?{ "actions": [ { "say": "Hey there! My name is X, I'm Charles' Scheduling assistant... Would you like to schedule and appointment?" }, { "listen": true } ] }
Train
. Here we write training phrases that will trigger the hello_world Task. You can add any phrase you’d like. Here are some phrases I added:{ "actions": [ { "collect": { "name": "user_details", "questions": [ { "question": "What is your first name?", "name": "user_first_name", "type": "Twilio.FIRST_NAME" }, { "question": "What is your last name?", "name": "user_last_name", "type": "Twilio.LAST_NAME" }, { "question": "What's your email?", "name": "user_email", "type": "Twilio.EMAIL" }, { "question": "On what date would you like to book your appointment?", "name": "appointment_date", "type": "Twilio.DATE" }, { "question": "At what time?", "name": "appointment_time", "type": "Twilio.TIME" }, { "question": "What is the purpose of you appointment? e.g check up", "name": "appointment_purpose" } ], "on_complete": { "redirect": "https://07714298.ngrok.io/webhook.php" } } } ] }
on_complete
action can either redirect the collected data to another task or to a given URL. In our case we are redirecting to our webhook URL.no_response
. Let’s copy the following snippet to program it:{ "actions": [ { "say": "Okay. Have a great day!" } ] }
GoogleCalendarClient.php
and copy the following code:<?php require __DIR__ . '/vendor/autoload.php'; $dotenv = Dotenv\Dotenv::create(__DIR__); $dotenv->load(); /** * Class GoogleCalendarClient makes API calls to Google API */ class GoogleCalendarClient { protected $service; /** * GoogleCalendarClient constructor */ public function __construct() { $apiKey = getenv( 'GOOGLE_API_KEY' ); $client = new Google_Client(); $client->setAccessType( 'offline' ); $client->useApplicationDefaultCredentials(); $client->setDeveloperKey( $apiKey ); $client->setScopes( [ 'https://www.googleapis.com/auth/calendar' ] ); $this->service = new Google_Service_Calendar( $client ); } /** * Creates an event * * @param array $eventDetails event details e.g summary, start, end, attendees, e.t.c * * @return array $user of a user */ public function createEvent( $eventDetails ) { $event = new Google_Service_Calendar_Event( $eventDetails ); $optionalArguments = [ 'sendNotifications' => true ]; $calendarId = 'primary'; $event = $this->service->events ->insert( $calendarId, $event, $optionalArguments ); return $event; } }
.env
file as well as the credentials.json
file to authenticate our requests. The createEvent()
method creates an event based on the arguments passed to it.webhook.php
file:<?php include_once( 'GoogleCalendarClient.php' ); if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) { $userDetails = $_REQUEST[ 'Memory' ]; $userDetails = json_decode( $userDetails ); $userDetails = $userDetails->twilio->collected_data->user_details->answers; $firstName = $userDetails->user_first_name->answer; $appointmentDate = $userDetails->appointment_date->answer; $appointmentTime = $userDetails->appointment_time->answer; $appointmentStartAndEndTime = formatAppointmentTime( $appointmentDate, $appointmentTime ); $eventDetails = array( 'summary' => $firstName.'\'s Appointment with Charles', 'location' => 'Plaza, Rabai Rd, Nairobi, Kenya', 'description' => $userDetails->appointment_purpose->answer, 'start' => array( 'dateTime' => $appointmentStartAndEndTime[0], 'timeZone' => 'Africa/Nairobi', ), 'end' => array( 'dateTime' => $appointmentStartAndEndTime[1], 'timeZone' => 'Africa/Nairobi', ), 'attendees' => array( array( 'email' => '[email protected]' ), array( 'email' => $userDetails->user_email->answer ), ), 'reminders' => array( 'useDefault' => FALSE, 'overrides' => array( array( 'method' => 'email', 'minutes' => 24 * 60 ), array( 'method' => 'popup', 'minutes' => 10 ), ), ), ); $client = new GoogleCalendarClient(); $client->createEvent( $eventDetails ); $message = "Thanks $firstName, your appointment has been booked for $appointmentDate at $appointmentTime"; $response = array( 'actions' => array ( array( 'say' => $message ) ) ); echo json_encode( $response ); } /** * Formats the date to the format 2015-05-28T09:00:00 * and adds 30 minutes to the start time. This works * with the assumption that an appointment is 30 minutes. * * @param String $date * @param String $time * * @return Array */ function formatAppointmentTime($date, $time) { $appointmentTime = array(); $start = date( 'Y-m-d H:i:s', strtotime( $date.$time ) ); $end = date( 'Y-m-d H:i:s', strtotime( $start . '+30 minutes' ) ); $start = str_replace( ' ', 'T', $start ); $end = str_replace( ' ', 'T', $end ); array_push( $appointmentTime, $start, $end ); return $appointmentTime; }