คู่มือส่วนเสริม สำหรับพาร์ทเนอร์ SMEDNA

ภาคต่อของคู่มือพาร์ทเนอร์ เล่มนี้พาสร้างส่วนเสริม (ข้อมูล ฟอร์ม หน้าจอ กฎอัตโนมัติ การส่งข้อมูลออก) ส่งให้ SMEDNA ตรวจ ขายผ่าน Edition แล้วดูผลที่ร้าน ทุกภาพถ่ายจากระบบจริงในเครื่องทดสอบ ข้อมูลทั้งหมดสมมติ

ลำดับงานของพาร์ทเนอร์

  1. เซ็น DPASMEDNA บันทึกวันที่เซ็นให้
  2. ได้บัญชีพาร์ทเนอร์เข้าคอนโซลพาร์ทเนอร์ ออกกุญแจ API ถ้าจะเชื่อมระบบ
  3. สร้างข้อมูล (ออบเจ็กต์/ฟิลด์)เลือกข้อมูลที่ร้านจะเก็บ
  4. ฟอร์มไปอยู่ในหน้าลูกค้าของร้าน
  5. หน้าจอ (รายการ/แดชบอร์ด/เมนู/การ์ด)ดูด้วยข้อมูลปลอมก่อน
  6. กฎอัตโนมัติ + ลองกับข้อมูลปลอมเมื่อ… ถ้า… ให้ทำ…
  7. การส่งออก (webhook/API) + ข้อความยินยอมร้านเห็นข้อความก่อนยินยอม
  8. ส่งตรวจกดส่งตรวจ แล้วเผยแพร่
  9. SMEDNA อนุมัติไม่ผ่านได้พร้อมเหตุผล แก้แล้วส่งใหม่
  10. ใส่ใน Edition แล้วขายปักส่วนเสริมใน Edition
  11. ร้านยินยอม/ติดตั้งร้านเห็นชัดว่าเก็บอะไร ส่งอะไร
  12. ดูผลและออกรุ่นใหม่บทที่ 5–6 ร้านยินยอมใหม่เมื่อขอบเขตเพิ่ม

จัดทำ 5 ตุลาคม 2026 · วันที่ในภาพคือวันที่ถ่ายภาพ · ภาพ X17 ใช้คำตอบ AI ตัวอย่าง

0 · เรื่องของเรา

อ่านบทนี้ก่อน ชื่อพาร์ทเนอร์ ร้าน และส่วนเสริมในทุกภาพมาจากตารางในบทนี้

สองพาร์ทเนอร์ สี่ส่วนเสริม เจ็ดร้าน

ร้านดีซอฟต์ เป็นบริษัทซอฟต์แวร์ ขายส่วนเสริมให้ร้านสัตว์เลี้ยง ร้านซ่อม และคลินิก ผ่าน Edition ของตัวเอง ส่วน ส่งดี โฮลเซล (พาร์ทเนอร์เดียวกับคู่มือเล่มแรก) ให้บอท LINE เขียนออเดอร์ประจำลงในส่วนเสริมของร้านโชห่วยผ่าน Partner API “ส่วนเสริม” คือชุดข้อมูล ฟอร์ม หน้าจอ และกฎอัตโนมัติที่พาร์ทเนอร์ประกอบเองบนหน้าจอ ไม่ต้องเขียนโค้ด และไม่มีโค้ดของพาร์ทเนอร์ทำงานในระบบ

ส่วนเสริมพาร์ทเนอร์เก็บอะไรกฎอัตโนมัติส่งข้อมูลออก
pet_health ประวัติสัตว์เลี้ยงร้านดีซอฟต์สัตว์เลี้ยงและวัคซีน ผูกกับลูกค้า (ข้อมูลส่วนบุคคล)เตือนก่อนนัดวัคซีน 3 วันรุ่น 1 ไม่มี รุ่น 2 มี
repair_jobs ใบงานซ่อมร้านดีซอฟต์ใบงานซ่อม ไม่ผูกลูกค้างานซ่อมเสร็จ · งานเลยกำหนด · สรุปงานค้างประจำวัน · รออะไหล่มี
standing_orders สั่งของประจำส่งดีออเดอร์ประจำ ผูกสินค้าออเดอร์ LINE ใหม่ · วันส่งของบอทเขียนผ่าน API
followup_visits นัดติดตามผลร้านดีซอฟต์นัดผู้ป่วย ผูกลูกค้า--
ร้าน (สมมติ)ใช้ส่วนเสริมเห็นในบท
ร้านน้องหมาน้องแมว เพ็ทช็อปประวัติสัตว์เลี้ยง4 ข้อมูลในหน้าลูกค้า · 6 ยินยอมรุ่น 2
บ้านเหมียวเพ็ทช็อปประวัติสัตว์เลี้ยง5 ใช้รุ่น 1 ต่อ ไม่ยินยอมส่งออก
ช่างเอกแอร์แอนด์ไฟฟ้าใบงานซ่อม4–5 ร้านหลัก: แดชบอร์ด กฎ ประวัติกฎ
ร้านซ่อมมือถือเจ๊ติ๋มใบงานซ่อม6 หยุด กลับมาใช้ ส่งออกข้อมูล ถอน
คลินิกกายภาพบำบัดฟื้นฟูดีนัดติดตามผล4 กล่องยินยอม · 7 ติดตั้งไม่ได้
ร้านป้าแดงของชำสั่งของประจำ4 ออเดอร์จากบอท LINE
ร้านเจ๊หมวยมินิมาร์ทสั่งของประจำร้านที่สองของส่งดี

บทที่ 2 สร้างส่วนเสริมที่ห้า grooming_log (บันทึกอาบน้ำตัดขน) ตั้งแต่หน้าว่างจนส่งตรวจ ส่วนเสริมนี้ไม่ได้ติดตั้งให้ร้านใด ส่วน หจก. ทดลองระบบ เป็นพาร์ทเนอร์ที่ยังไม่เซ็น DPA ใช้แสดงกรณีถูกปฏิเสธในบทที่ 7

ข้อมูลตัวอย่าง: อ่านก่อนเชื่อตัวเลข
  • ร้านทั้งเจ็ดใช้ส่วนเสริมมา 8 สัปดาห์ย้อนหลัง เพราะเราสร้างประวัติไว้ก่อนถ่ายภาพ แดชบอร์ด ประวัติกฎ และบันทึกการส่ง webhook จึงมีข้อมูลให้ดู
  • วันที่ในภาพคือ วันที่ถ่ายภาพ ตัวหนังสือในเล่มจึงไม่อ้างวันที่ตายตัว
  • ภาพ X17 (AI ช่วยร่าง) ใช้ คำตอบตัวอย่าง ที่เตรียมไว้ ไม่ได้เรียก AI จริง
  • กรณีคลินิกติดตั้งไม่ได้ (E02) ทำตอนที่ SMEDNA ยังไม่เปิด ส่วนเสริมสำหรับร้านคลินิก
  • รหัสสินค้าที่บอท LINE ใช้ มาจากใบรหัสสินค้าที่ร้านให้พาร์ทเนอร์ เพราะ Partner API ยังไม่มีรายการสินค้าให้ดึง
บางความสามารถ SMEDNA ต้องเปิดให้ก่อน เช่น ข้อมูลส่วนบุคคลของลูกค้า ส่วนเสริมสำหรับร้านคลินิก และ AI ช่วยร่าง บางเรื่องต้องรอคำตอบจากทนายก่อนเปิด ภาพในเล่มถ่ายจากเครื่องทดสอบ ก่อนสัญญากับร้าน ให้ถาม SMEDNA ว่าความสามารถที่ส่วนเสริมของคุณใช้เปิดให้แล้วหรือยัง (รายการอยู่ในภาคผนวก)

1 · ก่อนเริ่ม

ก่อนสร้างส่วนเสริมต้องมีสามอย่าง: สัญญา DPA ที่ SMEDNA บันทึกแล้ว ความสามารถที่ SMEDNA เปิดให้ และกุญแจ API ถ้าจะเชื่อมระบบของคุณเอง

X01

SMEDNA บันทึกวันที่เซ็น DPA

ทำอย่างไร

  1. พาร์ทเนอร์เซ็น DPA (สัญญาประมวลผลข้อมูลส่วนบุคคล) กับ SMEDNA
  2. (ทีม SMEDNA ทำ) เปิด /admin/partners เลือกร้านดีซอฟต์ กรอก “วันที่เซ็น DPA” แล้วกด “บันทึกเงื่อนไข”
X01 SMEDNA บันทึกวันที่เซ็น DPA

หน้าเดียวกันแสดงบัญชีทีมของพาร์ทเนอร์ (เจ้าขององค์กรและฝ่ายขาย) และแบรนด์ที่ร้านจะเห็น

วันที่เซ็น DPA ของร้านดีซอฟต์อยู่ในส่วน “เงื่อนไขสัญญา” ถ้ายังไม่มีวันที่นี้ สิทธิ์ข้อมูลส่วนเสริมใน API จะถูกปิด (ข้อ E01)

X02

SMEDNA เปิดความสามารถให้ทีละเรื่อง

ทำอย่างไร

  1. (ทีม SMEDNA ทำ) หน้าสวิตช์ความสามารถของผู้ดูแลระบบ
X02 SMEDNA เปิดความสามารถให้ทีละเรื่อง

ความสามารถแต่ละเรื่องมีสวิตช์ของตัวเอง ตัวที่เปิดแล้วบันทึกว่าใครรับรองและเมื่อไร ตัวที่ยังไม่มีคำรับรองจะปิดอยู่

X02 SMEDNA เปิดความสามารถให้ทีละเรื่อง (โหมดมืด)

โหมดมืด

พาร์ทเนอร์ไม่ต้องทำอะไรในหน้านี้ ก่อนขาย ให้ถาม SMEDNA ว่าความสามารถที่ส่วนเสริมของคุณใช้เปิดแล้วหรือยัง

X04

กุญแจ API ของบอทต้องได้สิทธิ์เขียนข้อมูลส่วนเสริม

ทำอย่างไร

  1. เข้าด้วยบัญชีส่งดี เปิดแท็บ “การเชื่อมต่อ” (/partner/integrations)
  2. ตั้งชื่อกุญแจ แล้วเลือก “ข้อมูลส่วนเสริม (Partner API ext)” เป็น “อ่านและเขียน”
X04 กุญแจ API ของบอทต้องได้สิทธิ์เขียนข้อมูลส่วนเสริม

ในเรื่องนี้ส่งดีออกกุญแจสองดอก: songdee-line-bot ให้บอทเขียนออเดอร์ และ songdee-reader อ่านได้อย่างเดียว ภาพนี้คือฟอร์มออกกุญแจ ด้านขวาตั้งปลายทาง webhook ที่จะรับเหตุการณ์

X04 กุญแจ API ของบอทต้องได้สิทธิ์เขียนข้อมูลส่วนเสริม (บนมือถือ)

บนมือถือ

บอทได้กุญแจที่เขียนข้อมูลส่วนเสริมได้ แยกจากกุญแจอ่านอย่างเดียว ข้อความสีส้มเตือนว่ากุญแจอ่านอย่างเดียวที่ไม่ตั้งวันหมดอายุจะใช้ได้ตลอดไป

