ISMS Plus SMS API
Programmatic SMS messaging — send single, bulk, OTP, and dynamic messages.
Single SMS
Send a single SMS message to one recipient
Secure OTP
Send one-time-password SMS messages
Bulk SMS
Send same message to multiple recipients
Dynamic SMS
Send unique messages to different recipients
Base Configuration
Authentication
Every request requires an api_token and sid (Sender ID).
XXXX-XXd2bbXX-XXfX-XXbf-XXXXX-XXXXXcXXXXX)sid — Your registered Sender ID (e.g.,
XXXXXXXXXX)Request IP — Must be whitelisted in ISMS Plus portal
Response Format
All SMS endpoints return a consistent JSON structure. Fields vary slightly by endpoint but follow this common shape.
Top-level Fields
| Parameter | Type | Description |
|---|---|---|
| status | string | Overall result — SUCCESS or FAILED |
| status_code | integer | Numeric status code — see API Status Codes |
| error_message | string | Human-readable error detail if failed; empty string on success |
| smsinfo | array | Array of SMS detail objects, one per recipient (see below) |
smsinfo Object Fields
| Parameter | Type | Description |
|---|---|---|
| smsinfo[].sms_status | string | Per-recipient status: SUCCESS, INVALID, DUPLICATE,
or
BLOCKED
|
| smsinfo[].status_message | string | Human-readable status message for this recipient |
| smsinfo[].msisdn | string | The recipient phone number (with country code prefix) |
| smsinfo[].sms_type | string | EN for English & BN for Unicode / Bangla |
| smsinfo[].csms_id | string | Your provided client reference ID |
| smsinfo[].reference_id | string | Server-generated unique reference ID (use for status checks) |
Send SMS
Send a single SMS message to one recipient.
Parameters
| Name | Required | Type | Length | Description |
|---|---|---|---|---|
| api_token | Required | Alphanumeric | 50 | Authentication token provided by SSL |
| sid | Required | Alphanumeric | 20 | Sender ID |
| msisdn | Required | Numeric | 16 | Recipient mobile phone number |
| sms | Required | Alphanumeric | 1000 | SMS message body |
| csms_id | Required | Alphanumeric | 20 | Unique client reference ID for this SMS |
Sample Request
{
"api_token": "XXXX-XXd2bbXX-XXfX-XXbf-XXXXX-XXXXXcXXXXX",
"sid": "XXXXXXXXXX",
"msisdn": "88019XXXXXXXX",
"sms": "Message Body",
"csms_id": "4473433434pZ684333392"
}
Success Response
{
"status": "SUCCESS",
"status_code": 200,
"error_message": "",
"smsinfo": [
{
"sms_status": "SUCCESS",
"status_message": "Success",
"msisdn": "88019XXXXXXXX",
"sms_type": "EN",
"sms_body": "Your sms body",
"csms_id": "4473433434pZ684333392",
"reference_id": "5da2f0b5ba3a2248110"
}
]
}
Failure Response
{
"status": "FAILED",
"status_code": 4025,
"error_message": "Invalid MSISDN",
"smsinfo": [
{
"sms_status": "INVALID",
"status_message": "Invalid MSISDN",
"msisdn": "88019XXXXXXXX",
"sms_type": "EN",
"csms_id": "4473433434pZ684333392",
"reference_id": "5da2f0b5ba3a2248110"
}
]
}
Secure OTP SMS with Signature
SMS body must be AES-256-CBC encrypted — plus
an additional X-Signature request header for payload integrity verification.
sms field is AES-256-CBC encrypted with SHA256(secret_key), and
X-Signature header is an HMAC-SHA256 of payload signed with secret_key.
The server rejects requests where either check fails with 4035 SIGNATURE_MISMATCH.
Request Headers
| Header | Type | Required | Description |
|---|---|---|---|
| Content-Type | string | Required | application/json |
| X-Signature | string | Required | HMAC-SHA256 signature of payload (hex string) — see generation steps below |
Request Parameters
| Name | Required | Type | Length | Description |
|---|---|---|---|---|
| api_token | Required | Alphanumeric | 50 | Authentication token provided by SSL |
| sid | Required | Alphanumeric | 20 | Sender ID |
| msisdn | Required | Numeric | 16 | Recipient mobile phone number |
| sms | Required | Encrypted | 1000 | SMS body encrypted using the user's secret key |
| csms_id | Required | Alphanumeric | 20 | Unique client reference ID for this SMS |
Signature Generation
X-Signature header value using these exact steps:
- Obtain your Secret Key from the ISMS Plus portal.
-
Encrypt SMS Text: Use AES-256-CBC with PKCS7 padding.
- Key: Take the first 32 characters of the
SHA256hex hash of your Secret Key. - Format: Base64 encode the concatenation of the
[16-byte raw IV]+[Base64 encoded ciphertext].
- Key: Take the first 32 characters of the
-
Generate Canonical String: Create a URL‑encoded query string using this exact pattern
csms_id=123&msisdn=456&sid=789&sms=encrypted_string. -
Compute HMAC: Calculate
HMAC-SHA256using the raw Secret Key as the key and the query string as the message. - Send the resulting lowercase hex digest as the
X-Signatureheader.
Sample Request
{
"api_token": "XXXX-XXd2bbXX-XXfX-XXbf-XXXXX-XXXXXcXXXXX",
"sid": "XXXXXXXXXX",
"msisdn": "88019XXXXXXXX",
"sms": "<AES-256-CBC-ENCRYPTED-BASE64-STRING>",
"csms_id": "4473433434pZ684333392"
}
Success Response
{
"status": "SUCCESS",
"status_code": 200,
"error_message": "",
"smsinfo": [
{
"sms_status": "SUCCESS",
"status_message": "Success",
"msisdn": "8801XXXXXXXXX",
"sms_type": "EN",
"csms_id": "4473433434pZ684333392",
"reference_id": "5d9d7ca5dac5e067314"
}
]
}
Failure Response
{
"status": "FAILED",
"error_message": "Client signature mismatch",
"status_code": 4035,
"smsinfo": []
}
Bulk SMS
Send a single SMS message body to multiple recipients in one request. Maximum 100 MSISDN per request.
4030.
Parameters
| Name | Required | Type | Length | Description |
|---|---|---|---|---|
| api_token | Required | Alphanumeric | 50 | Authentication token provided by SSL |
| sid | Required | Alphanumeric | 20 | Sender ID |
| msisdn | Required | Array<Numeric> | 16 each | Array of recipient mobile phone numbers |
| sms | Required | Alphanumeric | 1000 | SMS message body |
| batch_csms_id | Required | Alphanumeric | 20 | Unique client reference ID for this batch |
Sample Request
{
"api_token": "XXXX-XXd2bbXX-XXfX-XXbf-XXXXX-XXXXXcXXXXX",
"sid": "XXXXXXXXXX",
"msisdn": [
"88019XXXXXXXX",
"88017XXXXXXXX",
"88018XXXXXXXX"
],
"sms": "Message Body",
"batch_csms_id": "4437343343P3Z684333392"
}
Success Response
{
"status": "SUCCESS",
"status_code": 200,
"error_message": "",
"smsinfo": [
{
"sms_status": "SUCCESS",
"status_message": "Success",
"msisdn": "88019XXXXXXXX",
"sms_type": "EN",
"csms_id": "4473433434pZ684333392",
"reference_id": "5da2f0b5ba3a2248110"
},
{
"sms_status": "SUCCESS",
"status_message": "Success",
"msisdn": "88017XXXXXXXX",
"sms_type": "EN",
"csms_id": "4473433434pZ684333393",
"reference_id": "5da2f0b5ba3a2248111"
}
]
}
Failure Response
{
"status": "FAILED",
"status_code": 4028,
"error_message": "Invalid message data",
"smsinfo": [
{
"sms_status": "DUPLICATE",
"status_message": "Duplicated CSMS ID",
"msisdn": "88019XXXXXXXX",
"sms_type": "EN",
"csms_id": "4473433434pZ684333392",
"reference_id": "5da2f0b5ba3a2248110"
}
]
}
Dynamic SMS
Send unique SMS messages to different recipients in a single request. Each recipient gets a personalized message.
Parameters
| Name | Required | Type | Length | Description |
|---|---|---|---|---|
| api_token | Required | Alphanumeric | 50 | Authentication token provided by SSL |
| sid | Required | Alphanumeric | 20 | Sender ID |
| sms | Required | Array<Object> | — | Array of SMS objects with msisdn, text, csms_id |
| sms[].msisdn | Required | Numeric | 16 | Recipient mobile phone number |
| sms[].text | Required | Alphanumeric | 1000 | The SMS message body for this recipient |
| sms[].csms_id | Required | Alphanumeric | 20 | Unique client reference ID per SMS |
Sample Request
{
"api_token": "XXXX-XXd2bbXX-XXfX-XXbf-XXXXX-XXXXXcXXXXX",
"sid": "XXXXXXXXXX",
"sms": [
{
"msisdn": "88019XXXXXXXX",
"text": "Message Body 1",
"csms_id": "234444343222"
},
{
"msisdn": "88017XXXXXXXX",
"text": "Message Body 2",
"csms_id": "234444343223"
}
]
}
Success Response
{
"status": "SUCCESS",
"status_code": 200,
"error_message": "",
"smsinfo": [
{
"sms_status": "SUCCESS",
"status_message": "Success",
"msisdn": "88019XXXXXXXX",
"sms_type": "EN",
"csms_id": "234444343222",
"reference_id": "5da2f0b5ba3a2248110"
},
{
"sms_status": "SUCCESS",
"status_message": "Success",
"msisdn": "88017XXXXXXXX",
"sms_type": "EN",
"csms_id": "234444343223",
"reference_id": "5da2f0b5ba3a2248111"
}
]
}
Failure Response
{
"status": "FAILED",
"status_code": 4028,
"error_message": "Invalid message data",
"smsinfo": [
{
"sms_status": "DUPLICATE",
"status_message": "Duplicated CSMS ID",
"msisdn": "88019XXXXXXXX",
"sms_type": "EN",
"csms_id": "4473433434pZ684333392",
"reference_id": "5da2f0b5ba3a2248110"
}
]
}
API Status Codes
All API responses include a numeric status code indicating the result of your request.
| Code | Status | Description |
|---|---|---|
| 200 | SUCCESS | Request completed successfully |
| 4001 | Unauthorized | Authentication failed |
| 4002 | SID Not Permitted | Stakeholder not permitted to send SMS |
| 4003 | IP Blacklisted | IP is not whitelisted |
| 4004 | Invalid Request Format | JSON format is invalid or content type is not JSON |
| 4005 | End Point Not Found | The requested endpoint does not exist |
| 4020 | Invalid CSMS ID | Only for bulk and single SMS |
| 4022 | Required Parameter Missing | A required field is missing (sid, msisdn, etc.) |
| 4023 | Duplicate CMS ID | Only for bulk and single SMS |
| 4024 | Duplicate MSISDN | Only for single SMS |
| 4025 | Invalid MSISDN | The MSISDN provided is invalid |
| 4026 | Blocked MSISDN | The MSISDN is blocked |
| 4027 | Message Length Exceeded | Only for single SMS |
| 4028 | Invalid Message Data | Invalid MSISDN, SMS Body, SID, CSMSID, or missing mandatory field |
| 4029 | Too Many Requests | Rate limit exceeded |
| 4030 | Limit Exceed | Max MSISDN list exceeded for one request |
| 4031 | TPS Exceeded | Transactions per second limit exceeded |
| 4032 | Invalid SMS | Invalid SMS body |
| 4033 | Too Many OTP Requests | Too many OTPs sent to a single recipient within a time period |
| 4034 | Unable to Decrypt SMS | SMS body not encrypted, invalid secret key, or wrong encryption method |
| 4035 | Client Signature Mismatch | Signature header sent but process not followed correctly |
| 5000 | Internal Error | Server internal error |
SMS Status
Each SMS within a response carries its own delivery status.
| Status | Message | Description |
|---|---|---|
| SUCCESS | Success | SMS delivered successfully |
| INVALID | Invalid MSISDN | Message length exceeded or invalid phone number |
| DUPLICATE | Duplicate CMS ID | Duplicate MSISDN detected |
| BLOCKED | Blocked MSISDN | Too many OTP requests or MSISDN blocked |
Sample Code
Here are some examples of how to integrate the SMS API in different programming languages.
<?php $url = "https://smsplus.sslwireless.com/api/v3/send-sms"; $data = [ "api_token" => "your_api_token", "sid" => "XXXXXXXXXX", "msisdn" => "88019XXXXXXXX", "sms" => "Message Body", "csms_id" => "4473433434pZ684333392" ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Accept: application/json' ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?>
import requests url = "https://smsplus.sslwireless.com/api/v3/send-sms" headers = {"Content-Type": "application/json", "Accept": "application/json"} payload = { "api_token": "your_api_token", "sid": "XXXXXXXXXX", "msisdn": "88019XXXXXXXX", "sms": "Message Body", "csms_id": "4473433434pZ684333392" } response = requests.post(url, json=payload, headers=headers) print(response.json())
const payload = { api_token: "your_api_token", sid: "XXXXXXXXXX", msisdn: "88019XXXXXXXX", sms: "Message Body", csms_id: "4473433434pZ684333392" }; fetch("https://smsplus.sslwireless.com/api/v3/send-sms", { method: "POST", headers: {"Content-Type":"application/json", "Accept":"application/json"}, body: JSON.stringify(payload) }).then(r => r.json()).then(console.log);
curl -X POST https://smsplus.sslwireless.com/api/v3/send-sms \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -d '{ "api_token": "your_api_token", "sid": "XXXXXXXXXX", "msisdn": "88019XXXXXXXX", "sms": "Message Body", "csms_id": "4473433434pZ684333392" }'
package main import ( "bytes" "fmt" "net/http" ) func main() { url := "https://smsplus.sslwireless.com/api/v3/send-sms" payload := []byte(`{ "api_token": "your_api_token", "sid": "XXXXXXXXXX", "msisdn": "88019XXXXXXXX", "sms": "Message Body", "csms_id": "4473433434pZ684333392" }`) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") client := &http.Client{} resp, _ := client.Do(req) defer resp.Body.Close() fmt.Println("Status:", resp.Status) }
using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main() { var client = new HttpClient(); var url = "https://smsplus.sslwireless.com/api/v3/send-sms"; var json = @"{ "api_token": "your_api_token", "sid": "XXXXXXXXXX", "msisdn": "88019XXXXXXXX", "sms": "Message Body", "csms_id": "4473433434pZ684333392" }"; var content = new StringContent(json, Encoding.UTF8, "application/json"); client.DefaultRequestHeaders.Add("Accept", "application/json"); var response = await client.PostAsync(url, content); Console.WriteLine(await response.Content.ReadAsStringAsync()); } }
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Main { public static void main(String[] args) throws Exception { String url = "https://smsplus.sslwireless.com/api/v3/send-sms"; String json = "{\n" + " \"api_token\": \"your_api_token\",\n" + " \"sid\": \"XXXXXXXXXX\",\n" + " \"msisdn\": \"88019XXXXXXXX\",\n" + " \"sms\": \"Message Body\",\n" + " \"csms_id\": \"4473433434pZ684333392\"\n" + "}"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .header("Accept", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
<?php function encryptSms(string $plainText, string $secretKey): string { $method = 'AES-256-CBC'; $key = hash('sha256', $secretKey); // Derive key from portal Secret Key $ivLen = openssl_cipher_iv_length($method); $iv = openssl_random_pseudo_bytes($ivLen); $cipher = openssl_encrypt($plainText, $method, $key, 0, $iv); return base64_encode($iv . $cipher); } $apiToken = 'YOUR_API_TOKEN'; $secretKey = 'YOUR_SECRET_KEY'; $sid = 'YOUR_SID'; $msisdn = '01XXXXXXXXX'; $csmsId = 'SSIG-ID-001'; // Step 1: Encrypt the OTP message using the portal Secret Key $encryptedSms = encryptSms('Your OTP is 123456', $secretKey); // Step 2: Build signature payload $hashPayload = [ 'sid' => $sid, 'msisdn' => $msisdn, 'sms' => $encryptedSms, 'csms_id' => $csmsId, ]; // Step 3: Always sort the payload alphabetically by key // This ensures the receiver can recreate the exact same string ksort($hashPayload); // Step 4: Build the query string (e.g., sid=123&msisdn=456...) $queryString = http_build_query($hashPayload); // Step 5: Sign the query string $signature = hash_hmac('sha256', $queryString, $secretKey); // Step 3: Send request $data = [ 'api_token' => $apiToken, 'sid' => $sid, 'msisdn' => $msisdn, 'sms' => $encryptedSms, 'csms_id' => $csmsId, ]; $ch = curl_init('https://smsplus.sslwireless.com/api/v3/secure/otp-sms'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'X-Signature: ' . $signature, ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch); curl_close($ch);
import requests import hashlib import base64 import hmac from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Random import get_random_bytes def encrypt_sms(plain_text: str, secret_key: str) -> str: # 1. A 64-char hex string key_hash_hex = hashlib.sha256(secret_key.encode()).hexdigest() # 2. OpenSSL AES-256 uses the first 32 characters of that hex string key = key_hash_hex[:32].encode() # 3. Generate 16-byte random IV iv = get_random_bytes(16) # 4. Create cipher and pad data (PKCS7) cipher = AES.new(key, AES.MODE_CBC, iv) padded_data = pad(plain_text.encode('utf-8'), AES.block_size) # 5. Encrypt to raw bytes raw_ciphertext = cipher.encrypt(padded_data) # 6. openssl_encrypt with flag 0 returns a Base64 string base64_ciphertext = base64.b64encode(raw_ciphertext).decode('utf-8') # 7. base64_encode($iv . $encrypted) # Note: $iv is binary, $encrypted is the base64 string from step 6 combined = iv + base64_ciphertext.encode('utf-8') return base64.b64encode(combined).decode('utf-8') api_token = 'YOUR_API_TOKEN' secret_key = 'YOUR_SECRET_KEY' sid = 'YOUR_SID' msisdn = '01XXXXXXXXX' csms_id = 'SSIG-ID-001' # Step 1: Encrypt the OTP message encrypted_sms = encrypt_sms('Your OTP is 123456', secret_key) print("Encrypted SMS: ", encrypted_sms) # Step 2: Build signature payload hash_payload = { 'sid': sid, 'msisdn': msisdn, 'sms': encrypted_sms, 'csms_id': csms_id } # Step 3: Always sort the payload alphabetically by key # This ensures the receiver can recreate the exact same string hash_payload = dict(sorted(hash_payload.items())) # Step 4: Build the query string (e.g., sid=123&msisdn=456...) from urllib.parse import urlencode query_string = urlencode(hash_payload) # Step 5: Sign the query string signature = hmac.new(secret_key.encode(), query_string.encode(), hashlib.sha256).hexdigest() # Step 3: Send request data = { 'api_token': api_token, 'sid': sid, 'msisdn': msisdn, 'sms': encrypted_sms, 'csms_id': csms_id } headers = { 'Content-Type': 'application/json', 'X-Signature': signature } response = requests.post( 'https://smsplus.sslwireless.com/api/v3/secure/otp-sms', json=data, headers=headers ) print(response.json())
const crypto = require('crypto'); // fetch is available globally in Node 18+ // Encrypt SMS using AES-256-CBC function encryptSms(plainText, secretKey) { // OpenSSL uses first 32 bytes (chars) of that hex string as the AES-256 key const keyHex = crypto.createHash('sha256').update(secretKey).digest('hex'); const key = Buffer.from(keyHex.slice(0, 32)); // first 32 chars → 32 bytes const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); //Openssl_encrypt with flag=0 returns base64-encoded ciphertext let encryptedRaw = cipher.update(plainText, 'utf8'); encryptedRaw = Buffer.concat([encryptedRaw, cipher.final()]); const encryptedBase64 = encryptedRaw.toString('base64'); // mimic openssl_encrypt flag=0 // base64_encode($iv . $encrypted) → raw IV bytes + base64 string, then base64 encode return Buffer.concat([iv, Buffer.from(encryptedBase64)]).toString('base64'); } // Generate signature with new logic function generateSignature(csmsId, msisdn, sid, sms, secretKey) { // Step 1: Build payload map const payload = { csms_id: csmsId, msisdn, sid, sms }; // Step 2: Sort keys alphabetically const sortedKeys = Object.keys(payload).sort(); // Step 3: Build URL-encoded query string const queryString = sortedKeys .map(key => `${key}=${encodeURIComponent(payload[key])}`) .join('&'); // Step 4: HMAC-SHA256 with raw secret key return crypto.createHmac('sha256', secretKey) .update(queryString) .digest('hex'); // lowercase hex } (async () => { const apiToken = 'YOUR_API_TOKEN'; const secretKey = 'YOUR_SECRET_KEY'; const sid = 'YOUR_SID'; const msisdn = '01XXXXXXXXX'; const csmsId = 'SSIG-ID-001'; // Step 1: Encrypt the OTP message const encryptedSms = encryptSms('Your OTP is 123456', secretKey); // Step 2: Generate signature const signature = generateSignature(csmsId, msisdn, sid, encryptedSms, secretKey); // Step 3: Build request payload const payload = { api_token: apiToken, sid, msisdn, sms: encryptedSms, csms_id: csmsId }; // Step 4: Send request const response = await fetch('https://smsplus.sslwireless.com/api/v3/secure/otp-sms', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Signature': signature }, body: JSON.stringify(payload) }); const data = await response.json(); console.log(data); })();
package main import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/hmac" "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "fmt" "io" "net/http" "net/url" ) func sendSecureOtp() { apiToken := "***YOUR_API_TOKEN***" secretKey := "YOUR_SECRET_KEY" sid := "***YOUR_SID***" msisdn := "01XXXXXXXXX" csmsId := "SSIG-ID-XXX" encryptedSms, err := encryptSms("Your test pin is 1234", secretKey) if err != nil { fmt.Println("Encryption error:", err) return } signature, err := makeSignature(csmsId, msisdn, sid, encryptedSms, secretKey) println("Signature: ", signature) if err != nil { fmt.Println("Error to make signature error:", err) return } // Step 3: Send request payload := map[string]interface{}{ "api_token": apiToken, "sid": sid, "msisdn": msisdn, "sms": encryptedSms, "csms_id": csmsId, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", "https://smsplus.sslwireless.com/api/v3/secure/otp-sms", bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Signature", signature) client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Request error:", err) return } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) } func encryptSms(plainText, secretKey string) (string, error) { // 1.hash('sha256', $key) returns a 64-char hex string hash := sha256.Sum256([]byte(secretKey)) hashHex := hex.EncodeToString(hash[:]) // OpenSSL AES-256 uses the first 32 bytes of that string key := []byte(hashHex)[:32] block, err := aes.NewCipher(key) if err != nil { return "", err } // 2. Generate 16-byte IV iv := make([]byte, aes.BlockSize) if _, err := io.ReadFull(rand.Reader, iv); err != nil { return "", err } // 3. PKCS7 Padding paddedText := pkcs7Pad([]byte(plainText), aes.BlockSize) // 4. Encrypt to raw bytes ciphertext := make([]byte, len(paddedText)) mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(ciphertext, paddedText) //5. We must encode the ciphertext bytes to Base64 first base64Ciphertext := base64.StdEncoding.EncodeToString(ciphertext) // 6. Concatenate Binary IV + Base64 Ciphertext String // Then Base64 encode the whole thing combined := append(iv, []byte(base64Ciphertext)...) return base64.StdEncoding.EncodeToString(combined), nil } func pkcs7Pad(data []byte, blockSize int) []byte { padding := blockSize - (len(data) % blockSize) padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(data, padtext...) } func makeSignature(CsmsId string, msisdn string, sid string, encryptedSms string, userSecreteKey string) (string, error) { values := url.Values{} values.Set("csms_id", CsmsId) values.Set("msisdn", msisdn) values.Set("sid", sid) values.Set("sms", encryptedSms) queryString := values.Encode() h := hmac.New(sha256.New, []byte(userSecreteKey)) h.Write([]byte(queryString)) return hex.EncodeToString(h.Sum(nil)), nil }
using System; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Threading.Tasks; using System.Collections.Generic; using System.Linq; class Program { // Encrypt SMS using AES-256-CBC public static string EncryptSms(string plainText, string secretKey) { //hash('sha256', $key) returns a 64-char HEX string using var sha256 = SHA256.Create(); byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(secretKey)); string hexKey = BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); // openssl uses first 32 bytes of the hex string as the AES-256 key byte[] key = Encoding.UTF8.GetBytes(hexKey).Take(32).ToArray(); // Generate random IV byte[] iv = new byte[16]; using var rng = RandomNumberGenerator.Create(); rng.GetBytes(iv); using var aes = Aes.Create(); aes.Key = key; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using var encryptor = aes.CreateEncryptor(); byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); byte[] encryptedRaw = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); // flag=0 means openssl_encrypt returns base64-encoded output (not raw) string encryptedBase64 = Convert.ToBase64String(encryptedRaw); // base64_encode($iv . $encrypted) = raw IV bytes + base64 string bytes byte[] encryptedBytes = Encoding.UTF8.GetBytes(encryptedBase64); byte[] combined = new byte[iv.Length + encryptedBytes.Length]; Buffer.BlockCopy(iv, 0, combined, 0, iv.Length); Buffer.BlockCopy(encryptedBytes, 0, combined, iv.Length, encryptedBytes.Length); return Convert.ToBase64String(combined); } // Generate Signature public static string GenerateSignature(string csmsId, string msisdn, string sid, string sms, string secretKey) { var payload = new Dictionary<string, string> { { "csms_id", csmsId }, { "msisdn", msisdn }, { "sid", sid }, { "sms", sms } }; // Sort keys alphabetically var sortedPayload = payload.OrderBy(x => x.Key); // Create canonical query string var queryString = string.Join("&", sortedPayload.Select(x => $"{x.Key}={Uri.EscapeDataString(x.Value)}")); // HMAC SHA256 using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey)); byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(queryString)); return Convert.ToHexString(hash).ToLower(); } static async Task Main() { string apiToken = "YOUR_API_TOKEN"; string secretKey = "YOUR_SECRET_KEY"; string sid = "YOUR_SID"; string msisdn = "01XXXXXXXXX"; string csmsId = "SSIG-ID-XXX"; string otpMessage = "Your OTP is 123456"; // Step 1: Encrypt SMS string encryptedSms = EncryptSms(otpMessage, secretKey); // Step 2: Generate Signature string signature = GenerateSignature(csmsId, msisdn, sid, encryptedSms, secretKey); // Step 3: Build request payload var payload = new { api_token = apiToken, sid = sid, msisdn = msisdn, sms = encryptedSms, csms_id = csmsId }; var json = JsonSerializer.Serialize(payload); using var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Post, "https://smsplus.sslwireless.com/api/v3/secure/otp-sms"); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); // Add Signature Header request.Headers.Add("X-Signature", signature); var response = await client.SendAsync(request); string result = await response.Content.ReadAsStringAsync(); Console.WriteLine("Response:"); Console.WriteLine(result); } }
package smsplus; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Base64; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; import javax.crypto.Cipher; import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; public class SecureOtpSignatureSms { public static String encryptSms(String plainText, String secretKey) throws Exception { // STEP 1: hash('sha256', secretKey) → 64-character hex string String keyHex = sha256Hex(secretKey); byte[] keyBytes = keyHex.getBytes(StandardCharsets.UTF_8); // STEP 2: generate 16-byte IV byte[] iv = new byte[16]; new SecureRandom().nextBytes(iv); // STEP 3: AES-256-CBC encryption with PKCS5Padding (equivalent to PKCS7) Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(keyBytes, 0, 32, "AES"); // only first 32 bytes used IvParameterSpec ivSpec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); // STEP 4: base64 encode encrypted ciphertext String base64Encrypted = Base64.getEncoder().encodeToString(encryptedBytes); // STEP 5: prepend IV (raw) + then base64 encode the whole thing byte[] combined = new byte[iv.length + base64Encrypted.getBytes(StandardCharsets.UTF_8).length]; System.arraycopy(iv, 0, combined, 0, iv.length); System.arraycopy(base64Encrypted.getBytes(StandardCharsets.UTF_8), 0, combined, iv.length, base64Encrypted.getBytes(StandardCharsets.UTF_8).length); return Base64.getEncoder().encodeToString(combined); } private static String sha256Hex(String input) throws Exception { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); StringBuilder hexString = new StringBuilder(); for (byte b : hash) hexString.append(String.format("%02x", b)); return hexString.toString(); } // Generate HMAC-SHA256 signature (new logic) public static String generateSignature(String csmsId, String msisdn, String sid, String sms, String secretKey) throws Exception { // Step 1: Build payload map Map<String, String> payload = new TreeMap<>(); // TreeMap = sorted by key payload.put("csms_id", csmsId); payload.put("msisdn", msisdn); payload.put("sid", sid); payload.put("sms", sms); // Step 2: Build URL-encoded query string String queryString = payload.entrySet().stream() .map(e -> e.getKey() + "=" + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8)) .collect(Collectors.joining("&")); // Step 3: HMAC-SHA256 Mac mac = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); mac.init(secretKeySpec); byte[] hash = mac.doFinal(queryString.getBytes(StandardCharsets.UTF_8)); // Step 4: Convert to lowercase hex StringBuilder sb = new StringBuilder(); for (byte b : hash) { sb.append(String.format("%02x", b)); } return sb.toString(); } public static void main(String[] args) throws Exception { String apiToken = "YOUR_API_TOKEN"; String secretKey = "YOUR_SECRET_KEY"; String sid = "YOUR_SID"; String msisdn = "01XXXXXXXXX"; String csmsId = "SSIG-ID-XXX"; String url = "https://smsplus.sslwireless.com/api/v3/secure/otp-sms"; // Step 1: Encrypt the OTP message String encryptedSms = encryptSms("Your OTP is 123456", secretKey); // Step 2: Generate signature using new logic String signature = generateSignature(csmsId, msisdn, sid, encryptedSms, secretKey); // Step 3: Build JSON payload String json = String.format( "{\"api_token\":\"%s\",\"sid\":\"%s\",\"msisdn\":\"%s\",\"sms\":\"%s\",\"csms_id\":\"%s\"}", apiToken, sid, msisdn, encryptedSms, csmsId ); // Step 4: Send HTTP POST request HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .header("X-Signature", signature) .POST(HttpRequest.BodyPublishers.ofString(json)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
<?php $data = [ "api_token" => "***YOUR_API_TOKEN***", "sid" => "***YOUR_SID***", "msisdn" => ["01XXXXXXXXX","01XXXXXXXXX","01XXXXXXXXX"], "sms" => "Bulk SMS message content", "batch_csms_id" => "BATCH-001" ]; $ch = curl_init("https://smsplus.sslwireless.com/api/v3/send-sms/bulk"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $res = json_decode(curl_exec($ch), true); curl_close($ch); print_r($res);
import requests data = { "api_token": "***YOUR_API_TOKEN***", "sid": "***YOUR_SID***", "msisdn": ["01XXXXXXXXX", "01XXXXXXXXX", "01XXXXXXXXX"], "sms": "Bulk SMS message content", "batch_csms_id": "BATCH-001" } response = requests.post( "https://smsplus.sslwireless.com/api/v3/send-sms/bulk", json=data ) print(response.json())
const data = { api_token: "***YOUR_API_TOKEN***", sid: "***YOUR_SID***", msisdn: ["01XXXXXXXXX", "01XXXXXXXXX", "01XXXXXXXXX"], sms: "Bulk SMS message content", batch_csms_id: "BATCH-001" }; fetch("https://smsplus.sslwireless.com/api/v3/send-sms/bulk", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(data) }).then(r => r.json()).then(console.log);
package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" ) func main() { data := map[string]interface{}{ "api_token": "***YOUR_API_TOKEN***", "sid": "***YOUR_SID***", "msisdn": []string{"01XXXXXXXXX", "01XXXXXXXXX", "01XXXXXXXXX"}, "sms": "Bulk SMS message content", "batch_csms_id": "BATCH-001", } jsonData, _ := json.Marshal(data) resp, err := http.Post( "https://smsplus.sslwireless.com/api/v3/send-sms/bulk", "application/json", bytes.NewBuffer(jsonData), ) if err != nil { fmt.Println("Request error:", err) return } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }
using System; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; class Program { static async Task Main() { var data = new { api_token = "***YOUR_API_TOKEN***", sid = "***YOUR_SID***", msisdn = new[] {"01XXXXXXXXX", "01XXXXXXXXX", "01XXXXXXXXX"}, sms = "Bulk SMS message content", batch_csms_id = "BATCH-001" }; var client = new HttpClient(); var json = JsonSerializer.Serialize(data); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await client.PostAsync( "https://smsplus.sslwireless.com/api/v3/send-sms/bulk", content); Console.WriteLine(await response.Content.ReadAsStringAsync()); } }
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.List; import java.util.Map; public class BulkSms { public static void main(String[] args) throws Exception { String url = "https://smsplus.sslwireless.com/api/v3/send-sms/bulk"; String json = String.format( "{\"api_token\":\"%s\",\"sid\":\"%s\",\"msisdn\":[\"%s\",\"%s\",\"%s\"],\"sms\":\"%s\",\"batch_csms_id\":\"%s\"}", "***YOUR_API_TOKEN***", "***YOUR_SID***", "01XXXXXXXXX", "01XXXXXXXXX", "01XXXXXXXXX", "Bulk SMS message content", "BATCH-001" ); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
<?php $data = [ "api_token" => "***YOUR_API_TOKEN***", "sid" => "***YOUR_SID***", "sms" => [ ["msisdn"=>"01XXXXXXXXX","text"=>"Hello John!","csms_id"=>"DYN-001"], ["msisdn"=>"01XXXXXXXXX","text"=>"Hello Jane!","csms_id"=>"DYN-002"] ] ]; $ch = curl_init("https://smsplus.sslwireless.com/api/v3/send-sms/dynamic"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch); curl_close($ch);
import requests data = { "api_token": "***YOUR_API_TOKEN***", "sid": "***YOUR_SID***", "sms": [ { "msisdn": "01XXXXXXXXX", "text": "Hello John!", "csms_id": "DYN-001" }, { "msisdn": "01XXXXXXXXX", "text": "Hello Jane!", "csms_id": "DYN-002" } ] } response = requests.post( "https://smsplus.sslwireless.com/api/v3/send-sms/dynamic", json=data ) print(response.json())
const data = { api_token: "***YOUR_API_TOKEN***", sid: "***YOUR_SID***", sms: [ { msisdn: "01XXXXXXXXX", text: "Hello John!", csms_id: "DYN-001" }, { msisdn: "01XXXXXXXXX", text: "Hello Jane!", csms_id: "DYN-002" } ] }; fetch("https://smsplus.sslwireless.com/api/v3/send-sms/dynamic", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(data) }).then(r => r.json()).then(console.log);
curl -X POST https://smsplus.sslwireless.com/api/v3/send-sms/dynamic \ -H 'Content-Type: application/json' \ -d '{ "api_token": "***YOUR_API_TOKEN***", "sid": "***YOUR_SID***", "sms": [ {"msisdn":"01XXXXXXXXX","text":"Hello John!","csms_id":"DYN-001"}, {"msisdn":"01XXXXXXXXX","text":"Hello Jane!","csms_id":"DYN-002"} ] }'
package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" ) func main() { data := map[string]interface{}{ "api_token": "***YOUR_API_TOKEN***", "sid": "***YOUR_SID***", "sms": []map[string]string{ {"msisdn": "01XXXXXXXXX", "text": "Hello John!", "csms_id": "DYN-001"}, {"msisdn": "01XXXXXXXXX", "text": "Hello Jane!", "csms_id": "DYN-002"}, }, } jsonData, _ := json.Marshal(data) resp, err := http.Post( "https://smsplus.sslwireless.com/api/v3/send-sms/dynamic", "application/json", bytes.NewBuffer(jsonData), ) if err != nil { fmt.Println("Request error:", err) return } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }
using System; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; class Program { static async Task Main() { var data = new { api_token = "***YOUR_API_TOKEN***", sid = "***YOUR_SID***", sms = new[] { new { msisdn = "01XXXXXXXXX", text = "Hello John!", csms_id = "DYN-001" }, new { msisdn = "01XXXXXXXXX", text = "Hello Jane!", csms_id = "DYN-002" } } }; var client = new HttpClient(); var json = JsonSerializer.Serialize(data); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await client.PostAsync( "https://smsplus.sslwireless.com/api/v3/send-sms/dynamic", content); Console.WriteLine(await response.Content.ReadAsStringAsync()); } }
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class DynamicSms { public static void main(String[] args) throws Exception { String url = "https://smsplus.sslwireless.com/api/v3/send-sms/dynamic"; String json = String.format( "{\"api_token\":\"%s\",\"sid\":\"%s\",\"sms\":[{\"msisdn\":\"%s\",\"text\":\"%s\",\"csms_id\":\"%s\"},{\"msisdn\":\"%s\",\"text\":\"%s\",\"csms_id\":\"%s\"}]}", "***YOUR_API_TOKEN***", "***YOUR_SID***", "01XXXXXXXXX", "Hello John!", "DYN-001", "01XXXXXXXXX", "Hello Jane!", "DYN-002" ); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }