)>}]
شركة التطبيقات المتكاملة لتصميم وبرمجة البرمجيات الخاصة ش.ش.و.
Integrated Applications Programming Company
Home » Code Library » Sms (Ia.Cl.Models)

Public general use code classes and xml files that we've compiled and used over the years:

SMS API service support class.

    1: using Microsoft.AspNetCore.Mvc;
    2: using System;
    3: using System.Configuration;
    4: using System.IO;
    5: using System.Net;
    6: using System.Net.Http;
    7: using System.Text;
    8: using System.Text.RegularExpressions;
    9: using System.Threading.Tasks;
   10:  
   11: namespace Ia.Cl.Models
   12: {
   13:     ////////////////////////////////////////////////////////////////////////////
   14:  
   15:     /// <summary publish="true">
   16:     /// SMS API service support class. 
   17:     /// </summary>
   18:     /// 
   19:     /// <remarks> 
   20:     /// Copyright © 2001-2024 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
   21:     ///
   22:     /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
   23:     /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
   24:     ///
   25:     /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   26:     /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   27:     /// 
   28:     /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
   29:     /// 
   30:     /// Copyright notice: This notice may not be removed or altered from any source distribution.
   31:     /// </remarks>
   32:     public class Sms
   33:     {
   34:         private static readonly HttpClient httpClient = new HttpClient();
   35:  
   36:         ////////////////////////////////////////////////////////////////////////////
   37:  
   38:         /// <summary>
   39:         ///
   40:         /// </summary>
   41:         public Sms() { }
   42:  
   43:         ////////////////////////////////////////////////////////////////////////////
   44:  
   45:         /// <summary>
   46:         ///
   47:         /// </summary>
   48:         public static Ia.Cl.Models.Result Send(string phone, string senderName, string message)
   49:         {
   50:             // for non-unicode sending on letter is about 160 chars. You need concat value that is at least (chars/160) + 1
   51:             // unicode = 0, concat = 2;
   52:             return SendAsync(phone, senderName, message, 0, 2).Result;
   53:         }
   54:  
   55:         ////////////////////////////////////////////////////////////////////////////
   56:  
   57:         /// <summary>
   58:         ///
   59:         /// </summary>
   60:         public static Ia.Cl.Models.Result SendUtf8(string phone, string senderName, string message)
   61:         {
   62:             // unicode = 1 (for Arabic), concat = 2;
   63:             return SendAsync(phone, senderName, ConvertUtf8ToUnicodeHex(message), 1, 2).Result;
   64:         }
   65:  
   66:         ////////////////////////////////////////////////////////////////////////////
   67:  
   68:         /// <summary>
   69:         ///
   70:         /// </summary>
   71:         private static async Task<Ia.Cl.Models.Result> SendAsync(string phone, string senderName, string message, int unicode, int concat)
   72:         {
   73:             var result = new Ia.Cl.Models.Result();
   74:  
   75:             var apiToken = Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:BulkSmsApiToken");
   76:             var apiSecret = Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:BulkSmsApiSecret");
   77:  
   78:             var baseUrl = "https://api.bulksms.com/v1/messages";
   79:  
   80:             return await SendSms(baseUrl, apiToken, apiSecret, senderName, phone, message);
   81:         }
   82:  
   83:         ////////////////////////////////////////////////////////////////////////////
   84:  
   85:         /// <summary>
   86:         ///
   87:         /// </summary>
   88:         private static async Task<Ia.Cl.Models.Result> SendSms(string apiUrl, string apiToken, string apiSecret, string senderName, string phone, string message)
   89:         {
   90:             var result = new Ia.Cl.Models.Result();
   91:  
   92:             // remove all space chars
   93:             phone = Regex.Replace(phone, @"\s", "");
   94:  
   95:             // check that phone is all digits
   96:             if (Regex.IsMatch(phone, @"^\d{8,15}$"))
   97:             {
   98:                 // remove the leading "00" if they existed
   99:                 phone = Regex.Replace(phone, "^00", "");
  100:  
  101:                 if (phone.Length == 8) // if number is 8 digits we will assume it is from Kuwait and add the country code
  102:                 {
  103:                     // check if number is SMSable
  104:                     phone = "965" + phone; // this adds the country code to the number
  105:                 }
  106:  
  107:                 var requestContent = new
  108:                 {
  109:                     to = phone,
  110:                     from = senderName,
  111:                     body = message
  112:                 };
  113:  
  114:                 var jsonContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(requestContent), Encoding.UTF8, "application/json");
  115:  
  116:                 httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
  117:                     "Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{apiToken}:{apiSecret}")));
  118:  
  119:                 try
  120:                 {
  121:                     HttpResponseMessage response = await httpClient.PostAsync(apiUrl, jsonContent);
  122:  
  123:                     if (response.IsSuccessStatusCode)
  124:                     {
  125:                         result.AddSuccess("Message sent successfully!");
  126:                     }
  127:                     else
  128:                     {
  129:                         result.AddError("Failed to send message. Status Code: " + response.StatusCode);
  130:  
  131:                         string responseBody = await response.Content.ReadAsStringAsync();
  132:  
  133:                         result.AddError("Response: " + responseBody);
  134:                     }
  135:                 }
  136:                 catch (Exception e)
  137:                 {
  138:                 }
  139:             }
  140:             else
  141:             {
  142:                 result.AddError("Number has non-digit characters or number of characters is not within range.");
  143:             }
  144:  
  145:             return result;
  146:         }
  147:  
  148:         ////////////////////////////////////////////////////////////////////////////
  149:  
  150:         /// <summary>
  151:         ///
  152:         /// </summary>
  153:         private static string ConvertUtf8ToUnicodeHex(string line)
  154:         {
  155:             // convert a utf8 string to a hex representation of unicode
  156:             UTF8Encoding utf8 = new UTF8Encoding();
  157:  
  158:             // encode the string
  159:             byte[] bytes = utf8.GetBytes(line);
  160:             int count = utf8.GetCharCount(bytes);
  161:  
  162:             Decoder d = Encoding.UTF8.GetDecoder();
  163:             int charCount = d.GetCharCount(bytes, 0, bytes.Length);
  164:             char[] chars = new char[charCount];
  165:             int charsDecodedCount = d.GetChars(bytes, 0, bytes.Length, chars, 0);
  166:  
  167:             line = "";
  168:             foreach (char c in chars) line += ((ushort)c).ToString("X").PadLeft(4, '0');
  169:  
  170:             //result_l.Text += "\n<br><br>ΩΨΘ:03A903A80398";
  171:             return line;
  172:         }
  173:  
  174:         ////////////////////////////////////////////////////////////////////////////
  175:         ////////////////////////////////////////////////////////////////////////////
  176:     }
  177: }