2 · สร้างส่วนเสริมใน Studio

เจ้าของบัญชีร้านดีซอฟต์สร้าง grooming_log (บันทึกอาบน้ำตัดขน) สดในแท็บ “ส่วนเสริม” ของคอนโซลพาร์ทเนอร์ (/partner/extensions) ตั้งแต่หน้าว่างจนส่งตรวจ หน้าส่วนเสริมมีแท็บ ออบเจ็กต์ · ฟอร์ม · หน้าจอ · กฎอัตโนมัติ · ส่งข้อมูลออก · ช่วยร่าง · ตัวอย่าง · รุ่นที่เผยแพร่ · ร้านที่ติดตั้ง และปุ่ม บันทึกร่าง · ส่งตรวจ · เผยแพร่ ที่มุมขวาบน

ส่วนเสริม 4 แบบ ที่ต้องเลือกก่อนเริ่มสร้าง

แบบข้อมูลผูกกับกฎอัตโนมัติส่งข้อมูลออก
ประวัติสัตว์เลี้ยงลูกค้าตามวันที่ในรายการรุ่นแรกไม่มี
ใบงานซ่อมไม่ผูกเมื่อสถานะเปลี่ยน · ตามวันที่ · ทุกเช้าเหตุการณ์ + API อ่าน
สั่งของประจำสินค้าเมื่อมีรายการใหม่ · ตามวันที่API เขียนได้
นัดติดตามผลลูกค้า--
X10

เริ่มจากตั้งรหัสส่วนเสริม

ทำอย่างไร

  1. ที่หน้า “ส่วนเสริมของฉัน” พิมพ์รหัส grooming_log
  2. กด “+ สร้างส่วนเสริม”
X10 เริ่มจากตั้งรหัสส่วนเสริม

หน้านี้แสดงส่วนเสริมที่มีอยู่ จำนวนร้านที่ใช้งาน และงบ AI ช่วยร่างของวันนี้และเดือนนี้

ร่างใหม่เปิดที่แท็บ “ออบเจ็กต์” (ภาพถัดไป)

X11

ออบเจ็กต์: ข้อมูลที่ร้านจะเก็บ ผูกกับลูกค้า

ทำอย่างไร

  1. แท็บ “ออบเจ็กต์” ตั้งรหัส groom ชื่อ “อาบน้ำตัดขน” แล้วเลือกผูกกับ “ลูกค้า”
  2. เพิ่มฟิลด์ ชื่อสัตว์ · บริการ (ตัวเลือก อาบน้ำ/ตัดขน) · วันที่ทำ · เวลาที่ใช้ (นาที) แล้วกด “บันทึกร่าง”
X11 ออบเจ็กต์: ข้อมูลที่ร้านจะเก็บ ผูกกับลูกค้า

ติ๊ก “ใช้ค้นหา” ที่ช่องที่ต้องกรองหรือให้กฎนับวัน (ภาพนี้ใช้ 4 จาก 5 ช่อง) ส่วนเสริมเก็บข้อมูลเงิน เช่น ราคา ไม่ได้

บันทึกร่างได้ ไม่มีแถบแดงแจ้งข้อที่ต้องแก้

X12

ฟอร์มที่ไปอยู่ในหน้าลูกค้า

ทำอย่างไร

  1. แท็บ “ฟอร์ม” สร้าง groom_form ชื่อ “ข้อมูลอาบน้ำตัดขน” แล้วติ๊กช่องที่ให้กรอกทั้ง 4 ช่อง
  2. เลือก “วางที่: ฟอร์มลูกค้า”
X12 ฟอร์มที่ไปอยู่ในหน้าลูกค้า

ฟอร์มนี้จะไปอยู่ในกล่องแก้ไขลูกค้าของร้าน (ตัวอย่างจริงที่ร้านในภาพ X39)

ฟอร์มมี 4 ช่อง วางที่ฟอร์มลูกค้า

X13

หน้ารายการและแดชบอร์ด

ทำอย่างไร

  1. แท็บ “หน้าจอ” เพิ่มหน้ารายการ groom_list และแดชบอร์ดที่มีตัวเลขรวมเวลาที่ใช้ (นาที) กับกราฟแท่งแยกตามบริการ
  2. กด “ดูตัวอย่าง”
X13 หน้ารายการและแดชบอร์ด

ตัวอย่างใช้ข้อมูลปลอม 30 แถว ไม่ใช่ข้อมูลร้าน

เห็นตัวเลขรวมและกราฟแท่ง อาบน้ำ (bath) กับ ตัดขน (trim) จากข้อมูลปลอม

X14

เมนูของร้านและการ์ดบนแดชบอร์ด

ทำอย่างไร

  1. ในแท็บ “หน้าจอ” ส่วน “เมนู” เพิ่ม 2 รายการ: หน้ารายการ และแดชบอร์ด
  2. ส่วน “การ์ดบนแดชบอร์ด” เพิ่มการ์ด 1 ใบจากตัวเลขของแดชบอร์ด
X14 เมนูของร้านและการ์ดบนแดชบอร์ด

เมนูได้สูงสุด 5 รายการ แสดงในกลุ่ม “ส่วนเสริมจากพาร์ทเนอร์” ของร้าน การ์ดได้สูงสุด 2 ใบ ชี้ได้เฉพาะตัวเลขนับจำนวนหรือรวมค่า

เมนู 2 รายการ และการ์ด 1 ใบที่จะขึ้นบนแดชบอร์ดของร้าน (ตัวอย่างจริงที่ร้านในภาพ X34)

X15

กฎอัตโนมัติ: เลือกจากรายการ ไม่ต้องเขียนสูตร

ทำอย่างไร

  1. แท็บ “กฎอัตโนมัติ” ตั้งชื่อกฎ แล้วเลือก “เมื่อ”: ถึงวันที่ในรายการ · อาบน้ำตัดขน · วันที่ทำ · จำนวนวัน · 08:00
  2. “ให้ทำ”: แจ้งเตือนพนักงาน ข้อความ “ครบ 30 วัน ชวนกลับมาอาบน้ำ” พร้อมลิงก์ไปหน้าอาบน้ำตัดขน
X15 กฎอัตโนมัติ: เลือกจากรายการ ไม่ต้องเขียนสูตร

กฎหนึ่งข้อทำได้สูงสุด 3 อย่าง ช่องจำนวนวันในภาพเลือก “30 วันหลังวันที่ในช่อง” ตรงกับชื่อกฎที่ชวนลูกค้ากลับมาเมื่อครบสามสิบวันหลังวันที่ทำ ถ้าต้องการเตือนก่อนถึงวัน ให้เลือกแบบ “… วันก่อนวันที่ในช่อง” ก่อนส่งตรวจให้เช็กว่าจำนวนวันตรงกับที่ตั้งใจ

กฎใหม่ติ๊ก “เปิดใช้” อยู่ในรายการกฎ

X16

ลองกฎกับข้อมูลตัวอย่างก่อน

ทำอย่างไร

  1. กด “ลองกับข้อมูลตัวอย่าง” ใต้รายการกฎ
X16 ลองกฎกับข้อมูลตัวอย่างก่อน

ใช้ข้อมูลสมมติ ไม่เขียนอะไรและไม่แตะข้อมูลร้านจริง

เห็นว่ากฎเข้าเงื่อนไข 10 จาก 10 แถว และแต่ละแถวจะแจ้งพนักงานพร้อมลิงก์ไปหน้ารายการ

X17

ช่วยร่าง: AI เสนอ คนเลือกใช้เอง

ทำอย่างไร

  1. แท็บ “ช่วยร่าง” กล่อง “ให้ AI ช่วยร่าง” พิมพ์ “เพิ่มฟิลด์น้ำหนักและช่องหมายเหตุ” แล้วกด “ขอข้อเสนอ” (ปุ่มบอกค่าใช้จ่ายโดยประมาณ)
  2. อ่านข้อเสนอ ติ๊กยืนยันข้อที่ต้องการ แล้วกดใช้
X17 ช่วยร่าง: AI เสนอ คนเลือกใช้เอง

ภาพนี้ใช้คำตอบตัวอย่างที่เตรียมไว้ ไม่ได้เรียก AI จริง กล่องข้อเสนอขึ้นใต้ปุ่ม “ขอข้อเสนอ” ข้อความแรกอธิบายสิ่งที่เสนอ บรรทัดสรุปบอกว่า “AI เสนอ 4 ข้อ ใช้ได้ 3 ข้อ” พร้อมข้อที่ถูกตัดและเหตุผล ข้อที่ทำไม่ได้ขึ้นว่า “ทำในรุ่นนี้ยังไม่ได้” ตามด้วยสิ่งที่ขอ (เก็บราคาค่าบริการต่อครั้ง) และเหตุผล ข้อที่ใช้ได้บอกตำแหน่งที่จะแก้เป็นภาษาไทย เช่น “ออบเจ็กต์ อาบน้ำตัดขน › ช่องใหม่ น้ำหนัก (กก.)” ข้อที่ต้องยืนยันมีช่อง “ต้องติ๊กยืนยัน” ให้ติ๊ก

AI เสนอ 4 ข้อ ระบบให้ใช้ได้ 3 ข้อ ข้อที่ขอเก็บราคาถูกตัดเพราะส่วนเสริมเก็บข้อมูลเงินไม่ได้ หลังกดใช้ ร่างมีช่องน้ำหนักและหมายเหตุเพิ่ม (ภาพ X19)

คำตอบตัวอย่างผลของ AI เป็นแค่ข้อเสนอ ต้องกดใช้เอง และผ่านตัวตรวจชุดเดียวกับที่คนทำเอง ค่าใช้จ่ายหักจากงบ AI ช่วยร่างของพาร์ทเนอร์ ไม่ใช้ AI ก็ได้ กล่อง “เริ่มโดยไม่ใช้ AI” มีชุดตั้งต้นและช่องพิมพ์ชื่อฟิลด์ทีละบรรทัด
X18

ส่งข้อมูลออก: เลือกเอง ร้านเห็นข้อความล่วงหน้า

ทำอย่างไร

  1. แท็บ “ส่งข้อมูลออก” ติ๊ก “เพิ่มรายการ” และเลือกระดับ API ของพาร์ทเนอร์เป็น “อ่านอย่างเดียว”
  2. กด “บันทึกร่าง”
X18 ส่งข้อมูลออก: เลือกเอง ร้านเห็นข้อความล่วงหน้า

ไม่ติ๊กอะไรเลยและ API เป็น “ไม่ใช้” = ไม่มีข้อมูลออกจากร้าน ข้อความยินยอมสร้างให้เองจากสิ่งที่ติ๊ก ถ้ารุ่นใหม่ขอมากขึ้น ร้านต้องยินยอมใหม่ (บทที่ 6)

เห็นข้อความที่ร้านจะเห็นตอนยินยอม: “ส่งข้อมูลไปยังเซิร์ฟเวอร์ของพาร์ทเนอร์: เพิ่มรายการ · ระดับ API: อ่านอย่างเดียว”

X19

ดูตัวอย่างก่อนส่ง

ทำอย่างไร

  1. แท็บ “ตัวอย่าง”
