Repository navigation
Expand file tree
/
Copy pathtelesign.js
More file actions
81 lines (74 loc) · 3.36 KB
/
Copy pathtelesign.js
File metadata and controls
81 lines (74 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
'use strict';
const { OUTCOME, ProviderResult, classifyFailure } = require('../providerResult');
const VOICE_PASSCODE_PATTERN = /(?<![0-9])[0-9]{6}(?![0-9])/g;
const SUCCESS = new Set(['200', '203', '290', '291', '292', '100', '101', '102', '103', '3001']);
function buildVoiceMessage(message) {
const paced = message.replace(VOICE_PASSCODE_PATTERN, (passcode) => [...passcode].join(', '));
return `${paced} ${paced}`;
}
const provider = Object.freeze({
name: 'telesign',
authenticationMode: 'apiKey',
credentialSpec: Object.freeze({
mode: 'apiKey',
keyVaultSecretName: 'telesign-api-key',
identityKeyVaultSecretName: 'telesign-customer-id',
}),
createRequest({ channel, endpoint, delivery, credential }) {
if (!['sms', 'voice'].includes(channel)) throw new Error('unsupported channel');
if (typeof delivery.phoneNumber !== 'string'
|| !/^\+[1-9][0-9]{1,14}$/.test(delivery.phoneNumber)) {
throw new Error('invalid recipient');
}
const message = {
text: channel === 'voice' ? buildVoiceMessage(delivery.message) : delivery.message,
};
if (typeof delivery.locale === 'string' && delivery.locale.trim()) {
message.language = delivery.locale;
}
const correlationId = typeof delivery.correlationId === 'string' && delivery.correlationId
? delivery.correlationId : delivery.messageId;
return {
url: endpoint,
method: 'POST',
headers: {
Authorization: `Basic ${Buffer.from(`${credential.identity}:${credential.secret}`).toString('base64')}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
recipient: { phone_number: delivery.phoneNumber },
message,
channels: [{ channel }],
correlation_id: correlationId,
}),
};
},
interpretResponse(response) {
const payload = response.json && typeof response.json === 'object' && !Array.isArray(response.json)
? response.json : {};
const statusObject = payload.status && typeof payload.status === 'object' && !Array.isArray(payload.status)
? payload.status : {};
const code = typeof statusObject.code === 'number' && Number.isInteger(statusObject.code)
? String(statusObject.code) : 'UNKNOWN';
const recognized = SUCCESS.has(code);
const mappedOutcome = recognized ? OUTCOME.CONTINUE : OUTCOME.FAIL;
const outcome = response.ok ? mappedOutcome : OUTCOME.FAIL;
return new ProviderResult({
outcome,
statusRecognized: recognized,
providerHttpStatus: response.providerHttpStatus,
providerMessageId: typeof payload.reference_id === 'string' ? payload.reference_id : null,
providerStatusCode: code,
providerStatusDescription: typeof statusObject.description === 'string'
? statusObject.description : null,
failureReason: classifyFailure({
providerHttpStatus: response.providerHttpStatus,
outcome,
statusRecognized: recognized,
validJson: response.validJson,
}),
});
},
});
module.exports = provider;