Plugins › การเชื่อมต่อ
เริ่มต้น
เนื้อหา
Plugins
การดูแลระบบ
การ Deploy
สูตรสำเร็จ
การเชื่อมต่อ (Integrations)
ตั้งค่า → การเชื่อมต่อ คือที่ที่ผู้ดูแลเว็บเชื่อมบัญชีกับผู้ให้บริการภายนอก เช่น bot ของ Telegram, ผู้ให้บริการ AI หรือเพจ Facebook plugin เป็นตัวประกาศผู้ให้บริการ ส่วนผู้ดูแลเชื่อมบัญชีได้โดยไม่ต้องแก้ environment variable
หน้านี้มีอะไร
- หมวด ใช้กรองหน้า: โซเชียลและแชท, AI, แจ้งเตือน, อัตโนมัติ และ ตั้งในโค้ด ซึ่งแสดง adapter ของอีเมล ที่เก็บไฟล์ การค้นหา การเข้าสู่ระบบ และการชำระเงินที่ config ตั้งไว้ (อ่านอย่างเดียว)
- การ์ดต่อผู้ให้บริการ ที่ plugin เพิ่มเข้ามา: เปิดหรือปิด เชื่อมบัญชี ทดสอบ ตั้งเป็นค่าเริ่มต้น แก้ไข หรือ ตัดการเชื่อม เมื่อปิด plugin จะใช้ไม่ได้ แต่บัญชียังเก็บไว้
- หลายบัญชีต่อผู้ให้บริการ ตั้งชื่อแต่ละบัญชีได้ (เพจ Facebook สองเพจ, OpenAI key สองชุด) บัญชีแรกเป็นค่าเริ่มต้น
- plugin ทางการที่ยังไม่ได้ติดตั้งแสดงคำสั่ง
npm installเพราะ admin ติดตั้ง package เองไม่ได้ - การเชื่อมต่อที่ทดสอบไม่ผ่านหรือใช้งานล่าสุดล้มเหลวจะขึ้นใน "ต้องจัดการ" บนแดชบอร์ด
admin เห็นหน้านี้ รวมถึง บทบาท ที่ได้สิทธิ์ การเชื่อมต่อ ส่วนผู้ใช้ที่ถูกจำกัดอยู่ในบางส่วนของเว็บ (tenant) จะไม่เห็น การเชื่อม แก้ไข ตัดการเชื่อม และเปิด/ปิดผู้ให้บริการ บันทึกลง audit log
Secret
ค่าที่ตั้ง secret จะถูกเข้ารหัสในฐานข้อมูล (AES-256-GCM ด้วย key ที่ได้จาก secret) และไม่ถูกส่งกลับไปที่ admin
ซึ่งแสดงเป็น ••••1234 เวลาแก้การเชื่อมต่อ ถ้าไม่พิมพ์ secret ใหม่จะใช้ค่าเดิม
หลังหมุน secret การเชื่อมต่อจะอ่านด้วย previousSecrets ได้ และเข้ารหัสใหม่ด้วย secret ใหม่ตอนถูกใช้
รัน easy-cms secrets:rotate เพื่อทำทั้งหมดในครั้งเดียว แล้วค่อยลบ secret เก่าออก หน้านี้บอกว่ายังเหลือกี่รายการที่ใช้ secret เก่า
environment variable ที่ระบุใน env ใช้ก่อนค่าใน admin ถ้าตั้งครบทุกช่อง ผู้ให้บริการจะมีการเชื่อมต่อชื่อ "Environment" ที่แก้ใน admin ไม่ได้
ประกาศ integration
plugin เพิ่มของตัวเองใน integrations (เว็บประกาศเองก็ได้):
import { definePlugin } from '@easy-cms/core'
export const telegramPlugin = () =>
definePlugin((config) => ({
...config,
integrations: [
...(config.integrations ?? []),
{
id: 'telegram',
label: 'Telegram',
category: 'notifications',
plugin: '@acme/easy-cms-telegram',
docs: 'https://example.com/guide',
kind: 'fields',
fields: [
{ name: 'botToken', label: 'Bot token', secret: true, required: true },
{ name: 'chatId', label: 'Chat ID', required: true },
],
env: { botToken: 'TELEGRAM_BOT_TOKEN' },
// ตรวจค่าโดยไม่โพสต์อะไร ตอนเชื่อมจะรันก่อนเสมอ
test: async ({ botToken }) => {
const res = await fetch(`https://api.telegram.org/bot${botToken}/getMe`)
const body = await res.json()
return body.ok ? { ok: true, account: body.result.username } : { ok: false, message: body.description }
},
},
],
}))plugin อ่านการเชื่อมต่อฝั่ง server และแจ้งผลการใช้งาน:
const telegram = await cms.integrations.get('telegram') // ค่าเริ่มต้น หรือใส่ { name } เพื่อเลือกตัวอื่น
if (telegram) {
try {
await send(telegram.values.botToken, telegram.values.chatId, text)
await cms.integrations.markUsed('telegram')
} catch (error) {
await cms.integrations.markError('telegram', String(error)) // ขึ้นบนการ์ดและแดชบอร์ด
}
}get คืน null เมื่อยังไม่ได้เชื่อมหรือผู้ให้บริการถูกปิด
cms.integrations.all('telegram') คืนการเชื่อมต่อทั้งหมด (ของ environment ก่อน) เช่นเพื่อส่งไปทุกแชต
ค้นหาค่า และติ๊กตัวเลือก
ช่องที่มี lookup จะมีปุ่ม ค้นหา อยู่ข้าง ๆ Easy CMS รัน lookup ด้วยค่าที่กรอกไว้แล้ว (ตอนแก้การเชื่อมต่อ
จะใช้ secret ที่เก็บไว้แทนช่องที่เว้นว่าง) แล้วผู้ดูแลเลือกจากรายการ เช่นแชตที่มีคนส่งข้อความหาบอท ช่อง
multiselect เป็นกลุ่ม checkbox เก็บเป็น a,b,c
fields: [
{ name: 'botToken', label: 'Bot token', secret: true, required: true },
{
name: 'chatId',
label: 'Chat ID',
lookup: async ({ botToken }) => (await chatsOf(botToken)).map((c) => ({ value: String(c.id), label: c.title })),
},
{ name: 'events', type: 'multiselect', options: [{ value: 'order.created', label: 'คำสั่งซื้อใหม่' }, 'form.submitted'] },
]ข้อผิดพลาดที่ lookup throw จะขึ้นใต้ช่อง แสดงได้ไม่เกิน 100 รายการ
OAuth
kind: 'oauth' มีปุ่ม เชื่อม แทนช่องกรอก Easy CMS เซ็น state (ใช้ได้ 10 นาที) แล้วพาผู้ดูแลไปที่ authorizeUrl
ผู้ให้บริการพากลับมาที่ <api>/admin/integrations/<id>/callback และ exchange แลก code เป็นค่าต่างๆ
ถ้ามีหลายบัญชี (เพจทั้งหมดของผู้ใช้) ผู้ดูแลจะเลือกหนึ่งบัญชี:
{
id: 'facebook-page',
label: 'Facebook Page',
category: 'social',
kind: 'oauth',
oauth: {
authorizeUrl: ({ redirectUri, state }) =>
`https://www.facebook.com/v21.0/dialog/oauth?client_id=${process.env.META_APP_ID}&redirect_uri=${encodeURIComponent(redirectUri)}&state=${state}&scope=pages_manage_posts`,
exchange: async ({ code, redirectUri }) => {
const pages = await pagesFor(code, redirectUri) // API ของผู้ให้บริการ
return { accounts: pages.map((p) => ({ id: p.id, name: p.name, values: { token: p.access_token } })) }
},
},
}ทุกอย่างที่ exchange คืนมาถูกเข้ารหัส ส่วน id และ secret ของแอปเก็บไว้ใน environment variable
ขั้นต่อไป
- Plugins: เขียน plugin
- ความปลอดภัย: secret และการหมุน secret