uNoti SMS Providers: Bangladesh - MunifTanjim/unoti GitHub Wiki
Helpers:
const nonAsciiRegex = /[^\u0000-\u007F]/
export function includesNonAsciiCharacter(string: string): boolean {
return nonAsciiRegex.test(string)
}
export type SMSParams = {
to: string
text: string
}
Homepage: https://www.ajuratech.com
Dashboard: http://sms.ajuratech.com/Account/Login
import fetch from 'node-fetch'
import qs from 'qs'
import type { NotiProvider } from 'unoti'
type AjuraTechResponse = {
ErrorCode:
| '000'
| '001'
| '003'
| '004'
| '005'
| '006'
| '007'
| '008'
| '009'
| '010'
| '011'
| '012'
| '013'
| '014'
| '015'
| '017'
| '018'
| '019'
| '020'
| '021'
| '022'
| '023'
| '024'
| '025'
| '026'
| '027'
ErrorMessage:
| 'Done'
| 'login details cannot be blank'
| 'sender cannot be blank'
| 'message text cannot be blank'
| 'message data cannot be blank'
| 'error: generic error description'
| 'username or password is invalid'
| 'account not active'
| 'account locked, contact your account manager'
| 'api restriction'
| 'ip address restriction'
| 'invalid length of message text'
| 'mobile numbers not valid'
| 'account locked due to spam message contact support'
| 'senderid not valid'
| 'groupid not valid'
| 'multi message to group is not supported'
| 'schedule date is not valid'
| 'message or mobile number cannot be blank'
| 'insufficient credits'
| 'invalid jobid'
| 'parameter missing'
| 'invalid template or template mismatch'
| '{Field} can not be blank or empty'
| 'invalid date range'
| 'invalid optin user'
| string
JobId: string
MessageData: Array<{
Number: string
MessageId: string
}>
}
type AjuraTechAuthParams =
| { user: string; password: string }
| { APIKey: string }
type AjuraTechQueryParams = AjuraTechAuthParams & {
senderid: string
channel: 'Normal' | string
DCS: 0 | 8
flashsms: 0 | 1
number: string
text: string
schedtime?: string
groupid?: string
}
const nonAsciiRegex = /[^\u0000-\u007F]/
function includesNonAsciiCharacter(string: string): boolean {
return nonAsciiRegex.test(string)
}
export const getAjuratechSMSProvider = ({
id = 'ajuratech',
apiUrl = 'http://sms.ajuratech.com/api/mt/SendSMS',
user,
password,
from,
}: {
id?: string
apiUrl?: string
user: string
password: string
from: string
}): NotiProvider<SMSParams> => {
const ajuratechSMSProvider: NotiProvider<SMSParams> = {
id,
send: async (request) => {
const { to, text } = request
const hasNonAsciiText = includesNonAsciiCharacter(text)
const queryParams: AjuraTechQueryParams = {
user,
password,
senderid: from,
channel: 'Normal',
DCS: hasNonAsciiText ? 8 : 0,
flashsms: 0,
number: to,
text,
}
const response = await fetch(`${apiUrl}?${qs.stringify(queryParams)}`)
const data: AjuraTechResponse = await response.json()
if (data.ErrorCode !== '000') {
throw new Error(
`AjuraTech SMS Failure: ${JSON.stringify({
ErrorCode: data.ErrorCode,
ErrorMessage: data.ErrorMessage,
})}`
)
}
const id = data.MessageData.length ? data.MessageData[0].MessageId : ''
return {
id,
}
},
}
return ajuratechSMSProvider
}
Dashboard: https://user.mobireach.com.bd
import camaro from 'camaro'
import fetch from 'node-fetch'
import qs from 'qs'
import type { NotiProvider } from 'unoti'
type MobiReachResponse = {
ArrayOfServiceClass: {
ServiceClass: {
MessageId: '0' | string
Status: '-1' | string
StatusText: 'Error occurred' | 'success' | string
ErrorCode: '1504' | '1505' | string
ErrorText:
| 'auth_fail'
| 'dest_address_missing'
| 'source_address_missing'
| 'username_missing'
| string
SMSCount: '0' | '1' | string
CurrentCredit: '0' | string
}
}
}
const mobireachResponseTemplate: MobiReachResponse = {
ArrayOfServiceClass: {
ServiceClass: {
MessageId: '/ArrayOfServiceClass/ServiceClass/MessageId',
Status: '/ArrayOfServiceClass/ServiceClass/Status',
StatusText: '/ArrayOfServiceClass/ServiceClass/StatusText',
ErrorCode: '/ArrayOfServiceClass/ServiceClass/ErrorCode',
ErrorText: '/ArrayOfServiceClass/ServiceClass/ErrorText',
SMSCount: '/ArrayOfServiceClass/ServiceClass/SMSCount',
CurrentCredit: '/ArrayOfServiceClass/ServiceClass/CurrentCredit',
},
},
}
export const getMobireachSMSProvider = ({
id = 'mobireach',
apiUrl = 'https://api.mobireach.com.bd/SendTextMessage',
user,
password,
from,
}: {
id?: string
apiUrl?: string
user: string
password: string
from: string
}): NotiProvider<SMSParams> => {
const mobireachSMSProvider: NotiProvider<SMSParams> = {
id,
send: async (request) => {
const { to, text } = request
const queryParams = {
Username: user,
Password: password,
From: from,
To: to,
Message: text,
submit: 'submit',
}
const response = await fetch(`${apiUrl}?${qs.stringify(queryParams)}`)
const xmlString = await response.text()
const { ArrayOfServiceClass }: MobiReachResponse = await camaro.transform(
xmlString,
mobireachResponseTemplate
)
if (ArrayOfServiceClass.ServiceClass.StatusText !== 'success') {
throw new Error(
`MobiReach SMS Failure: ${JSON.stringify(
ArrayOfServiceClass.ServiceClass
)}`
)
}
const id = ArrayOfServiceClass.ServiceClass.MessageId
return {
id,
}
},
}
return mobireachSMSProvider
}
Dashboard: https://isms.sslwireless.com
import camaro from 'camaro'
import fetch from 'node-fetch'
import qs from 'qs'
import type { NotiProvider } from 'unoti'
type SSLWirelessResponse = {
REPLY: {
PARAMETER: 'OK' | 'All PARAMETERS ARE NOT EXISTS' | string
LOGIN: 'SUCCESSFULL' | 'FAIL' | string
PUSHAPI: 'ACTIVE' | string
STAKEHOLDERID: 'OK' | string
PERMITTED: 'OK' | string
SMSINFO: {
MSISDN: string
SMSTEXT: string
CSMSID: string
REFERENCEID: string
SMSVALUE: 'SMS or Mobile is empty' | string
}
}
}
const sslWirelessResponseTemplate: SSLWirelessResponse = {
REPLY: {
PARAMETER: '/REPLY/PARAMETER',
LOGIN: '/REPLY/LOGIN',
PUSHAPI: '/REPLY/PUSHAPI',
STAKEHOLDERID: '/REPLY/STAKEHOLDERID',
PERMITTED: '/REPLY/PERMITTED',
SMSINFO: {
MSISDN: '/REPLY/SMSINFO/MSISDN',
SMSTEXT: '/REPLY/SMSINFO/SMSTEXT',
CSMSID: '/REPLY/SMSINFO/CSMSID',
REFERENCEID: '/REPLY/SMSINFO/REFERENCEID',
SMSVALUE: '/REPLY/SMSINFO/SMSVALUE',
},
},
}
const method = 'POST'
const headers = {
'content-type': 'application/x-www-form-urlencoded',
}
export const getSslWirelessSMSProvider = ({
id = 'sslwireless',
apiUrl = 'https://sms.sslwireless.com/pushapi/dynamic/server.php',
user,
password,
from,
}: {
id?: string
apiUrl?: string
user: string
password: string
from: string
}): NotiProvider<SMSParams> => {
const sslWirelessSMSProvider: NotiProvider<SMSParams> = {
id,
send: async (params) => {
const { to, text } = params
const hasNonAsciiText = includesNonAsciiCharacter(text)
if (hasNonAsciiText) {
throw new Error(
`SSLWireless SMS Failure: non-ascii characters not supported!`
)
}
const body = qs.stringify({
user,
pass: password,
sid: from,
'sms[0][0]': to,
'sms[0][1]': text,
'sms[0][2]': Math.floor(Date.now() / 1000),
})
const response = await fetch(apiUrl, { method, headers, body })
const xmlString = await response.text()
const { REPLY }: SSLWirelessResponse = await camaro.transform(
xmlString,
sslWirelessResponseTemplate
)
if (REPLY.PERMITTED !== 'OK') {
throw new Error(`SSLWireless SMS Failure: ${JSON.stringify(REPLY)}`)
}
const id = REPLY.SMSINFO.REFERENCEID
return {
id,
}
},
}
return sslWirelessSMSProvider
}
Dashboard: https://ismsplus.sslwireless.com
import fetch from 'node-fetch'
import type { NotiProvider } from 'unoti'
type SMSPlusSSLWirelessResponse = {
status: 'SUCCESS' | 'FAILED'
status_code: 200 | 4001 | 4002 | 4022 | 4025 | number
error_message:
| ''
| 'Unauthorized'
| 'SID/Stakeholder is not permitted'
| 'The api token field is required.'
| 'Invalid MSISDN'
| string
smsinfo: Array<{
sms_status: 'INVALID' | 'SUCCESS' | 'FAILED'
status_message: 'Success' | 'Invalid MSISDN' | string
msisdn: string
sms_type: 'EN' | string
sms_body: string
csms_id: string
reference_id: string
}>
}
const method = 'POST'
const headers = {
'content-type': 'application/json',
}
export const getSmsPlusSslWirelessSMSProvider = ({
id = 'smsplus-sslwireless',
apiUrl = 'https://smsplus.sslwireless.com/api/v3/send-sms',
apiToken,
from,
}: {
id?: string
apiUrl?: string
apiToken: string
from: string
}): NotiProvider<SMSParams> => {
const smsPlusSslWirelessSMSProvider: NotiProvider<SMSParams> = {
id,
send: async (params) => {
const { to, text } = params
const body = JSON.stringify({
api_token: apiToken,
sid: from,
msisdn: to,
sms: text,
csms_id: '123456',
})
const response = await fetch(apiUrl, { method, body, headers })
const data: SMSPlusSSLWirelessResponse = await response.json()
if (data.status_code !== 200) {
throw new Error(
`SMSPlusSSLWireless SMS Failure: ${JSON.stringify(data)}`
)
}
const id =
data.smsinfo && data.smsinfo.length
? data.smsinfo.map((info) => info.reference_id).join(',')
: String(Date.now())
return {
id,
}
},
}
return smsPlusSslWirelessSMSProvider
}