Page 1 of 1

SMS Text messaging

PostPosted: Tue Jun 14, 2022 10:32 pm
by TimStone
Has anyone tried integrating SMS messaging into their application ? Currently we do texting via email but I would like to find a more direct way.

There are two issues here:

1) A texting API for SMS
2) A cost effective provider of SMS services.

My clients would like to use texting to communicate with their clients ( about the progress of their work, no marketing interest ).

I would enjoy hearing your ideas.

Re: SMS Text messaging

PostPosted: Tue Jun 14, 2022 11:31 pm
by vilian
In the link bellow there is a sample to send SMS using Zenvia Plataform.

http://fivewin.com.br/index.php?/topic/31298-envio-sms-zenvia/&tab=comments#comment-293818

Re: SMS Text messaging

PostPosted: Wed Jun 15, 2022 5:29 am
by anserkk
There are many bulk SMS service providers who will charge you per SMS. They will also provide API which can be easily integrated with your FiveWin application. You will have to find out such providers in your country.

Re: SMS Text messaging

PostPosted: Wed Jun 15, 2022 8:13 am
by Mike Serra
Hi Tim:
We use an SMS service provider (URL: https://www.smsarena.es/). We create an account for our clients, we obtain the APIKEY and then, using a code similar to the one I indicate below, we send the SMS. Our clients are the ones who are in charge of buying the SMS packs to send to their clients.

Code: Select all  Expand view


// /////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////////////
function SendSMS(cFrom,cTo,cMessage,cUserApikey)
   local cFinalURL:="http://api.smsarena.es/http/sms.php?auth_key=#APIKEY#&id=#ID#&from=#FROMPHONE#&to=#TOPHONE#&text=#MESSAGE#"
   cFinalURL:=strtran(cFinalURL,"#APIKEY#",alltrim(cUserApikey))
   cFinalURL:=strtran(cFinalURL,"#TOPHONE#",alltrim(cto))
   cFinalURL:=strtran(cFinalURL,"#FROMPHONE#",alltrim(cfrom))
   cFinalURL:=strtran(cFinalURL,"#MESSAGE#",alltrim(cmessage))
   cFinalURL:=strtran(cFinalURL,"#ID#",allstr(count++))   //<-- a incremental counter for each customer

   cResponse:=alltrim(SendPostToUrl(cFinalURL))
   if alltrim(upper(substr(cResponse,1,2)))=="OK"
       bSendOK:=.t.
       update(count) //<-- This function only update the counter
       InsertLog("SMS OK: "+alltrim(::cret),"servicesms")
   else
      bSendOK:=.f.
      InsertLog("SMS ERROR: "+alltrim(::cret),"servicesms")
   end if
return

// /////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////////////
function SendPostToUrlfunction SendPostToUrl( cUrl, cParams,cContentType,cAuthorization,bPost )
   local oOle,cRet:='',uRet
   default cContentType:="application/x-www-form-urlencoded"
   default cAuthorization:="",cParams:="",bPost:=.t.
       
   try
    oOle := CreateObject( 'MSXML2.XMLHTTP' )
   catch
    oOle := CreateObject( 'Microsoft.XMLHTTP' )
   end
   
   oOle:Open( iif(bPost,'POST','GET'), cUrl, .f. )
   oOle:SetRequestHeader( "Content-Type",cContentType)
   
   if !empty(cAuthorization)
      oOle:SetRequestHeader( "Authorization",cAuthorization)
   end if
       
   oOle:Send( cParams )
   SysRefresh()
       
   #ifdef __XHARBOUR__
      cRet := oOle:ResponseBody
   #else
      AEval(oOle:ResponseBody,{|uRet|cRet+=Chr(uRet)})
   #endif
Return cRet

 


There are different calls to the URL to obtain information, for example to know the remaining credits, etc. I have been using this method for quite some time without any problem. I think that from the USA you can use this provider. If it were not so, surely there will be other providers whose operation will be of similar characteristics.

Regards

P.S. Excuse my English

Re: SMS Text messaging

PostPosted: Wed Jun 15, 2022 5:49 pm
by TimStone
Thank you for the posts so far.

These are examples of sending an SMS text message. However, what about receiving replies ? Tracking the thread ? Does the API initiate a popup where the message thread is displayed as it is in applications that now provide for messaging ?

I can write code to send / save / display messages but I'm thinking there is a need to receive replies.

Re: SMS Text messaging

PostPosted: Thu Jun 16, 2022 8:20 am
by Marc Venken
Tim,

You can read the reply's in the online software or ..

- Your API reads it and you do what you want (make a treat)

- They send for every reply a mail and you read the mail for processing

- They send a SMS back, but that is for the customer to see

- They send to a online platform and you connect to that by API for processing.

Re: SMS Text messaging

PostPosted: Thu Jun 16, 2022 8:34 am
by Marc Venken
Tim,

We use this company, but the Belgium site of it. Maybe you can see find idea's

https://www.coupontools.com/en/sms-marketing-software

Re: SMS Text messaging

PostPosted: Sat Jun 18, 2022 12:48 pm
by cnavarro
Tim
http://www.twilio.com
It has a very simple API to use from CURL and Harbour

Re: SMS Text messaging

PostPosted: Mon Oct 03, 2022 9:08 pm
by TimStone
Do you have a sample of the code to use Twillio ? They seem to be the best option for me in the US.

Also, can we attach a PDF to a text, or must we host it somewhere else and provide a link ?

Thanks.

Re: SMS Text messaging

PostPosted: Fri Nov 04, 2022 12:37 am
by TimStone
I have followed up on this. As everyone indicates, SENDING the SMS is not a problem. It is pretty simple.

Where I have a problem is getting the reply to a text message. So far, the companies I have focused on are assuming we are using a webapplication, and they send a webhook notification when a reply is received by their server. It requires a URL, and then links to your web application.

My problem is that this is a business based computer setup at their location, and they don't have a website. Therein lies the complication. I'm asking if it is possible to get around this, and I could just build a service that checks their server periodically to see if a reply exists, or if they have the ability to supply a URL for the webhooks, and I can just query that. NO REPLIES SO FAR.

Right now I'm focusing on two different options, Twilio and Plivio. Both are competitors, and have a large user base, so hopefully they will be in business for awhile. Both operate the same way.

If anyone has further insite I'd appreciate your input.

Re: SMS Text messaging - FOLLOW UP

PostPosted: Mon Nov 07, 2022 8:49 pm
by TimStone
I wanted to put some closure on this.

1). I selected Twilio here in the US. They have a free trial setup for developers
2). I reached out to their tech support on some questions and they were very responsive/helpful
3). I am able to easily integrate outgoing messages to their service, and that part works fine.
4). Receiving replies is a bit more complicated ( as noted in my previous post ). There response is to add in a service which queries their service on fixed intervals, and obtain the messages that way. I haven't tried that yet but am working on understanding what data actually is returned, and then I can parse it and provide it in the proper threads.
5). This all is done with cURL code which I'm already using elsewhere in my program.