X19 ดูตัวอย่างก่อนส่ง

แสดงฟอร์มตามที่ร้านจะเห็น เติมด้วยข้อมูลปลอม ไม่อ่านข้อมูลร้านใด

เห็นฟอร์มอาบน้ำตัดขน 6 ช่อง รวมน้ำหนักและหมายเหตุที่ได้จากขั้น X17

X20

ส่งให้ SMEDNA ตรวจ

ทำอย่างไร

  1. กด “ส่งตรวจ” แล้วกด “เผยแพร่” ที่มุมขวาบน
X20 ส่งให้ SMEDNA ตรวจ

ภาพก่อนกด แท็บ “รุ่นที่เผยแพร่” ยังว่าง (ยังไม่เคยเผยแพร่)

รุ่น #1 ของ grooming_log ไปรอในคิวตรวจของ SMEDNA (บทที่ 3)

3 · SMEDNA ตรวจและอนุมัติ

ทีม SMEDNA ตรวจที่ /admin/partner-extensions พาร์ทเนอร์ไม่ต้องเข้าหน้านี้ แต่ควรรู้ว่าจะถูกตรวจอย่างไร และต้องออกแบบให้อยู่ในเพดานใด บทนี้จบที่การใส่ส่วนเสริมใน Edition เพื่อขาย

X21

หน้าตรวจของ SMEDNA

ทำอย่างไร

  1. (ทีม SMEDNA ทำ) เปิดหน้า “ตรวจส่วนเสริมพาร์ทเนอร์” แล้วเลื่อนลงไปท้ายหน้า
X21 หน้าตรวจของ SMEDNA

ท้ายหน้าเป็นคิวตรวจ แต่ละรุ่นที่รอตรวจขึ้นเป็นการ์ด ภาพนี้คือ grooming_log #1 ของบริษัท ร้านดีซอฟต์ จำกัด มีช่อง “หมายเหตุ / เหตุผล” และปุ่มตัดสิน (ข้อ X22) เหนือคิวคือการ์ดตั้งค่าเพดาน (ข้อ X25)

เห็นรุ่นที่รอตรวจ ทีม SMEDNA อนุมัติหรือไม่อนุมัติได้จากการ์ดนี้

X22

ไม่อนุมัติ พร้อมเหตุผล

ทำอย่างไร

  1. (ทีม SMEDNA ทำ) ที่รายการ grooming_log #1 ใส่เหตุผล “ป้ายกฎยาวเกิน ช่วยย่อ”
  2. กด “ไม่อนุมัติ”
X22 ไม่อนุมัติ พร้อมเหตุผล

แต่ละรุ่นในคิวมีปุ่ม อนุมัติ · ไม่อนุมัติ · ระงับ · ส่งมอบ Edition

รุ่น #1 ไม่ผ่าน พาร์ทเนอร์แก้ตามเหตุผลแล้วส่งใหม่

X23

แก้แล้วส่งใหม่

ทำอย่างไร

  1. เจ้าของบัญชีร้านดีซอฟต์ย่อชื่อกฎเหลือ “ชวนลูกค้ากลับมาอาบน้ำ”
  2. กด “บันทึกร่าง” “ส่งตรวจ” และ “เผยแพร่” อีกครั้ง
X23 แก้แล้วส่งใหม่

ชื่อกฎสั้นลงตามเหตุผลที่ได้รับ ส่วนอื่นของกฎเหมือนเดิม

รุ่นถัดไปเข้าคิวตรวจอีกครั้ง

X24

อนุมัติ

ทำอย่างไร

  1. (ทีม SMEDNA ทำ) กด “อนุมัติ” ที่รุ่นใหม่ในคิว
X24 อนุมัติ

หลังกด “อนุมัติ” รุ่นนั้นออกจากคิว คิวขึ้นว่า “ไม่มีรายการรอตรวจ”

รุ่นนั้นพร้อมใส่ใน Edition และให้ร้านติดตั้ง พาร์ทเนอร์เห็นรุ่นที่อนุมัติแล้วในแท็บ “รุ่นที่เผยแพร่” (ตัวอย่างสถานะ “อนุมัติแล้ว” ในภาพ N01)

X25

เพดานที่ต้องออกแบบให้อยู่ใน

ทำอย่างไร

  1. (ทีม SMEDNA ทำ) ตั้งค่าในการ์ด “ตั้งค่า Partner Studio” ส่วนบนของหน้าตรวจ
X25 เพดานที่ต้องออกแบบให้อยู่ใน

การ์ด “ตั้งค่า Partner Studio” มี 4 แท็บ: เพดานของส่วนเสริม · เพดานกฎอัตโนมัติ · งบ AI ของ Studio (บาท) · หมวดร้านที่นับเป็นคลินิก ใต้แต่ละช่องบอกช่วงที่ตั้งได้และค่าที่ใช้จริง เช่น “ช่วง 1–50 · ใช้จริง 10” การ์ดบนสุดเป็นตัวชี้วัดสำหรับทีม SMEDNA

ค่าในตารางมาจากเครื่องทดสอบ SMEDNA ปรับได้ภายในช่วงที่ระบบกำหนด

เรื่องค่าในเครื่องทดสอบ
ออบเจ็กต์10
ฟิลด์40
ช่อง “ใช้ค้นหา”5
ฟอร์ม10
หน้าจอ10
ตัวเลขหรือกราฟต่อแดชบอร์ด6
การ์ดบนแดชบอร์ดของร้าน2
เมนู5
รายการต่อร้าน5,000
ส่วนเสริมที่ร้านหนึ่งติดตั้งได้2
X03

ใส่ใน Edition แล้วขาย

ทำอย่างไร

  1. เจ้าของบัญชีร้านดีซอฟต์เปิดแท็บ “Edition” (/partner/editions)
  2. กด “แก้ไข” ที่ Edition เพื่อปักส่วนเสริมที่อนุมัติแล้ว
X03 ใส่ใน Edition แล้วขาย

ร้านดีซอฟต์มี 3 Edition ที่เผยแพร่แล้ว: คลินิกฟื้นฟู ช่างซ่อม และสัตว์เลี้ยง ร้านที่ใช้ Edition ไหนจะได้รับข้อเสนอส่วนเสริมที่ปักไว้ใน Edition นั้น

เห็น 3 Edition สถานะ “เผยแพร่แล้ว” แต่ละอันมีปุ่ม แก้ไข และ ถอนเผยแพร่

4 · ร้านติดตั้งและใช้งาน

ผู้ใช้คือเจ้าของและพนักงานของร้านสมมติ ร้านเห็นแบรนด์ของพาร์ทเนอร์ที่มุมซ้ายบน จัดการส่วนเสริมในหน้า “ส่วนเสริมจากพาร์ทเนอร์” (/settings/extensions) และเปิดหน้าจอของส่วนเสริมจากเมนูกลุ่ม “ส่วนเสริมจากพาร์ทเนอร์”

X30

ส่วนเสริมที่ร้านติดตั้ง

ทำอย่างไร

  1. เข้าด้วยบัญชีร้านช่างเอกแอร์แอนด์ไฟฟ้า เปิด /settings/extensions
X30 ส่วนเสริมที่ร้านติดตั้ง

การ์ดใบงานซ่อม รุ่น 1 สถานะ “ใช้งานอยู่” มีปุ่ม หยุด · ถอน · JSON · CSV · กฎอัตโนมัติ รายการใบงานขึ้นเลขงานกับชื่ออุปกรณ์ เช่น “J-0075 · เครื่องซักผ้า” และมีปุ่ม “+ เพิ่มรายการ”

X30 ส่วนเสริมที่ร้านติดตั้ง (บนมือถือ)

บนมือถือ

ลิงก์ “คู่มือส่วนเสริมสำหรับร้านค้า” ด้านบนพาเจ้าของร้านไปที่คู่มือในแอป

X31

ก่อนติดตั้ง ร้านเห็นว่าส่วนเสริมเก็บอะไร

ทำอย่างไร

  1. คลินิกกายภาพบำบัดฟื้นฟูดีเปิด /settings/extensions แล้วกดติดตั้ง “นัดติดตามผล” ที่ได้รับข้อเสนอ
X31 ก่อนติดตั้ง ร้านเห็นว่าส่วนเสริมเก็บอะไร

กล่องยินยอมบอกช่องที่จะเก็บไว้ในร้าน และบอกว่าพาร์ทเนอร์ไม่เห็นข้อมูลลูกค้าของร้าน เพราะส่วนเสริมนี้ไม่ส่งอะไรออก ถ้าส่วนเสริมส่งข้อมูลออก กล่องจะมีรายการส่งออกด้วย (ภาพ N03)

ร้านเลือก “ยินยอม” หรือ “ยกเลิก” ภาพนี้เปิดดูอย่างเดียว ร้านคลินิกยังติดตั้งจริงไม่ได้ (ข้อ E02)

X32

งานค้างทั้งหมดในหน้าเดียว

ทำอย่างไร

  1. เปิดเมนู “งานค้าง” (/ext/repair_jobs/open_jobs)
  2. เลือก “กำลังซ่อม” ในช่องสถานะ แล้วกด “กรอง”
X32 งานค้างทั้งหมดในหน้าเดียว

หน้า “งานค้าง” ที่พาร์ทเนอร์ออกแบบ มีช่อง “สถานะ” ที่เป็นรายการให้เลือก (ในภาพเลือก “กำลังซ่อม”) กับปุ่ม “กรอง” ตารางมีเลขที่ใบงาน อุปกรณ์ สถานะ ช่าง และกำหนดเสร็จ วันที่แสดงเป็นวันที่ไทย เช่น “11 ต.ค. 2569”

X32 งานค้างทั้งหมดในหน้าเดียว (บนมือถือ)

บนมือถือ

เห็นใบงาน “กำลังซ่อม” 9 ใบ

X33

สรุปงานซ่อม: งานค้างและชั่วโมงงาน

ทำอย่างไร

  1. เปิดเมนู “สรุปงานซ่อม” (/ext/repair_jobs/job_dash)
X33 สรุปงานซ่อม: งานค้างและชั่วโมงงาน

แดชบอร์ดของร้านช่างเอก

X33 สรุปงานซ่อม: งานค้างและชั่วโมงงาน (บนมือถือ)

บนมือถือ

ตัวเลขตรงกับที่นับจากฐานข้อมูลตอนถ่ายภาพ

เห็นผล · ร้านช่างเอก19 งานค้าง · 312 ชั่วโมง
ร้านเห็นงานค้างและชั่วโมงงานที่ประเมินไว้ในหน้าเดียว ใบงานทั้งหมดแยกตามสถานะ: ซ่อมเสร็จ 45 · กำลังซ่อม 9 · ส่งคืนแล้ว 8 · ตรวจอาการ 5 · รับเครื่อง 5 (ไม่นับใบงานที่ลบแล้ว 3 ใบ)
X34

การ์ดบนแดชบอร์ดของร้าน

ทำอย่างไร

  1. เปิด /dashboard แล้วเลื่อนลงล่าง
X34 การ์ดบนแดชบอร์ดของร้าน

