@codebucket/whatsapp
Version:
A reusable WhatsApp Business API client with template and non-template support, webhook handling, pluggable storage, and text sanitization
81 lines (80 loc) • 3.06 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendWhatsApp = sendWhatsApp;
exports.handleWhatsAppWebhook = handleWhatsAppWebhook;
// src/client.ts
const axios_1 = __importDefault(require("axios"));
const template_1 = require("./template");
const phoneNumberCache = new Map();
async function getBusinessPhoneNumber(phoneNumberId, accessToken) {
if (phoneNumberCache.has(phoneNumberId)) {
return phoneNumberCache.get(phoneNumberId);
}
const token = accessToken || process.env.WABA_TOKEN;
const url = `https://graph.facebook.com/v22.0/${phoneNumberId}`;
const resp = await axios_1.default.get(url, {
params: {
access_token: token,
fields: 'display_phone_number'
}
});
const display = resp.data.display_phone_number;
phoneNumberCache.set(phoneNumberId, display);
return display;
}
async function sendWhatsApp(opts, store) {
// 1) build or pick the payload
let payload;
let warnings = [];
if ('templateName' in opts) {
const result = await (0, template_1.createWhatsAppTemplatePayload)({
businessAccountId: opts.businessAccountId,
accessToken: opts.accessToken,
to: opts.to,
templateName: opts.templateName,
language: opts.language,
variables: opts.variables
});
payload = result.payload;
warnings = result.warnings;
}
else {
payload = { ...opts.messagePayload };
}
// 2) inject messaging_product automatically
payload.messaging_product = 'whatsapp';
// 3) send to Graph API
const url = `https://graph.facebook.com/v22.0/${opts.senderUserId}/messages`;
const resp = await axios_1.default.post(url, payload, {
headers: { Authorization: `Bearer ${opts.accessToken}`, 'Content-Type': 'application/json' }
});
let senderPhoneNumber = await getBusinessPhoneNumber(opts.senderUserId, opts.accessToken);
// 4) persist outgoing
if (store)
await store.saveOutgoingMessage(opts.senderUserId, {
senderUserId: opts.senderUserId,
senderPhoneNumber,
accessToken: opts.accessToken,
to: opts.to,
messagePayload: payload
}, resp.data);
return { response: resp.data, warnings };
}
async function handleWhatsAppWebhook(payload, store) {
for (const entry of payload.entry) {
const accountId = entry.changes[0].value.metadata.phone_number_id;
if (store) {
for (const msg of entry.changes[0].value.messages || []) {
await store.saveIncomingMessage(accountId, msg);
}
if (store.saveMessageStatus) {
for (const st of entry.changes[0].value.statuses || []) {
await store.saveMessageStatus(accountId, st);
}
}
}
}
}