Collect Digits

👍

You're ready for this tutorial if you've got the following:

A FreeClimb account
A registered application
A configured FreeClimb Number
Your tools and language installed


Node.js

An incoming call is initiated by FreeClimb POSTing to the resource specified in the voiceUrl in App Config. The callConnectUrl and the statusCallbackUrl in your App Config specifies the callback for connected out dial calls and status updates respectively. In this tutorial the Say and GetDigits PerCL actions are used to greet the calling party and provide a short color selection menu. As part of the GetDigits PerCL action the ColorSelectionDone actionUrl is provided to process the selection results.

Create your package.json file and save in the root directory of your project:

{
  "name": "node-get-digits-tutorial",
  "version": "1.0.0",
  "dependencies": {
    "@freeclimb/sdk": "^1.0.0",
    "body-parser": "^1.19.0",
    "dotenv": "^8.1.0",
    "express": "^4.17.1"
  }
}

Install the package by running the following in the command line/terminal:

yarn install

Example code:

require('dotenv').config()
const express = require('express')
const bodyParser = require('body-parser')
const freeclimbSDK = require('@freeclimb/sdk')
const app = express()
app.use(bodyParser.json())
const port = process.env.PORT || 3000
// Where your app is hosted ex. www.myapp.com
const host = process.env.HOST
 
const freeclimb = freeclimbSDK()
// Handles incoming calls
app.post('/incomingCall', (req, res) => {
  // Create PerCL say script
  const greeting = freeclimb.percl.say('Hello')
  // Create PerCL say script
  const greetingPause = freeclimb.percl.pause(100)
  // Create PerCL say script
  const promptForColor = freeclimb.percl.say('Please select a color. Enter one for green, two for red, and three for blue.')
  // Create options for getDigits script
  const options = {
    prompts: freeclimb.percl.build(promptForColor),
    maxDigits: 1,
    minDigits: 1,
    flushBuffer: true
  }
  // Create PerCL for getDigits script
  const getDigits = freeclimb.percl.getDigits(`${host}/colorSelectionDone`, options)
  // Build and respond with Percl script
  const percl = freeclimb.percl.build(greeting, greetingPause, getDigits)
  res.status(200).json(percl)
})

Successful completion of the GetDigits PerCL action will result in the receipt of a FreeClimb request at the URL defined in the action’s original request. Upon receipt of the request additional PerCL actions are created to provide audio feedback on the color selected as well as gracefully terminating the call. The sample uses additional Say and Hangup PerCl actions to achieve this.

app.post('/colorSelectionDone', (req, res) => {
  // Get FreeClimb response
  const getDigitResponse = req.body
  // Get the digits the user entered
  const digits = getDigitResponse.digits
  // Create PerCL say script based on the selected DTMF with US English as the language
  if(digits){
    colors = {
      '1': 'green',
      '2': 'red',
      '3': 'blue'
    }
    const color = colors[digits]
    let sayResponse = color ? `You selected ${color}` : 'you did not select a number between 1 and 3'
    let say = freeclimb.percl.say(sayResponse)
    // Create PerCL hangup script
    const hangup = freeclimb.percl.hangup()
    // Build PerCL script
    const percl = freeclimb.percl.build(say, hangup)
    // Repsond with PerCL scripts
    res.status(200).json(percl)
  }
})

Handle status updates:

// Specify this route with 'Status Callback URL' in App Config
app.post('/status', (req, res) => {
  // handle status changes
  res.status(200)
})

Start the server:

app.listen(port, () => {
  console.log(`Starting server on port ${port}`)
})

Java

Upon receipt of a FreeClimb incoming call POST at the InboundCall controller any number of PerCL actions may be supplied in the JSON encoded response. In this tutorial the Say and GetDigits PerCL actions are used to greet the calling party and provide a short color selection menu. As part of the GetDigits PerCL action the ColorSelectionDone actionUrl is provided to process the selection results.