การ์ด “ชั่วโมงซ่อมที่ประเมินรวม 312” อยู่ในกลุ่ม “ส่วนเสริมจากพาร์ทเนอร์” ใต้การ์ดของระบบ

เจ้าของร้านเห็นตัวเลขจากส่วนเสริมทันทีที่เปิดแอป

X35

เปลี่ยนสถานะ กฎแจ้งทีมเอง

ทำอย่างไร

  1. ที่ /settings/extensions กดรูปดินสอที่ใบงาน J-0075
  2. เปลี่ยนสถานะเป็น “ซ่อมเสร็จ” แล้วกด “บันทึก”
X35 เปลี่ยนสถานะ กฎแจ้งทีมเอง

ฟอร์มใบงานมาจากส่วนเสริม: อุปกรณ์ หมายเหตุ สถานะ ช่าง กำหนดเสร็จ เวลาซ่อมที่ประเมิน

ใบงานเป็น “ซ่อมเสร็จ” และกฎ “งานซ่อมเสร็จ” ทำงานในรอบถัดไป (ดูประวัติกฎในภาพ X51)

X36

แจ้งเตือนจากส่วนเสริมเข้าที่ทีมงาน

ทำอย่างไร

  1. กดไอคอนระฆังเพื่อเปิดการแจ้งเตือน
X36 แจ้งเตือนจากส่วนเสริมเข้าที่ทีมงาน

แต่ละรายการระบุว่า “จากส่วนเสริม ใบงานซ่อม”

X36 แจ้งเตือนจากส่วนเสริมเข้าที่ทีมงาน (บนมือถือ)

บนมือถือ

เห็นแจ้งเตือน “สรุปงานค้างประจำวัน” และ “งานเลยกำหนด” จากกฎ ส่วนแจ้งเตือน “งานซ่อมเสร็จ” ของวันนั้นใช้เพดานต่อวันที่ตั้งไว้ในเครื่องทดสอบ (20 ครั้ง) ครบแล้ว รอบใหม่จึงถูกข้าม

X37

หน้ากฎของร้าน: กฎไหนทำงาน กฎไหนหยุด

ทำอย่างไร

  1. กดปุ่ม “กฎอัตโนมัติ” บนการ์ดส่วนเสริม (/ext/repair_jobs/automations)
X37 หน้ากฎของร้าน: กฎไหนทำงาน กฎไหนหยุด

กฎ “รออะไหล่” หยุดเองเพราะล้มติดกัน 3 ครั้ง ระบบบอกว่าไม่พบรายการที่กฎต้องแก้ (อาจถูกลบไปแล้ว) ใต้กฎ “งานซ่อมเสร็จ” มีบรรทัด “วันนี้ข้ามไป 7 รอบเพราะเกินโควต้าต่อวัน” บอกร้านว่าวันนี้กฎนี้ไม่ได้ทำกี่รอบเพราะเกินโควต้า (พาร์ทเนอร์ดูรายละเอียดทีละรอบได้ในภาพ E04)

X37 หน้ากฎของร้าน: กฎไหนทำงาน กฎไหนหยุด (บนมือถือ)

บนมือถือ

เห็นสถานะของแต่ละกฎ กฎที่หยุดมีปุ่ม “เปิดกฎนี้อีกครั้ง” และรู้ว่าวันนี้กฎไหนถูกข้ามเพราะเกินโควต้ากี่รอบ

X38

เจ้าของร้านเปิดกฎกลับเองได้

ทำอย่างไร

  1. กด “เปิดกฎนี้อีกครั้ง” ที่กฎรออะไหล่ (ปุ่มในภาพ X37)
X38 เจ้าของร้านเปิดกฎกลับเองได้

หลังกด “เปิดกฎนี้อีกครั้ง” กฎรออะไหล่ขึ้นป้าย “ทำงาน” เหมือนอีก 3 กฎ บรรทัด “รอบล่าสุด” ยังเป็นรอบที่ล้มก่อนกดเปิด

กฎกลับมาทำงาน ไม่ต้องรอพาร์ทเนอร์

X39

ข้อมูลสัตว์เลี้ยงอยู่ในหน้าลูกค้า

ทำอย่างไร

  1. เข้าด้วยบัญชีร้านน้องหมาน้องแมว เปิดลูกค้า สมศักดิ์ ทองสุข แล้วกดแก้ไข
X39 ข้อมูลสัตว์เลี้ยงอยู่ในหน้าลูกค้า

ส่วน “ประวัติสัตว์เลี้ยง” “สัตว์เลี้ยง” และ “ประวัติวัคซีน” ในกล่องแก้ไขลูกค้ามาจากส่วนเสริม ชนิดสัตว์และชื่อวัคซีนขึ้นเป็นคำไทย เช่น “โมโม่ · หมา” และ “มะลิ · รวม 5 โรค”

X39 ข้อมูลสัตว์เลี้ยงอยู่ในหน้าลูกค้า (บนมือถือ)

บนมือถือ

เห็นสัตว์เลี้ยง 2 ตัว และประวัติวัคซีน 3 รายการ เพิ่มหรือแก้ได้จากกล่องเดียวกัน

X40

นัดวัคซีนที่ใกล้ถึง

ทำอย่างไร

  1. เปิดหน้า “ใกล้ถึงนัดวัคซีน” (/ext/pet_health/due_soon) แล้วกรองวันนัดครั้งถัดไป
X40 นัดวัคซีนที่ใกล้ถึง

รายการแสดงชื่อสัตว์ วัคซีน วันนัดครั้งถัดไป และชื่อลูกค้า

เห็น 6 นัดในวันเดียวกัน

เห็นผล · วัคซีน6 นัด ในอีก 3 วัน
คือกลุ่มที่กฎ “เตือนก่อนนัดวัคซีน 3 วัน” แจ้งทีมให้ จากประวัติวัคซีนทั้งหมด 72 รายการของร้าน ร้านไม่ต้องไล่ดูเอง
X41

ออเดอร์จาก LINE เข้าระบบเอง

ทำอย่างไร

  1. เข้าด้วยบัญชีร้านป้าแดงของชำ เปิดหน้า “ออเดอร์วันนี้” (/ext/standing_orders/todays_orders)
X41 ออเดอร์จาก LINE เข้าระบบเอง

คอลัมน์ “ช่องทาง” เป็น LINE เพราะบอทของส่งดีเขียนออเดอร์ผ่าน API ระบบจดที่มาว่า API ไว้ในข้อมูลด้วย (ไฟล์ผลลัพธ์ในบทที่ 8) แต่หน้าจอยังไม่แสดงป้ายที่มา

X41 ออเดอร์จาก LINE เข้าระบบเอง (บนมือถือ)

บนมือถือ

เห็นออเดอร์สถานะ “ใหม่” พร้อมรอบส่งและสินค้า โดยร้านไม่ต้องพิมพ์เอง

X42

สัดส่วนช่องทางสั่งของ

ทำอย่างไร

  1. เปิดหน้า “สรุปออเดอร์ประจำ” (/ext/standing_orders/order_dash)
X42 สัดส่วนช่องทางสั่งของ

ออเดอร์ทั้งหมด แท่งแยกตามช่องทาง และแยกตามรอบส่ง

ราว 3 ใน 4 ของออเดอร์มาจากบอท LINE

เห็นผล · ร้านป้าแดงLINE 61 จาก 81 ออเดอร์ (75%)
ออเดอร์ประจำส่วนใหญ่เข้าระบบเองจากบอท ร้านไม่ต้องพิมพ์ทีละรายการ ที่เหลือ: โทร 10 · หน้าร้าน 10 นับจากฐานข้อมูลตอนทำเล่ม
X43

พนักงานสิทธิ์ดูอย่างเดียว

ทำอย่างไร

  1. เข้าด้วยบัญชีพนักงาน บอย ช่วยงาน ของร้านช่างเอก (ดูลูกค้าได้อย่างเดียว) เปิดเมนู “งานค้าง”
X43 พนักงานสิทธิ์ดูอย่างเดียว

พนักงานเห็นเมนูกลุ่ม “ส่วนเสริมจากพาร์ทเนอร์” ตามสิทธิ์ และอ่านใบงานได้ หน้ารายการนี้ไม่มีปุ่มแก้ไข

X43 พนักงานสิทธิ์ดูอย่างเดียว (บนมือถือ)

บนมือถือ

อ่านได้ ส่วนการแก้ข้อมูลระบบปฏิเสธ (ข้อ E10)

5 · ตามดูผล

พาร์ทเนอร์ดูว่าร้านไหนใช้รุ่นไหน กฎทำงานอย่างไร และ webhook ส่งถึงไหม เห็นได้เท่าที่ร้านยินยอม

X50

ร้านไหนใช้รุ่นไหน

ทำอย่างไร

  1. เปิด repair_jobs ใน Studio แท็บ “ร้านที่ติดตั้ง”
X50 ร้านไหนใช้รุ่นไหน

ร้านช่างเอกแอร์แอนด์ไฟฟ้า และร้านซ่อมมือถือเจ๊ติ๋ม ใช้งานอยู่ที่รุ่น 1 ทั้งคู่

กด “ประวัติการทำงานของกฎ” ที่แถวของร้านเพื่อดูรอบกฎ (ภาพถัดไป)

X51

ประวัติกฎแบบละเอียด (ร้านยินยอมส่งข้อมูล)

ทำอย่างไร

  1. กด “ประวัติการทำงานของกฎ” ที่แถวร้านช่างเอก
X51 ประวัติกฎแบบละเอียด (ร้านยินยอมส่งข้อมูล)

ภาพตัดมาจากกลางตาราง จึงไม่เห็นหัวตาราง แต่ละแถวคือหนึ่งรอบของกฎ มีเวลา ชื่อกฎ (เช่น “งานซ่อมเสร็จ” “สรุปงานค้างประจำวัน” “งานเลยกำหนด” “รออะไหล่”) เหตุการณ์ที่ทำให้กฎทำงาน (เช่น “แก้ไขรายการ” “ทุกวัน” “ถึงวันที่ในรายการ”) สถานะ “สำเร็จ” “ล้ม” หรือ “ข้าม” ข้อความบอกสาเหตุของแถวที่ล้มหรือข้าม และรหัสรายการ 8 ตัวอักษรท้ายแถว ไม่มีชื่อลูกค้าหรือค่าที่กรอก ตัวเลือก “ทุกกฎ” ที่อยู่เหนือภาพใช้เลือกดูทีละกฎ

รอบล่าสุดของกฎ “งานซ่อมเสร็จ” “สรุปงานค้างประจำวัน” และ “งานเลยกำหนด” ขึ้นว่า “สำเร็จ” ส่วนกฎ “รออะไหล่” ขึ้นว่า “ล้ม” 3 แถว (ข้อ X37) และกฎ “งานซ่อมเสร็จ” มีแถว “ข้าม” (ข้อ E04)

เห็นผล · ร้านช่างเอกสรุปงานค้างประจำวัน 57 รอบ · งานซ่อมเสร็จ 30 รอบ
พาร์ทเนอร์ตามได้ทุกรอบโดยไม่เห็นข้อมูลลูกค้า นับตอนทำเล่ม: งานซ่อมเสร็จถูกข้ามอีก 7 รอบเพราะเต็มเพดานต่อวัน · งานเลยกำหนด 4 รอบ · กฎรออะไหล่ล้ม 3 รอบเพราะใบงานเป้าหมายถูกลบไปแล้ว จึงหยุดเอง (X37)
X52

