AMNAT AI — ชุดแก้ไขและตรวจหาสาเหตุ 20261108-r2 วันที่ 8 พฤศจิกายน 2569 สถานะที่ยืนยันได้ ตรวจโค้ดจริงจาก ZIP ที่แนบมา: api_chat.php, config.php, profile.php แก้ไขจากไฟล์เดิม ไม่สร้างระบบใหม่ ไม่เปลี่ยนชื่อตาราง/คอลัมน์ คงทุกฟังก์ชันเดิม รวม chat, save_lead_or_order, บัญชีผู้ใช้และ Super Admin ไม่มีการเชื่อมต่อโฮสต์จริง ไม่มีการเรียก Gemini จริง ไม่มีการแก้ฐานข้อมูลใด ต้นเหตุที่ยืนยันจาก Log ล่าสุด ref=a57f7e9b5770b1c8 เวลา 13:31:56 Asia/Bangkok: Call to undefined function str_starts_with() | file=api_chat.php | line=464 จุดนี้ตรวจชื่อโมเดลก่อนส่งคำขอ Gemini จึงหยุดก่อนเรียก API และก่อนหักพอยต์ของคำขอนี้ ยืนยันว่าฟังก์ชันนี้ไม่พร้อมใช้ใน PHP ที่ประมวลผลคำขอ แต่ Log ยังไม่ยืนยัน PHP version อาจเป็น PHP เวอร์ชันเก่าหรือการปิดฟังก์ชัน ต้องอ่าน PHP version/การตั้งค่าจริงเพื่อแยกสาเหตุ แก้ไขรุ่น r2 แทนการเรียก str_starts_with และ str_contains ทั้งหมดใน 3 ไฟล์ด้วย strpos พร้อมเทียบค่าแบบ strict ครอบคลุมการเลือกโมเดล, แปลงเบอร์ +66, ตรวจชนิด API request และตรวจ URL รูปโปรไฟล์ ไม่ต้องเปลี่ยน API Key หรือฐานข้อมูลเพื่อแก้ Error นี้ เพิ่มตัวตรวจ PHP 8+ และสถานะฟังก์ชันเดิมในหน้าตรวจของ Super Admin จำลองการไม่มีฟังก์ชันทั้งสองด้วย disable_functions: ทำซ้ำ Error เดิมได้ก่อนแก้ หลังแก้ ผ่าน PHP Syntax และ regression 32 กรณีในสภาวะเดียวกัน ยังต้องยืนยันการตอบ Gemini บนโฮสต์จริงหลังอัปโหลด เพราะไม่เคยเรียก API จริงในงานนี้ สิ่งที่แก้ 1. config.php: ส่ง status/reply และ success/error คู่กัน เพื่อให้หน้าโปรไฟล์และหน้าจัดการเดิมอ่าน Error ได้ 2. เพิ่มตัวบันทึก Error ส่วนกลาง: รุ่นไฟล์, request ID, ชนิด Exception, ข้อความ, ชื่อไฟล์และบรรทัด ปกปิดค่าคีย์/รหัสผ่านที่ตั้งใน config และข้อความที่อาจมีค่าข้อมูลใน PDO Error ไม่บันทึก request body, ประวัติแชท, provider response body หรือ stack arguments 3. ย้าย exception/fatal handlers ให้ทำงานก่อนเริ่ม Session และตรวจ PDO MySQL ก่อนเชื่อมต่อ 4. Gemini: ใช้ฟิลด์ systemInstruction ตามเอกสาร REST, ตรวจผลตั้งค่า cURL และเก็บ cURL errno/ข้อความ เก็บ HTTP status และ error status enum ของ Google โดยไม่พิมพ์ response body ใช้ x-goog-api-key ใน header, SSL_VERIFYPEER=true, SSL_VERIFYHOST=2, ไม่ตาม redirect คง gemini-2.5-flash และ thinkingBudget=0 ไม่มี retry สร้างคำตอบอัตโนมัติ การเปลี่ยนชื่อฟิลด์ JSON นี้ไม่ได้พิสูจน์ว่ารูป snake_case เดิมเป็นสาเหตุ 5. ยอมรับคำตอบที่ finishReason=STOP และมีข้อความเท่านั้น ไม่หักพอยต์กรณีคำตอบถูกบล็อก, ว่าง, JSON เสีย, HTTP ล้มเหลว, TLS ล้มเหลว หรือ MAX_TOKENS 6. profile.php: แสดง request ID เมื่อผิดพลาด, อ่าน error แบบเดิมได้ ไม่เอาข้อความ fallback ที่ AI ไม่พร้อมใส่เป็นประวัติคำตอบของ Gemini 7. เพิ่ม amnat_diagnostics.php ที่ต้องล็อกอิน Super Admin ก่อน ตรวจ PHP/Session/PDO/schema/cURL/TLS/CA และอ่าน metadata ของโมเดลเมื่อกดปุ่มเท่านั้น ไม่เรียก generateContent และไม่หักพอยต์ ผล metadata ผ่านไม่ได้แปลว่าโควต้าสร้างคำตอบผ่าน พอยต์ คงกติกาเดิม: ได้คำตอบสมบูรณ์และร้าน active จึงใช้ UPDATE แบบมีเงื่อนไขหัก 1 พอยต์ UPDATE ต้องมี points_balance > 0; คำขอแข่งกันไม่ทำให้ค่าติดลบจากคำสั่งนี้ กรณีพอยต์หมดก่อนเริ่มจะไม่เรียก Gemini การบันทึก quick_form/cart_order ไม่เรียก Gemini และไม่หักพอยต์ ข้อจำกัดเดิม: คำขอพร้อมกันอาจเรียก Gemini ไปแล้ว ก่อนคำขอหนึ่งพบว่าพอยต์ถูกใช้อีกคำขอ และยังไม่มี request ledger สำหรับกันการส่งซ้ำหลังอินเทอร์เน็ตหลุด ชุดนี้ไม่ได้เปลี่ยน schema เพื่อเพิ่ม ledger และไม่ได้อ้างว่ารองรับ exactly-once billing ติดตั้ง 1. ดาวน์โหลด ZIP แล้วแตกไฟล์บนคอมพิวเตอร์ของคุณ 2. cPanel > Domains > ai.amnatai.com: ตรวจ Document Root ที่โดเมนนี้ใช้จริง ไม่เดาว่าเป็น public_html และไม่แก้โฟลเดอร์ WordPress 3. สำรอง api_chat.php, config.php, profile.php เดิมนอกโฟลเดอร์เว็บไซต์ ห้ามวางไฟล์ .bak หรือ ZIP ที่มี config.php ไว้ในที่ดาวน์โหลดผ่านเว็บได้ 4. config.php ในชุดนี้คงค่าการเชื่อมต่อ/คีย์/รหัสผ่านจากไฟล์ที่คุณแนบไว้ ถ้าค่าบนเซิร์ฟเวอร์เปลี่ยนหลังส่ง ZIP ให้ปรับค่าในไฟล์ใหม่นี้ให้ตรงก่อนอัปโหลด ไม่ต้องสร้างฐานข้อมูลใหม่หรือ import SQL 5. อัปโหลดแทนไฟล์เดิมทั้ง 3 ไฟล์: config.php, api_chat.php, profile.php อัปโหลด amnat_diagnostics.php เพิ่มในโฟลเดอร์เดียวกัน ไม่ต้องอัปโหลดเอกสารหรือโฟลเดอร์ offline-tests 6. ตั้ง permission ตามโฮสต์ (โดยทั่วไป 0644; ไม่ใช้ 0777) และใช้ PHP 8+ 7. หากโฮสต์เปิด OPcache โดยไม่ตรวจ timestamp ให้ใช้คำสั่งรีสตาร์ต PHP ของโฮสต์ หรือให้ Support รีโหลด PHP/OPcache สำหรับโดเมนนี้ ห้ามสร้างหน้า reset แบบสาธารณะ 8. Ctrl+F5 หน้าโปรไฟล์เดิมพร้อม ?u=slug ของร้านที่ใช้งานจริง ตรวจโดยยังไม่สร้างคำตอบเสียเงิน 1. ล็อกอิน https://ai.amnatai.com/super_admin.php 2. เปิด https://ai.amnatai.com/amnat_diagnostics.php ในเบราว์เซอร์เดียวกัน 3. ตรวจ build=20261108-r2 และรายการ PHP, PDO MySQL, cURL, JSON, Session, schema 4. กดปุ่มตรวจ DNS/SSL/API Key/Model หนึ่งครั้ง เป็น models.get metadata เท่านั้น ไม่ใช่การ generate คำตอบ HTTP 200 + generateContent supported=yes ยืนยันเฉพาะการอ่าน metadata และ transport 5. ถ้า cURL 60 ให้ Hosting ตรวจ CA bundle/เวลาระบบ ห้ามปิด SSL Verification cURL 6/7 ให้ตรวจ DNS/outbound HTTPS port 443; 28 คือ timeout HTTP 400/401/403 ตรวจ API Key และข้อจำกัดสิทธิ์; 404 ตรวจโมเดล; 429 ตรวจโควต้า 6. ถ้าหน้าตรวจขึ้น Error ก่อนแสดงตาราง ดู error_log ของโดเมนเดียวกัน ตรวจว่า Session/PDO extension ถูกเปิดสำหรับ PHP เวอร์ชันของเว็บไซต์ ไม่ใช่เฉพาะ CLI ยืนยันการสนทนาจริงหลังตรวจผ่าน ขั้นตอนนี้จะใช้ API จริง จึงทำเพียงหนึ่งข้อความที่ใช้งานได้ เช่น ถามสินค้าของร้าน 1. จด points_balance ของร้านจากหลังบ้านก่อนส่ง 2. ส่งข้อความหนึ่งครั้งจาก profile.php?u=slug จริง 3. ตรวจว่าเป็นคำตอบเกี่ยวกับร้าน ไม่ใช่ข้อความ fallback และพอยต์ลด 1 4. ถ้าล้มเหลว ให้เก็บข้อความ [ref: ...] กับ error_log บรรทัดที่มี ref เดียวกัน ตัวอย่างโครงสร้าง: [AMNAT AI build=20261108-r2 ref=...] Chat unexpected error | type=Error | message=... | file=... | line=... หรือ Gemini HTTP=... status=... model=... 5. ส่งบรรทัดนี้และผลหน้าตรวจกลับมาเพื่อแก้ตรงตำแหน่ง ห้ามส่ง API Key/รหัสผ่าน 6. ลบ amnat_diagnostics.php หลังตรวจเสร็จ ถ้ายังได้ Log แบบเดิมที่ไม่มี build/ref ให้ตรวจ Document Root, เวลา Log และ OPcache ก่อนทดลอง API ซ้ำ ผลตรวจในสภาพแวดล้อมนี้ - PHP 8.3.6: php -l ผ่านทั้ง 4 ไฟล์ - JavaScript ของ profile.php: node --check ผ่าน (แทนส่วน PHP ที่แทรกข้อมูลด้วย fixture) - Offline regression 32 กรณีผ่าน ใช้ฟังก์ชันจริงจากไฟล์ส่งมอบ แต่จำลอง PDO/cURL - ทดสอบเต็ม endpoint ขณะไม่มี PDO driver: ส่ง JSON error ที่ตรงกับ frontend ได้ - ตรวจชื่อฟังก์ชันก่อน/หลัง: ไม่มีฟังก์ชันเดิมถูกลบ - UTF-8 ไม่มี BOM ทั้ง 4 ไฟล์ - ยังไม่ได้ทดสอบ MySQL จริง, concurrent requests จริง, browser UI/เสียงจริง, cPanel Session จริง, DNS/CA ของโฮสต์, API Key/สิทธิ์/โควต้า Gemini จริง - ได้รับภาพ error_log ที่ระบุข้อผิดพลาดนี้ชัดเจน แต่ไม่มีสิทธิ์เข้า cPanel ในการทำงานครั้งนี้ เอกสารอ้างอิงที่ตรวจรูปแบบ REST https://ai.google.dev/api/generate-content https://ai.google.dev/gemini-api/docs/thinking คำเตือนเฉพาะไฟล์นี้: ZIP มี config.php พร้อมค่าความลับที่คุณส่งมา ให้เก็บส่วนตัวและไม่เผยแพร่