Skip to content

Commit 169b8d4

Browse files
authored
Merge pull request #27 from ArtiStyle/master
merge: add sms aero and playmobile transporters
2 parents de8e0f2 + 324ba1c commit 169b8d4

File tree

4 files changed

+242
-0
lines changed

4 files changed

+242
-0
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"homepage": "https://github.com/FrankAst/sms-sender",
2626
"license": "MIT",
2727
"dependencies": {
28+
"axios": "^0.18.0",
2829
"isomorphic-fetch": "^2.2.1",
2930
"mongoose": "^5.0.4",
3031
"babel-runtime": "^6.26.0"

src/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
export { default as Smsc } from './transporters/Smsc';
44
export { default as Sns } from './transporters/Sns';
55
export { default as Mobizon } from './transporters/Mobizon';
6+
export { default as PlayMobile } from './transporters/PlayMobile';
7+
export { default as Aero } from './transporters/Aero';

src/transporters/Aero.js

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// @flow
2+
import 'isomorphic-fetch';
3+
import axios from 'axios';
4+
import type {
5+
SendSmsResponseT,
6+
GetStatusResponseT,
7+
SmsStatusT,
8+
ProviderI,
9+
GetCostResponseT,
10+
GetBalanceResponseT,
11+
} from '../definitions';
12+
13+
type CredentialsT = {|
14+
email: string,
15+
apiKey: string,
16+
|};
17+
18+
export default class PlayMobile implements ProviderI {
19+
credentials: CredentialsT;
20+
21+
constructor(credentials: CredentialsT) {
22+
this.credentials = credentials;
23+
}
24+
25+
// make request to Aero API
26+
async _send(cmd: 'sms/send' | 'sms/status', params: Object): Promise<Object> {
27+
const { email, apiKey } = this.credentials || {};
28+
const extendedParams = {
29+
...params,
30+
};
31+
const url = `https://${email}:${apiKey}@gate.smsaero.ru/v2/${cmd}`;
32+
try {
33+
const res = await axios.get(url, {
34+
params: extendedParams,
35+
});
36+
return res.data;
37+
} catch (e) {
38+
return { error: e.response.status, errMsg: e.response.statusText };
39+
}
40+
}
41+
// eslint-disable-next-line class-methods-use-this
42+
_prepareStatus(status: number): SmsStatusT {
43+
switch (status) {
44+
case 2:
45+
return 'error';
46+
case 6:
47+
return 'error';
48+
case 0:
49+
return 'pending'; //
50+
case 4:
51+
return 'pending'; // - Waiting for sending
52+
case 8:
53+
return 'pending'; // - Given to operator
54+
case 1:
55+
return 'ok'; // - Delivered
56+
case 3:
57+
return 'ok'; // - Delivered
58+
default:
59+
return 'error';
60+
}
61+
}
62+
63+
// send message
64+
async sendSms(phone: string, message: string): Promise<SendSmsResponseT> {
65+
const params = {
66+
number: phone,
67+
text: message,
68+
sign: 'SMS Aero',
69+
channel: 'DIRECT',
70+
};
71+
const rawResponse = await this._send('sms/send', params);
72+
const res = {
73+
messageId: `${rawResponse.id}-${phone}`,
74+
rawResponse,
75+
};
76+
return res;
77+
}
78+
79+
// get status of message (messageId format: id-phoneNumber)
80+
async getStatus(messageId: string): Promise<GetStatusResponseT> {
81+
const params = {
82+
id: messageId.trim().split('-')[0],
83+
};
84+
const rawResponse = await this._send('sms/status', params);
85+
const res = {
86+
status: this._prepareStatus(rawResponse.status),
87+
rawResponse,
88+
};
89+
return res;
90+
}
91+
92+
// get current provider name
93+
// eslint-disable-next-line class-methods-use-this
94+
getProviderName(): string {
95+
return 'Aero';
96+
}
97+
// eslint-disable-next-line
98+
async getBalance(): Promise<GetBalanceResponseT> {
99+
throw new Error(`PlayMobile does not support getting balance`);
100+
}
101+
// eslint-disable-next-line
102+
async getCost(phone: string, message: string): Promise<GetCostResponseT> {
103+
throw new Error(`PlayMobile does not support getting cost`);
104+
}
105+
}

src/transporters/PlayMobile.js

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// @flow
2+
import 'isomorphic-fetch';
3+
import axios from 'axios';
4+
5+
import type {
6+
SendSmsResponseT,
7+
GetStatusResponseT,
8+
SmsStatusT,
9+
ProviderI,
10+
GetCostResponseT,
11+
GetBalanceResponseT,
12+
} from '../definitions';
13+
14+
type CredentialsT = {|
15+
url: string,
16+
login: string,
17+
password: string,
18+
|};
19+
20+
type OptionsT = { mesId: number, phone: string, message: string };
21+
22+
export default class PlayMobile implements ProviderI {
23+
credentials: CredentialsT;
24+
25+
constructor(credentials: CredentialsT) {
26+
this.credentials = credentials;
27+
}
28+
29+
// make request to PlayMobile API
30+
async _send(cmd: 'send' | 'get-status', params: Object): Promise<Object> {
31+
const { login, password, url } = this.credentials || {};
32+
const stringToEncode = `${login}:${password}`;
33+
try {
34+
const response = await axios({
35+
method: 'post',
36+
url: `${url}/${cmd}`,
37+
data: params,
38+
headers: {
39+
'Content-Type': 'application/json',
40+
Authorization: `Basic ${Buffer.from(stringToEncode).toString('base64')}`,
41+
},
42+
});
43+
return cmd === 'get-status'
44+
? { body: response.data }
45+
: { statusCode: response.status, body: response.data };
46+
} catch (e) {
47+
return {
48+
statusCode: e.response.status,
49+
errMsg: (e.response && e.response.statusText) || ' ',
50+
};
51+
}
52+
}
53+
54+
// get more detailed description on https://smsc.kz/api/http/status_messages/statuses/#menu
55+
// eslint-disable-next-line class-methods-use-this
56+
_prepareStatus(status: string): SmsStatusT {
57+
switch (status) {
58+
case 'failed':
59+
return 'error'; // - Not delivered
60+
case 'notDelivered':
61+
return 'pending'; // - Waiting for sending
62+
case 'deferred':
63+
return 'pending'; // - Given to operator
64+
case 'transmitted':
65+
return 'ok'; // - Delivered
66+
case 'delivered':
67+
return 'ok'; // - Delivered
68+
default:
69+
return 'error';
70+
}
71+
}
72+
73+
// send message
74+
async sendSms(phone: string, message: string): Promise<SendSmsResponseT> {
75+
const mesId = Math.floor(100000 + Math.random() * 900000);
76+
const params = this.createParams({
77+
mesId,
78+
phone,
79+
message,
80+
});
81+
const rawResponse = await this._send('send', params);
82+
const res = {
83+
messageId: `${mesId}-${phone}`,
84+
rawResponse,
85+
};
86+
return res;
87+
}
88+
89+
// get status of message (messageId format: id-phoneNumber)
90+
async getStatus(messageId: string): Promise<GetStatusResponseT> {
91+
const params = {
92+
'message-id': [messageId.trim().split('-')[0]],
93+
};
94+
const rawResponse = await this._send('get-status', params);
95+
const res = {
96+
status: this._prepareStatus(rawResponse.status),
97+
rawResponse,
98+
};
99+
return res;
100+
}
101+
102+
// get current provider name
103+
// eslint-disable-next-line class-methods-use-this
104+
getProviderName(): string {
105+
return 'PlayMobile';
106+
}
107+
// eslint-disable-next-line
108+
async getBalance(): Promise<GetBalanceResponseT> {
109+
throw new Error(`PlayMobile does not support getting balance`);
110+
}
111+
// eslint-disable-next-line
112+
async getCost(phone: string, message: string): Promise<GetCostResponseT> {
113+
throw new Error(`PlayMobile does not support getting cost`);
114+
}
115+
// eslint-disable-next-line class-methods-use-this
116+
createParams(options: OptionsT): Object {
117+
const { mesId, phone, message } = options || {};
118+
return {
119+
messages: [
120+
{
121+
'message-id': mesId,
122+
recipient: phone,
123+
sms: {
124+
ttl: '300',
125+
originator: 'smsSender',
126+
content: {
127+
text: message,
128+
},
129+
},
130+
},
131+
],
132+
};
133+
}
134+
}

0 commit comments

Comments
 (0)