There are already posts on this forum with the working code to use cURL for posting to this service provider so I won't repeat them here.

It appears the real push today is for OUTGOING texts and emails, and most services are not focused on replies unless you are writing automated systems.

I hope others will look into, and share, some of their practices with good email and text usage for businesses, and how they apply them in their applications.

Re: SMS Text messaging

PostPosted: Tue Nov 08, 2022 9:25 am
by NWKL
Hi, can you share your code for send with twillio? Reinaldo some time ago post an solution for this in fwh forum, maybe he can help us with this.

thanks

Re: SMS Text messaging

PostPosted: Tue Nov 08, 2022 6:01 pm
by TimStone
This is Reinaldo's code.

Code: Select all  Expand view

#INCLUDE "hbClass.ch"
#include "hbcurl.ch"

#define ACCOUNT_SID  "xxxxxxxxxx$#B<SHJGHKxxxx"
#define AUTH_TOKEN   "x@#$F&^%DEE"
#define TEL_FROM     "555-555-55555"

CLASS TTwilioSMS

   DATA hCurl
   DATA httpcode
   DATA cLogFile        INIT "Twilio.log"
   DATA cResponse
   DATA cDestinationNum
   DATA cSMSText
   DATA cUrl            INIT "https://api.twilio.com/2010-04-01/Accounts/" + ACCOUNT_SID + "/Messages.json"
   DATA cVoiceUrl       INIT "https://api.twilio.com/2010-04-01/Accounts/" + ACCOUNT_SID + "/Calls.json"
   DATA nError          INIT 0
   DATA nMaxLogSize     INIT 32768
   DATA cDateStart, cDateEnd
   DATA cvoiceMail, cReplyEmail
   DATA lDebug          INIT .F.

   METHOD New()
   METHOD End()
   METHOD Send()
   METHOD Reset()

   METHOD MakePhoneCall()
     
   METHOD GetMessagesLog()

