Send an SMS During a Call
This how-to guide is for sending a message in the context of an active call using PerCL, the Performance Command Language. For simply sending a message, see Send an SMS Message in the API Reference.
You're ready for this how-to guide if you've got the following:
A FreeClimb account
A registered application
A configured FreeClimb number
Your tools and language installed
Trial accounts: A verified number
Node.js
To send a message using PerCL you need to use the Sms
PerCl command. In this example, our voice application will answer a call and send a text message. The status of the outgoing message is tracked using the notificationUrl
property of the Sms
command.
An incoming call is initiated and FreeClimb POSTs to the incomingCall
endpoint to determine how to handle it. The PerCL script assembled in response will send a text message from the incoming number to the configured mobile number informing them that a call is coming in. As the message is processed, its various status states are sent to the notificationUrl
, which the application logs.
Create your package.json file and save in the root directory of your project:
{
"name": "node-send-sms-during-a-call-how-to-guide",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@freeclimb/sdk": "^3.8.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 {
PerclScript,
Sms
} = require('@freeclimb/sdk')
const app = express()
app.use(bodyParser.json())
const port = process.env.PORT || 80
const host = process.env.HOST
app.post('/incomingCall', (req, res) => {
res.status(200).json(new PerclScript({
commands: [
new Sms({
to: req.body.to,
from: req.body.from,
text: 'Incoming Phone Call',
notificationUrl: `${host}/notificationUrl`
})
]
}).build())
})
// Receive status updates of the sms
app.post('/notificationUrl', (req, res) => {
console.log('Outbound Message Status Change: ', req.body)
})
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}`)
})
Java
To send a message using PerCL you need to use the Sms
PerCl command. In this example, our voice application will answer a call and send a text message. The status of the outgoing message is tracked using the notificationUrl
property of the Sms
command.
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:
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.vailsys.freeclimb.api.FreeClimbException;
import com.vailsys.freeclimb.api.message.Status;
import com.vailsys.freeclimb.percl.PerCLScript;
import com.vailsys.freeclimb.percl.Sms;
import com.vailsys.freeclimb.webhooks.call.VoiceCallback;
import com.vailsys.freeclimb.webhooks.message.MessageStatus;
//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 String inboundCall(@RequestBody String body) {
VoiceCallback voiceCallback;
try {
// convert json string to object
voiceCallback = VoiceCallback.createFromJson(body);
PerCLScript script = new PerCLScript();
// send an sms message to the caller
Sms sms = new Sms(voiceCallback.getFrom(), fromNumber, "Hello from FreeClimb");
// set notificationUrl for when the message changes status
sms.setNotificationUrl(notificationUrl);
script.add(sms);
return script.toJson();
} catch (FreeClimbException pe) {
// handle errors
}
return "[]";
}
When the status of the message changes, such as it was successfully sent or failed to send, the notificationUrl
callback will be called with a MessageStatus
object containing the status of the message, as well as additional information about the message. In the example below, we check the status of the message to see if it failed to send.
@RequestMapping(value = {
"/notificationUrl" }, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String notificationUrl(@RequestBody String body) {
MessageStatus messageStatus;
try {
messageStatus = MessageStatus.createFromJson(body);
Status status = messageStatus.getStatus();
if (status == Status.FAILED || status == Status.REJECTED) {
// message Failed to send
}
} catch (FreeClimbException e) {
// handle errors
}
return "[]";
}
C#
To send a message using PerCL you need to use the Sms
PerCl command. In this example, our voice application will answer a call and send a text message. The status of the outgoing message is tracked using the notificationUrl
property of the Sms
command.
Our voice application will answer a call and ask the user for a phone number to send a text message to. It then sends the message to the entered number and tells the user if it was able to send the message. There are three methods below on the ASP.NET Core MVC controller class that are handling this voice application. The first, InboundCall
, is what is called when a call is received for the application. The others are callbacks used by the main application.
Example code:
[HttpPost] // POST /voice
public ActionResult voice (VoiceRequest freeClimbRequest) {
// Create an empty PerCL script container
PerCLScript script = new PerCLScript ();
// Verify inbound 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 + "PhoneNumDone";
GetDigits getDigits = new GetDigits (getDigitsUrl);
// Set the max and min number of expected digits to 1
getDigits.setMaxDigits (10);
getDigits.setMinDigits (10);
// 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 enter the 10 digits phone number to send the text message to.");
// 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");
}
In the InboundCall
method, we answer the call (see Accept an Incoming Call for more detail) and ask the user to enter a phone number using the GetDigits
PerCL command (see Collect Digits for more detail).
In the PhoneNumDone
method, we get the phone number the user entered from the information in the request message sent by FreeClimb and then create the Sms
PerCL command, setting the to
and from
phone number fields, and setting a hard-coded text
value. We also set the notificationUrl
property, which is a URL that is called when the status of our message changes. This lets us track the status of the message. The notificationUrl
handler would typically look for a failure or delivered status and carry out actions appropriate to your application. In this how-to guide’s status callback, MessageStatusCallback
, we log the status.
Example code:
[HttpPost ("GetDigits")] // /voice/GetDigits
public ActionResult GetDigits (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 == 10)) {
// create properly formatted phone num
string phoneNum = "+1" + getDigitsStatusCallback.getDigits;
// create and add PerCL sms script to PerCL container
Sms sms = new Sms (FromPhoneNumber, phoneNum, "Hello from FreeClimb SMS");
// add a notification URL so we can track status of the message
sms.setNotificationUrl(AppUrl + "MessageStatusCallback");
script.Add (sms);
// Create PerCL say script with US English as the language
Say say = new Say ();
say.setLanguage (ELanguage.EnglishUS);
// Set color selected prompt
say.setText ("We'll send the text message now. 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");
}
public ActionResult MessageStatusCallback(MessageStatus status)
{
// note this returns no PerCL; it's just a status message informating us of a change in status of a message we sent
// Read the entire FreeClimb request JSON context
// just log for tutorial. your app may need to take action based on status change
Console.WriteLine ("Message Status Callback. Message ID: " + status.getMessageId + ". Message Status: " + status.getStatus.ToString ());
// just return OK
return Ok();
}
Updated about 1 month ago