unismsgateway 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -15
- package/dist/scripts/test-live.js +6 -3
- package/dist/src/lib/hubtel-gateway.d.ts +3 -0
- package/dist/src/lib/hubtel-gateway.js +28 -14
- package/dist/src/lib/nest-gateway.d.ts +1 -0
- package/dist/src/lib/nest-gateway.js +81 -44
- package/dist/src/lib/platform.js +6 -3
- package/dist/src/lib/route-gateway.d.ts +10 -0
- package/dist/src/lib/route-gateway.js +53 -16
- package/dist/src/lib/types.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,23 +37,24 @@ import { init, getSmsPlatform, reset, smsPlatform } from 'unismsgateway';
|
|
|
37
37
|
|
|
38
38
|
| Field | Type | Description |
|
|
39
39
|
| ------------ | --------------- | -------------------------------------- |
|
|
40
|
-
| `platformId` | `'route'
|
|
40
|
+
| `platformId` | `'route' \| 'hubtel' \| 'nest'` | Which gateway to use. |
|
|
41
41
|
| `param` | `IgatewayParam` | Provider-specific options (see below). |
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
### `IgatewayParam` (all fields optional except what your `platformId` requires)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
| Field | Type
|
|
48
|
-
| -------------- |
|
|
49
|
-
| `username` | `string`
|
|
50
|
-
| `password` | `string`
|
|
51
|
-
| `host` | `string`
|
|
52
|
-
| `port` | `number`
|
|
53
|
-
| `protocol` | `'http'
|
|
54
|
-
| `clientId` | `string`
|
|
55
|
-
| `clientSecret` | `string`
|
|
56
|
-
| `apiKey` | `string`
|
|
47
|
+
| Field | Type | Used by | Description |
|
|
48
|
+
| -------------- | --------- | --------------- | ---------------------------------------------------------------------- |
|
|
49
|
+
| `username` | `string` | `route` | Route Mobile account username. **Required** for `route`. |
|
|
50
|
+
| `password` | `string` | `route` | Route Mobile account password. **Required** for `route`. |
|
|
51
|
+
| `host` | `string` | `route`, `nest` | API host. See per-gateway defaults below. |
|
|
52
|
+
| `port` | `number` | `route` | TCP port for Route Mobile. Default: `8080`. |
|
|
53
|
+
| `protocol` | `'http' \| 'https'` | `route`, `nest` | HTTPS or HTTP to the provider API. |
|
|
54
|
+
| `clientId` | `string` | `hubtel` | Hubtel client ID. **Required** for `hubtel`. |
|
|
55
|
+
| `clientSecret` | `string` | `hubtel` | Hubtel client secret. **Required** for `hubtel`. |
|
|
56
|
+
| `apiKey` | `string` | `nest` | SMSOnlineGH API key (`Authorization: key …`). **Required** for `nest`. |
|
|
57
|
+
| `debug` | `boolean` | all | If `true`, the active gateway logs each request/response to the console (prefix `[unismsgateway:…]`). Off by default. |
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
Validation runs in `smsPlatform` when the instance is constructed: missing required fields for the chosen `platformId` throw `Error` with a clear message.
|
|
@@ -80,9 +81,9 @@ Nothing is read from the environment unless **you** wire it. Required fields are
|
|
|
80
81
|
|
|
81
82
|
| `platformId` | Required in `param` | Optional in `param` (defaults in this library) |
|
|
82
83
|
| ------------ | -------------------------- | --------------------------------------------------------------------------------------------- |
|
|
83
|
-
| `nest` | `apiKey` | `host` (default `api.smsonlinegh.com`), `protocol` (default `https`)
|
|
84
|
-
| `hubtel` | `clientId`, `clientSecret` |
|
|
85
|
-
| `route` | `username`, `password` | `host` (default `rslr.connectbind.com`), `protocol` (default `http`), `port` (default `8080`) |
|
|
84
|
+
| `nest` | `apiKey` | `host` (default `api.smsonlinegh.com`), `protocol` (default `https`), `debug` |
|
|
85
|
+
| `hubtel` | `clientId`, `clientSecret` | `debug` |
|
|
86
|
+
| `route` | `username`, `password` | `host` (default `rslr.connectbind.com`), `protocol` (default `http`), `port` (default `8080`), `debug` |
|
|
86
87
|
|
|
87
88
|
|
|
88
89
|
**Suggested env names for your app** (optional; you can rename them). Credential keys (`NEST_`*, `HUBTEL_`*, `ROUTE_*`) match [live test](#live-integration-test-environment-variables) and `.env.example`. Platform selection differs: the test script requires `GATEWAY_PLATFORM` (or `TEST_ALL`); in your app you choose any name (the example below uses `SMS_PLATFORM_ID`):
|
|
@@ -340,7 +341,7 @@ console.log(balance.balance, balance.model);
|
|
|
340
341
|
| Field | Type | Required | Description |
|
|
341
342
|
| --------- | -------- | -------- | ---------------------------------------------------------------------- |
|
|
342
343
|
| `From` | `string` | yes | Sender ID or label. |
|
|
343
|
-
| `To` | `string
|
|
344
|
+
| `To` | `string \| number` | yes |
|
|
344
345
|
| `Content` | `string` | yes | Message body. |
|
|
345
346
|
| `Type` | `number` | no | Message type; **nest** maps this to request body `type` (default `0`). |
|
|
346
347
|
|
|
@@ -357,9 +358,14 @@ Returns `Promise<SendResult>`. Optional `callback` is invoked with the same resu
|
|
|
357
358
|
messageId?: string;
|
|
358
359
|
data?: any;
|
|
359
360
|
error?: string;
|
|
361
|
+
statusCode?: number; // HTTP status from the provider when available (nest, etc.)
|
|
360
362
|
}
|
|
361
363
|
```
|
|
362
364
|
|
|
365
|
+
When `success` is `false`, always read **`error`** — it contains a human-readable reason (provider status codes, API handshake labels, network errors, and so on). For **`nest`**, if the API rejects the send but returns JSON, **`data`** is the **full parsed response body** (not only `response.data`), so you can inspect `handshake` and any provider fields. For HTTP errors, `data` may be the raw response body string. **`statusCode`** is set when the adapter knows the HTTP status (for example nest).
|
|
366
|
+
|
|
367
|
+
**Debugging:** Set `param.debug: true` when calling `init()` to print request URLs, bodies, and responses to the console. The live test script enables debug for the `nest` platform so you can trace `quickSend` and `getBalance` without changing application code.
|
|
368
|
+
|
|
363
369
|
**Example**
|
|
364
370
|
|
|
365
371
|
```javascript
|
|
@@ -91,8 +91,10 @@ function testPlatform(platformId) {
|
|
|
91
91
|
param.apiKey = requireEnv('NEST_API_KEY');
|
|
92
92
|
if (env('NEST_HOST'))
|
|
93
93
|
param.host = env('NEST_HOST');
|
|
94
|
-
if (env('NEST_PROTOCOL'))
|
|
94
|
+
if (env('NEST_PROTOCOL')) {
|
|
95
95
|
param.protocol = env('NEST_PROTOCOL');
|
|
96
|
+
}
|
|
97
|
+
param.debug = true;
|
|
96
98
|
break;
|
|
97
99
|
case 'hubtel':
|
|
98
100
|
param.clientId = requireEnv('HUBTEL_CLIENT_ID');
|
|
@@ -105,11 +107,12 @@ function testPlatform(platformId) {
|
|
|
105
107
|
param.host = env('ROUTE_HOST');
|
|
106
108
|
if (env('ROUTE_PORT'))
|
|
107
109
|
param.port = Number(env('ROUTE_PORT'));
|
|
108
|
-
if (env('ROUTE_PROTOCOL'))
|
|
110
|
+
if (env('ROUTE_PROTOCOL')) {
|
|
109
111
|
param.protocol = env('ROUTE_PROTOCOL');
|
|
112
|
+
}
|
|
110
113
|
break;
|
|
111
114
|
}
|
|
112
|
-
platform = (0, lib_1.init)({ platformId, param
|
|
115
|
+
platform = (0, lib_1.init)({ platformId, param });
|
|
113
116
|
pass(`Initialized ${platformId} platform`);
|
|
114
117
|
}));
|
|
115
118
|
// 2. Balance check (only nest and hubtel expose getBalance)
|
|
@@ -2,12 +2,15 @@ import { ISmsGatewayDelegate, QuickSendParams, SendResult } from './types';
|
|
|
2
2
|
export interface HubtelSmsGatewayConfig {
|
|
3
3
|
clientId: string;
|
|
4
4
|
clientSecret: string;
|
|
5
|
+
debug?: boolean;
|
|
5
6
|
}
|
|
6
7
|
/**
|
|
7
8
|
* Wraps hubtel-sms-extended and maps API responses to {@link SendResult}.
|
|
8
9
|
*/
|
|
9
10
|
export declare class HubtelSmsGateway implements ISmsGatewayDelegate {
|
|
10
11
|
private _client;
|
|
12
|
+
private _debug;
|
|
11
13
|
constructor(config: HubtelSmsGatewayConfig);
|
|
14
|
+
private log;
|
|
12
15
|
quickSend(params: QuickSendParams, callback?: Function): Promise<SendResult>;
|
|
13
16
|
}
|
|
@@ -16,41 +16,55 @@ const hubtel_sms_extended_1 = require("hubtel-sms-extended");
|
|
|
16
16
|
*/
|
|
17
17
|
class HubtelSmsGateway {
|
|
18
18
|
constructor(config) {
|
|
19
|
+
this._debug = config.debug || false;
|
|
19
20
|
this._client = new hubtel_sms_extended_1.HubtelSms({
|
|
20
21
|
clientId: config.clientId,
|
|
21
22
|
clientSecret: config.clientSecret
|
|
22
23
|
});
|
|
23
24
|
}
|
|
25
|
+
log(...args) {
|
|
26
|
+
if (this._debug) {
|
|
27
|
+
console.log('[unismsgateway:hubtel]', ...args);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
24
30
|
quickSend(params, callback) {
|
|
31
|
+
var _a;
|
|
25
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
this.log('quickSend params:', JSON.stringify(params));
|
|
34
|
+
let result;
|
|
26
35
|
try {
|
|
27
36
|
const raw = yield this._client.quickSend({
|
|
28
37
|
From: params.From,
|
|
29
38
|
To: String(params.To),
|
|
30
39
|
Content: params.Content
|
|
31
40
|
});
|
|
32
|
-
|
|
33
|
-
const
|
|
41
|
+
this.log('quickSend raw response:', JSON.stringify(raw));
|
|
42
|
+
const ok = Number(raw === null || raw === void 0 ? void 0 : raw.Status) === 0;
|
|
43
|
+
result = {
|
|
34
44
|
success: ok,
|
|
35
|
-
messageId: String(raw.MessageId),
|
|
45
|
+
messageId: (raw === null || raw === void 0 ? void 0 : raw.MessageId) != null ? String(raw.MessageId) : undefined,
|
|
36
46
|
data: raw,
|
|
37
|
-
error: ok
|
|
47
|
+
error: ok
|
|
48
|
+
? undefined
|
|
49
|
+
: `Hubtel API Error: Status=${raw === null || raw === void 0 ? void 0 : raw.Status}, NetworkId=${(_a = raw === null || raw === void 0 ? void 0 : raw.NetworkId) !== null && _a !== void 0 ? _a : 'n/a'}`
|
|
38
50
|
};
|
|
39
|
-
if (callback) {
|
|
40
|
-
callback(result);
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
51
|
}
|
|
44
52
|
catch (error) {
|
|
45
|
-
const
|
|
53
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
54
|
+
this.log('quickSend error:', errorMessage);
|
|
55
|
+
result = {
|
|
46
56
|
success: false,
|
|
47
|
-
error:
|
|
57
|
+
error: errorMessage,
|
|
58
|
+
data: error instanceof Error && error.response
|
|
59
|
+
? error.response
|
|
60
|
+
: null
|
|
48
61
|
};
|
|
49
|
-
if (callback) {
|
|
50
|
-
callback(result);
|
|
51
|
-
}
|
|
52
|
-
return result;
|
|
53
62
|
}
|
|
63
|
+
this.log('quickSend result:', JSON.stringify(result));
|
|
64
|
+
if (callback) {
|
|
65
|
+
callback(result);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
54
68
|
});
|
|
55
69
|
}
|
|
56
70
|
}
|
|
@@ -3,6 +3,7 @@ export declare class NestSmsGateway implements ISmsGateway {
|
|
|
3
3
|
private config;
|
|
4
4
|
constructor(config: NestSmsConfig);
|
|
5
5
|
init(): ISmsGateway;
|
|
6
|
+
private log;
|
|
6
7
|
private makeRequest;
|
|
7
8
|
quickSend(params: QuickSendParams, callback?: Function): Promise<SendResult>;
|
|
8
9
|
getBalance(): Promise<{
|
|
@@ -38,59 +38,80 @@ class NestSmsGateway {
|
|
|
38
38
|
this.config = {
|
|
39
39
|
host: config.host || DEFAULT_HOST,
|
|
40
40
|
protocol: config.protocol || DEFAULT_PROTOCOL,
|
|
41
|
-
apiKey: config.apiKey
|
|
41
|
+
apiKey: config.apiKey,
|
|
42
|
+
debug: config.debug || false
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
45
|
init() {
|
|
45
46
|
return this;
|
|
46
47
|
}
|
|
48
|
+
log(...args) {
|
|
49
|
+
if (this.config.debug) {
|
|
50
|
+
console.log('[unismsgateway:nest]', ...args);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
47
53
|
makeRequest(endpoint, data) {
|
|
48
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
55
|
return new Promise((resolve, reject) => {
|
|
50
|
-
var _a;
|
|
51
56
|
const postData = data ? JSON.stringify(data) : '';
|
|
52
57
|
const protocol = this.config.protocol || DEFAULT_PROTOCOL;
|
|
53
58
|
const httpModule = protocol === 'https' ? https : http;
|
|
54
59
|
const defaultPort = protocol === 'https' ? 443 : 80;
|
|
60
|
+
const host = this.config.host || DEFAULT_HOST;
|
|
61
|
+
const hostname = host.includes(':') ? host.split(':')[0] : host;
|
|
62
|
+
const port = host.includes(':')
|
|
63
|
+
? parseInt(host.split(':')[1], 10)
|
|
64
|
+
: defaultPort;
|
|
55
65
|
const options = {
|
|
56
|
-
hostname
|
|
57
|
-
port
|
|
58
|
-
? parseInt(this.config.host.split(':')[1])
|
|
59
|
-
: defaultPort,
|
|
66
|
+
hostname,
|
|
67
|
+
port,
|
|
60
68
|
path: `/v5/${endpoint}`,
|
|
61
69
|
method: 'POST',
|
|
62
70
|
headers: {
|
|
63
|
-
'Host':
|
|
71
|
+
'Host': hostname,
|
|
64
72
|
'Content-Type': 'application/json',
|
|
65
73
|
'Accept': 'application/json',
|
|
66
74
|
'Authorization': `key ${this.config.apiKey}`,
|
|
67
75
|
'Content-Length': Buffer.byteLength(postData)
|
|
68
76
|
}
|
|
69
77
|
};
|
|
78
|
+
this.log(`POST /v5/${endpoint}`, data ? JSON.stringify(data) : '(no body)');
|
|
70
79
|
const req = httpModule.request(options, (res) => {
|
|
71
80
|
let responseBody = '';
|
|
72
81
|
res.on('data', (chunk) => {
|
|
73
82
|
responseBody += chunk;
|
|
74
83
|
});
|
|
75
84
|
res.on('end', () => {
|
|
85
|
+
var _a;
|
|
86
|
+
const statusCode = (_a = res.statusCode) !== null && _a !== void 0 ? _a : 0;
|
|
87
|
+
this.log(`HTTP ${statusCode} response:`, responseBody);
|
|
76
88
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
resolve(parsed);
|
|
89
|
+
const parsed = JSON.parse(responseBody);
|
|
90
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
91
|
+
resolve({ statusCode, body: parsed });
|
|
80
92
|
}
|
|
81
93
|
else {
|
|
82
|
-
|
|
94
|
+
const err = new Error(`HTTP ${statusCode}: ${responseBody}`);
|
|
95
|
+
err.statusCode = statusCode;
|
|
96
|
+
err.rawBody = responseBody;
|
|
97
|
+
reject(err);
|
|
83
98
|
}
|
|
84
99
|
}
|
|
85
|
-
catch (
|
|
86
|
-
|
|
100
|
+
catch (_b) {
|
|
101
|
+
const err = new Error(`Failed to parse gateway response (HTTP ${statusCode}): ${responseBody}`);
|
|
102
|
+
err.statusCode = statusCode;
|
|
103
|
+
err.rawBody = responseBody;
|
|
104
|
+
reject(err);
|
|
87
105
|
}
|
|
88
106
|
});
|
|
89
107
|
});
|
|
90
108
|
req.on('error', (error) => {
|
|
109
|
+
this.log('Network error:', error.message);
|
|
91
110
|
reject(error);
|
|
92
111
|
});
|
|
93
|
-
|
|
112
|
+
if (postData) {
|
|
113
|
+
req.write(postData);
|
|
114
|
+
}
|
|
94
115
|
req.end();
|
|
95
116
|
});
|
|
96
117
|
});
|
|
@@ -98,57 +119,73 @@ class NestSmsGateway {
|
|
|
98
119
|
quickSend(params, callback) {
|
|
99
120
|
var _a, _b, _c, _d, _e;
|
|
100
121
|
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
-
const endpoint = 'message/sms/send';
|
|
102
|
-
// SMSOnlineGH v5 expects: text, sender, destinations[] (see API docs — not from/to/content).
|
|
103
122
|
const requestBody = {
|
|
104
123
|
text: params.Content,
|
|
105
|
-
type: params.Type
|
|
124
|
+
type: (_a = params.Type) !== null && _a !== void 0 ? _a : 0,
|
|
106
125
|
sender: params.From,
|
|
107
126
|
destinations: [String(params.To)]
|
|
108
127
|
};
|
|
128
|
+
this.log('quickSend params:', JSON.stringify(params));
|
|
129
|
+
let result;
|
|
109
130
|
try {
|
|
110
|
-
const response = yield this.makeRequest(
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
131
|
+
const { statusCode, body: response } = yield this.makeRequest('message/sms/send', requestBody);
|
|
132
|
+
const handshakeId = (_b = response.handshake) === null || _b === void 0 ? void 0 : _b.id;
|
|
133
|
+
const handshakeLabel = (_c = response.handshake) === null || _c === void 0 ? void 0 : _c.label;
|
|
134
|
+
const handshakeOk = Number(handshakeId) === 0;
|
|
135
|
+
const responseData = (_d = response.data) !== null && _d !== void 0 ? _d : null;
|
|
136
|
+
const batchId = responseData && typeof responseData === 'object'
|
|
137
|
+
? responseData.batch
|
|
138
|
+
: undefined;
|
|
139
|
+
const firstDest = responseData && typeof responseData === 'object'
|
|
140
|
+
? (_e = responseData.destinations) === null || _e === void 0 ? void 0 : _e[0]
|
|
116
141
|
: undefined;
|
|
117
|
-
|
|
142
|
+
let errorMsg;
|
|
143
|
+
if (!handshakeOk) {
|
|
144
|
+
if (handshakeLabel) {
|
|
145
|
+
errorMsg = `API Error [code ${handshakeId}]: ${handshakeLabel}`;
|
|
146
|
+
}
|
|
147
|
+
else if (handshakeId !== undefined && handshakeId !== null) {
|
|
148
|
+
errorMsg = `API Error: handshake code=${handshakeId}`;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
errorMsg = `Unexpected API response: ${JSON.stringify(response)}`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
result = {
|
|
118
155
|
success: handshakeOk,
|
|
119
|
-
data,
|
|
120
156
|
messageId: batchId || (firstDest === null || firstDest === void 0 ? void 0 : firstDest.id),
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
157
|
+
// On failure, expose the full raw response so callers can inspect it.
|
|
158
|
+
data: handshakeOk ? responseData : response,
|
|
159
|
+
error: errorMsg,
|
|
160
|
+
statusCode
|
|
125
161
|
};
|
|
126
|
-
if (callback) {
|
|
127
|
-
callback(result);
|
|
128
|
-
}
|
|
129
|
-
return result;
|
|
130
162
|
}
|
|
131
163
|
catch (error) {
|
|
164
|
+
const httpErr = error;
|
|
132
165
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
133
|
-
|
|
166
|
+
result = {
|
|
134
167
|
success: false,
|
|
135
|
-
error: errorMessage
|
|
168
|
+
error: errorMessage,
|
|
169
|
+
statusCode: httpErr.statusCode,
|
|
170
|
+
// Preserve whatever raw body we got for inspection.
|
|
171
|
+
data: httpErr.rawBody !== undefined ? httpErr.rawBody : null
|
|
136
172
|
};
|
|
137
|
-
if (callback) {
|
|
138
|
-
callback(result);
|
|
139
|
-
}
|
|
140
|
-
return result;
|
|
141
173
|
}
|
|
174
|
+
this.log('quickSend result:', JSON.stringify(result));
|
|
175
|
+
if (callback) {
|
|
176
|
+
callback(result);
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
142
179
|
});
|
|
143
180
|
}
|
|
144
181
|
getBalance() {
|
|
145
|
-
var _a, _b;
|
|
182
|
+
var _a, _b, _c, _d;
|
|
146
183
|
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
-
|
|
148
|
-
const response = yield this.makeRequest(
|
|
184
|
+
this.log('getBalance called');
|
|
185
|
+
const { body: response } = yield this.makeRequest('account/balance');
|
|
149
186
|
return {
|
|
150
|
-
balance: ((_a = response.data) === null || _a === void 0 ? void 0 : _a.balance)
|
|
151
|
-
model: ((
|
|
187
|
+
balance: (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.balance) !== null && _b !== void 0 ? _b : 0,
|
|
188
|
+
model: (_d = (_c = response.data) === null || _c === void 0 ? void 0 : _c.model) !== null && _d !== void 0 ? _d : 'quantity'
|
|
152
189
|
};
|
|
153
190
|
});
|
|
154
191
|
}
|
package/dist/src/lib/platform.js
CHANGED
|
@@ -52,18 +52,21 @@ class smsPlatform {
|
|
|
52
52
|
username: param.username,
|
|
53
53
|
password: param.password,
|
|
54
54
|
protocol: param.protocol || 'http',
|
|
55
|
-
port: param.port || 8080
|
|
55
|
+
port: param.port || 8080,
|
|
56
|
+
debug: param.debug
|
|
56
57
|
});
|
|
57
58
|
case 'hubtel':
|
|
58
59
|
return new hubtel_gateway_1.HubtelSmsGateway({
|
|
59
60
|
clientId: param.clientId,
|
|
60
|
-
clientSecret: param.clientSecret
|
|
61
|
+
clientSecret: param.clientSecret,
|
|
62
|
+
debug: param.debug
|
|
61
63
|
});
|
|
62
64
|
case 'nest':
|
|
63
65
|
return new nest_gateway_1.NestSmsGateway({
|
|
64
66
|
apiKey: param.apiKey,
|
|
65
67
|
host: param.host,
|
|
66
|
-
protocol: param.protocol
|
|
68
|
+
protocol: param.protocol,
|
|
69
|
+
debug: param.debug
|
|
67
70
|
});
|
|
68
71
|
default:
|
|
69
72
|
throw new Error(`Unsupported platform: ${platformId}`);
|
|
@@ -5,8 +5,18 @@ export interface RouteSmsGatewayConfig {
|
|
|
5
5
|
password: string;
|
|
6
6
|
protocol: 'http' | 'https';
|
|
7
7
|
port: number;
|
|
8
|
+
debug?: boolean;
|
|
8
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Adapts routemobilesms to {@link ISmsGatewayDelegate}.
|
|
12
|
+
*
|
|
13
|
+
* NOTE: routemobilesms stores config in module-level state via the constructor,
|
|
14
|
+
* then exposes `routeSms.sendAsync` as a static-style call. The instance is
|
|
15
|
+
* intentionally discarded after construction.
|
|
16
|
+
*/
|
|
9
17
|
export declare class RouteSmsGateway implements ISmsGatewayDelegate {
|
|
18
|
+
private _debug;
|
|
10
19
|
constructor(config: RouteSmsGatewayConfig);
|
|
20
|
+
private log;
|
|
11
21
|
quickSend(params: QuickSendParams, callback?: Function): Promise<SendResult>;
|
|
12
22
|
}
|
|
@@ -11,9 +11,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.RouteSmsGateway = void 0;
|
|
13
13
|
const routemobilesms_1 = require("routemobilesms");
|
|
14
|
-
/**
|
|
15
|
-
* Adapts routemobilesms static `sendAsync` API to {@link ISmsGatewayDelegate}.
|
|
16
|
-
*/
|
|
17
14
|
function toRouteDestination(to) {
|
|
18
15
|
if (typeof to === 'number') {
|
|
19
16
|
return to;
|
|
@@ -22,8 +19,18 @@ function toRouteDestination(to) {
|
|
|
22
19
|
const n = Number(digits);
|
|
23
20
|
return Number.isNaN(n) ? 0 : n;
|
|
24
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Adapts routemobilesms to {@link ISmsGatewayDelegate}.
|
|
24
|
+
*
|
|
25
|
+
* NOTE: routemobilesms stores config in module-level state via the constructor,
|
|
26
|
+
* then exposes `routeSms.sendAsync` as a static-style call. The instance is
|
|
27
|
+
* intentionally discarded after construction.
|
|
28
|
+
*/
|
|
25
29
|
class RouteSmsGateway {
|
|
26
30
|
constructor(config) {
|
|
31
|
+
this._debug = config.debug || false;
|
|
32
|
+
// routemobilesms configures itself through its constructor and exposes
|
|
33
|
+
// sendAsync as a static method — the returned instance is not needed.
|
|
27
34
|
new routemobilesms_1.routeSms({
|
|
28
35
|
host: config.host,
|
|
29
36
|
username: config.username,
|
|
@@ -32,8 +39,15 @@ class RouteSmsGateway {
|
|
|
32
39
|
port: config.port
|
|
33
40
|
});
|
|
34
41
|
}
|
|
42
|
+
log(...args) {
|
|
43
|
+
if (this._debug) {
|
|
44
|
+
console.log('[unismsgateway:route]', ...args);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
35
47
|
quickSend(params, callback) {
|
|
48
|
+
var _a, _b;
|
|
36
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
this.log('quickSend params:', JSON.stringify(params));
|
|
37
51
|
const sendParams = {
|
|
38
52
|
From: params.From,
|
|
39
53
|
To: toRouteDestination(params.To),
|
|
@@ -42,24 +56,47 @@ class RouteSmsGateway {
|
|
|
42
56
|
if (params.Type !== undefined) {
|
|
43
57
|
sendParams.config = { type: params.Type, dlr: 0 };
|
|
44
58
|
}
|
|
45
|
-
const raw = yield routemobilesms_1.routeSms.sendAsync(sendParams);
|
|
46
59
|
let result;
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
try {
|
|
61
|
+
const raw = yield routemobilesms_1.routeSms.sendAsync(sendParams);
|
|
62
|
+
this.log('quickSend raw response:', JSON.stringify(raw));
|
|
63
|
+
if (raw === undefined || raw === null) {
|
|
64
|
+
result = {
|
|
65
|
+
success: false,
|
|
66
|
+
error: 'No response received from Route SMS gateway',
|
|
67
|
+
data: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
else if (Array.isArray(raw) && raw.length > 0) {
|
|
71
|
+
const first = raw[0];
|
|
72
|
+
const ok = first.status === 'successful';
|
|
73
|
+
result = {
|
|
74
|
+
success: ok,
|
|
75
|
+
messageId: first.id,
|
|
76
|
+
data: raw,
|
|
77
|
+
error: ok
|
|
78
|
+
? undefined
|
|
79
|
+
: `Route SMS Error [${(_a = first.code) !== null && _a !== void 0 ? _a : 'unknown'}]: ${(_b = first.message) !== null && _b !== void 0 ? _b : 'Send failed'}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
result = {
|
|
84
|
+
success: false,
|
|
85
|
+
error: 'Unexpected response format from Route SMS gateway',
|
|
86
|
+
data: raw
|
|
87
|
+
};
|
|
88
|
+
}
|
|
49
89
|
}
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
90
|
+
catch (error) {
|
|
91
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
92
|
+
this.log('quickSend error:', errorMessage);
|
|
53
93
|
result = {
|
|
54
|
-
success:
|
|
55
|
-
|
|
56
|
-
data:
|
|
57
|
-
error: ok ? undefined : (first.message || first.code || 'Send failed')
|
|
94
|
+
success: false,
|
|
95
|
+
error: errorMessage,
|
|
96
|
+
data: null
|
|
58
97
|
};
|
|
59
98
|
}
|
|
60
|
-
|
|
61
|
-
result = { success: false, error: 'Unexpected response from route SMS gateway', data: raw };
|
|
62
|
-
}
|
|
99
|
+
this.log('quickSend result:', JSON.stringify(result));
|
|
63
100
|
if (callback) {
|
|
64
101
|
callback(result);
|
|
65
102
|
}
|
package/dist/src/lib/types.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface SendResult {
|
|
|
10
10
|
messageId?: string;
|
|
11
11
|
data?: any;
|
|
12
12
|
error?: string;
|
|
13
|
+
/** HTTP status code returned by the gateway (when available). */
|
|
14
|
+
statusCode?: number;
|
|
13
15
|
}
|
|
14
16
|
export interface IgatewayParam {
|
|
15
17
|
host?: string;
|
|
@@ -20,6 +22,8 @@ export interface IgatewayParam {
|
|
|
20
22
|
clientSecret?: string;
|
|
21
23
|
apiKey?: string;
|
|
22
24
|
protocol?: 'http' | 'https';
|
|
25
|
+
/** Set to true to print request/response details to console for debugging. */
|
|
26
|
+
debug?: boolean;
|
|
23
27
|
}
|
|
24
28
|
export interface IgatewaySettings {
|
|
25
29
|
platformId: PlatformId;
|
|
@@ -37,6 +41,7 @@ export interface NestSmsConfig {
|
|
|
37
41
|
apiKey: string;
|
|
38
42
|
host?: string;
|
|
39
43
|
protocol?: 'http' | 'https';
|
|
44
|
+
debug?: boolean;
|
|
40
45
|
}
|
|
41
46
|
export interface NestSendResponse {
|
|
42
47
|
handshake: {
|
package/package.json
CHANGED