Skip to content

Commit 31e19f7

Browse files
YozhikMborodayev
authored andcommitted
[feat]: added new provider Mobizon (#8)
* feat: added new provider `Mobizon` * Update README.md
1 parent bf947f9 commit 31e19f7

File tree

5 files changed

+213
-11
lines changed

5 files changed

+213
-11
lines changed

README.md

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# sms-sender :envelope: :rocket:
1+
# sms-sender :envelope: :rocket:
22

33
[![travis build](https://img.shields.io/travis/FrankAst/sms-sender.svg)](https://travis-ci.org/FrankAst/sms-sender)
44
[![codecov coverage](https://img.shields.io/codecov/c/github/FrankAst/sms-sender.svg)](https://codecov.io/github/FrankAst/sms-sender)
@@ -8,22 +8,20 @@
88
[![Greenkeeper badge](https://badges.greenkeeper.io/FrankAst/sms-sender.svg)](https://greenkeeper.io/)
99
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
1010

11-
1211
This is a wrapper for [AWS.SNS](https://aws.amazon.com/sns/) and [SMSC API](https://smsc.ru).
1312

1413
## Installation
1514

16-
1715
```bash
1816
yarn add @frankast/sms-sender
1917
```
2018

2119
## API
2220

23-
There are two providers `Smsc.js` (default) and `Sns.js`. If you want to use `Sns.js` do not forget to add `aws-sdk` optional dependency.
24-
21+
There are three providers `Smsc.js` (default), `Sns.js`, `Mobizon`. If you want to use `Sns.js` do not forget to add `aws-sdk` optional dependency.
2522

2623
#### Sending SMS
24+
2725
To send an SMS you have to create an instance of provider and call `sendSms()` method:
2826

2927
```js
@@ -42,6 +40,7 @@ const response = await smsc.sendSms('phone_number', 'message');
4240
```
4341

4442
#### Get delivery status of SMS
43+
4544
To check the delivery status of SMS call `getStatus()` method:
4645

4746
```js
@@ -72,6 +71,7 @@ const response = await smsc.getStatus('40-77718637484'); // takes messageId (id-
7271
P.S. You can get status codes [here](https://github.com/FrankAst/sms-sender/blob/3946a34f0d68369914e1ac6c180cc2a5948b718d/src/transporters/Smsc.js#L49) or in [SMSC docs](https://smsc.kz/api/http/status_messages/statuses/#menu).
7372

7473
#### Get cost of SMS
74+
7575
To get a cost of SMS call `getCost()` method:
7676

7777
```js
@@ -81,7 +81,10 @@ const response = await smsc.getCost('phone_number','message');
8181
// response = { cost: '0', rawResponse: { cnt: 1, cost: '25' } };
8282
```
8383

84+
`getCost()` is not available for `Mobizon` provider.
85+
8486
#### Get current balance
87+
8588
To get the current balance on your account call `getBalance()` method:
8689

8790
```js
@@ -92,12 +95,13 @@ To get the current balance on your account call `getBalance()` method:
9295
```
9396

9497
## Examples
98+
9599
Here is an example of usage with RegExp:
96100

97101
```js
98102
// @flow
99103

100-
import { Smsc, Sns } from '@frankast/sms-sender';
104+
import { Smsc, Sns, Mobizon } from '@frankast/sms-sender';
101105

102106
// don't forget to put your credentials
103107
const providers = {
@@ -111,6 +115,10 @@ const providers = {
111115
accessKeyId: '',
112116
secretAccessKey: '',
113117
}),
118+
119+
mobizon: new Mobizon({
120+
apiKey: '',
121+
}),
114122
};
115123

116124
async function send(phone: string, message: string): Promise<Object> {
@@ -128,13 +136,12 @@ async function send(phone: string, message: string): Promise<Object> {
128136
send('+77081113344', 'hello world').then(res => {
129137
console.log(res);
130138
});
131-
132-
133139
```
134140

135141
Other examples are available in [./examples](https://github.com/FrankAst/sms-sender/tree/master/examples).
136142

137143
## Contribution
144+
138145
Feel free to submit pull request to us. Also, be sure all tests has passed otherwise pull request won't be accepted.
139146

140147
## License

src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
export { default as Smsc } from './transporters/Smsc';
44
export { default as Sns } from './transporters/Sns';
5+
export { default as Mobizon } from './transporters/Mobizon';

src/transporters/Mobizon.js

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// @flow
2+
3+
import 'isomorphic-fetch';
4+
import { URLSearchParams } from 'url';
5+
6+
import type {
7+
SendSmsResponseT,
8+
GetStatusResponseT,
9+
GetBalanceResponseT,
10+
SmsStatusT,
11+
ProviderI,
12+
} from '../definitions';
13+
14+
type CredentialsT = {|
15+
apiKey: string,
16+
|};
17+
18+
export default class Mobizon implements ProviderI {
19+
credentials: CredentialsT;
20+
21+
constructor(credentials: CredentialsT) {
22+
this.credentials = credentials;
23+
}
24+
25+
async _send(params: Object): Promise<Object> {
26+
const { apiKey } = this.credentials || {};
27+
const extendedParams = {
28+
apiKey,
29+
...params,
30+
};
31+
const paramsUrl = new URLSearchParams(extendedParams);
32+
const url = `https://api.mobizon.com/service/message/sendsmsmessage?${paramsUrl.toString()}`;
33+
const res = await fetch(url);
34+
return res.json();
35+
}
36+
37+
async sendSms(phone: string, message: string): Promise<SendSmsResponseT> {
38+
const params = {
39+
recipient: phone,
40+
text: message,
41+
};
42+
const { data } = await this._send(params);
43+
const res = {
44+
messageId: data.messageId,
45+
rawResponse: data,
46+
};
47+
return res;
48+
}
49+
50+
// eslint-disable-next-line class-methods-use-this
51+
_prepareStatus(status: string): SmsStatusT {
52+
switch (status) {
53+
case 'NEW':
54+
return 'pending'; // Новое сообщение, еще не было отправлено
55+
case 'ENQUEUD':
56+
return 'pending'; // Прошло модерацию и поставлено в очередь на отправку
57+
case 'ACCEPTED':
58+
return 'pending'; // Отправлено из системы и принято оператором
59+
case 'UNDELIV':
60+
return 'error'; // Не доставлено получателю
61+
case 'REJECTD':
62+
return 'error'; // Отклонено оператором
63+
case 'PDLIVRD':
64+
return 'pending'; // Идет кусочками, первый пошел
65+
case 'DELIVRD':
66+
return 'ok'; // Доставлено получателю полностью
67+
case 'EXPIRED':
68+
return 'error'; // Доставка не удалась, истек срок жизни сообщения
69+
case 'DELETED':
70+
return 'error'; // Удалено из-за ограничений и не доставлено
71+
default:
72+
return 'error';
73+
}
74+
}
75+
76+
async getStatus(messageId: string | string[]): Promise<GetStatusResponseT> {
77+
const { apiKey } = this.credentials || {};
78+
const params = {
79+
apiKey,
80+
ids: Array.isArray(messageId) ? messageId.join(',') : messageId,
81+
};
82+
83+
const paramsUrl = new URLSearchParams(params);
84+
85+
const url = `https://api.mobizon.com/service/message/getsmsstatus?${paramsUrl.toString()}`;
86+
const response = await fetch(url);
87+
const { data } = await response.json();
88+
89+
const res = {
90+
status: data.map(d => this._prepareStatus(d.status)),
91+
rawResponse: data,
92+
};
93+
return res;
94+
}
95+
96+
async getBalance(): Promise<GetBalanceResponseT> {
97+
const { apiKey } = this.credentials || {};
98+
const params = {
99+
apiKey,
100+
};
101+
102+
const paramsUrl = new URLSearchParams(params);
103+
104+
const url = `https://api.mobizon.com/service/user/getownbalance/?${paramsUrl.toString()}`;
105+
const response = await fetch(url);
106+
const { data } = await response.json();
107+
108+
const res = {
109+
balance: data.balance,
110+
rawResponse: data,
111+
};
112+
return res;
113+
}
114+
115+
// eslint-disable-next-line class-methods-use-this
116+
async getCost() {
117+
return {
118+
cost: '',
119+
rawResponse: {},
120+
};
121+
}
122+
123+
// eslint-disable-next-line class-methods-use-this
124+
getProviderName(): string {
125+
return 'mobizon';
126+
}
127+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/* @flow */
2+
3+
import fetchMock from 'fetch-mock';
4+
import Mobizon from '../Mobizon';
5+
6+
describe('Mobizon', () => {
7+
const apiKey = '38d0a2492a33901f547ef22099e6535589500936';
8+
const mobizon = new Mobizon({ apiKey });
9+
10+
beforeEach(() => {
11+
fetchMock.reset();
12+
});
13+
14+
it('sendSms', async () => {
15+
const rawResponse = {
16+
data: { campaignId: '18633289', messageId: '39335551', status: 1 },
17+
};
18+
fetchMock.mock({
19+
matcher: `https://api.mobizon.com/service/message/sendsmsmessage?apiKey=${apiKey}&recipient=${77478446651}&text=HELLO`,
20+
response: rawResponse,
21+
});
22+
23+
const res = await mobizon.sendSms('77478446651', 'HELLO');
24+
expect(res).toEqual({
25+
messageId: '39335551',
26+
rawResponse: rawResponse.data,
27+
});
28+
});
29+
30+
it('getStatus', async () => {
31+
const rawResponse = {
32+
data: [
33+
{
34+
id: '39335551',
35+
status: 'DELIVRD',
36+
segNum: '1',
37+
startSendTs: '2018-04-09 19:36:09',
38+
statusUpdateTs: '2018-04-09 19:36:13',
39+
},
40+
],
41+
};
42+
fetchMock.mock({
43+
matcher: `https://api.mobizon.com/service/message/getsmsstatus?apiKey=${apiKey}&ids=39335551`,
44+
response: rawResponse,
45+
});
46+
47+
const res = await mobizon.getStatus('39335551');
48+
expect(res).toEqual({
49+
status: ['ok'],
50+
rawResponse: rawResponse.data,
51+
});
52+
});
53+
54+
it('getBalance', async () => {
55+
const rawResponse = { data: { balance: '83.5300', currency: 'KZT' } };
56+
fetchMock.mock({
57+
matcher: `https://api.mobizon.com/service/user/getownbalance/?apiKey=${apiKey}`,
58+
response: rawResponse,
59+
});
60+
61+
const res = await mobizon.getBalance();
62+
expect(res).toEqual({
63+
balance: '83.5300',
64+
rawResponse: rawResponse.data,
65+
});
66+
});
67+
});

yarn.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -2349,9 +2349,9 @@ flat-cache@^1.2.1:
23492349
graceful-fs "^4.1.2"
23502350
write "^0.2.1"
23512351

2352-
flow-bin@^0.68.0:
2353-
version "0.68.0"
2354-
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.68.0.tgz#86c2d14857d306eb2e85e274f2eebf543564f623"
2352+
flow-bin@^0.69.0:
2353+
version "0.69.0"
2354+
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.69.0.tgz#053159a684a6051fcbf0b71a2eb19a9679082da6"
23552355

23562356
for-in@^1.0.1, for-in@^1.0.2:
23572357
version "1.0.2"

0 commit comments

Comments
 (0)