Voice-call: fix Twilio status callbacks
This commit is contained in:
@@ -389,12 +389,12 @@ export class TwilioProvider implements VoiceCallProvider {
|
|||||||
|
|
||||||
// Build request params - always use URL-based TwiML.
|
// Build request params - always use URL-based TwiML.
|
||||||
// Twilio silently ignores `StatusCallback` when using the inline `Twiml` parameter.
|
// Twilio silently ignores `StatusCallback` when using the inline `Twiml` parameter.
|
||||||
const params: Record<string, string> = {
|
const params: Record<string, string | string[]> = {
|
||||||
To: input.to,
|
To: input.to,
|
||||||
From: input.from,
|
From: input.from,
|
||||||
Url: url.toString(), // TwiML serving endpoint
|
Url: url.toString(), // TwiML serving endpoint
|
||||||
StatusCallback: statusUrl.toString(), // Separate status callback endpoint
|
StatusCallback: statusUrl.toString(), // Separate status callback endpoint
|
||||||
StatusCallbackEvent: "initiated ringing answered completed",
|
StatusCallbackEvent: ["initiated", "ringing", "answered", "completed"],
|
||||||
Timeout: "30",
|
Timeout: "30",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,33 @@ export async function twilioApiRequest<T = unknown>(params: {
|
|||||||
accountSid: string;
|
accountSid: string;
|
||||||
authToken: string;
|
authToken: string;
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
body: Record<string, string>;
|
body: URLSearchParams | Record<string, string | string[]>;
|
||||||
allowNotFound?: boolean;
|
allowNotFound?: boolean;
|
||||||
}): Promise<T> {
|
}): Promise<T> {
|
||||||
|
const bodyParams =
|
||||||
|
params.body instanceof URLSearchParams
|
||||||
|
? params.body
|
||||||
|
: Object.entries(params.body).reduce<URLSearchParams>(
|
||||||
|
(acc, [key, value]) => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
for (const entry of value) {
|
||||||
|
acc.append(key, entry);
|
||||||
|
}
|
||||||
|
} else if (typeof value === "string") {
|
||||||
|
acc.append(key, value);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
new URLSearchParams(),
|
||||||
|
);
|
||||||
|
|
||||||
const response = await fetch(`${params.baseUrl}${params.endpoint}`, {
|
const response = await fetch(`${params.baseUrl}${params.endpoint}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Basic ${Buffer.from(`${params.accountSid}:${params.authToken}`).toString("base64")}`,
|
Authorization: `Basic ${Buffer.from(`${params.accountSid}:${params.authToken}`).toString("base64")}`,
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
body: new URLSearchParams(params.body),
|
body: bodyParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -26,4 +43,3 @@ export async function twilioApiRequest<T = unknown>(params: {
|
|||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
return text ? (JSON.parse(text) as T) : (undefined as T);
|
return text ? (JSON.parse(text) as T) : (undefined as T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user