ร้านที่ไม่ยินยอม เห็นแค่ยอดรวมรายวัน

ทำอย่างไร

  1. เปิด pet_health ใน Studio แท็บ “ร้านที่ติดตั้ง” แล้วกด “ประวัติการทำงานของกฎ” ที่แถวบ้านเหมียวเพ็ทช็อป
X52 ร้านที่ไม่ยินยอม เห็นแค่ยอดรวมรายวัน

ระบบบอกว่าร้านยังไม่ได้ยินยอมให้ส่งข้อมูลให้คุณ จึงแสดงเฉพาะจำนวนต่อวันของแต่ละกฎ ไม่มีเวลาและรหัสรายการ

บ้านเหมียวยังใช้รุ่น 1 ที่ไม่มีการส่งออก จึงเห็นเป็น วัน · กฎ · สถานะ · จำนวน

เห็นผล · บ้านเหมียว24 รอบ
รวมทุกวัน พาร์ทเนอร์รู้ว่ากฎทำงานกี่ครั้ง แต่ไม่รู้ว่ารอบไหนเกี่ยวกับข้อมูลชิ้นใด
X53

ปลายทาง webhook และผลการส่ง

ทำอย่างไร

  1. เจ้าของบัญชีร้านดีซอฟต์เปิดแท็บ “การเชื่อมต่อ” (/partner/integrations)
  2. เลื่อนลงไปที่ตาราง “ประวัติการส่งล่าสุด” มุมขวาบนของตารางมีตัวเลือกสถานะ: ทั้งหมด · ส่งสำเร็จ · ไม่สำเร็จ · รอส่ง
X53 ปลายทาง webhook และผลการส่ง

ภาพเปิดที่ตาราง “ประวัติการส่งล่าสุด” ของร้านดีซอฟต์ มีคอลัมน์ เหตุการณ์ · URL · สถานะ · ครั้งที่ลอง · เวลา ตัวเลือกสถานะมุมขวาบนของตารางตั้งไว้ที่ “ทั้งหมด” สี่แถวบนเป็น ext.record.updated ที่ขึ้นว่า “ไม่สำเร็จ” ครั้งที่ลอง 0 พร้อมข้อความแดง “ร้านปิดการส่งข้อมูลแล้ว ไม่ส่งซ้ำ” ถัดลงไปเป็น ext.automation.fired ที่ขึ้นว่า “ไม่สำเร็จ · HTTP 500” ลอง 6 ครั้ง และมีตัวหนังสือแดง “HTTP 500” ใต้สถานะ

ส่งไม่สำเร็จมี 2 แบบทั้ง 2 แบบอยู่ในภาพนี้
แบบที่ 1 ปลายทางของคุณตอบกลับว่าผิดพลาด แถวขึ้นว่า “ไม่สำเร็จ · HTTP 500” ระบบลองส่งจนครบ 6 ครั้งแล้วจึงหยุด ในเล่มนี้ปลายทางทดสอบของร้านดีซอฟต์ถูกตั้งให้ตอบ 500 กับเหตุการณ์ ext.automation.fired โดยตั้งใจ ให้แก้ที่ปลายทางของคุณ แล้วกด “ทดสอบส่ง”
แบบที่ 2 คือสี่แถวบน ร้านปิดการส่งข้อมูลของส่วนเสริมนี้แล้ว แถวขึ้นว่า “ไม่สำเร็จ” พร้อมข้อความแดง “ร้านปิดการส่งข้อมูลแล้ว ไม่ส่งซ้ำ” (รหัส EXT_EGRESS_CLOSED) และครั้งที่ลอง 0 เพราะไม่มีอะไรถูกส่งออกไปเลย ปัญหาไม่ได้อยู่ที่ปลายทางของคุณ จึงแก้ที่ปลายทางไม่ได้ ถ้าจะให้ส่งอีก ต้องให้ร้านเป็นผู้ตัดสินใจ

รู้ว่าครั้งไหนส่งสำเร็จ ครั้งไหนล้ม และล้มเพราะอะไร เลือก “ไม่สำเร็จ” ที่มุมขวาบนของตารางเพื่อดูเฉพาะครั้งที่ล้ม ถ้าเป็นแบบที่ปลายทางตอบผิดพลาด ให้แก้ฝั่งของคุณแล้วกด “ทดสอบส่ง” ที่ปลายทางของคุณ (อยู่เหนือตาราง) ตัวอย่างข้อมูลการส่งที่สำเร็จและที่ล้ม ประเภทละ 5 รายการ อยู่ในไฟล์ deliveries.json บทที่ 8

เห็นผล · การส่ง webhookร้านดีซอฟต์ สำเร็จ 48 · ล้ม 42
นับจากบันทึกการส่งตอนทำเล่ม ความล้ม 38 ครั้งเป็นเหตุการณ์ ext.automation.fired ที่ปลายทางทดสอบของร้านดีซอฟต์ตอบ HTTP 500 โดยตั้งใจ เพื่อให้เห็นหน้าตาของการส่งที่ล้ม อีก 4 ครั้งเป็น ext.record.updated ที่ร้านปิดการส่งข้อมูลแล้ว ครั้งที่ลอง 0 ส่วนส่งดี สำเร็จ 20 · ล้ม 0 (ภาพ X54)
X54

การเรียก API ของบอท

ทำอย่างไร

  1. เจ้าของบัญชีส่งดีเปิดแท็บ “การเชื่อมต่อ” แล้วเลื่อนลงไปที่กุญแจของบอท
  2. ใต้กุญแจเป็นตาราง “ประวัติการส่งล่าสุด” ของส่งดี
  3. ดูคำขอและคำตอบจริงของบอทในบทที่ 8 (ไฟล์ api-ext-*.json)
X54 การเรียก API ของบอท

ด้านบนของภาพคือกุญแจ songdee-line-bot ที่บอทใช้ ได้สิทธิ์ อ่านข้อมูลส่วนเสริม · เขียนข้อมูลส่วนเสริม · อ่าน หมดอายุ 5/11/2569 ถัดลงมาคือตาราง “ประวัติการส่งล่าสุด” ของส่งดี ตัวเลือกมุมขวาบนตั้งไว้ที่ “ทั้งหมด” ทุกแถวเป็น ext.record.created ที่ขึ้นว่า “ส่งสำเร็จ · HTTP 200” ลอง 1 ครั้ง

เห็นว่าบอทสร้าง อ่าน และส่งซ้ำได้โดยไม่เกิดออเดอร์ซ้ำ เพราะใช้ Idempotency-Key ตารางประวัติการส่งใต้กุญแจบอกด้วยว่า webhook ของส่งดีส่งถึงปลายทางครบทุกครั้ง

6 · ออกรุ่นใหม่และวงจรชีวิต

รุ่น 2 ของ pet_health เพิ่มการส่งข้อมูลออก ร้านที่ใช้รุ่น 1 ต้องยินยอมใหม่ก่อน จากนั้นตามร้านเจ๊ติ๋มผ่านการหยุด กลับมาใช้ ส่งออกข้อมูล และถอนการติดตั้ง

N01

รุ่นใหม่ที่ขอส่งข้อมูลออกเพิ่ม

ทำอย่างไร

  1. เปิด pet_health ใน Studio แท็บ “รุ่นที่เผยแพร่”
N01 รุ่นใหม่ที่ขอส่งข้อมูลออกเพิ่ม

รุ่น #1 และ #2 สถานะ “อนุมัติแล้ว” ทั้งคู่ รุ่น #2 เพิ่มการส่งข้อมูลออก

ร้านที่ใช้รุ่น 1 จะได้รับข้อเสนอรุ่น 2 ซึ่งต้องยินยอมใหม่

N02

ร้านเห็นว่ามีรุ่นใหม่ที่ต้องยินยอม

ทำอย่างไร

  1. ร้านน้องหมาน้องแมวเปิด /settings/extensions
N02 ร้านเห็นว่ามีรุ่นใหม่ที่ต้องยินยอม

การ์ดมีป้าย “รอยินยอมเวอร์ชันใหม่ · รุ่น 2” และปุ่ม “ยินยอมเวอร์ชันใหม่” ระหว่างนี้ร้านใช้รุ่น 1 ต่อตามปกติ

N02 ร้านเห็นว่ามีรุ่นใหม่ที่ต้องยินยอม (บนมือถือ)

บนมือถือ

ข้อเสนออาจขึ้นช้าราวครึ่งนาทีหลังรุ่นใหม่ได้รับอนุมัติ

N03

ยินยอมใหม่ เฉพาะเมื่อขอบเขตเพิ่ม

ทำอย่างไร

  1. กด “ยินยอมเวอร์ชันใหม่”
N03 ยินยอมใหม่ เฉพาะเมื่อขอบเขตเพิ่ม

กล่องมีหัวข้อ “ส่งข้อมูลไปยังเซิร์ฟเวอร์ของพาร์ทเนอร์” เพิ่ม บอกว่าส่งอะไร และไม่ส่งอะไร เช่น ไม่ส่งค่าที่กรอก ไม่ส่งชื่อ ไม่ส่งเบอร์โทร

N03 ยินยอมใหม่ เฉพาะเมื่อขอบเขตเพิ่ม (บนมือถือ)

บนมือถือ

ร้านอ่านแล้วเลือก “ยินยอม” หรือ “ยกเลิก”

N04

ร้านกดยินยอม

ทำอย่างไร

  1. กด “ยินยอม” ในกล่องเดียวกับภาพ N03
N04 ร้านกดยินยอม

หลังกด “ยินยอม” การ์ดประวัติสัตว์เลี้ยงขึ้น “รุ่น 2” และ “ใช้งานอยู่”

ร้านเปลี่ยนไปใช้รุ่น 2 ทันที

N05

ก่อนและหลังยินยอม

ทำอย่างไร

  1. เปิดประวัติกฎของร้านน้องหมาน้องแมวกับบ้านเหมียวเทียบกัน (แท็บ “ร้านที่ติดตั้ง” ของ pet_health)

ไม่มีภาพแยก หน้าตาเหมือนภาพ X51 (ละเอียด) และ X52 (รวม)

ร้านน้องหมาน้องแมวที่ยินยอมแล้วเห็นแบบละเอียด บ้านเหมียวที่ยังไม่ยินยอมยังเห็นแบบรวม

เห็นผล · ก่อน/หลังละเอียด vs รวม
สิ่งที่พาร์ทเนอร์เห็นขึ้นกับความยินยอมของร้าน ไม่ใช่การตั้งค่าของพาร์ทเนอร์
N06

หยุดชั่วคราว ข้อมูลยังอยู่

ทำอย่างไร

  1. ร้านซ่อมมือถือเจ๊ติ๋มเปิด /settings/extensions
  2. กด “หยุด” ที่การ์ดใบงานซ่อม
N06 หยุดชั่วคราว ข้อมูลยังอยู่

