Google Cloud Functions for Simple API with Webex CC

In our last post we looked at using a public API in order to make time of day routing decisions in the Flow Editor instead of using Routing Strategies.  One of the big risks to that, as I see it, is the reliance on that third-party service.  I’m sure the folks at timeapi.io are fine people and always pay their bills, but I don’t know them and not sure about trusting them with my call center. I also took this as an opportunity to try out a few tools I have not played with much before: Ruby and Google Cloud Platform.  Here we will use both to create a Google Cloud Function that should be very cheap and dependable to run.  The same could always be managed on an existing server that has similar uptime requirements or an Azure Function or AWS Lambda or written in python or node or whatever.  We will also create an authentication method between our Function and Webex to keep timeapi.io from just redirecting to us.

Part 1: Googling it..

First we need to create out Cloud Function. Functions by default are restricted to user access so we need to make sure we enable it for regular old internet sources to hit it too.  Because we want to handle authentication on our own, we’ll also add a couple of environment variables that we can store credentials in.

Next we need to load in our source code. This is a pretty basic function that will authenticate the user based on basic auth, get the time zone out of the request, get the current into and then reply in a preformatted way that Webex can make sense of.

require "functions_framework"
require "json"
require "tzinfo"
require "active_support/all"
require 'base64'

USER_NAME = ENV["USER_NAME"] # pull Username from Enviroment
USER_PASS = ENV["USER_PASS"] # pull Password from Enviroment

FunctionsFramework.http "get_time" do |request|
  # authenticate the user
  if request.each_header.to_h.key?('HTTP_AUTHORIZATION') && request.each_header.to_h['HTTP_AUTHORIZATION'] != "Basic #{Base64.encode64(USER_NAME + ":" + USER_PASS).strip}"
    STDERR.puts "Un-Authorized #{request.each_header.to_h['HTTP_AUTHORIZATION']} @ #{request.each_header.to_h['REMOTE_ADDR']}"
    return [403, {}, ["forbidden"]]
  end

  timezone_name = request.params["timezone"] || "America/New_York" # get timezone from API call, default to EST
  week = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"] # set day name array for mapping

  now = Time.now # get current time
  now = now.in_time_zone(timezone_name) # convert time to requested timezone
  # build formatted response
  now_json = {  :current_state=>"NOT_SPECIFIED", 
                :hour=>now.hour, 
                :minute=>now.min, 
                :second=>now.sec, 
                :year=>now.year, 
                :month=>now.month, 
                :day_of_month=>now.day, 
                :day=>now.wday, 
                :day_of_week=> week[now.wday],
                :timezone=>timezone_name,
                :timezone_abbr=>now.zone,
                :timestamp=>now
              }.to_json

  return [200, {"Content-Type"=>"application/json"}, [now_json]] # respond to API call
end

Now that we have our function built you should be able to test it from your browser or curl.  From Google Function under Triggers you can find the URL to use.

We should get back a nicely formatted time.

So now we should be ready to go.  Google Cloud Functions are that easy.  Paste code into source and you’re up and running.

Part 2: Webex-ing it…

Now that we have our time API up and running we can move to the Webex side.  Since we are using an authenticated endpoint we will want to build a Connector in Webex Control Hub.  The Flow will then use the authentication attached to this Connector to send the API requests. Another plus side of the connector is that it will store some of the URL structure for you so you don’t have to use vanity URLs or try and remember the somewhat obscure trigger they provide.

From Webex Control Hub Go to Contact Center -> Connectors and we want to add a Custom Connector

Next give it a  name, URL and authentication.  Pro Tip: If you want to build other APIs under the same Google Cloud project you can just add in the host part of the URL and when we build the REST step in the flow editor add in the script trigger there.  That way you can reuse the same Connector for multiple apps.

Now we have out connector with authentication we want to update our existing schedule Flow to use it instead of timeapi.io and then make sure our variables match the JSON.

Now when we call that same number we are using the Google Cloud Function which you are responsible for upkeep instead of “somebody on the internet.”  In the next posts we’ll keep on the wagon of Google Cloud Functions and Ruby and look at other ways we can expand functionality even more.