clean setTwilioWebhooks and twilio webhook verification
This commit is contained in:
parent
e77e7d17e0
commit
6a2e76857b
@ -2,6 +2,7 @@ import { BlitzApiRequest, BlitzApiResponse } from "blitz";
|
|||||||
|
|
||||||
import db from "db";
|
import db from "db";
|
||||||
import twilio from "twilio";
|
import twilio from "twilio";
|
||||||
|
import setTwilioWebhooks from "../onboarding/api/queue/set-twilio-webhooks";
|
||||||
|
|
||||||
export default async function ddd(req: BlitzApiRequest, res: BlitzApiResponse) {
|
export default async function ddd(req: BlitzApiRequest, res: BlitzApiResponse) {
|
||||||
/*await Promise.all([
|
/*await Promise.all([
|
||||||
@ -49,7 +50,12 @@ export default async function ddd(req: BlitzApiRequest, res: BlitzApiResponse) {
|
|||||||
console.log("messagesReceived", messagesReceived.sort((a, b) => a.dateCreated.getTime() - b.dateCreated.getTime()));
|
console.log("messagesReceived", messagesReceived.sort((a, b) => a.dateCreated.getTime() - b.dateCreated.getTime()));
|
||||||
// console.log("messagesReceived", messagesReceived);*/
|
// console.log("messagesReceived", messagesReceived);*/
|
||||||
|
|
||||||
setTimeout(() => {
|
/*setTwilioWebhooks.enqueue({
|
||||||
res.status(200).end();
|
phoneNumberId: "PNb77c9690c394368bdbaf20ea6fe5e9fc",
|
||||||
}, 1000 * 60 * 5);
|
organizationId: "95267d60-3d35-4c36-9905-8543ecb4f174",
|
||||||
|
});*/
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
res.status(200).end();
|
||||||
|
// }, 1000 * 60 * 5);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import twilio from "twilio";
|
|||||||
import appLogger from "../../../../integrations/logger";
|
import appLogger from "../../../../integrations/logger";
|
||||||
import db from "../../../../db";
|
import db from "../../../../db";
|
||||||
import insertIncomingMessageQueue from "../queue/insert-incoming-message";
|
import insertIncomingMessageQueue from "../queue/insert-incoming-message";
|
||||||
|
import { smsUrl } from "../../../../integrations/twilio";
|
||||||
|
|
||||||
type ApiError = {
|
type ApiError = {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
@ -53,13 +54,12 @@ export default async function incomingMessageHandler(req: BlitzApiRequest, res:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`;
|
|
||||||
const phoneNumber = phoneNumbers.find((phoneNumber) => {
|
const phoneNumber = phoneNumbers.find((phoneNumber) => {
|
||||||
// if multiple organizations have the same number
|
// if multiple organizations have the same number
|
||||||
// find the organization currently using that phone number
|
// find the organization currently using that phone number
|
||||||
// maybe we shouldn't let multiple organizations use the same phone number
|
// maybe we shouldn't let multiple organizations use the same phone number
|
||||||
const authToken = phoneNumber.organization.twilioAuthToken ?? "";
|
const authToken = phoneNumber.organization.twilioAuthToken ?? "";
|
||||||
return twilio.validateRequest(authToken, twilioSignature, url, req.body);
|
return twilio.validateRequest(authToken, twilioSignature, smsUrl, req.body);
|
||||||
});
|
});
|
||||||
if (!phoneNumber) {
|
if (!phoneNumber) {
|
||||||
const statusCode = 400;
|
const statusCode = 400;
|
||||||
|
@ -4,7 +4,7 @@ import type twilio from "twilio";
|
|||||||
import type { ApplicationInstance } from "twilio/lib/rest/api/v2010/account/application";
|
import type { ApplicationInstance } from "twilio/lib/rest/api/v2010/account/application";
|
||||||
|
|
||||||
import db from "../../../../db";
|
import db from "../../../../db";
|
||||||
import getTwilioClient from "../../../../integrations/twilio";
|
import getTwilioClient, { getTwiMLName, smsUrl, voiceUrl } from "../../../../integrations/twilio";
|
||||||
|
|
||||||
type Payload = {
|
type Payload = {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
@ -45,7 +45,7 @@ async function getTwimlApplication(
|
|||||||
): Promise<ApplicationInstance> {
|
): Promise<ApplicationInstance> {
|
||||||
try {
|
try {
|
||||||
if (organizationTwimlAppSid) {
|
if (organizationTwimlAppSid) {
|
||||||
return updateTwimlApplication(twilioClient, organizationTwimlAppSid);
|
return await updateTwimlApplication(twilioClient, organizationTwimlAppSid);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// twiml app with sid `organizationTwimlAppSid` probably doesn't exist anymore
|
// twiml app with sid `organizationTwimlAppSid` probably doesn't exist anymore
|
||||||
@ -59,33 +59,23 @@ async function getTwimlApplication(
|
|||||||
|
|
||||||
return twilioClient.applications.create({
|
return twilioClient.applications.create({
|
||||||
friendlyName: getTwiMLName(),
|
friendlyName: getTwiMLName(),
|
||||||
smsUrl: `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`,
|
smsUrl,
|
||||||
smsMethod: "POST",
|
smsMethod: "POST",
|
||||||
voiceUrl: `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/call`,
|
voiceUrl,
|
||||||
voiceMethod: "POST",
|
voiceMethod: "POST",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateTwimlApplication(twilioClient: twilio.Twilio, twimlAppSid: string) {
|
async function updateTwimlApplication(twilioClient: twilio.Twilio, twimlAppSid: string) {
|
||||||
await twilioClient.applications.get(twimlAppSid).update({
|
await twilioClient.applications.get(twimlAppSid).update({
|
||||||
smsUrl: `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`,
|
friendlyName: getTwiMLName(),
|
||||||
|
smsUrl,
|
||||||
smsMethod: "POST",
|
smsMethod: "POST",
|
||||||
voiceUrl: `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/call`,
|
voiceUrl,
|
||||||
voiceMethod: "POST",
|
voiceMethod: "POST",
|
||||||
});
|
});
|
||||||
|
|
||||||
return twilioClient.applications.get(twimlAppSid).fetch();
|
return twilioClient.applications.get(twimlAppSid).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTwiMLName() {
|
|
||||||
switch (serverRuntimeConfig.app.baseUrl) {
|
|
||||||
case "local.shellphone.app":
|
|
||||||
return "Shellphone LOCAL";
|
|
||||||
case "dev.shellphone.app":
|
|
||||||
return "Shellphone DEV";
|
|
||||||
case "www.shellphone.app":
|
|
||||||
return "Shellphone";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default setTwilioWebhooks;
|
export default setTwilioWebhooks;
|
||||||
|
@ -5,6 +5,7 @@ import type { CallInstance } from "twilio/lib/rest/api/v2010/account/call";
|
|||||||
|
|
||||||
import db, { CallStatus, Direction } from "../../../../db";
|
import db, { CallStatus, Direction } from "../../../../db";
|
||||||
import appLogger from "../../../../integrations/logger";
|
import appLogger from "../../../../integrations/logger";
|
||||||
|
import { voiceUrl } from "../../../../integrations/twilio";
|
||||||
|
|
||||||
const { serverRuntimeConfig } = getConfig();
|
const { serverRuntimeConfig } = getConfig();
|
||||||
const logger = appLogger.child({ route: "/api/webhook/call" });
|
const logger = appLogger.child({ route: "/api/webhook/call" });
|
||||||
@ -17,7 +18,6 @@ type ApiError = {
|
|||||||
export default async function incomingCallHandler(req: BlitzApiRequest, res: BlitzApiResponse) {
|
export default async function incomingCallHandler(req: BlitzApiRequest, res: BlitzApiResponse) {
|
||||||
console.log("req.body", req.body);
|
console.log("req.body", req.body);
|
||||||
|
|
||||||
const url = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/call`;
|
|
||||||
const twilioSignature = req.headers["X-Twilio-Signature"] || req.headers["x-twilio-signature"];
|
const twilioSignature = req.headers["X-Twilio-Signature"] || req.headers["x-twilio-signature"];
|
||||||
if (!twilioSignature || Array.isArray(twilioSignature)) {
|
if (!twilioSignature || Array.isArray(twilioSignature)) {
|
||||||
const statusCode = 400;
|
const statusCode = 400;
|
||||||
@ -42,7 +42,7 @@ export default async function incomingCallHandler(req: BlitzApiRequest, res: Bli
|
|||||||
if (
|
if (
|
||||||
!phoneNumber ||
|
!phoneNumber ||
|
||||||
!phoneNumber.organization.twilioAuthToken ||
|
!phoneNumber.organization.twilioAuthToken ||
|
||||||
!twilio.validateRequest(phoneNumber.organization.twilioAuthToken, twilioSignature, url, req.body)
|
!twilio.validateRequest(phoneNumber.organization.twilioAuthToken, twilioSignature, voiceUrl, req.body)
|
||||||
) {
|
) {
|
||||||
const statusCode = 400;
|
const statusCode = 400;
|
||||||
const apiError: ApiError = {
|
const apiError: ApiError = {
|
||||||
@ -93,7 +93,7 @@ export default async function incomingCallHandler(req: BlitzApiRequest, res: Bli
|
|||||||
// find the organization currently using that phone number
|
// find the organization currently using that phone number
|
||||||
// maybe we shouldn't let multiple organizations use the same phone number
|
// maybe we shouldn't let multiple organizations use the same phone number
|
||||||
const authToken = phoneNumber.organization.twilioAuthToken ?? "";
|
const authToken = phoneNumber.organization.twilioAuthToken ?? "";
|
||||||
return twilio.validateRequest(authToken, twilioSignature, url, req.body);
|
return twilio.validateRequest(authToken, twilioSignature, voiceUrl, req.body);
|
||||||
});
|
});
|
||||||
if (!phoneNumber) {
|
if (!phoneNumber) {
|
||||||
const statusCode = 400;
|
const statusCode = 400;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { NotFoundError } from "blitz";
|
import { getConfig, NotFoundError } from "blitz";
|
||||||
import twilio from "twilio";
|
import twilio from "twilio";
|
||||||
|
|
||||||
import type { Organization } from "db";
|
import type { Organization } from "db";
|
||||||
@ -19,3 +19,20 @@ export default function getTwilioClient(organization: MinimalOrganization | null
|
|||||||
accountSid: organization.twilioAccountSid,
|
accountSid: organization.twilioAccountSid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { serverRuntimeConfig } = getConfig();
|
||||||
|
|
||||||
|
export const smsUrl = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`;
|
||||||
|
|
||||||
|
export const voiceUrl = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/call`;
|
||||||
|
|
||||||
|
export function getTwiMLName() {
|
||||||
|
switch (serverRuntimeConfig.app.baseUrl) {
|
||||||
|
case "local.shellphone.app":
|
||||||
|
return "Shellphone LOCAL";
|
||||||
|
case "dev.shellphone.app":
|
||||||
|
return "Shellphone DEV";
|
||||||
|
case "www.shellphone.app":
|
||||||
|
return "Shellphone";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user