143 lines
4.4 KiB
JavaScript
143 lines
4.4 KiB
JavaScript
// Node.jsでLINE WORKSのBot APIを使って特定ユーザーにメッセージを送信するサンプル(HTTPS対応)
|
||
const express = require('express');
|
||
const bodyParser = require('body-parser');
|
||
const fetch = require('node-fetch');
|
||
const jwt = require('jsonwebtoken');
|
||
const fs = require('fs');
|
||
const https = require('https');
|
||
const cors = require('cors'); // 追加
|
||
|
||
const app = express();
|
||
app.use(cors({
|
||
origin: [
|
||
'https://neo999.next-hd.net',
|
||
'https://nextoffice.next-hd.co.jp',
|
||
], // 許可するオリジン
|
||
optionsSuccessStatus: 200
|
||
}));
|
||
//app.use(bodyParser.json());
|
||
|
||
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S'; // 任意のAPIキーを設定
|
||
|
||
// アクセストークン取得
|
||
async function getAccessToken() {
|
||
const clientId = 'V58hNobcAqRcQPerySMz';
|
||
const clientSecret = 'gJ84XQtigD';
|
||
const serviceAccount = 'x94xh.serviceaccount@works-nextgroup2';
|
||
const privateKey = fs.readFileSync('./private_20250530180606.key', 'utf8');
|
||
const apiUrl = 'https://auth.worksmobile.com/oauth2/v2.0/token';
|
||
const now = Math.floor(Date.now() / 1000);
|
||
|
||
// JWT生成
|
||
const payload = {
|
||
'iss': clientId,
|
||
'sub': serviceAccount,
|
||
'iat': now,
|
||
'exp': now + 60 * 5,
|
||
'aud': apiUrl
|
||
};
|
||
const assertion = jwt.sign(payload, privateKey, { 'algorithm': 'RS256' });
|
||
|
||
const body = new URLSearchParams({
|
||
'assertion': assertion,
|
||
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
||
'client_id': clientId,
|
||
'client_secret': clientSecret,
|
||
'scope': 'bot'
|
||
});
|
||
|
||
const response = await fetch(apiUrl, {
|
||
'method': 'POST',
|
||
'headers': { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
'body': body.toString()
|
||
});
|
||
|
||
if (response.ok) {
|
||
const data = await response.json();
|
||
return data.access_token;
|
||
} else {
|
||
console.error('アクセストークン取得失敗:', await response.text());
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// メッセージ送信
|
||
async function sendLineworksMessage(botId, userId, messageText) {
|
||
const accessToken = await getAccessToken();
|
||
if (!accessToken) return;
|
||
|
||
const apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/users/${userId}/messages`;
|
||
|
||
const body = {
|
||
'content': {
|
||
'type': 'text',
|
||
'text': messageText
|
||
}
|
||
};
|
||
|
||
const response = await fetch(apiUrl, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=UTF-8',
|
||
'Authorization': `Bearer ${accessToken}`
|
||
},
|
||
body: JSON.stringify(body)
|
||
});
|
||
|
||
if (response.ok) {
|
||
console.log('送信成功');
|
||
} else {
|
||
console.error('送信失敗', await response.text());
|
||
}
|
||
}
|
||
|
||
// APIエンドポイント
|
||
app.post('/lwSendMessage', async (req, res) => {
|
||
let rawBody = '';
|
||
req.on('data', (chunk) => {
|
||
rawBody += chunk; // リクエストデータをそのまま取得
|
||
});
|
||
|
||
req.on('end', () => {
|
||
// APIキーの検証
|
||
const apiKey = req.headers['x-api-key'];
|
||
if (!apiKey || apiKey !== API_KEY) {
|
||
return res.status(401).json({ error: 'APIキーが不正です' });
|
||
}
|
||
|
||
// botIdとuserIdをヘッダーから取得
|
||
const botId = req.headers['x-bot-id'];
|
||
const userId = req.headers['x-user-id'];
|
||
if (!botId || !userId) {
|
||
return res.status(400).json({ error: 'x-bot-id, x-user-idは必須です' });
|
||
}
|
||
|
||
// リクエストボディ全体をmessageTextとして使用
|
||
const messageText = rawBody;
|
||
console.log('messageText:', messageText);
|
||
|
||
if (!messageText) {
|
||
return res.status(400).json({ error: 'messageTextは必須です' });
|
||
}
|
||
|
||
try {
|
||
sendLineworksMessage(botId, userId, messageText);
|
||
res.json({ result: 'ok' });
|
||
} catch (e) {
|
||
res.status(500).json({ error: e.message });
|
||
}
|
||
});
|
||
|
||
});
|
||
|
||
// HTTPSサーバー起動
|
||
const PORT = 30309;
|
||
const sslOptions = {
|
||
cert: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/fullchain.pem'),
|
||
key: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/privkey.pem')
|
||
};
|
||
|
||
https.createServer(sslOptions, app).listen(PORT, () => {
|
||
console.log(`APIサーバー起動: https://neo999.next-hd.net:${PORT}/lwSendMessage`);
|
||
});
|