Create your build.gradle file and save it to the root directory in your project:

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This is a general purpose Gradle build.
 * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds
 */

buildscript {
    repositories {
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
  //Add the dependency
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE"
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

bootJar {
    baseName = 'gs-spring-boot'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url 'https://jitpack.io' }
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile "org.springframework.boot:spring-boot-starter-web"
    testCompile "junit:junit"
    compile 'com.github.FreeClimbAPI:FreeClimb-Java-SDK:3.0.0'
}
sourceSets {
    main {
        java {
            srcDirs = ['src'] // changed line
        }
    }
}

Build the file by running the following in your terminal/command line:

gradle build

Example code:

/* 
 * AFTER RUNNING PROJECT WITH COMMAND: 
 * `gradle build && java -Dserver.port=0080 -jar build/libs/gs-spring-boot-0.1.0.jar`
 * CALL NUMBER ASSOCIATED WITH THIS FreeClimb App (CONFIGURED IN FreeClimb DASHBOARD)
 * EXPECT A PROMPT TO ENTER A KEY ASSOCIATED WITH A COLOR,
 * THEN EXPECT A MESSAGE WHICH REPEATS THE COLOR THAT WAS SELECTED.
*/

package main.java.collect_digits;

import org.springframework.web.bind.annotation.RestController;
import com.vailsys.freeclimb.api.FreeClimbException;
import com.vailsys.freeclimb.api.call.CallStatus;
import com.vailsys.freeclimb.percl.Language;
import com.vailsys.freeclimb.percl.Pause;
import com.vailsys.freeclimb.percl.PerCLScript;
import com.vailsys.freeclimb.percl.Say;
import com.vailsys.freeclimb.percl.GetDigits;
import com.vailsys.freeclimb.percl.GetDigitsNestable;
import com.vailsys.freeclimb.webhooks.application.ApplicationVoiceCallback;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.LinkedList;

import com.vailsys.freeclimb.webhooks.percl.GetDigitsActionCallback;
import com.vailsys.freeclimb.percl.Hangup;

Example code:

@RestController
public class CollectDigitsController {
  // Get base URL from environment variables
  private String baseUrl = System.getenv("HOST");

  // To properly communicate with FreeClimb's API, set your FreeClimb app's
  // VoiceURL endpoint to '{yourApplicationURL}/InboundCall' for this example
  // Your FreeClimb app can be configured in the FreeClimb Dashboard
  @RequestMapping(value = {
      "/InboundCall" }, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  public ResponseEntity<?> inboundCall(@RequestBody String str) {
    ApplicationVoiceCallback applicationVoiceCallback;
    // Convert JSON into application voice callback object
    try {
      applicationVoiceCallback = ApplicationVoiceCallback.createFromJson(str);
    } catch (FreeClimbException pe) {
      PerCLScript exceptionScript = new PerCLScript();
      Say errorSay = new Say("There was an error handling the incoming call.");
      exceptionScript.add(errorSay);
      return new ResponseEntity<>(exceptionScript.toJson(), HttpStatus.OK);
    }

    // Create an empty PerCL script container
    PerCLScript script = new PerCLScript();

    // Verify call is in the Ringing state
    if (applicationVoiceCallback.getCallStatus() == CallStatus.RINGING) {

      // Create PerCL say script with US English as the language
      Say sayGreeting = new Say("Hello");
      sayGreeting.setLanguage(Language.ENGLISH_US);

      // Add PerCL say script to PerCL container
      script.add(sayGreeting);

      // Create PerCL pause script
      Pause pause = new Pause(100);

      // Add PerCL pause script to PerCL container
      script.add(pause);

      // Create PerCL getdigits script
      GetDigits getDigits = new GetDigits(baseUrl + "/ColorSelectionDone");
      // Set maximum digits to 1
      getDigits.setMaxDigits(1);
      // Set minimum digits to 1
      getDigits.setMinDigits(1);
      // Set buffer flush to true
      getDigits.setFlushBuffer(true);

      // Create an empty GetDigitsNestable list
      LinkedList<GetDigitsNestable> prompts = new LinkedList<>();

      // Create PerCL say script with US English as the language
      Say sayPrompt = new Say("Please select a color. Enter one for green, two for red, and three for blue.");
      sayPrompt.setLanguage(Language.ENGLISH_US);

      // Add PerCL say script to GetDigitsNestable list
      prompts.add(sayPrompt);

      // Add GetDigitsNestable list to PerCL getdigits script
      getDigits.setPrompts(prompts);

      // Add PerCL getdigits script to PerCL container
      script.add(getDigits); // ISSUES ARISE
    }

    // Respond with the PerCL script
    return new ResponseEntity<>(script.toJson(), HttpStatus.OK);
  }

Successful completion of the GetDigits PerCL action will result in the receipt of a FreeClimb request at the URL defined in the action’s original request. Upon receipt of the request additional PerCL actions are created to provide audio feedback on the color selected as well as gracefully terminating the call. The sample uses additional Say and Hangup PerCl actions to achieve this.

@RequestMapping(value = {
      "/ColorSelectionDone" }, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  public ResponseEntity<?> ColorSelectionDone(@RequestBody String str) {
    GetDigitsActionCallback getDigitsCallback;
    // Convert JSON into getdigits action callback object
    try {
      getDigitsCallback = GetDigitsActionCallback.createFromJson(str);
    } catch (FreeClimbException pe) {
      PerCLScript errorScript = new PerCLScript();
      Say sayError = new Say("There was an error processing the color selection.");
      errorScript.add(sayError);
      return new ResponseEntity<>(errorScript.toJson(), HttpStatus.OK);
    }

    // Create an empty PerCL script container
    PerCLScript script = new PerCLScript();

    // Verify one DTMF was received
    if (getDigitsCallback.getDigits() != null && getDigitsCallback.getDigits().length() == 1) {

      // Create PerCL say script based on the selected DTMF with US English as the
      // language
      Say say;
      switch (getDigitsCallback.getDigits()) {
      case "1":
        say = new Say("You selected green. Goodbye.");
        break;
      case "2":
        say = new Say("You selected red. Goodbye.");
        break;
      case "3":
        say = new Say("You selected blue. Goodbye.");
        break;
      default:
        say = new Say("Invalid selection. Goodbye.");
        break;
      }
      say.setLanguage(Language.ENGLISH_US);

      // Add PerCL say script to PerCL container
      script.add(say);

      // Create PerCL hangup script and add it to PerCL container
      script.add(new Hangup());
    }

    // Respond with the PerCL script
    return new ResponseEntity<>(script.toJson(), HttpStatus.OK);
  }
}

C#

Upon receipt of a FreeClimb incoming call POST at the InboundCall controller any number of PerCL actions may be supplied in the JSON encoded response. In this tutorial the Say and GetDigits PerCL actions are used to greet the calling party and provide a short color selection menu. As part of the GetDigits PerCL action the ColorSelectionDone actionUrl is provided to process the selection results.

Example code:

HttpPost ("InboundCall")] // POST voice/InboundCall
    public ActionResult InboundCall (CallStatusCallback freeClimbRequest) {
      // Create an empty PerCL script container
      PerCLScript script = new PerCLScript ();
      // Verify inbund call is in proper state
      if (freeClimbRequest.getCallStatus == ECallStatus.Ringing) {
        // Create PerCL say script with US English as the language
        Say say = new Say ();
        say.setLanguage (ELanguage.EnglishUS);
        // Set greeting prompt
        say.setText ("Hello");

        // Add PerCL say script to PerCL container
        script.Add (say);

        // Create PerCL pause script with a 100 millisecond pause
        Pause pause = new Pause (100);

        // Add PerCL pause script to PerCL container
        script.Add (pause);

        // Create PerCL getdigits script
        string getDigitsUrl = AppUrl + "/voice/ColorSelectionDone";

        GetDigits getDigits = new GetDigits (getDigitsUrl);
        // Set the max and min number of expected digits to 1
        getDigits.setMaxDigits (1);
        getDigits.setMinDigits (1);
        // Set the DTMF buffer flush to false
        getDigits.setFlushBuffer (EBool.False);

        // Create PerCL say script with US English as the language
        say = new Say ();
        say.setLanguage (ELanguage.EnglishUS);
        // Set color selection menu prompt
        say.setText ("Please select a color. Enter one for green, two for red or three for yellow.");

        // Add main selection menu prompt to the getdigits script
        getDigits.setPrompts (say);

        // Add PerCL getdigits script to PerCL container
        script.Add (getDigits);
      }

      // Convert PerCL container to JSON and append to response
      return Content (script.toJson (), "application/json");
    }

Upon invocation of the ColorSelectionDone controller additional PerCL actions may accompany the response. In this tutorial the PerCL Say and Hangup actions are used to provide audio feedback on the color selected as well as gracefully terminate the call.

Example code:

[HttpPost("ColorSelectionDone")] // POST voice/ColorSelectionDone
    public ActionResult ColorSelectionDone (GetDigitsActionCallback getDigitsStatusCallback) {
      // Create an empty PerCL script container
      PerCLScript script = new PerCLScript ();
      // Verify the getdigits contains a single digit response
      if ((getDigitsStatusCallback.getDigits != null) && (getDigitsStatusCallback.getDigits.Length == 1)) {
        // Verify digit one selected
        if (string.Equals (getDigitsStatusCallback.getDigits, "1") == true) {
          // Create PerCL say script with US English as the language
          Say say = new Say ();
          say.setLanguage (ELanguage.EnglishUS);
          // Set color selected prompt
          say.setText ("You selected green. Goodbye.");

          // Add PerCL say script to PerCL container
          script.Add (say);

          // Create PerCL hangup script and add to the container
          script.Add (new Hangup ());
        }
        // Verify digit two selected
        else if (string.Equals (getDigitsStatusCallback.getDigits, "2") == true) {
          // Create PerCL say script with US English as the language
          Say say = new Say ();
          say.setLanguage (ELanguage.EnglishUS);
          // Set color selected prompt
          say.setText ("You selected red. Goodbye.");

          // Add PerCL say script to PerCL container
          script.Add (say);

          // Create PerCL hangup script and add to the container
          script.Add (new Hangup ());
        }
        // Verify digit three selected
        else if (string.Equals (getDigitsStatusCallback.getDigits, "3") == true) {
          // Create PerCL say script with US English as the language
          Say say = new Say ();
          say.setLanguage (ELanguage.EnglishUS);
          // Set color selected prompt
          say.setText ("You selected yellow. Goodbye.");

          // Add PerCL say script to PerCL container
          script.Add (say);

          // Create PerCL hangup script and add to the container
          script.Add (new Hangup ());
        }
        // Invalid selection
        else {
          // Create PerCL say script with US English as the language
          Say say = new Say ();
          say.setLanguage (ELanguage.EnglishUS);
          // Set invalid selection prompt
          say.setText ("Invalid selection. Goodbye.");

          // Add PerCL say script to PerCL container
          script.Add (say);

          // Create PerCL hangup script and add to the container
          script.Add (new Hangup ());
        }
      }
      // unexpected getdigit response
      else {
        // Create PerCL say script with US English as the language
        Say say = new Say ();
        say.setLanguage (ELanguage.EnglishUS);
        // Set error selection prompt
        say.setText ("There was an error retrieving your selection. Goodbye.");

        // Add PerCL say script to PerCL container
        script.Add (say);

        // Create PerCL hangup script and add to the container
        script.Add (new Hangup ());
      }

      // Convert PerCL container to JSON and append to response
      return Content (script.toJson (), "application/json");
    }