fix: move onParse to root and support trailing slash in webhook route
This commit is contained in:
1 parent
ee1c7820c3
commit
32e9fd5ac6
2 files changed
+56
-53
No files matched your search
@@ -29,6 +29,11 @@ const CORS_ORIGIN = process.env.CORS_ORIGIN || "http://localhost:5173";
|
|||||||
const JWT_SECRET = process.env.JWT_SECRET || "homaroma_secret_2026_scent";
|
const JWT_SECRET = process.env.JWT_SECRET || "homaroma_secret_2026_scent";
|
||||||
|
|
||||||
const app = new Elysia()
|
const app = new Elysia()
|
||||||
|
.onParse(async ({ request }) => {
|
||||||
|
if (request.url.includes('/api/line/webhook')) {
|
||||||
|
return await request.text();
|
||||||
|
}
|
||||||
|
})
|
||||||
.use(
|
.use(
|
||||||
cors({
|
cors({
|
||||||
origin: [
|
origin: [
|
||||||
|
|||||||
@@ -3,66 +3,64 @@ import * as line from '@line/bot-sdk';
|
|||||||
import { lineConfig, lineClient } from '../lib/lineClient';
|
import { lineConfig, lineClient } from '../lib/lineClient';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
export const lineRoutes = new Elysia({ prefix: '/line' })
|
const webhookHandler = async ({ request, body, set }: { request: Request, body: any, set: any }) => {
|
||||||
.onParse(async ({ request, contentType }) => {
|
// 1. Verify Signature
|
||||||
if (contentType?.includes('application/json')) {
|
const signature = request.headers.get('x-line-signature');
|
||||||
return await request.text();
|
if (!signature) {
|
||||||
}
|
set.status = 400;
|
||||||
})
|
return { error: 'Missing Signature' };
|
||||||
.post('/webhook', async ({ request, body, set }) => {
|
}
|
||||||
// 1. Verify Signature
|
|
||||||
const signature = request.headers.get('x-line-signature');
|
|
||||||
if (!signature) {
|
|
||||||
set.status = 400;
|
|
||||||
return { error: 'Missing Signature' };
|
|
||||||
}
|
|
||||||
|
|
||||||
// In our onParse hook, we intercepted the body and returned it as a raw text string.
|
// In our global onParse hook, we intercepted the body and returned it as a raw text string.
|
||||||
const rawBody = typeof body === 'string' ? body : JSON.stringify(body);
|
const rawBody = typeof body === 'string' ? body : JSON.stringify(body);
|
||||||
|
|
||||||
if (!rawBody) {
|
if (!rawBody) {
|
||||||
set.status = 400;
|
set.status = 400;
|
||||||
return { error: 'Empty Body' };
|
return { error: 'Empty Body' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const hash = crypto
|
const hash = crypto
|
||||||
.createHmac('SHA256', lineConfig.channelSecret)
|
.createHmac('SHA256', lineConfig.channelSecret)
|
||||||
.update(rawBody)
|
.update(rawBody)
|
||||||
.digest('base64');
|
.digest('base64');
|
||||||
|
|
||||||
console.log('[LINE Webhook] Signature Check - Received:', signature, 'Calculated:', hash);
|
console.log('[LINE Webhook] Signature Check - Received:', signature, 'Calculated:', hash);
|
||||||
|
|
||||||
if (hash !== signature) {
|
if (hash !== signature) {
|
||||||
console.error('[LINE Webhook] Invalid Signature Blocked');
|
console.error('[LINE Webhook] Invalid Signature Blocked');
|
||||||
set.status = 401;
|
set.status = 401;
|
||||||
return { error: 'Invalid Signature' };
|
return { error: 'Invalid Signature' };
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parsedBody = typeof body === 'string' ? JSON.parse(body) : body;
|
const parsedBody = typeof body === 'string' ? JSON.parse(body) : body;
|
||||||
const events: line.WebhookEvent[] = parsedBody.events || [];
|
const events: line.WebhookEvent[] = parsedBody.events || [];
|
||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
if (event.type === 'message' && event.message.type === 'text') {
|
if (event.type === 'message' && event.message.type === 'text') {
|
||||||
// Ignore verification dummy tokens
|
// Ignore verification dummy tokens
|
||||||
if (event.replyToken === '00000000000000000000000000000000' || event.replyToken === 'ffffffffffffffffffffffffffffffff') {
|
if (event.replyToken === '00000000000000000000000000000000' || event.replyToken === 'ffffffffffffffffffffffffffffffff') {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Simple echo bot for now
|
|
||||||
await lineClient.replyMessage({
|
|
||||||
replyToken: event.replyToken,
|
|
||||||
messages: [{
|
|
||||||
type: 'text',
|
|
||||||
text: `คุณส่งข้อความว่า: ${event.message.text}`
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simple echo bot for now
|
||||||
|
await lineClient.replyMessage({
|
||||||
|
replyToken: event.replyToken,
|
||||||
|
messages: [{
|
||||||
|
type: 'text',
|
||||||
|
text: `คุณส่งข้อความว่า: ${event.message.text}`
|
||||||
|
}]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return { success: true };
|
|
||||||
} catch (err) {
|
|
||||||
console.error('[LINE Webhook] Error:', err);
|
|
||||||
set.status = 500;
|
|
||||||
return { error: 'Webhook processing failed' };
|
|
||||||
}
|
}
|
||||||
});
|
return { success: true };
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[LINE Webhook] Error:', err);
|
||||||
|
set.status = 500;
|
||||||
|
return { error: 'Webhook processing failed' };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const lineRoutes = new Elysia({ prefix: '/line' })
|
||||||
|
.post('/webhook', webhookHandler)
|
||||||
|
.post('/webhook/', webhookHandler);
|
||||||
Reference in new issue
Block a user