6 คะแนน โดย GN⁺ 2025-08-16 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เพื่อแก้ปัญหาการใช้งานที่ช้าและขั้นตอนการเข้าใช้งานที่ยุ่งยากของแอป PureGym ผู้เขียนจึงปรับแต่งให้เหมาะกับ Apple Wallet เป็นการส่วนตัว
  • เดิมที QR code ต้องเปิดแอปและรอโหลดข้อมูลทุกครั้ง เป็นวิธีเข้าใช้งานที่ไม่มีประสิทธิภาพและใช้เวลาราว 47 วินาที
  • ผู้เขียนสร้าง Wallet pass ที่ต่ออายุอัตโนมัติได้ ผ่านกระบวนการทางเทคนิคต่างๆ เช่น reverse engineering, การใช้ mitmproxy และเฟรมเวิร์ก PassKit
  • ระหว่างทางยังพบการทำงานภายในของ PureGym ที่เปิดเผยอยู่บนเว็บ เช่น ช่องโหว่ด้านความปลอดภัยของรหัส PIN, โครงสร้างการยืนยันตัวตนของ API และข้อมูลตำแหน่งสาขา
  • ท้ายที่สุดจึงสร้างประสบการณ์ผู้ใช้ที่ เข้าได้ภายใน 3 วินาที และย้ำชัดว่าเป็นเพียงการทดลองส่วนตัว ไม่ใช่บริการทางการ

47 วินาที: จุดเริ่มต้นของความไม่สะดวก

  • เวลา 11:15 น. ของวันธรรมดา การเปิดแอปที่หน้าทางเข้า PureGym ใช้เวลาถึง 47 วินาที
  • สัญญาณอ่อน ต้องเชื่อมต่อ Wi-Fi เปิดแอป และกดข้ามการแจ้งเตือนต่างๆ รวมถึงข้อเสนอส่วนลดพิเศษ กว่า QR code จะปรากฏ
  • ต้องรอนานกว่าจะเห็น QR code จริงๆ และทำให้รู้สึกเกรงใจสมาชิกคนอื่นที่รออยู่
  • หากเกิดขึ้นสัปดาห์ละ 6 ครั้ง จะเสียเวลาไป 282 วินาทีต่อสัปดาห์กับประสบการณ์ที่ไม่มีประสิทธิภาพ
  • เมื่อเทียบกับประสบการณ์แบบแทบไม่ต้องหยิบอะไรขึ้นมาใช้ของ Amazon Fresh แล้ว UX การเข้าใช้งานของ PureGym ถือว่าล้าหลังมาก

ปริศนาของ PIN อายุ 8 ปี

  • ผู้เขียนใช้ รหัส PIN 8 หลัก เดิมมานาน 8 ปี
  • PIN นี้ไม่เคยหมดอายุและไม่เคยถูกเปลี่ยน
  • ในทางกลับกัน QR code ในแอป จะถูกเปลี่ยนเป็นค่าใหม่ทุก 1 นาที
  • จึงเกิดความขัดแย้งอย่างมากระหว่างระดับความปลอดภัยที่แท้จริงกับการนำไปใช้จริง
  • วิธีแบบ PIN ถูกปล่อยให้ใช้ได้นานผิดปกติ แต่ QR code กลับถูกปกป้องอย่างเข้มงวด เป็นสภาวะของ "การแสดงความปลอดภัย"

ทำความเข้าใจ PureGym ด้วย mitmproxy

  • ตอนแรกผู้เขียนพยายามนำภาพหน้าจอ QR code ไปใส่ใน Apple Wallet แต่ใช้งานไม่ได้ทันที
  • QR code ของ PureGym ถูกสร้างแบบไดนามิก หมดอายุราว 1 สัปดาห์ แต่ในแอปจะรีเฟรชทุก 1 นาที
  • จากการค้นหาเรโปที่เกี่ยวกับ "PureGym" บน GitHub ทำให้พบโครงสร้างการยืนยันตัวตนของ API
    • PIN 8 หลักสำหรับล็อกอินถูกใช้เป็นรหัสผ่าน API เช่นกัน
    • ข้อมูล basic auth ที่เข้ารหัสด้วย Base64 ก็มีความปลอดภัยต่ำ
  • เพื่อวิเคราะห์ทราฟฟิกของแอป ผู้เขียนจึงดักจับคำขอด้วยเครื่องมือพร็อกซีอย่าง mitmproxy
    • โครงสร้าง JSON ของ QR code ประกอบด้วย part1 (id คงที่), part2 (timestamp), part3 (salt สำหรับรีเฟรช)
    • API ยังบอกทั้งจังหวะการรีเฟรชและเงื่อนไขการหมดอายุไว้อย่างครบถ้วน