หลังกด “หยุด” ป้ายเปลี่ยนเป็น “ร้านหยุดไว้” ปุ่ม “หยุด” กลายเป็น “เริ่มใหม่” รายการใบงานถูกซ่อน แต่ยังกด JSON หรือ CSV ได้

ข้อมูลเดิมยังอยู่ครบ กด “เริ่มใหม่” เมื่อจะใช้ต่อ (ข้อถัดไป)

N07

กลับมาใช้ต่อด้วยความยินยอม

ทำอย่างไร

  1. กด “เริ่มใหม่” แล้วยืนยันข้อความยินยอมปัจจุบัน
N07 กลับมาใช้ต่อด้วยความยินยอม

หลังยืนยัน ป้ายกลับเป็น “ใช้งานอยู่” รายการใบงานกลับมา แต่ละแถวขึ้นเลขงานกับชื่ออุปกรณ์ เช่น “J-0030 · ตู้เย็น”

ร้านใช้งานได้ตามเดิม ใบงานเดิมยังอยู่ครบ

N08

ร้านดึงข้อมูลของตัวเองออกได้ทุกเมื่อ

ทำอย่างไร

  1. กด “JSON” หรือ “CSV” บนการ์ด (ปุ่มในภาพ N07)

ไม่มีภาพแยก กดแล้วได้ไฟล์ หน้าจอยังเหมือนภาพ N07

ได้ไฟล์ข้อมูลของส่วนเสริมทั้งหมดในร้าน สรุปไฟล์ JSON ของร้านเจ๊ติ๋มอยู่ในบทที่ 8

N09

ถอนการติดตั้ง

ทำอย่างไร

  1. กด “ถอน” บนการ์ด (ปุ่มในภาพ N07)
N09 ถอนการติดตั้ง

หลังกด “ถอน” ป้ายเปลี่ยนเป็น “ถอนแล้ว” การ์ดเหลือปุ่ม เริ่มใหม่ · JSON · CSV ไม่มีรายการใบงานและปุ่มกฎอัตโนมัติ

ส่วนเสริมถูกถอดออกจากร้าน ข้อมูลยังเก็บไว้จนถึงรอบลบข้อมูล ตามที่กล่องยินยอมแจ้งร้านไว้ ระหว่างนี้ยังกด JSON หรือ CSV ได้ แต่ควรเก็บไฟล์ไว้ก่อนถอน

7 · เมื่อระบบปฏิเสธ

แต่ละกรณีบอกรหัสเหตุผล (reason_code) ที่ระบบตอบ ทำไม และแก้อย่างไร ให้ระบบของคุณตรวจด้วยรหัสนี้ ไม่ใช่เลขสถานะ HTTP กรณีที่ไม่มีหน้าจอจะชี้ไปที่ไฟล์ผลลัพธ์ในบทที่ 8

E01

พาร์ทเนอร์ที่ยังไม่เซ็น DPA

ทำอย่างไร

  1. เข้าด้วยบัญชี หจก. ทดลองระบบ ที่ยังไม่เซ็น DPA เปิดแท็บ “การเชื่อมต่อ”
E01 พาร์ทเนอร์ที่ยังไม่เซ็น DPA

ตัวเลือก “ข้อมูลส่วนเสริม” และ “ข้อมูลติดต่อลูกค้า” ถูกปิด พร้อมข้อความ “ต้องมีสัญญา DPA ก่อนเปิดสิทธิ์ข้อมูลส่วนเสริม ติดต่อ SMEDNA”

รหัสDPA_NOT_SIGNED
ทำไมยังไม่มีวันที่เซ็น DPA ถ้าเรียก API ตรง ระบบตอบรหัสนี้ (ไฟล์ api-ext-dpa-not-signed.json ในบทที่ 8)
แก้อย่างไรเซ็น DPA กับ SMEDNA แล้วให้ SMEDNA บันทึกวันที่ (ข้อ X01)
E02

คลินิกติดตั้งไม่ได้

ทำอย่างไร

  1. คลินิกกายภาพบำบัดฟื้นฟูดีกด “ยินยอม” ในกล่องของ “นัดติดตามผล” (กล่องเดียวกับภาพ X31)
E02 คลินิกติดตั้งไม่ได้

หลังกด “ยินยอม” มุมขวาล่างขึ้นข้อความ “ร้านประเภทนี้เขียนข้อมูลส่วนบุคคลผ่านส่วนเสริมไม่ได้” กล่องยินยอมยังเปิดอยู่ และไม่มีการติดตั้ง

รหัสEXT_VERTICAL_BLOCKED
ทำไมร้านประเภทคลินิกยังติดตั้งส่วนเสริมที่เก็บข้อมูลผูกกับลูกค้าไม่ได้ จนกว่า SMEDNA จะเปิดความสามารถนี้ตามคำตอบทนาย กรณีนี้ทำตอนที่ยังไม่เปิด
แก้อย่างไรรอ SMEDNA แจ้งว่าเปิดแล้ว ระหว่างนี้อย่าเพิ่งสัญญาว่าจะติดตั้งให้คลินิก
E03

ยินยอมด้วยข้อความที่ไม่ใช่รุ่นล่าสุด

ทำอย่างไร

  1. ร้านน้องหมาน้องแมวกด “ยินยอม” ด้วยข้อความยินยอมที่ไม่ตรงกับรุ่นที่เสนออยู่
E03 ยินยอมด้วยข้อความที่ไม่ใช่รุ่นล่าสุด

ร้านเห็นข้อความ “ข้อความยินยอมไม่ตรงกับรุ่นที่เสนอ โหลดใหม่แล้วยินยอมอีกครั้ง” ภาพนี้จำลองโดยแก้ค่าที่ส่งไป

รหัสEXT_CONSENT_MISMATCH
ทำไมข้อความที่ร้านกดยินยอมไม่ตรงกับรุ่นที่เสนออยู่ตอนนี้ เช่น มีรุ่นใหม่ออกมาระหว่างที่เปิดกล่องค้างไว้
แก้อย่างไรโหลดหน้าใหม่ แล้วกด “ยินยอม” อีกครั้ง
E04

กฎถูกข้ามเพราะเต็มเพดานต่อวัน

ทำอย่างไร

  1. ดูประวัติกฎของร้านช่างเอก (ภาพ X51) แล้วเลื่อนลงไปหาแถวที่ขึ้นว่า “ข้าม”
E04 กฎถูกข้ามเพราะเต็มเพดานต่อวัน

ภาพคือท้ายตารางประวัติกฎของร้านช่างเอก (เลื่อนลงมาจากภาพ X51) มี 7 แถวที่ขึ้นว่า “ข้าม” ของกฎ “งานซ่อมเสร็จ” พร้อมเหตุผล “ข้ามเพราะเกินโควต้าวันนี้” แถว “ล้ม” 3 แถวด้านบนเป็นกฎ “รออะไหล่” (ข้อ X37) คอลัมน์ที่สองเป็นชื่อกฎ ท้ายตารางมีปุ่ม “ดูเพิ่ม”

รหัสAUTOMATION_QUOTA
ทำไมกฎหนึ่งข้อทำงานได้จำนวนจำกัดต่อวันต่อร้าน รอบที่เกินถูกข้าม ไม่ใช่ล้ม นับตอนทำเล่ม กฎ “งานซ่อมเสร็จ” ของร้านช่างเอกถูกข้าม 7 รอบ
แก้อย่างไรออกแบบกฎให้ทำงานเท่าที่จำเป็น เช่น รวมเป็นสรุปวันละครั้ง หรือขอ SMEDNA ปรับเพดาน
E05

กฎสั่งสิ่งที่ไม่อนุญาต

ทำอย่างไร

  1. ในร่างทดลอง guide_errors_demo ตั้งกฎให้ทำ sale.create (สร้างการขาย) แล้วกด “บันทึกร่าง”
E05 กฎสั่งสิ่งที่ไม่อนุญาต

แถบแดงบอกตำแหน่งที่ผิด “กฎทำ sale.create ไม่ได้” และแจ้งว่าร่างยังมีข้อที่ต้องแก้

รหัสACTION_NOT_ALLOWED
ทำไมกฎทำได้เฉพาะสิ่งในรายการที่อนุญาต เช่น แจ้งเตือนพนักงาน หรือแก้ข้อมูลของส่วนเสริมเอง สร้างการขายไม่ได้
แก้อย่างไรเปลี่ยนสิ่งที่กฎทำเป็นแจ้งเตือนพนักงาน หรือแก้ข้อมูลของส่วนเสริม
E06

ชื่อกฎมีเบอร์โทร

ทำอย่างไร

  1. ตั้งชื่อกฎว่า “โทร 0811110101” แล้วกด “บันทึกร่าง”
E06 ชื่อกฎมีเบอร์โทร

แถบแดงบอกว่า “ชื่อที่แสดงต้องไม่เกิน 80 ตัวอักษร และไม่มีลิงก์ เบอร์ หรืออีเมล”

รหัสไม่มีรหัส เป็นข้อที่ต้องแก้ในร่าง
ทำไมชื่อกฎห้ามยาวเกิน 80 ตัวอักษร และห้ามมีลิงก์ เบอร์โทร หรืออีเมล
แก้อย่างไรลบเบอร์โทรออกจากชื่อกฎ
E07

กฎประจำวันใส่เงื่อนไขไม่ได้

ทำอย่างไร

  1. ตั้งกฎแบบทำงานตามเวลาประจำวัน แล้วเพิ่มเงื่อนไข “ถ้า”
E07 กฎประจำวันใส่เงื่อนไขไม่ได้

แถบแดงบอกว่า “กฎตามเวลาประจำวันมีเงื่อนไขไม่ได้”

รหัสไม่มีรหัส เป็นข้อที่ต้องแก้ในร่าง
ทำไมกฎประจำวันทำงานวันละครั้ง ไม่ได้ทำงานกับรายการใดรายการหนึ่ง จึงไม่มีรายการให้ตรวจเงื่อนไข
แก้อย่างไรเอาเงื่อนไขออก หรือใช้กฎแบบ “ถึงวันที่ในรายการ” แทน
E08

กุญแจไม่มีสิทธิ์เขียน

ทำอย่างไร

  1. บอทใช้กุญแจ songdee-reader ที่อ่านได้อย่างเดียวเขียนออเดอร์
E08 กุญแจไม่มีสิทธิ์เขียน

กุญแจ songdee-reader (ซ้ายล่าง) ได้สิทธิ์ “อ่านข้อมูลส่วนเสริม, อ่าน” ไม่มี “เขียนข้อมูลส่วนเสริม” ต่างจากกุญแจของบอทในภาพ X54 คำตอบที่ถูกปฏิเสธไม่มีหน้าจอ ดูไฟล์ api-ext-403-read-key.json ในบทที่ 8

รหัสext_scope_required
ทำไมกุญแจนี้ไม่ได้สิทธิ์เขียนข้อมูลส่วนเสริม
แก้อย่างไรออกกุญแจใหม่ที่เลือก “ข้อมูลส่วนเสริม” เป็น “อ่านและเขียน” (ข้อ X04)
E09

แก้ข้อมูลโดยไม่บอกรุ่น หรือบอกรุ่นเก่า

