Open13
twilio

Programmable message

Incoming webhook

Incoming webhook request contents

Verify request


Verification logic
import { HttpException, Injectable, NestMiddleware } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NextFunction, Request, Response } from 'express';
import { validateRequest } from 'twilio/lib/webhooks/webhooks';
@Injectable()
export class TwilioSignatureMiddleware implements NestMiddleware {
constructor(private readonly configService: ConfigService) {}
use(req: Request, res: Response, next: NextFunction) {
const signature = req.headers['x-twilio-signature'] as string;
if (!signature) {
throw new HttpException('No signature provided', 403);
}
// somehow req.protocol return http(it may be because of alb->ecs connection is http)
const url = 'https://' + req.get('host') + req.originalUrl;
const sortedBody = Object.keys(req.body)
.sort()
.reduce((acc, key) => {
acc[key] = req.body[key];
return acc;
}, {});
const authToken = this.configService.get('TWILIO_ACCOUNT_AUTH_TOKEN');
const isValid = validateRequest(authToken, signature, url, sortedBody);
if (!isValid) {
throw new HttpException('Invalid signature', 403);
}
next();
}
}

Node SDK

API Key

Initialize Client
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Twilio } from 'twilio';
import { MessageInstance } from 'twilio/lib/rest/api/v2010/account/message';
@Injectable()
export class TwilioSMSService {
private readonly twilioClient: Twilio;
private readonly twilioPhoneNumber: string;
constructor(private readonly configService: ConfigService) {
const apiKeySid = this.configService.get('TWILIO_API_KEY_SID');
const apiKeySecret = this.configService.get('TWILIO_API_KEY_SECRET');
const accountSid = this.configService.get('TWILIO_ACCOUNT_SID');
this.twilioClient = new Twilio(apiKeySid, apiKeySecret, {
accountSid: accountSid,
autoRetry: true, //defaultではリトライなしなので必要なら明示
maxRetries: 3,
});
this.twilioPhoneNumber = this.configService.get('TWILIO_PHONE_NUMBER');
}
send(to: string, body: string): Promise<MessageInstance> {
return this.twilioClient.messages.create({
body,
from: this.twilioPhoneNumber,
to,
});
}
}
Error: accountSid must start with AC. The given SID indicates an API Key which requires the accountSid to be passed as an additional option
アカウントのTokenではなくAPI keyを利用する場合にはオプションでアカウントのSIDを渡さないといけない

Long Text as MMS

Encode