ENDCLASS


//------------------------------------------------------------------------------------------------
METHOD New() CLASS TTwilioSMS

   ::hCurl := curl_easy_init()

RETURN Self


//------------------------------------------------------------------------------------------------
METHOD Send() CLASS TTwilioSMS
   Local cPostFields
   Local httpcode

   curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, 1 )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_USERPWD, ACCOUNT_SID + ':' + AUTH_TOKEN )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )

   cPostFields := 'To='    + ::cDestinationNum + ; // Line[ 3 ] +;
                  '&From=' + TEL_FROM +;
                  '&Body=' + curl_easy_escape( ::hCurl, AllTrim( ::cSMSText ) )


   If ::lDebug
      LogFile( ::cLogFile, { cPostFields } )
   endif


   curl_easy_setopt( ::hcurl, HB_CURLOPT_POSTFIELDS, cPostFields )
   ::nError := curl_easy_perform( ::hCurl )
   curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @httpcode )

   ::httpcode := httpcode

   IF ::nError = HB_CURLE_OK

      ::cResponse = curl_easy_dl_buff_get( ::hCurl )

   Else

      LogData( ::cLogFile, { "Twilio error sending SMS.  Details below:" },      ::nMaxLogSize )
      LogData( ::cLogFile, { "To", ::cDestinationNum, "SMS Text:", ::cSMSText }, ::nMaxLogSize )
      LogData( ::cLogFile, { "Error Num:", ::nError, "Httpcode:", ::httpcode }, ::nMaxLogSize )
      LogData( ::cLogFile, curl_easy_strerror( ::nError ), ::nMaxLogSize )

   ENDIF

return NIL            

//------------------------------------------------------------------------------------------------
METHOD Reset() CLASS TTwilioSMS
     
   curl_easy_reset( ::hCurl )

return NIL



//------------------------------------------------------------------------------------------------
METHOD End() CLASS TTwilioSMS

   curl_easy_cleanup( ::hCurl )
   ::hCurl := Nil  
   hb_gcAll( .t. )

return NIL