ทำอย่างไร

  1. บอทแก้ออเดอร์ (PATCH) โดยไม่ส่ง If-Match หรือส่งค่าของรุ่นเก่า

ไม่มีหน้าจอ ดูไฟล์ในบทที่ 8 ข้อ 8.2

รหัสEXT_IF_MATCH_REQUIRED · EXT_ETAG_MISMATCH
ทำไมการแก้ข้อมูลต้องบอกรุ่นของรายการที่อ่านมา (If-Match) ไม่ส่งได้ 428 ส่งรุ่นเก่าได้ 412 เพื่อกันการเขียนทับงานของคนอื่น
แก้อย่างไรอ่านรายการใหม่ แล้วส่ง If-Match ตามค่าล่าสุด
E10

พนักงานดูอย่างเดียวพยายามแก้

ทำอย่างไร

  1. พนักงาน บอย ช่วยงาน (ดูอย่างเดียว) พยายามเพิ่มหรือแก้ใบงาน

ไม่มีภาพแยก หน้าที่พนักงานเห็นอยู่ในภาพ X43

รหัสสิทธิ์ไม่พอ (403)
ทำไมบัญชีพนักงานนี้ได้สิทธิ์ดูอย่างเดียว
แก้อย่างไรให้เจ้าของร้านเพิ่มสิทธิ์ให้พนักงาน

8 · สำหรับนักพัฒนา

ผลลัพธ์จริงจากเครื่องทดสอบ ค่าลับถูกปิดบังแล้ว

8.1 บอท LINE เขียนออเดอร์

บอทใช้กุญแจ songdee-line-bot (อ่านและเขียน) ส่วนรหัสสินค้ามาจากใบรหัสสินค้าที่ร้านให้ เพราะ Partner API ยังไม่มีรายการสินค้าให้ดึง

api-ext-create.json — สร้างออเดอร์ (มี Idempotency-Key)
ตอบ 201 พร้อมรหัสแถวและรุ่น (rev) ของแถว
{
  "request": "POST /api/v1/partner-api/ext/standing_orders/standing_order?business_id={groc1}",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 201,
  "request_headers": {
    "Idempotency-Key": "guide-ext-out-1"
  },
  "body": {
    "id": "00000000-0000-4000-b000-000000000107",
    "rev": 1
  }
}
api-ext-replay.json — ส่งซ้ำด้วยคีย์เดิม
ได้แถวเดิม ไม่เกิดออเดอร์ซ้ำ ถ้าส่งโดยไม่มี Idempotency-Key ระบบตอบ 428 (EXT_IDEMPOTENCY_KEY_REQUIRED)
{
  "request": "the same POST sent a second time with the same Idempotency-Key",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "first": {
    "status": 201,
    "body": {
      "id": "00000000-0000-4000-b000-000000000107",
      "rev": 1
    }
  },
  "second": {
    "status": 201,
    "body": {
      "id": "00000000-0000-4000-b000-000000000107",
      "rev": 1
    }
  },
  "same_id": true
}
api-ext-428-no-idempotency.json — ไม่มี Idempotency-Key
{
  "request": "POST …/standing_order?business_id={groc1}  (no Idempotency-Key)",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 428,
  "body": {
    "detail": {
      "reason_code": "EXT_IDEMPOTENCY_KEY_REQUIRED"
    }
  }
}
api-ext-get.json — อ่านแถวเดียว
{
  "request": "GET /api/v1/partner-api/ext/standing_orders/standing_order/{id}?business_id={groc1}",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 200,
  "response_headers": {
    "ETag": "\"1\""
  },
  "body": {
    "id": "00000000-0000-4000-b000-000000000101",
    "object_key": "standing_order",
    "subject_id": "00000000-0000-4000-b000-000000000102",
    "parent_id": null,
    "data": {
      "round": "sat",
      "units": 14,
      "status": "new",
      "channel": "line",
      "line_ref": "LINE-fc65-0060",
      "deliver_on": "2026-10-10"
    },
    "data_extra": {},
    "rev": 1,
    "schema_rev": 1,
    "created_at": "2026-09-30T13:37:00+07:00",
    "updated_at": "2026-09-30T13:37:00+07:00",
    "created_by": null,
    "updated_by": null,
    "stale": false
  }
}
api-ext-list.json — อ่านรายการ
{
  "request": "GET /api/v1/partner-api/ext/standing_orders/standing_order?business_id={groc1}&limit=3",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 200,
  "body": {
    "items": [
      {
        "id": "00000000-0000-4000-b000-000000000101",
        "object_key": "standing_order",
        "subject_id": "00000000-0000-4000-b000-000000000102",
        "parent_id": null,
        "data": {
          "round": "sat",
          "units": 14,
          "status": "new",
          "channel": "line",
          "line_ref": "LINE-fc65-0060",
          "deliver_on": "2026-10-10"
        },
        "data_extra": {},
        "rev": 1,
        "schema_rev": 1,
        "created_at": "2026-09-30T13:37:00+07:00",
        "updated_at": "2026-09-30T13:37:00+07:00",
        "created_by": null,
        "updated_by": null,
        "stale": false
      },
      {
        "id": "00000000-0000-4000-b000-000000000103",
        "object_key": "standing_order",
        "subject_id": "00000000-0000-4000-b000-000000000104",
        "parent_id": null,
        "data": {
          "round": "thu",
          "units": 13,
          "status": "new",
          "channel": "line",
          "line_ref": "LINE-fc65-0059",
          "deliver_on": "2026-10-09"
        },
        "data_extra": {},
        "rev": 1,
        "schema_rev": 1,
        "created_at": "2026-09-30T12:30:00+07:00",
        "updated_at": "2026-09-30T12:30:00+07:00",
        "created_by": null,
        "updated_by": null,
        "stale": false
      },
      {
        "id": "00000000-0000-4000-b000-000000000105",
        "object_key": "standing_order",
        "subject_id": "00000000-0000-4000-b000-000000000106",
        "parent_id": null,
        "data": {
          "round": "mon",
          "units": 12,
          "status": "new",
          "channel": "line",
          "line_ref": "LINE-fc65-0058",
          "deliver_on": "2026-10-08"
        },
        "data_extra": {},
        "rev": 1,
        "schema_rev": 1,
        "created_at": "2026-09-29T12:23:00+07:00",
        "updated_at": "2026-09-29T12:23:00+07:00",
        "created_by": null,
        "updated_by": null,
        "stale": false
      }
    ],
    "next_cursor": "MjAyNi0xMC0wNFQwOTo1OTowMCswMDowMHw3NmY1NDE2Mi1hN2RkLTRhZDYtOWU1Yi1lMzY5ZjI5NmZlMTE=",
    "stale": false
  }
}

8.2 การแก้ข้อมูลต้องมี If-Match

api-ext-428-no-if-match.json — PATCH ไม่มี If-Match
{
  "request": "PATCH /api/v1/partner-api/ext/standing_orders/standing_order/{id}?business_id={groc1}  (no If-Match)",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 428,
  "body": {
    "detail": {
      "reason_code": "EXT_IF_MATCH_REQUIRED"
    }
  }
}
api-ext-412-stale.json — PATCH ด้วยรุ่นที่ล้าสมัย
{
  "request": "PATCH …/{id}?business_id={groc1}  (If-Match: \"999\")",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 412,
  "request_headers": {
    "If-Match": "\"999\""
  },
  "body": {
    "detail": {
      "reason_code": "EXT_ETAG_MISMATCH"
    }
  }
}

8.3 กุญแจผิดสิทธิ์ และ DPA

api-ext-403-read-key.json — คีย์อ่านอย่างเดียวพยายามเขียน
{
  "request": "POST …/standing_order?business_id={groc1}  (a key that may only read)",
  "auth": "Bearer pk_7p03xJRWH…(ตัดทอน)",
  "status": 403,
  "body": {
    "detail": {
      "message": "This key has no ext scope for this call",
      "reason_code": "ext_scope_required"
    }
  }
}
api-ext-dpa-not-signed.json — พาร์ทเนอร์ที่ยังไม่มี DPA
{
  "request": "GET …/standing_order?business_id={groc2}  (partner DPA cleared)",
  "auth": "Bearer pk__JlOUc-ke…(ตัดทอน)",
  "status": 403,
  "body": {
    "detail": {
      "reason_code": "DPA_NOT_SIGNED"
    }
  }
}

8.4 webhook

ลายเซ็น = hex(hmac_sha256(ความลับ, เวลา + “.” + เนื้อหาดิบ)) ตรวจใหม่ฝั่งผู้รับ

webhook-ext.record.updated.http — คำขอที่ปลายทางได้รับ
POST /webhook HTTP/1.1
X-Partner-Event: ext.record.updated
X-Partner-Delivery: 00000000-0000-4000-b000-000000000112
X-Partner-Timestamp: 1790819940
X-Partner-Signature: 77c64a64…
Content-Type: application/json

{
  "data": {
    "record_id": "00000000-0000-4000-b000-000000000113",
    "object_key": "job",
    "subject_id": null,
    "subject_kind": "none",
    "extension_key": "repair_jobs",
    "changed_fields": [
      "status"
    ]
  },
  "links": {
    "self": "/api/v1/partner-api/ext/repair_jobs/job/00000000-0000-4000-b000-000000000113?business_id=00000000-0000-4000-a000-0000000000e3"
  },
  "event_id": "00000000-0000-4000-b000-000000000114",
  "event_type": "ext.record.updated",
  "business_id": "00000000-0000-4000-a000-0000000000e3",
  "occurred_at": "2026-10-01T08:57:00+07:00"
}
webhook-ext.record.created.http — ext.record.created
POST /webhook HTTP/1.1
X-Partner-Event: ext.record.created
X-Partner-Delivery: 00000000-0000-4000-b000-000000000108
X-Partner-Timestamp: 1790819940
X-Partner-Signature: bc42a6f7…
Content-Type: application/json

{
  "data": {
    "record_id": "00000000-0000-4000-b000-000000000109",
    "object_key": "standing_order",
    "subject_id": "00000000-0000-4000-b000-000000000110",
    "subject_kind": "product",
    "extension_key": "standing_orders",
    "changed_fields": [
      "channel",
      "deliver_on",
      "round",
      "status",
      "units"
    ]
  },
  "links": {
    "self": "/api/v1/partner-api/ext/standing_orders/standing_order/00000000-0000-4000-b000-000000000109?business_id=00000000-0000-4000-a000-0000000000e6"
  },
  "event_id": "00000000-0000-4000-b000-000000000111",
  "event_type": "ext.record.created",
  "business_id": "00000000-0000-4000-a000-0000000000e6",
  "occurred_at": "2026-10-01T08:57:00+07:00"
}
webhook-ext.automation.fired.http — ext.automation.fired
POST /webhook HTTP/1.1
X-Partner-Event: ext.automation.fired
X-Partner-Delivery: 00000000-0000-4000-b000-000000000115
X-Partner-Timestamp: 1790819940
X-Partner-Signature: 32f8bab5…
Content-Type: application/json