PassKit: ศักยภาพของ Apple Wallet

  • pass ของ Apple Wallet ไม่ใช่แค่การ์ดแบบคงที่ แต่เป็นโครงสร้างคล้ายมินิแอปที่รองรับการรีเฟรชเอง การแจ้งเตือนแบบพุช และการตอบสนองตามตำแหน่ง
  • การทำ PassKit ต้องมีทั้งสเปก JSON, ทรัพยากรรูปภาพ, การลงลายมือชื่อด้วยใบรับรอง และเว็บเซอร์วิสสำหรับการอัปเดตแบบเรียลไทม์
  • จำเป็นต้องออก Pass Type ID และใบรับรอง WWDR จากพอร์ทัลนักพัฒนาของ Apple
  • แม้การลงลายมือชื่อและการจัดการใบรับรองจะยุ่งยาก แต่เมื่อทำสำเร็จแล้วจะมอบประสบการณ์ที่ลื่นไหลบนอุปกรณ์จริง

สร้างแบ็กเอนด์ด้วย Swift

  • แม้โดยทั่วไปจะใช้ Node.js แต่ผู้เขียนเลือกพัฒนาเว็บเซอร์วิส PassKit ด้วย Vapor ที่ใช้ Swift
    • เมื่อ pass ต้องอัปเดต ระบบจะส่ง silent push เพื่ออัปเดตให้อัตโนมัติ
    • ทำให้เกิดการรีเฟรช pass อย่างเป็นธรรมชาติโดยที่ผู้ใช้แทบไม่สังเกตเห็น

ทำระบบตำแหน่งของ PureGym ทั่วประเทศแบบอัตโนมัติ

  • pass ของ Apple Wallet สามารถแสดงขึ้นมาอัตโนมัติเมื่ออยู่ในตำแหน่งที่กำหนด
  • แม้เว็บไซต์ทางการของ PureGym จะไม่มีพิกัดละเอียด แต่ API ให้รายการพิกัดของทุกสาขาทั่วประเทศมาได้
  • ผู้เขียนจึงพาร์สพิกัดของทุกสาขาและกำหนดสาขาใกล้เคียงให้กับแต่ละ pass
  • ข้อเสียคือถ้า PureGym อยู่ในศูนย์การค้า pass ก็อาจเด้งขึ้นมาแม้จะแค่มาช้อปปิ้ง เป็นความรำคาญเล็กน้อย

การเชื่อมต่อกับ Apple Watch

  • pass ของ Apple Wallet ซิงก์ไปยัง Apple Watch โดยอัตโนมัติโดยไม่ต้องตั้งค่าเพิ่ม
  • แค่กดสองครั้งที่ข้อมือแล้วสแกน ใช้เวลาเพียง 3 วินาที จนเข้ายิมได้
  • ลดเวลาได้มากกว่า 93%

การเปลี่ยนแปลงในรูปตัวเลข

  • เวลาเข้าใช้งานผ่านแอป PureGym เดิม: 47 วินาที
  • เวลาเข้าใช้งานผ่าน Apple Wallet pass: 3 วินาที
  • เวลาเฉลี่ยที่ประหยัดได้ต่อสัปดาห์: 4.4 นาที (3.8 ชั่วโมงต่อปี)
  • สมาชิกข้างๆ ถามว่า "มีแอปแบบนี้ด้วยเหรอ" 23 ครั้ง และผู้เขียนก็อธิบายทุกครั้งว่าไม่เป็นทางการ
  • แม้จะมีคนขอ แต่ไม่มีแผนเผยแพร่เนื่องจากข้อจำกัดด้านลิขสิทธิ์และนโยบายบริการ

