We started attempting to add SMS support to our FusionPBX configuration a couple of months ago and found conflicting information online. This link started me down the right path, but gives some bad information--such as, I found that the information given by Caleb was outdated. And the comments by Yukon on that original one are outdated as well. I don't know this for sure, but it appears that sometime in the past, someone has worked to implement some of the Flowroute code into the SMS app and make it work in general for multiple carriers.
I just followed the directions at https://github.com/fusionpbx/fusionpbx-apps/tree/master/sms. Unfortunately, it wouldn't work. I stuck with it, found and fixed some bugs and here's the result:
First, we're on version 4.2.4, so not the newest version, but still newer than what some of those links were talking about.
Second, I just downloaded the Github code on 8/23/2018, so it is current as of this writing. If you find this later and it has been updated after that time, these instructions may not apply.
Third, what is on Github is broken. I am brand new to Github, but I have submitted the changes below back to the project. I'm including them below, along with an explanation, in case I've done something wrong and they do not get accepted.
Fourth, contrary to what is mentioned in some of the comments in that first link above, the SMS app code above from Github, with the relatively minor fixes I'll detail below, will give you SIP SIMPLE to SMS gateway integration. There are a few caveats, but I'll spell it out: it works to send from SIP-registered extension to Freeswitch which passes it via FusionPBX script to carrier to cell phone and then the reverse. Kudos to all the contributors!
Here are the caveats:
How to make SMS app work:
Try running the following command from the fs_cli:
This can give you some insight into any remaining errors or typos.
Remaining changes are to fix problems on specific carriers, to add carriers or for specific softphone support. They are optional.
How to make SMS work with Twilio - Please note that we used Twilio only as a test. I did get it working, but in order to do so, I had to remove the ACL check in the web hook for receiving messages. This is because they are now sending messages back from AWS and so they can come from IP addresses all over the place--you can't whitelist them all! In order to properly secure this, you would need to add the signature checking as detailed here. It's not something we're going to use. Good luck! However, I will detail the other item you'll need to change to make Twilio work:
How to make SMS work with Telnyx - We added support for this carrier. Unless you need to use this carrier, there is no reason you'll need to add this to your installation.
Fixing formatting on sending from Groundwire - We noticed a sending problem on messages sent from the Groundwire softphone. It is inserting some extra headers into the body of the message. Here's some code to clean up formatting. I'm interested in knowing if anyone else has issues with Groundwire in this way. It's always been solid for us. Please note that the misspelling of "lenght" in the code is intentional--that's how it comes through in the header, at least on IOS. YMMV.
Two caveats: 1. There may be better ways to do this that I haven't thought of/don't know about--I'm pretty new to Lua programming. 2. There may be situations where this conflicts with something else. I did try to account for this with the checks in the code, but that's part of the reason I'm putting it out for more eyes on it.
Additions to app_config.php:
If you are adding this to an existing installation, you may simply follow the directions above. However, the following additions will need to be made to the app_config.php to automate installations to include Telnyx.
I just followed the directions at https://github.com/fusionpbx/fusionpbx-apps/tree/master/sms. Unfortunately, it wouldn't work. I stuck with it, found and fixed some bugs and here's the result:
First, we're on version 4.2.4, so not the newest version, but still newer than what some of those links were talking about.
Second, I just downloaded the Github code on 8/23/2018, so it is current as of this writing. If you find this later and it has been updated after that time, these instructions may not apply.
Third, what is on Github is broken. I am brand new to Github, but I have submitted the changes below back to the project. I'm including them below, along with an explanation, in case I've done something wrong and they do not get accepted.
Fourth, contrary to what is mentioned in some of the comments in that first link above, the SMS app code above from Github, with the relatively minor fixes I'll detail below, will give you SIP SIMPLE to SMS gateway integration. There are a few caveats, but I'll spell it out: it works to send from SIP-registered extension to Freeswitch which passes it via FusionPBX script to carrier to cell phone and then the reverse. Kudos to all the contributors!
Here are the caveats:
- From what I can tell, sending media beyond text (pictures, sound, video) is not supported. So no MMS.
- Zoiper seems to have a problem with sending. Like really bad! When I tried sending from Zoiper to a cell phone, it duplicated the message over 130 times. I haven't tracked down this problem yet. An older version of Linphone (3.x) seems to have a similar problem.
- Groundwire iOS
- Grandstream Wave iOs/Android
- X-Lite (desktop)
- Yealink/Grandstream desk phones
- Linphone (4.1.1 Win32)
How to make SMS app work:
- Follow the installation steps from https://github.com/fusionpbx/fusionpbx-apps/tree/master/sms.
- I also had to manually copy the /sms folder from my install folder (which happens to be /var/www/html/app/sms/resources/install/scripts/app, into /usr/share/freeswitch/scripts/app, and set appropriate permissions as needed (same as other folders/files in that structure).
- In the SMS Lua script (ours is at /usr/share/freeswitch/scripts/app/sms/index.lua), search for
//Get User_name
and replace with--Get User_name
. This should be in thecarrier=="thinq"
section. This is the big one that kept it from running at all.
[ERR] mod_lua.cpp:203 /usr/share/freeswitch/scripts/app.lua:48: attempt to call a nil value
stack traceback:
/usr/share/freeswitch/scripts/app.lua:48: in main chunk
Try running the following command from the fs_cli:
luarun /usr/share/freeswitch/scripts/app/sms/index.lua
This can give you some insight into any remaining errors or typos.
Remaining changes are to fix problems on specific carriers, to add carriers or for specific softphone support. They are optional.
How to make SMS work with Twilio - Please note that we used Twilio only as a test. I did get it working, but in order to do so, I had to remove the ACL check in the web hook for receiving messages. This is because they are now sending messages back from AWS and so they can come from IP addresses all over the place--you can't whitelist them all! In order to properly secure this, you would need to add the signature checking as detailed here. It's not something we're going to use. Good luck! However, I will detail the other item you'll need to change to make Twilio work:
- In the SMS Lua script, look for
-- Can be either +1NANNNNXXXX or NANNNNXXXX") then
. This should be about line 244, and is in the Twilio-specific section. Immediately after this line and before the line that starts "cmd =...", put this line of code in:
api_url = string.gsub(api_url, "{ACCOUNTSID}", access_key);
This simply makes it so you only need to enter the access key once in your default settings. The code then inserts it into the api_url. This just makes it cleaner. (It kind of dawned on me after the fact that I could just edit the api_url and hard-code the access key into it, so you can do it either way. However, I'm not sure why this wasn't just written with variable replacements from the start.)
- In the "sms_hook_twilio.php" file (ours is at /var/www/html/app/sms/hook), you will need to add the signature checking mentioned above. If you want to temporarily get this working for test purposes, as we did, you can disable the IP checking as follows. I do NOT recommend this in production!
if (check_acl()) {if (1==1){
, with://if (check_acl()) {
if (1==1){
How to make SMS work with Telnyx - We added support for this carrier. Unless you need to use this carrier, there is no reason you'll need to add this to your installation.
- In the SMS Lua script, look for:
cmd = "curl -X POST '" .. api_url .."' -H \"Content-Type:multipart/form-data\"
Immediately after this line (and before the outdented "end" line, paste in the following (this should be at about line 278 in the original file):
Code:
elseif (carrier == "telnyx") then
if to:len() < 11 then
to = "1" .. to;
end
if outbound_caller_id_number:len() < 11 then
outbound_caller_id_number = "1" .. outbound_caller_id_number;
end
--Get delivery_status_webhook_url
sql = "SELECT default_setting_value FROM v_default_settings ";
sql = sql .. "where default_setting_category = 'sms' and default_setting_subcategory = '" .. carrier .. "_delivery_status_webhook_url' and default_setting_enabled = 'true'";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[sms] SQL: "..sql.."; params:" .. json.encode(params) .. "\n");
end
status = dbh:query(sql, function(rows)
delivery_status_webhook_url = rows["default_setting_value"];
end);
cmd ="curl -X POST \"" .. api_url .."\" -H \"Content-Type: application/json\" -H \"x-profile-secret: " .. secret_key .. "\" -d '{\"from\": \"+" .. outbound_caller_id_number .. "\", \"to\": \"+" .. to .. "\", \"body\": \"" .. body .. "\", \"delivery_status_webhook_url\": \"" .. delivery_status_webhook_url .. "\"}'";
- You'll need to add a "sms_hook_telnyx.php" file (ours is at /var/www/html/app/sms/hook), making sure it has appropriate permissions. Here are the contents:
PHP:
<?php
include "../root.php";
require_once "resources/require.php";
require_once "../sms_hook_common.php";
if (check_acl()) {
if ($_SERVER['CONTENT_TYPE'] == 'application/json') {
$data = json_decode(file_get_contents("php://input"));
if ($debug) {
error_log('[SMS] REQUEST: ' . print_r($data, true));
}
$to = intval(preg_replace('/(^[\+][1])/','', $data->to));
route_and_send_sms($data->from, $to, $data->body);
} else {
die("no");
}
} else {
error_log('ACCESS DENIED [SMS]: ' . print_r($_SERVER['REMOTE_ADDR'], true));
die("access denied");
}
?>
- You'll need to add these new settings to Advanced/Default Settings. In the Sms section (Category: sms):
- Subcategory: carriers, Type: array, Value: telnyx
- Subcategory: telnyx_access_key, Type: text, Value: <blank> (actually, this one stays blank--it isn't used. Just adding it for consistency with the other carriers.)
- Subcategory: telnyx_api_url, Type: text, Value: https://sms.telnyx.com/messages
- Subcategory: telnyx_delivery_status_webhook_url, Type: text, Value: <see below>
- Subcategory: telnyx_secret_key, Type: text, Value: <profile secret generated from Telnyx messaging account>
- Of course, don't forget to add their IPs to the ACL under Advanced/Access Controls. I had to try a test, have it fail, look up the failure in ssl_error_log and see what address they were sending from.
- You'll also need to add your webhook URL on Telnyx's site under the appropriate messaging profile. For Telnyx it should be: https://YOURDOMAIN/app/sms/hook/sms_hook_telnyx.php. And of course, make sure to assign the messaging profile to the phone number you are wanting to use.
Fixing formatting on sending from Groundwire - We noticed a sending problem on messages sent from the Groundwire softphone. It is inserting some extra headers into the body of the message. Here's some code to clean up formatting. I'm interested in knowing if anyone else has issues with Groundwire in this way. It's always been solid for us. Please note that the misspelling of "lenght" in the code is intentional--that's how it comes through in the header, at least on IOS. YMMV.
Two caveats: 1. There may be better ways to do this that I haven't thought of/don't know about--I'm pretty new to Lua programming. 2. There may be situations where this conflicts with something else. I did try to account for this with the checks in the code, but that's part of the reason I'm putting it out for more eyes on it.
- In the SMS Lua script, look for
body = message:getBody();
, then skip theend
line and insert the following before theif (debug["info"]) then
line:
Code:
--Clean body up for Groundwire send
smsraw = body;
smstempst, smstempend = string.find(smsraw, 'Content%-lenght:');
if (smstempend == nil) then
body = smsraw;
else
smst2st, smst2end = string.find(smsraw, '\r\n\r\n', smstempend);
if (smst2end == nil) then
body = smsraw;
else
body = string.sub(smsraw, smst2end + 1);
end
end
Additions to app_config.php:
If you are adding this to an existing installation, you may simply follow the directions above. However, the following additions will need to be made to the app_config.php to automate installations to include Telnyx.
PHP:
$apps[$x]['default_settings'][$y]['default_setting_uuid'] = '9b36edac-eeac-4a3e-b8d4-664962e3f78c';
$apps[$x]['default_settings'][$y]['default_setting_category'] = 'sms';
$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = 'carriers';
$apps[$x]['default_settings'][$y]['default_setting_name'] = 'array';
$apps[$x]['default_settings'][$y]['default_setting_value'] = 'telnyx';
$apps[$x]['default_settings'][$y]['default_setting_enabled'] = 'true';
$apps[$x]['default_settings'][$y]['default_setting_description'] = '';
$y++;
$apps[$x]['default_settings'][$y]['default_setting_uuid'] = '2f246db7-eb07-4c2c-a752-e81466276c89';
$apps[$x]['default_settings'][$y]['default_setting_category'] = 'sms';
$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = 'telnyx_api_url';
$apps[$x]['default_settings'][$y]['default_setting_name'] = 'text';
$apps[$x]['default_settings'][$y]['default_setting_value'] = 'https://sms.telnyx.com/messages';
$apps[$x]['default_settings'][$y]['default_setting_enabled'] = 'false';
$apps[$x]['default_settings'][$y]['default_setting_description'] = '';
$y++;
$apps[$x]['default_settings'][$y]['default_setting_uuid'] = '604c1f7c-e830-441d-9596-31c8d091f8c2';
$apps[$x]['default_settings'][$y]['default_setting_category'] = 'sms';
$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = 'telnyx_access_key';
$apps[$x]['default_settings'][$y]['default_setting_name'] = 'text';
$apps[$x]['default_settings'][$y]['default_setting_value'] = '';
$apps[$x]['default_settings'][$y]['default_setting_enabled'] = 'false';
$apps[$x]['default_settings'][$y]['default_setting_description'] = '';
$y++;
$apps[$x]['default_settings'][$y]['default_setting_uuid'] = 'abcd3f80-71c2-4b58-ae9d-3a37cb503faf';
$apps[$x]['default_settings'][$y]['default_setting_category'] = 'sms';
$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = 'telnyx_secret_key';
$apps[$x]['default_settings'][$y]['default_setting_name'] = 'text';
$apps[$x]['default_settings'][$y]['default_setting_value'] = '';
$apps[$x]['default_settings'][$y]['default_setting_enabled'] = 'false';
$apps[$x]['default_settings'][$y]['default_setting_description'] = '';
$y++;