{
  "data": {
    "run_id": "00000000-0000-4000-b000-000000000116",
    "record_id": "00000000-0000-4000-b000-000000000117",
    "object_key": "job",
    "extension_key": "repair_jobs",
    "automation_key": "job_done"
  },
  "links": {
    "businesses": "/api/v1/partner-api/businesses"
  },
  "event_id": "00000000-0000-4000-b000-000000000118",
  "event_type": "ext.automation.fired",
  "business_id": "00000000-0000-4000-a000-0000000000e3",
  "occurred_at": "2026-10-01T08:58:00+07:00"
}

# ปลายทางจำลองตอบ 500 กับครั้งนี้ (ระบบบันทึกเป็นความล้มเหลวและลองส่งใหม่ตามรอบ)
webhook-verify-ext.txt — ผลตรวจลายเซ็นใหม่
ลายเซ็นตรงทั้งสามรายการ เหตุการณ์สุดท้ายปลายทางตอบ 500 ซึ่งเป็นกรณีล้มที่ตั้งไว้เพื่อทดสอบ
algorithm: hex(hmac_sha256(secret, f"{timestamp}." + raw_body))

event: ext.record.created
  hook: songdee
  timestamp: 1790819940
  signature (received):   bc42a6f7…
  signature (recomputed): bc42a6f7…
  result: OK
  endpoint answered: 200

event: ext.record.updated
  hook: raandee
  timestamp: 1790819940
  signature (received):   77c64a64…
  signature (recomputed): 77c64a64…
  result: OK
  endpoint answered: 200

event: ext.automation.fired
  hook: raandee
  timestamp: 1790819940
  signature (received):   32f8bab5…
  signature (recomputed): 32f8bab5…
  result: OK
  endpoint answered: 500
deliveries.json — บันทึกการส่ง สำเร็จและล้ม
{
  "request": "GET /api/v1/partner-api/webhooks/deliveries?status=failed|delivered&limit=5",
  "auth": "Bearer <JWT ของผู้ใช้>",
  "status": 200,
  "body": {
    "failed": [
      {
        "id": "00000000-0000-4000-b000-000000000119",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000120",
        "status": "failed",
        "attempt": 0,
        "response_code": null,
        "error": "EXT_EGRESS_CLOSED",
        "next_attempt_at": null,
        "created_at": "2026-09-30T13:24:00+07:00",
        "delivered_at": null
      },
      {
        "id": "00000000-0000-4000-b000-000000000121",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000122",
        "status": "failed",
        "attempt": 0,
        "response_code": null,
        "error": "EXT_EGRESS_CLOSED",
        "next_attempt_at": null,
        "created_at": "2026-09-30T12:24:00+07:00",
        "delivered_at": null
      },
      {
        "id": "00000000-0000-4000-b000-000000000123",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000124",
        "status": "failed",
        "attempt": 0,
        "response_code": null,
        "error": "EXT_EGRESS_CLOSED",
        "next_attempt_at": null,
        "created_at": "2026-09-29T11:24:00+07:00",
        "delivered_at": null
      },
      {
        "id": "00000000-0000-4000-b000-000000000125",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000126",
        "status": "failed",
        "attempt": 0,
        "response_code": null,
        "error": "EXT_EGRESS_CLOSED",
        "next_attempt_at": null,
        "created_at": "2026-09-29T10:24:00+07:00",
        "delivered_at": null
      },
      {
        "id": "00000000-0000-4000-b000-000000000127",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.automation.fired",
        "event_id": "00000000-0000-4000-b000-000000000128",
        "status": "failed",
        "attempt": 6,
        "response_code": 500,
        "error": "HTTP 500",
        "next_attempt_at": null,
        "created_at": "2026-09-28T09:24:00+07:00",
        "delivered_at": null
      }
    ],
    "delivered": [
      {
        "id": "00000000-0000-4000-b000-000000000129",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000130",
        "status": "delivered",
        "attempt": 1,
        "response_code": 200,
        "error": null,
        "next_attempt_at": null,
        "created_at": "2026-09-07T06:24:00+07:00",
        "delivered_at": "2026-09-07T06:24:00+07:00"
      },
      {
        "id": "00000000-0000-4000-b000-000000000131",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000132",
        "status": "delivered",
        "attempt": 1,
        "response_code": 200,
        "error": null,
        "next_attempt_at": null,
        "created_at": "2026-09-07T05:24:00+07:00",
        "delivered_at": "2026-09-07T05:24:00+07:00"
      },
      {
        "id": "00000000-0000-4000-b000-000000000133",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000134",
        "status": "delivered",
        "attempt": 1,
        "response_code": 200,
        "error": null,
        "next_attempt_at": null,
        "created_at": "2026-09-06T04:24:00+07:00",
        "delivered_at": "2026-09-06T04:24:00+07:00"
      },
      {
        "id": "00000000-0000-4000-b000-000000000135",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000136",
        "status": "delivered",
        "attempt": 1,
        "response_code": 200,
        "error": null,
        "next_attempt_at": null,
        "created_at": "2026-09-05T13:24:00+07:00",
        "delivered_at": "2026-09-05T13:24:00+07:00"
      },
      {
        "id": "00000000-0000-4000-b000-000000000137",
        "webhook_id": "00000000-0000-4000-a000-0000000000d9",
        "url": "https://example.com/raandee/hook",
        "event_type": "ext.record.updated",
        "event_id": "00000000-0000-4000-b000-000000000138",
        "status": "delivered",
        "attempt": 1,
        "response_code": 200,
        "error": null,
        "next_attempt_at": null,
        "created_at": "2026-09-05T12:24:00+07:00",
        "delivered_at": "2026-09-05T12:24:00+07:00"
      }
    ]
  }
}

8.5 ส่งออกข้อมูลของร้านและ AI

export-repair_jobs.summary.json — สรุปไฟล์ส่งออกของร้านเจ๊ติ๋ม
{
  "status": 200,
  "top_level_keys": [
    "install_id",
    "extension_key",
    "status",
    "revision",
    "records"
  ],
  "records_in_db": 30
}
ai-draft-fixture.json — คำตอบตัวอย่างที่ใช้แทน AI ในภาพ X17
{
  "plan_th": "เพิ่มช่องน้ำหนัก (กก.) และหมายเหตุในออบเจ็กต์อาบน้ำตัดขน แล้วใส่สองช่องนี้ในฟอร์มเดิม ส่วนราคาเป็นข้อมูลเงิน ส่วนเสริมเก็บไม่ได้ จึงแยกไว้เป็นความต้องการเฉพาะ",
  "patch": [
    {
      "op": "add",
      "path": "/objects/0/fields/-",
      "value": {
        "key": "weight_kg",
        "type": "number",
        "label": {
          "th": "น้ำหนัก (กก.)"
        }
      }
    },
    {
      "op": "add",
      "path": "/objects/0/fields/-",
      "value": {
        "key": "note",
        "type": "text",
        "label": {
          "th": "หมายเหตุ"
        }
      }
    },
    {
      "op": "add",
      "path": "/forms/0/sections/0/fields/-",
      "value": "weight_kg"
    },
    {
      "op": "add",
      "path": "/forms/0/sections/0/fields/-",
      "value": "note"
    }
  ],
  "custom": [
    {
      "need_th": "เก็บราคาค่าบริการอาบน้ำตัดขนต่อครั้ง",
      "reason_code": "FACT_REJECTED"
    }
  ],
  "issues": [],
  "ok": true,
  "needs_tick": [
    0,
    1
  ],
  "dropped": [
    {
      "op": 4,
      "code": "MONEY_FIELD",
      "path": "/objects/0/fields/5"
    }
  ],
  "attempt_id": "00000000-0000-4000-b000-0000000000a1",
  "prompt_version": "2c-1"
}

9 · บนมือถือ

ภาพบนมือถือ (390 พิกเซล) ของหน้าที่ร้านใช้บ่อย

X04 บนมือถือ

X04

X30 บนมือถือ

X30

X32 บนมือถือ

X32

X33 บนมือถือ

X33

X36 บนมือถือ

X36

X37 บนมือถือ

X37

X39 บนมือถือ

X39

X41 บนมือถือ

X41

X43 บนมือถือ

X43

N02 บนมือถือ

N02

N03 บนมือถือ

N03

10 · ภาคผนวก

รหัสเหตุผล ความสามารถที่ SMEDNA เปิดให้ และคำถามที่พบบ่อย เพดานของส่วนเสริมอยู่ที่ข้อ X25

รหัสเหตุผลที่พบในเล่ม

รหัสความหมาย
DPA_NOT_SIGNEDพาร์ทเนอร์ยังไม่เซ็น DPA
EXT_VERTICAL_BLOCKEDประเภทธุรกิจนี้ยังติดตั้งไม่ได้
EXT_CONSENT_MISMATCHข้อความยินยอมไม่ตรงกับรุ่นที่เสนอ
AUTOMATION_QUOTAกฎเต็มเพดานต่อวัน รอบถูกข้าม
ACTION_TARGET_MISSINGรายการที่กฎต้องแก้ถูกลบไปแล้ว
ACTION_NOT_ALLOWEDกฎสั่งสิ่งนอกรายการที่อนุญาต
EXT_EGRESS_CLOSED“ร้านปิดการส่งข้อมูลแล้ว ไม่ส่งซ้ำ” ร้านปิดการส่งข้อมูลของส่วนเสริมนี้ ระบบจึงไม่ส่งและไม่ส่งซ้ำ (ครั้งที่ลอง 0 · ภาพ X53)
ext_scope_requiredกุญแจไม่มีสิทธิ์ข้อมูลส่วนเสริมที่ต้องใช้
EXT_IDEMPOTENCY_KEY_REQUIREDสร้างรายการผ่าน API โดยไม่มี Idempotency-Key
EXT_IF_MATCH_REQUIRED · EXT_ETAG_MISMATCHแก้ข้อมูลโดยไม่มีหรือไม่ตรง If-Match

ความสามารถที่ SMEDNA ต้องเปิดให้

Studio และการติดตั้งส่วนเสริม · ส่วนเสริมที่เก็บข้อมูลผูกกับลูกค้า (ข้อมูลส่วนบุคคล) · กฎอัตโนมัติ · การส่งข้อมูลออก (webhook) · Partner API ของส่วนเสริม · หน้าจอของส่วนเสริม · AI ช่วยร่าง
ต้องรอคำตอบทนายก่อนเปิด: ส่วนเสริมสำหรับร้านคลินิก · กฎที่ส่งข้อความหาลูกค้า · เบอร์โทรและอีเมลลูกค้าผ่าน API

ทำไมผมเห็นแค่ยอดรวมของบางร้าน

เพราะร้านนั้นยังไม่ยินยอมให้ส่งข้อมูลออก ดูข้อ X52 และ N05

ตัวเลขในเล่มตรงกับระบบจริงไหม

เป็นข้อมูลสมมติ นับจากฐานข้อมูลของเครื่องทดสอบตอนทำเล่ม ตัวเลขใน “เห็นผล” บอกว่าร้านจะเห็นอะไร ไม่ใช่ผลที่รับประกันกับร้านได้

ใช้ AI ร่างแล้วต้องตรวจไหม

ต้อง ผลของ AI เป็นแค่ข้อเสนอ ผ่านตัวตรวจชุดเดียวกับที่คนทำเอง และ SMEDNA ตรวจอีกชั้นก่อนอนุมัติ