โบนัส: เชื่อมต่อกับ Home Assistant

  • ใช้ endpoint ของ API สำหรับ จำนวนคนภายในยิม เพื่อแสดงความหนาแน่นปัจจุบันของยิมบนแดชบอร์ด IoT
  • ช่วยตัดสินใจได้ว่าจะกลับมาในช่วงเวลาที่คนน้อยกว่าโดยอิงจากข้อมูล เพิ่มทั้งประสิทธิภาพและแรงจูงใจในการออกกำลังกาย

ความจริงและจริยธรรมของงานวิศวกรรม

  • แม้จะเริ่มจากการแก้ปัญหาความไม่สะดวกส่วนตัวล้วนๆ แต่ก็เป็นจุดที่ PureGym ไม่ได้ปรับปรุงมาหลายปี
  • บางครั้งต้นแบบที่สร้างจากภายนอกองค์กรก็แก้ปัญหาได้เร็วกว่าที่อยู่ในโรดแมปทางการ
  • อย่างไรก็ตาม ในทางการแล้วสิ่งนี้อาจขัดต่อข้อกำหนดการใช้งาน และ PureGym สามารถบล็อกได้ทุกเมื่อ
  • ผู้เขียนไม่ทำระบบอัตโนมัติหรือแชร์ต่อโดยเด็ดขาด ใช้เพื่อการทดลองส่วนตัวเท่านั้น และยึดหลักอย่างการแคชเพื่อความเสถียร

ขั้นต่อไปและบทสรุป

  • ต่อไปอาจมีการเสนอไอเดียขยายผล เช่น "การแจ้งเตือนความอับอาย"
  • แม้ประโยชน์เชิงรูปธรรมจะไม่ใหญ่มาก แต่ผู้เขียนก็พอใจกับการปรับลด "ขั้นตอนที่ไม่จำเป็น" ได้ปีละ 3.8 ชั่วโมง
  • หาก PureGym นำไปทำเป็นฟีเจอร์ทางการ ก็อาจช่วยอำนวยความสะดวกให้ผู้ใช้ได้มากขึ้น
  • จึงเป็นกรณีตัวอย่างของการสร้าง "ประสบการณ์ที่ไม่เป็นทางการแต่ได้ผล"