//------------------------------------------------------------------------------------------------
//must define ::cDateStart and ::cDateEnd before calling this method.
METHOD GetMessagesLog() CLASS TTwilioSMS
   Local cparms := '?DateSent%3E=' + ::cDateStart + "&DateSent%3C=" + ::cDateEnd + "&PageSize=600"
   Local httpcode

   curl_easy_setopt( ::hCurl, HB_CURLOPT_HTTPGET, 1 )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cUrl + cParms )

   curl_easy_setopt( ::hCurl, HB_CURLOPT_USERPWD, ACCOUNT_SID + ':' + AUTH_TOKEN )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )

   ::nError := curl_easy_perform( ::hCurl )

   curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @httpcode )

   ::httpcode := httpcode

   IF ::nError = HB_CURLE_OK

      ::cResponse = curl_easy_dl_buff_get( ::hCurl )
      ::cResponse := StrTran( ::cResponse, Chr(10), "" )

   Else

      LogData( ::cLogFile, { "Twilio error sending SMS.  Details below:" },      ::nMaxLogSize )
      LogData( ::cLogFile, { "To", ::cDestinationNum, "SMS Text:", ::cSMSText }, ::nMaxLogSize )
      LogData( ::cLogFile, { "Error Num:", ::nError, "Httpcode:", ::httpcode }, ::nMaxLogSize )
      LogData( ::cLogFile, curl_easy_strerror( ::nError ), ::nMaxLogSize )

   ENDIF

   //MemoWrit( "Twilio.log", ::cResponse )

RETURN NIL

//------------------------------------------------------------------------------------------------
/*sample makeing a call using url to fetch parameters
https://www.twilio.com/docs/voice/api/call-resource

EXCLAMATION_MARK='!'
curl -X POST https://api.twilio.com/2010-04-01/Accou ... Calls.json \
--data-urlencode "Twiml=<Response><Say>Ahoy there$EXCLAMATION_MARK</Say></Response>" \
--data-urlencode "To=+15558675310" \
--data-urlencode "From=+15552223214" \
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN
*/

//Twilml sample parameter "Twiml=<Response><Say>Ahoy there$EXCLAMATION_MARK</Say></Response>"


METHOD MakePhoneCall() CLASS TTwilioSMS
   Local cPostFields
   Local httpcode

   curl_easy_setopt( ::hCurl, HB_CURLOPT_POST, 1 )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_URL, ::cVoiceUrl )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_USERPWD, ACCOUNT_SID + ':' + AUTH_TOKEN )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_DL_BUFF_SETUP )
   curl_easy_setopt( ::hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )

   cPostFields := 'To='    + ::cDestinationNum + ; // Line[ 3 ] +;
                  '&From=' + TEL_FROM +;
                  '&CallReason=' + "medical appointment reminder" +;
                  '&Twiml=<Say voice="alice" language="es-MX">' + ::cVoiceMail + '</Say>' +;
                  '&CallerId='   + ::cReplyEmail


   curl_easy_setopt( ::hcurl, HB_CURLOPT_POSTFIELDS, cPostFields )
   ::nError := curl_easy_perform( ::hCurl )
   curl_easy_getinfo( ::hCurl, HB_CURLINFO_RESPONSE_CODE, @httpcode )

   ::httpcode := httpcode

   IF ::nError = HB_CURLE_OK

      ::cResponse = curl_easy_dl_buff_get( ::hCurl )

   Else

      LogData( ::cLogFile, { "Twilio error making voice call.  Details below:" },      ::nMaxLogSize )
      LogData( ::cLogFile, { "To", ::cDestinationNum, "Message:", ::cVoiceMail }, ::nMaxLogSize )
      LogData( ::cLogFile, { "Error Num:", ::nError, "Httpcode:", ::httpcode }, ::nMaxLogSize )
      LogData( ::cLogFile, curl_easy_strerror( ::nError ), ::nMaxLogSize )

   ENDIF

RETURN NIL
 
 


Here is what I modified:

1). #Define items: I changed these to DATA items. My clients will have their own accounts, so I created a Dialog for them to save those values in a file, and then within the Send routine, I bring in those values to use for sending the text. Those are the Account SSDI, AUTH, and PHONE.

2). I do not use the CALL feature so I removed it.

3). I have my own logging utility, so I substituted in my own process for his log routine.

4). I've made a couple of other changes specific to my implementation.

5). I modified the Send() Method to accept the text and phone number to be used in sending the SMS.

I would suggest setting up the account, then testing with Reinaldo's code, substituting in your own account info, then modifying it in steps.