1 ความคิดเห็น

 
GN⁺ 2025-08-16
ความคิดเห็นบน Hacker News
  • คิดว่าเป็นบทความที่สนุกและสร้างแรงบันดาลใจมาก ถ่ายทอดแก่นแท้ของความเป็นวิศวกรได้ดี และทำให้เห็นว่า OP เป็นแฮ็กเกอร์ตัวจริง
    ตอนที่อยู่สหรัฐฯ 3 เดือน เคยสมัคร PureGym แล้วได้รับ PIN จากนั้นก็ยกเลิกสมาชิกไป แต่ภายหลัง Chrome แจ้งว่า PureGym PIN รั่วไหล
    2 ปีต่อมากลับไปสหรัฐฯ อีกครั้งแล้วได้ PIN เดิม จึงคิดว่านี่เป็นปัญหาด้านความปลอดภัยที่ร้ายแรงมาก
    แอปและโทเค็นของ PureGym ก็น่าสนใจเหมือนกัน และยังพบช่องโหว่ด้านความปลอดภัยในระบบเปิดใช้งานเก้าอี้ไฮโดรนวดด้วย ซึ่งถูกออกแบบมาให้รับ PIN อะไรก็ได้
    • การที่ Chrome แจ้งว่า PureGym PIN รั่วไหลน่าจะเป็น false positive เพราะเรื่องแบบนี้เกิดขึ้นได้เวลาที่ Chrome ใช้ HaveIBeenPwned API
      ตัวอย่างเช่น PIN อย่าง 87623103 จะถูกแฮชเป็น 558B4C37F6E3FF9A5E1115C66CEF0703E3F2ADEE และเมื่อค้นหาในช่วงแฮชของ HaveIBeenPwned ก็จะพบว่ามีประวัติรั่วไหลจริงหลายครั้ง
  • เป็นเรื่องที่ควรหยุดคิดสักนิดว่า แป้นพิมพ์กดจริงที่ตั้งอยู่นอกอาคารนั้นถูกปกคลุมด้วยสภาพอากาศแบบอังกฤษ โปรตีนเชก และความเสียใจ แถมยังอาจถูกถ่ายทอดสดลง TikTok ผ่าน Ring doorbell ของบ้านใครสักคนได้ด้วย แต่กลับยังยอมรับ PIN เก่าของฉันได้แบบไม่มีปัญหา ขณะที่ QR code แบบดิจิทัลกลับต้องใช้การหมุนเวียนการเข้ารหัสที่ซับซ้อนจนแม้แต่ NSA ยังต้องทึ่ง
  • ชอบอ่านเรื่องแบบนี้มาก แทนที่จะรอให้แอปทำงานได้ถูกต้อง ก็จำ PIN เองไปเลย เลยเข้าได้เร็วกว่าแนวทางที่ OP เสนอเสียอีก และยังสะดวกกว่าเพราะไม่ต้องใช้เครื่องมือหรือบริการแยกต่างหาก
  • ตอนเห็นบทความที่บอกว่า “มีเหตุผลที่เขาไม่ทำ Apple Wallet” ถ้าดูจากภาพหน้าจอของแอป PureGym แล้ว ดูเหมือนมันแทบจะเป็นแค่ mobile website ที่ห่อบาง ๆ ไว้ หรือไม่ก็ใช้เทคโนโลยีอย่าง Flutter โอกาสที่จะมีนักพัฒนาภายในบริษัทที่จัดการรายละเอียดจุกจิกของ Apple API ได้ครบถ้วนนั้นดูน้อยมาก
    • นี่แหละประเด็นสำคัญ PureGym มีธุรกิจหลักคือรับคนสมัครบริการให้ได้มากที่สุดและทำให้ยกเลิกได้ยาก ไม่ใช่การพัฒนา ถ้าโชคดีก็อาจมี web developer ภายในที่พอประคองเว็บไซต์กับฐานข้อมูลไว้ได้ แล้วจ้างคนนอกให้ทำให้มันดูเหมือนแอป ถ้าโชคร้ายก็อาจเอางานเว็บทั้งหมดไปจ้างเอเจนซีภายนอกจนแม้แต่จะเปลี่ยนตัวอักษรในหัวข้อหนึ่งตัวก็ยังต้องจ่ายเพิ่ม
    • แต่ก็อดสงสัยไม่ได้ว่าทำไมถึงไม่เรียนรู้ ทั้งที่มีเครื่องมืออย่าง Google, Stack Overflow, LLM มากมาย แต่ก็ยังไม่ดีขึ้น คิดว่าน่าจะเป็นเพราะไม่มีใครสนใจ UX เลย หรือไม่ก็ทีม backend ออกไปกันหมดนานแล้ว เหลือแค่ทีมเล็ก ๆ ที่ใช้วิศวกรราคาถูกคอยประคองระบบขั้นต่ำสุด
    • ถ้าจะเพิ่ม Apple Wallet ก็ต้องรองรับ Android Wallet ด้วย ดังนั้นโค้ดที่ต้องดูแลก็จะเพิ่มขึ้น ถึงอย่างนั้นอย่างน้อยก็น่าจะทำให้แอปแสดง QR code ทันทีเมื่อเปิดแอปได้
    • ฉันก็มีแอป PureGym อยู่ในมือถือเหมือนกัน และมันก็ให้ความรู้สึกเหมือนเป็นแอปที่แค่ห่อเว็บไซต์ PureGym เอาไว้จริง ๆ
  • คำพูดนี้จริงยิ่งกว่าทอง 8 หลักของ PIN ประตูยิมก็คือรหัสผ่าน API และผู้ใช้ส่วนใหญ่ไม่ได้เป็นคนตั้งเองด้วยซ้ำ หวังว่าคงมี rate limiting สำหรับการลองผิด และดูเหมือนแค่รู้ที่อยู่อีเมลก็เข้าถึง API ได้ทันทีแล้ว อีกอย่างก็สงสัยว่าขอบเขตสิทธิ์ที่ร้องขอได้นั้นถูกจำกัดไว้อย่างเหมาะสมหรือไม่
    • OP เอง
      ถ้าถามว่าเข้าถึง API ได้ทันทีไหม คำตอบคือใช่ และจากที่ใช้ทั้งแอปและเว็บไซต์จริงก็ยังไม่เคยติด rate limit เลย มันค่อนข้างใจกว้างกับการลองผิด
      scope ที่กล่าวถึงในโพสต์เป็นตัวเดียวกับที่แอปทางการและไคลเอนต์ไม่เป็นทางการบน GitHub ใช้
      ความเป็นไปได้ที่จะมี scope เพิ่มเติมนั้นต่ำมาก ดูPureGym PHP Wrapperและ PureGym Attendance Pythonประกอบได้
  • เจอการคุยเรื่อง roadmap ของแอปแบบ PureGym นี้บ่อยมากในวงการ IT
    ประมาณว่า “ถ้าสร้างฟีเจอร์นี้ เราก็ต้องรับผิดชอบมันเองนะ”
    และก็มักมีมุกว่า “จริง งั้นใส่ไว้ใน roadmap ปี 2028 แล้วกัน”
    • ในประชุมของแผนกฉันก็เหมือนกัน เวลาคุยเรื่อง roadmap กับแผนงาน ประเด็นหลักคือ “สิ่งนี้ช่วยรายได้เราไหม หรือเป็นงานที่มีแต่ค่าใช้จ่าย”
      งานเดิมกับ wishlist ก็ยาวอยู่แล้ว เลยไม่ค่อยมีการเพิ่มฟีเจอร์ใหม่
      คิดว่าสิ่งที่ PureGym ควรทำที่สุดตอนนี้คือให้เงินนักพัฒนาที่ทำแอปนี้สักหลายพันปอนด์ พร้อมสมาชิกใช้ฟรีตลอดชีพ
  • สงสัยว่าค่าใบรับรอง Pass Type ID ที่ออกจาก Apple Developer Portal มีราคาเท่าไร
    อยากสร้าง pass สำหรับ Apple Wallet แต่รู้สึกว่าการตั้งค่าบัญชีนักพัฒนาและค่าใช้จ่ายเพิ่มเติมเป็นภาระ
    • เท่าที่รู้รวมอยู่ในค่าสมาชิกนักพัฒนาพื้นฐานแล้ว เพียงแต่ต้องต่ออายุสมาชิกนักพัฒนาทุกปีเพื่อให้ใช้งานต่อได้
  • ถ้ามี push notification เด้งมาทุกนาทีเพื่อรับโค้ดใหม่ จะไม่กระทบแบตเตอรี่หรือ
    • ถ้าอ่านจากบทความหลัก การรีเฟรชโค้ดเกิดขึ้นสัปดาห์ละครั้ง จึงคาดว่าสูงสุดก็น่าจะสัปดาห์ละครั้ง
    • push notification มีสิ่งที่เรียกว่า background mode อยู่แล้ว จึงจะถูกประมวลผลเมื่อโทรศัพท์พร้อมเท่านั้น
      ถ้าแบตใกล้หมดหรืออยู่ในโหมดประหยัดพลังงาน มันอาจไม่ถูกส่งเลย ซึ่งเป็นโครงสร้างที่ออกแบบมาเพื่อลดการใช้แบตเตอรี่ให้น้อยที่สุด
      ส่วนการแจ้งเตือนที่สำคัญกว่านั้นต้องมีองค์ประกอบ UI แสดงแน่นอน และจะมาถึงโดยไม่ขึ้นกับสถานะประหยัดพลังงาน
  • เป็นบทความที่สนุกและเต็มไปด้วยรายละเอียดทางเทคนิค อ่านเพลินมาก