14 ความเจ็บปวดของการสร้างระบบชำระเงินเอง
(arnon.dk)- ระบบชำระเงินและระบบรายได้เป็นสิ่งจำเป็นสำหรับการสร้างรายได้ แต่เป็น ระบบหลักที่ซับซ้อน ซึ่งเกี่ยวข้องตั้งแต่การเงิน ผลิตภัณฑ์ ซัพพอร์ตลูกค้า กฎหมาย คอมพลายแอนซ์ ไปจนถึงฝ่ายขาย ทำให้ความขัดข้องเล็กน้อยอาจลุกลามเป็นปัญหาการดำเนินงานใหญ่ได้
- บริษัทระยะเริ่มต้นหรือทีมผลิตภัณฑ์ใหม่มักมองการชำระเงินเป็นเพียง ปัญหาทางวิศวกรรม และมีแนวโน้มจะสร้างเองได้ง่าย แต่ตัวเลือกจริงแบ่งเป็นสร้างเอง ใช้ third-party หรือแบบไฮบริด
- ระบบชำระเงินจริงต้องจัดการ idempotency, การจัดการวันที่, การวัดปริมาณการใช้งาน, ภาษี, การคืนเงิน, ลำดับชั้นของลูกค้า, สัญญาเฉพาะ, การเปลี่ยนราคา และ การรับรู้รายได้ ไปพร้อมกัน
- ปัญหาบางอย่างแก้ครั้งเดียวแล้วเสถียรได้ แต่กฎภาษี ความผิดพลาดของลูกค้า การแก้ไขด้วยมือ และข้อกำหนดใบแจ้งหนี้รายประเทศจะขยายตัวต่อเนื่องตามการเติบโตและการขยายไปต่างประเทศ
- ควรมุ่งเน้นที่การอัปเดตการใช้งานที่เป็นเอกลักษณ์ของผลิตภัณฑ์และเหตุการณ์ในวงจรชีวิตลูกค้า แล้วปล่อยให้ระบบ subscription, billing, accounting และ revenue recognition อยู่กับ ระบบชำระเงินสำเร็จรูปและ ERP ให้มากที่สุดจะปลอดภัยกว่า
ทำไมการชำระเงินจึงไม่ใช่แค่ฟีเจอร์ธรรมดา
- ระบบชำระเงินและระบบรายได้เป็นสิ่งที่ธุรกิจจำเป็นต้องมีเพื่อทำรายได้
- เมื่อทำงานปกติจะไม่ค่อยสะดุดตา แต่จริง ๆ แล้วเป็น ระบบเหมือนหนวดปลาหมึก ที่แตะหลายองค์กรและหลายฟังก์ชันพร้อมกัน
- การเงิน
- ผลิตภัณฑ์
- ประสบการณ์ผู้ใช้
- ซัพพอร์ตลูกค้า
- ลูกค้า
- กฎหมาย
- คอมพลายแอนซ์
- ฝ่ายขาย
- หากส่วนหนึ่งพัง ปัญหาอาจขยายไปยังพื้นที่ที่เชื่อมโยงกันได้อย่างรวดเร็ว และในความเป็นจริงก็พังบ่อย
- หากไม่สามารถเก็บรายได้อย่างถูกต้องและถูกกฎหมาย ปัญหาที่ผู้ดำเนินธุรกิจต้องรับมือจะเพิ่มขึ้นอย่างมาก
รูปแบบการสร้าง 3 แบบ
- โดยทั่วไป ระบบชำระเงินมีแนวทาง 3 แบบ
- สร้างเอง
- ใช้ระบบ third-party เต็มรูปแบบ
- ไฮบริดที่ผสมการสร้างเองกับ third-party
- บริษัทระยะเริ่มต้นหรือทีมที่เริ่มผลิตภัณฑ์ใหม่มักมีแนวโน้มจะสร้างเอง เพราะมีวิศวกรและอยากคงความเรียบง่ายไว้
- หากมองการชำระเงินเหมือน “แค่เอาไฟล์ billing ไปวางไว้ใน S3 แล้วให้ CRON job ดึงไปชำระเงิน” ก็จะ เข้าใจผิดว่าการชำระเงินเป็นปัญหาทางวิศวกรรมเท่านั้น
- เช่นเดียวกับที่เราไม่ควรสร้างระบบความปลอดภัยหรือการจัดการวันที่เองทั้งหมด การชำระเงินก็ไม่ควรสร้างเองทั้งหมดตั้งแต่แรก
- ระบบชำระเงินที่ดีที่สุดคือระบบที่ไม่จำเป็นต้องสร้างเองทั้งหมด
14 ความเจ็บปวดของระบบชำระเงินที่สร้างเอง
-
Idempotency
- คำขอเรียกเก็บเงินและเก็บเงินทุกครั้งต้องมีเอกลักษณ์และเป็น idempotent
- ปัญหานี้จะปรากฏเมื่อ retry เพราะข้อจำกัดของ API หรือเมื่อเพิ่มจำนวน instance ของระบบชำระเงิน
- หากจัดการไม่ถูกต้อง จะเกิดความเสี่ยง เรียกเก็บเงินซ้ำ
-
การจัดการวันที่
- ต้องตัดสินใจว่าจะเรียกเก็บเงินทุก 30 วัน หรือเรียกเก็บตามวันสมัครของแต่ละเดือน
- ต้องจัดการเงื่อนไขอย่าง leap day และ time zone ไปด้วย
-
การคิดตามสัดส่วนและส่วนที่เหลือ
- ต้องตัดสินใจว่าจะคิดตามสัดส่วนเฉพาะตอนอัปเกรด หรือใช้กับการดาวน์เกรดด้วย
- มีตัวเลือกอย่างการคืนเงิน เครดิต การเพิกเฉย หรือการบล็อกการอัปเกรด/ดาวน์เกรด
-
การวัดปริมาณการใช้งาน
- วิธีคำนวณการใช้งานอาจมีได้หลายสิบแบบ
- อาจแตกต่างกันตามประเภทลูกค้า หรือเปลี่ยนบ่อย
-
รูปแบบใบแจ้งหนี้
- หากดำเนินงานในประเทศเดียวอาจดูง่าย
- เมื่อขยายตัว ต้องจัดการไม่เพียง sales tax แต่รวมถึง VAT, GST และค่าธรรมเนียมเพิ่มเติมตามประเทศด้วย
- อาจต้องมี template แยกตามตลาด
ความซับซ้อนที่เพิ่มขึ้นใน B2B และการขยายทั่วโลก
-
ลำดับชั้นลูกค้าที่ซับซ้อน
- โดยเฉพาะลูกค้า B2B อาจมีบริษัทย่อยและพาร์ตเนอร์ และต้องการจัดการความสัมพันธ์ด้านการเรียกเก็บเงิน
- ต้องมีวิธีรวมการใช้งานไปยังผู้จ่ายเงินจริง
- ความต้องการเหล่านี้มักปรากฏหลังจากเติบโตและขยายแล้ว
- หากนิติบุคคลของลูกค้าหรือสถานที่ใช้งานต่างกัน ภาษีก็อาจต่างกัน
- ตามกฎหมายอาจต้องแยก bill และ invoice ออกจากกัน
- กฎที่เกี่ยวข้องอาจเปลี่ยนทุกไม่กี่เดือน
-
การเก็บเงินและการป้องกันการเลิกใช้
- ต้องกำหนดว่าจะเลิก retry การชำระเงินเมื่อใด
- หากเกิด chargeback ต้องตัดสินใจว่าจะปิดบัญชี ระงับบัญชี หรือคืนเงิน
-
การหยุดชั่วคราวและกลับมาใช้งาน
- เมื่อลูกค้าหยุด subscription ชั่วคราว ต้องกำหนดว่าจะอนุญาตสิทธิ์เข้าถึงในระดับใด
-
เครดิตและการคืนเงิน
- หากคืนเงินเต็มจำนวนเท่านั้นจะค่อนข้างเรียบง่าย
- หากเกิดข้อผิดพลาดบางส่วน อาจต้องเลือกคืนเงินบางส่วนหรือให้ store credit
- ต้องตัดสินใจแยกต่างหากด้วยว่าเครดิตมีวันหมดอายุหรือไม่
ภาษี สัญญา และความผิดพลาดของคน
-
การจัดการภาษี
- แค่การที่รายการต่างกันใช้อัตราภาษีต่างกันก็ซับซ้อนแล้ว
- ในระดับทั่วโลก อัตราภาษีและกฎภาษีเปลี่ยนแปลงบ่อย
-
สัญญาเฉพาะ
- หากทำเฉพาะ PLG อาจไม่ใช่ปัญหา
- เมื่อเริ่มทำสัญญา จะเกิดข้อยกเว้นและเงื่อนไขพิเศษอย่างรวดเร็ว ซึ่งตั้งค่าด้วยสมมติฐานเดิมได้ไม่ง่าย
-
ความผิดพลาดของคน
- ลูกค้าย่อมทำผิดพลาด และต้องมีการแก้ไขตามมา
- ภายในบริษัทเองก็อาจตั้งค่าลูกค้าผิด และต้องแก้ไขภายหลัง
- การออกเครดิตและออกใบแจ้งหนี้ใหม่ เป็นงานที่ใช้เวลามาก
- กรณีที่ข้อมูลทางกฎหมายของลูกค้าเปลี่ยนก็ต้องรองรับด้วย
- ที่อยู่
- VAT ID เป็นต้น
-
การเปลี่ยนราคาแบบเลือกกลุ่ม
- การเปลี่ยนราคามักไม่ได้มีผลกับลูกค้าทุกคน
- เมื่อใช้เฉพาะกับลูกค้าใหม่ ต้องรักษาเวอร์ชันราคาที่แตกต่างกันไว้เพื่อคงสัญญาเดิม
-
การรับรู้รายได้และรายได้ค้างรับ
- กฎการรับรู้รายได้ตาม IFRS-15 มี เอกสาร PDF 64 หน้า
- หากทำ ERP integration แบบเฉพาะเองด้วย ความซับซ้อนจะยิ่งเพิ่มขึ้น
ปัญหาที่จบในครั้งเดียวกับปัญหาที่ขยายต่อเนื่อง
- ปัญหาบางอย่างเปลี่ยนบ่อยกว่าที่คาดมาก ส่วนบางปัญหาเมื่อจัดการครั้งเดียวแล้วแทบไม่ต้องแตะอีก
- Idempotency เป็นตัวอย่างของปัญหาทางวิศวกรรมที่เมื่อแก้แล้วก็แทบไม่ต้องกลับไปยุ่งอีก
- กฎภาษีเปลี่ยนบ่อยทั่วโลก
- ยิ่งขยายไปหลายประเทศมากขึ้น กฎหมายภาษีที่ต้องติดตามก็ยิ่งเพิ่มขึ้น
- ความผิดพลาดของลูกค้าเกิดขึ้นค่อนข้างสม่ำเสมอ
- ยิ่งเติบโต ขนาดของปัญหาก็ยิ่งใหญ่ขึ้น
- ต้องใช้ซัพพอร์ตลูกค้าและการแก้ไขด้วยมือมากขึ้น
- ตอนแรกการชำระเงินดูเหมือนเป็นปัญหาทางวิศวกรรม แต่จริง ๆ แล้วหยั่งรากอยู่ใน พื้นที่ปัญหาที่ซับซ้อน ซึ่งแม้แต่คนมีประสบการณ์ในอุตสาหกรรมก็ยังเข้าใจได้ยาก
พื้นที่ที่ไม่จำเป็นต้องสร้างเอง
- ควรส่งต่อปัญหาด้านการชำระเงินให้ระบบภายนอกมากที่สุดเท่าที่ทำได้
- แนะนำแนวทางซื้อโซลูชันสำเร็จรูปให้มากที่สุด
- ส่วนใหญ่ของงาน subscription และ billing ระบบชำระเงินสามารถจัดการได้
- การรับรู้รายได้และบัญชีควรปล่อยให้เป็นหน้าที่ของฟีเจอร์ที่มีอยู่แล้วใน ERP หรือระบบอื่นที่ใช้อยู่
- ทีมผลิตภัณฑ์ควรโฟกัสเฉพาะส่วนที่เป็นเอกลักษณ์ของผลิตภัณฑ์ เช่น การอัปเดตการใช้งาน และเหตุการณ์พื้นฐานในวงจรชีวิตลูกค้า
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เป็นบทความที่ดีสำหรับคนที่ต้องตัดสินใจเรื่อง billing แต่ยังมีประสบการณ์ไม่มาก และก็มีประโยชน์เป็นข้อมูลอ้างอิงสำหรับคนที่มีประสบการณ์ด้วย
แต่ประโยคที่ว่า “จะโยนไฟล์สำหรับ billing ไว้ใน S3 แล้วให้ CRON job มาเก็บ payment ไม่ได้เหรอ?” ทำให้ผมหัวเราะดังมาก ในมุมวิศวกรแล้วมันไม่ใช่ความคิดที่ดีในสถานการณ์ไหนเลย
แนวทางตัดสินใจเรื่อง สถาปัตยกรรม billing ที่ผมชอบคือแยก billing ออกจาก entitlement ให้มากที่สุด ถ้าเป็นการสมัครสมาชิกแบบชำระล่วงหน้า ก็ควรเก็บไว้ใน entitlement แค่วันหมดอายุและรายละเอียดสิทธิ์ที่ได้รับระหว่างช่วงเวลาที่ active ส่วนระบบ billing ก็เก็บ subscription แล้วค่อยซิงก์ไปฝั่ง entitlement เมื่อต้องใช้ วิธีนี้ทำให้จัดการ billing แบบ manual, ดีบักหรือแพตช์ปัญหาชั่วคราว, หรือเชื่อมต่อกับ Stripe ได้ง่ายขึ้น
แน่นอนว่าต้องเผื่อการขยายในอนาคตไว้ แต่การตัดสินใจนี้โดยตัวมันเองไม่ได้จำกัดระบบมากนัก มันไม่ใช่ไอเดียต้นฉบับของผม แต่ยิ่งชอบมากขึ้นหลังจากเคยลองวิธีอื่นที่สำเร็จน้อยกว่า
ปัญหาจำนวนมากเกิดจากความต่างระหว่าง payment กับ billing https://www.wingback.com/blog/saas-payment-vs-saas-billing ตอนเริ่มมีลูกค้ากลุ่มแรก คุณสามารถเริ่มได้ง่าย ๆ ด้วย Stripe หรือ invoice แบบ manual เพราะแค่ต้องรับ recurring payment ไม่กี่รายการ
แต่เมื่อเวลาผ่านไป คุณจะเริ่มมี entitlement ที่ซับซ้อนขึ้น, หลายแผนราคา, การคุ้มครองลูกค้าเดิม, และลูกค้า enterprise ที่ต้องการรอบ billing, เงื่อนไข, และการให้สิทธิ์แบบกำหนดเองมากขึ้นเรื่อย ๆ billing มักไม่ได้เป็นจุดโฟกัสทางเทคนิค จึงเกิดการแฮ็กเล็ก ๆ และฟีเจอร์เสริมสะสมกันไปเรื่อย ๆ จนสุดท้ายกลายเป็นความยุ่งเหยิงที่ดึงทรัพยากรจากการพัฒนาผลิตภัณฑ์ ทำให้การขายช้าลง หรือจำกัดสิ่งที่คุณสามารถขายได้
ความซับซ้อนของ billing เต็มไปด้วยกับดักแอบแฝงและข้อยกเว้นมากมาย และทุกวันนี้ยิ่งซับซ้อนขึ้นเพราะแผนราคาส่วนใหญ่มีทั้งข้อจำกัดหลายแบบและองค์ประกอบตามการใช้งาน อีกทั้ง SaaS ยังขายไปทั่วโลก ในบริษัทระยะหลัง ๆ ยังมีทีมวิศวกรกว่า 15 คนที่ดูแล billing อย่างเดียวด้วย ผมเห็นด้วยว่า ถ้ามันไม่ใช่แกนหลักของผลิตภัณฑ์ ก็ไม่ควรสร้างระบบ billing เอง อ้างอิงไว้ก่อนว่าผมเป็น CTO ของแพลตฟอร์ม SaaS billing ชื่อ Wingback
ตอนนี้ผมยิ่งอยากสร้างระบบแบบนั้นขึ้นมาเอง และรู้สึกว่าตัวเองมีคุณสมบัติเหมาะสมกว่าที่คิดเสียอีก
https://arnon.dk/why-you-should-separate-your-billing-from-e...
ลูกค้าจะเก็บ entitlement ไว้ในระบบของเราและตรวจสอบเมื่อจำเป็น ส่วนเมื่อ subscription ถูกต่ออายุหรือลบออกทางฝั่งผู้ให้บริการ payment เราก็จะเพิ่มกฎและสิทธิ์ตามนั้น วิธีนี้ทำให้ทำงานกับผู้ให้บริการ payment หนึ่งรายหรือหลายรายได้ง่ายขึ้น และยังแยก ขอบเขตความรับผิดชอบ ได้ชัดเจนด้วย ขอบทความที่เกี่ยวข้องและเข้ากับบริบทนี้มากกว่ามาแชร์ด้วย: https://warrant.dev/use-cases/pricing-tiers-and-entitlements..., https://arnon.dk/why-you-should-separate-your-billing-from-e...
ระบบ entitlement ในอุดมคติควรเป็นแบบ dynamic กล่าวคือกฎควรถูกเก็บไว้ในฐานข้อมูล ต้องรองรับสถานการณ์เฉพาะครั้งอย่างลูกค้า enterprise ได้ และควรมีชั้น policy อยู่ด้านบน ตัวอย่างเช่น แผน Pro ใช้ได้ไม่เกิน 5 ที่นั่ง, แผน Growth ใช้ฟีเจอร์บางอย่างได้วันละ N ครั้ง ระบบควรรองรับได้แทบทุกสถานการณ์แบบนี้
การมี UI ให้ผู้ที่ไม่ใช่สายเทคนิคสามารถแก้ไขรายลูกค้าได้โดยไม่ต้องให้วิศวกรเข้ามาเกี่ยวข้องก็เป็นข้อดีมาก ในบทบาทวิศวกรก่อนหน้านี้ เรื่องแบบนี้คอยฉุดทีมพัฒนาอยู่เสมอ
เรายังมีชุด entitlement ด้วย แต่ตรงกลางจะมีกลไกเชิง policy ที่ตัดสินใจว่าเมื่อไรควรใช้หรือไม่ใช้ entitlement ประเด็นสำคัญคือ entitlement ไม่ได้เป็นปัญหาของ billing อย่างเดียว กลไก policy คือกาวที่เชื่อม entitlement เข้ากับทุกอย่างอื่น ดังนั้นคุณสามารถมอบสิทธิ์ให้ผู้บริหารของลูกค้ารายใหญ่ที่สุดได้โดยไม่ต้องผูกกับ billing เลย
เมื่อก่อนผมเคยสร้างระบบ billing และบัญชีลูกหนี้ให้กับเครือร้านขายยาขนาดเล็กแห่งหนึ่ง แล้วบริษัทประกันก็มักจะส่งเช็กก้อนใหญ่พอสมควรมาโดยไม่แจ้งล่วงหน้า
ทั้งที่เราไม่ได้เรียกเก็บอะไรเลย แต่เช็ก 150,000 ดอลลาร์ ก็ส่งมาทางไปรษณีย์ แล้วอีกหลายเดือนค่อยรู้ว่าเป็นความผิดพลาดและขอเงินคืน เรามีบัญชีพิเศษชื่อ magic money สำหรับเก็บเงินแบบนี้ โลกของ billing นี่มันบ้าจริง ๆ
หรือพูดง่าย ๆ คือแค่เรียกมันว่า magic money แล้วปล่อยให้หนี้ในบัญชีบุคคลยังคงอยู่เหมือนเดิมใช่ไหม
ผมไม่คิดว่าการเข้าหัวข้อนี้โดยโฟกัสแค่ความเจ็บปวดของการสร้างระบบเรียกเก็บเงินเองจะเหมาะนัก ถ้าหลายบริษัทอยากไปทางนั้น ก็ปล่อยให้เป็นแบบนั้นได้
ยอมรับว่าระบบเรียกเก็บเงินซับซ้อนมาก แต่ถ้า Chargebee, Solvimon, Stripe, Recurly, Orb, Metronome, Lago, Togai ฯลฯ มีองค์ความรู้นั้น ก็อาจรวบรวมความรู้นั้นไว้ในที่เดียวได้
สุดท้ายคำตอบก็คือแนวทางที่เหมาะกับตัวเอง ถ้าเป็น SaaS แบบ subscription ก็มีวิธีแก้ที่เหมาะกับแบบนั้น และถ้าเป็น API แบบคิดค่าบริการตามการใช้งาน ก็มีโซลูชันการเรียกเก็บเงินที่เหมาะกับแบบนั้น
แทนที่จะห้ามปรามแนวปฏิบัตินั้น เราสามารถรวบรวมความรู้ วิธีการ กระบวนทัศน์ programming pattern แนวปฏิบัติที่ดี และแนวปฏิบัติที่ดีที่สุดไว้ในที่เดียวได้ นอกจากนี้ยังมีข้อยกเว้นอย่างบริษัทนอกสหรัฐฯ หรือยุโรปที่ใช้โซลูชันเรียกเก็บเงินอย่าง Stripe ไม่ได้ เช่น ถ้าเป็นบริษัทในเวเนซุเอลาที่เปิดบัญชี Stripe ไม่ได้ สุดท้ายก็ต้องสร้างโซลูชันเรียกเก็บเงินเองและเชื่อมต่อกับ SOAP-XML API ที่เข้าใจยากของ payment gateway ท้องถิ่น
อีกอย่างหนึ่ง “การสร้างระบบเรียกเก็บเงินเอง” ให้ความรู้สึกคล้ายกับการ “สร้าง SIEM เอง” ด้วยชุด Elastic + Grafana ไม่ได้แนะนำหรอก แต่ก็เข้าใจว่าทำไมหลายทีมในฝ่ายความปลอดภัยไอทีถึงเลือกทางนี้
ระบบเรียกเก็บเงินซับซ้อนน้อยกว่าสิ่งที่นักพัฒนาต้องรับมือเสียอีก บทความนี้วาดภาพข้อกำหนดทางกฎหมายที่ยุ่งยากให้เหมือนเป็นอุปสรรคใหญ่ แต่ในอีกมุมหนึ่งก็หมายความว่าสเปกหาได้ง่ายและมีเอกสารประกอบดีมาก มีบางส่วนที่เปลี่ยนบ่อยก็จริง แต่ส่วนพวกนั้นก็มักติดป้ายและอธิบายไว้ชัดเจน
เห็นด้วยว่าทั้ง SaaS แบบ subscription และ API แบบคิดตามการใช้งานต่างก็มีรูปแบบการเรียกเก็บเงินที่เหมาะกับตัวเอง แต่ประเด็นคือจะยอมให้โยนภาระความรับผิดไปที่ลูกค้าหรือไม่ รายได้สำคัญพอจะคุ้มกับการตรวจสอบหรือไม่ และจะรับค่าธรรมเนียมหรือความสูญเสียไหวหรือเปล่า
อีกเรื่องที่บทความนี้ไม่ได้พูดถึงคือ affiliate sales ซึ่งถ้าทำลึกแค่ไหน งานก็เพิ่มขึ้นได้มากตามนั้น
มันคือระบบที่ทำให้คนอื่นสามารถรับค่าตอบแทนแบบคอมมิชชันจากการขายบนแพลตฟอร์มได้
ต้องติดตาม affiliate code ไปจนถึงการขายและผู้ใช้ ส่งเงินจ่ายออกผ่านผู้ให้บริการชำระเงินที่ affiliate ตั้งค่าไว้ และถ้าจะทำให้ดีจริงก็ต้องมี UI ให้ดูสถิติผู้เข้าชม อัตรา conversion และประวัติการจ่ายเงินด้วย
โชคดีที่ส่วนใหญ่ค่อยๆ สร้างแบบ incremental ได้ แค่ผูกโค้ดเฉพาะกับผู้ใช้ แล้วผูกโค้ดนั้นกับการขายที่มีอัตราคอมมิชชันที่กำหนดไว้ ที่เหลือจะทำมือหรือข้ามไปก็ได้ เช่น ผมจ่ายเงินให้ affiliate เดือนละครั้งผ่าน Zelle หรือ PayPal และใช้เวลาไม่ถึง 10 นาที ไม่มีฟรอนต์เอนด์สำหรับติดตาม conversion และก็ไม่เคยมีใครปฏิเสธจะทำ affiliate เพราะเรื่องนั้น
สิ่งที่น่าประทับใจจริงๆ คือความจำเป็นที่ต้องสามารถหมุน เครื่องจักร Rube Goldberg ทั้งชุดนี้ย้อนกลับได้
คุณอยากให้ “คำสั่งซื้อ” คงสภาพนิ่งที่สุดเท่าที่จะทำได้ และ “ใบแจ้งหนี้” ก็ยังมีภาระผูกพันทางกฎหมายด้วย
เช่น ซื้อมา 5 ชิ้นแล้วได้ส่วนลด แต่ต้องการแค่ 3 ชิ้น และยังมีการพิมพ์ชื่อกับที่อยู่ผิด สมมติว่าไม่เป็นไร ก็ยกเลิกใบแจ้งหนี้ ออกใบแจ้งหนี้ใหม่ยอดเท่าเดิมแต่แก้ชื่อและที่อยู่ จากนั้นรอให้ของตีกลับมาถึงและผ่านการตรวจสอบก่อน แล้วค่อยออกเครดิตอีกครั้งและออกใบแจ้งหนี้ใหม่อีกรอบ
การขนส่งสินค้าคืนค้างอยู่ในสถานะกำกวมไปพักหนึ่ง ลูกค้าก็สั่งเพิ่มอีก 5 ชิ้น มีชิ้นหนึ่งมาถึงแล้วแตก และลูกค้าอยากได้เงินคืนไม่ใช่เปลี่ยนสินค้า วันที่จัดส่งแยกเป็น 2 รอบ ทำให้ระบบไม่ใช้ส่วนลดสำหรับ 5 ชิ้นขึ้นไป เรื่องที่ตอนแรกคิดว่าเป็นแค่คำสั่งซื้อธรรมดา 2 รายการ กลับกลายเป็นธุรกรรมและเอกสารมากมายในพริบตา ลูกค้ายังลืมรหัสผ่านและไปสร้างบัญชีใหม่ด้วยอีเมลอีกอัน พอกลับมาดูล็อกในอีก 1 ปีให้หลัง ก็แทบจะดูไม่ออกว่าทำไมซื้อแค่ 3 ชิ้นถึงได้ส่วนลด
ไม่ค่อยเห็นด้วยกับคำแนะนำนี้ ฟีเจอร์ครึ่งหนึ่งที่บทความพูดถึงอาจไม่จำเป็น และสามารถค่อย ๆ สร้างแบบเป็นขั้นเป็นตอนได้เมื่อธุรกิจเติบโตขึ้น
ต้องเข้าใจแนวคิดอย่างอินวอยซ์ เครดิต รอบภาษี และการเปลี่ยนแปลงการคิดตามสัดส่วนเวลา แต่ความรู้นั้นไม่ใช่เหตุผลว่าต้องจ้างภายนอกหรือซื้อเสมอไป มันคือข้อมูลเพื่อช่วยให้ตัดสินใจเรื่อง สร้างเองหรือซื้อ ได้ดีขึ้น
API ภายนอกที่ SaaS ต้องมีมีแค่ตัวประมวลผลบัตรเครดิตตัวเดียว ถ้าจะจัดเต็มหน่อยก็สักสองตัว แน่นอนว่าหลังจากผ่านปีแรกไป งานที่ต้องทำด้วยมือจะเพิ่มขึ้นมาก นักบัญชีจะชี้ให้เห็นความผิดพลาดงี่เง่าต่าง ๆ และคุณก็จะได้เรียนรู้เรื่องบัญชีมากขึ้น
ถึงอย่างนั้น ถ้าวันนี้ต้องเริ่มธุรกิจใหม่ ผมก็จะเปรียบเทียบหลายโซลูชันอยู่ดี แต่ก็มั่นใจว่าการทำเองไม่ได้ได้น่ากลัวขนาดนั้น
การสร้างระบบมักจะดูเหมือนง่ายเสมอ และในวันแรกมันก็ง่ายจริง ๆ แต่ไม่นานคุณจะใช้เวลาไปกับการอธิบายให้ CFO ฟังว่าทำไมรายงานถึงเละเทะไปหมด และอธิบายให้ทีมซัพพอร์ตฟังว่าทำไมอินวอยซ์ถึงล้มเหลว ทำไมคิดราคาค่าสมาชิกลูกค้าผิด รวมถึงกรณียกเว้นอีกสารพัดที่คุณไม่เคยรู้มาก่อนว่ามีอยู่
หลังจากนั้นก็ต้องตามข้อกำหนดที่เปลี่ยนไปให้ทัน หรือไม่ก็พบว่าเกตเวย์ที่เลือกไว้ไม่รองรับภูมิภาคที่กำลังเติบโตของคุณ
ก่อนจะพูดว่า “ก็แค่ทำให้ดีขึ้นสิ” ต้องจำไว้ว่านั่นก็ใช้เวลาเหมือนกัน เป็นเวลาที่ไม่ได้เอาไปลงกับผลิตภัณฑ์ ไม่ได้เอาไปปรับปรุงโมเดลราคา และเป็นเวลาที่หมดไปกับการอยู่กับที่แทนที่จะใช้สร้างการเติบโตให้ธุรกิจ
นอกนั้นอาจพอมองข้ามได้ แต่ถ้าสุดท้ายคำนวณภาษีไม่ได้ หรือดันไปละเมิดกฎหมาย KYC เข้าจริง ๆ จะลำบากมาก
อีกอย่างคือบางระบบแพงกว่าที่คิด และการที่มีบริษัทดูฉลาดจำนวนมากใช้อยู่ ไม่ได้แปลว่ามันเหมาะกับเป้าหมายของคุณ โดยเฉพาะไม่ได้รับประกันเลยว่าจะเหมาะกับเป้าหมายที่คุณต้องการ การซื้อไม่ได้แปลว่าไม่ต้องศึกษาข้อมูล
เป้าหมายของคนที่ดูแลบิลลิงแบบนี้เรียบง่ายมาก คือ ต้องมีตัวเลือกที่เหมาะสมพอให้ทีมขายปิดดีลได้ ต้องทำงานร่วมกับทีมขายเพื่อหาว่าขอบเขตแบบไหนที่ “ทำให้พัฒนาได้ง่ายและเพียงพอสำหรับการปิดดีล”
เรื่องนี้ย้ำเท่าไรก็ไม่พอ ทีมขายคือคนที่สร้างรายได้จริง ๆ อย่าบ่นงอแงเพียงเพราะมันไม่ใช่ระบบบิลลิงที่สมบูรณ์แบบ ฟังแล้วอาจช็อก แต่ปัญหาที่มีความสัมพันธ์ทางธุรกิจเป็นเดิมพัน บางครั้งก็ต้องพับแขนเสื้อแล้วทำด้วยมือ
ควรทำให้เรียบง่ายที่สุดเท่าที่ทำได้ แต่ต้องเป็นระบบที่ทีมอื่นในบริษัทอ่านแล้วเข้าใจได้ และถึงจะมีอัตโนมัติทำงานอยู่ก็ยังปรับด้วยมือได้ง่าย นี่คือเหตุผลประมาณ 80% ว่าทำไม Stripe ถึงให้ความรู้สึกว่าใช้งานดี การปรับด้วยมือเป็นส่วนหนึ่งของชีวิต และในบางธุรกิจแม้จะไม่บ่อย สุดท้ายก็จำเป็นอยู่ดี
การคิดตามสัดส่วนเวลา รอบบิลที่ต่างกัน ช่วงทดลองใช้ฟรี การทดสอบราคาใหม่ ราคาแยกตามภูมิภาค ภาษีแยกตามภูมิภาค การแสดงแพ็กเกจเป็นหลายสกุลเงิน และการปล่อยราคาใหม่ ล้วนทำให้ทุกอย่างกลายเป็นการผสมกันของ 6 สกุลเงิน × X ภูมิภาค × Y ผลิตภัณฑ์ × Z รอบบิล × L ภาษา
แล้วยังต้องเพิ่มการสมัครสมาชิกใหม่ รวมแพลนสมาชิกเข้าด้วยกัน ยกเลิกแพลนเก่าโดยย้ายลูกค้าไปยังแพลนทางเลือกใหม่อย่างนุ่มนวล และต้องสื่อสารกับลูกค้าให้ดี ถ้าเป็น SaaS แทบทั้งหมดนี้ต้องอัตโนมัติ บริการตัวเองได้ และทดสอบมาดี ไม่อย่างนั้นคุณจะจมตายอยู่กับงานซัพพอร์ตลูกค้าและการยกเลิกใช้งาน
การปล่อยการเปลี่ยนราคาอาจใช้เวลาตั้งแต่ 3 วันถึง 2 เดือน และการจัดการกับร่องรอยของสัญญาแบบกำหนดเองในช่วงแรก ๆ เป็นฝันร้าย ถ้าอัตโนมัติได้ไม่ง่าย ก็ทำไม่ได้ เพราะกินเวลามากเกินไป
ถ้าเราวางระบบบิลลิงบนผลิตภัณฑ์แบบที่พูดถึงในที่นี้ ก็น่าจะทำสัญญาเฉพาะตามเซกเมนต์ลูกค้าและปล่อยการเปลี่ยนราคาได้ดีกว่านี้มาก
มีปัญหาอีก 2 อย่างที่บทความนี้ไม่ได้พูดถึง แต่ผมเคยเจอเองตอนจัดการโดยตรง
อย่างแรกคือ การปิดรอบสิ้นเดือน·สิ้นไตรมาส บทความพูดถึงบัญชีแยกประเภท แต่พอเริ่มต้องรับมือกับบริษัทมหาชนที่ต้องรายงานตัวเลข จะมีช่วงปิดรอบที่เข้มงวดและทุกอย่างต้องเดินไปอย่างราบรื่น
อย่างที่สองคือการทำบัญชีเงินสดระหว่างทาง บทความนี้สมมติว่าตัวประมวลผลการชำระเงินถูกต้อง 100% และไม่มีปัญหาอะไร แต่พอธุรกิจใหญ่พอ คุณต้องสามารถจับคู่เงินทุกก้อนที่เข้าบัญชีธนาคารกับอินวอยซ์หรือรายการเรียกเก็บเงินที่เฉพาะเจาะจงได้ ต้องหาอินวอยซ์ที่ไม่มีรายการในสเตตเมนต์ธนาคารที่ตรงกัน และในทางกลับกันก็ต้องจัดการกรณีที่มีเงินเข้าแต่ไม่เชื่อมกับรายการในอินวอยซ์ ความสามารถในการจัดการเครดิตเข้าบัญชีธนาคารที่ไม่ได้เชื่อมกับอินวอยซ์บิลลิงก็สำคัญเช่นกัน
จะบอกว่านี่เป็นปัญหาของฝ่ายบัญชีทั้งหมดก็ได้ แต่จริง ๆ แล้วมันผูกติดกับระบบอย่างมาก จนสองทีมต้องทำงานร่วมกันเพื่อไม่ให้เกิดความไม่ตรงกันระหว่างสมุดบัญชี
นักบัญชีจริง ๆ ต้องอยู่ดึกถึงเที่ยงคืนซ้ำแล้วซ้ำเล่าเพราะการปิดรอบ ส่วนคนสายเทคหรือสายธุรกิจก็จะเจอสถานการณ์ที่ต้องขออะไรบางอย่างจากทีมบัญชี แต่ในช่วงปิดรอบทีมบัญชีกลับเหมือนหายไปจากโลกใบนี้ แม้จะเจอในฐานะคนในครอบครัวก็ยังเหมือนกัน
บัญชีภายในกับบัญชีธนาคารจะค่อย ๆ คลาดกันไปทีละน้อย และนักบัญชีก็จะไม่รู้ด้วยซ้ำว่าควรเริ่มไล่หาปัญหาจากตรงไหน
อยากรู้ว่าทุกคนใช้ การจัดการสิทธิ์ ด้วยอะไร ใช้ระบบ feature flag, ใช้ SaaS แยกอย่าง Stigg หรือทำระบบภายในเองกันแน่
ที่โพสต์บน HN เช้านี้ก็เพราะเขียนเรื่องการใช้ feature flag กับการจัดการสิทธิ์: https://prefab.cloud/blog/modeling-product-entitlements-with.... ได้แรงบันดาลใจจากบทความของ Arnon เกี่ยวกับรูปแบบ SKU ด้วย
แม้ feature flag จะดูไม่ใช่ที่ที่สมบูรณ์แบบสำหรับการจัดการสิทธิ์ แต่จากประสบการณ์ มันมักเป็นเครื่องมือที่ดีที่สุดเท่าที่มีอยู่ในมือเวลาต้องจัดการโจทย์แบบนี้ อยากฟังมุมมองอื่น ๆ
ลิมิตและ flag เหล่านี้จะผูกกับ “แพ็กเกจ” และแพ็กเกจสามารถผูกกับบัญชีได้ ถ้ารวมหลายแพ็กเกจเข้าด้วยกัน ค่าตัวเลขจะใช้ค่าที่มากกว่า และแท็กจะรวมแบบยูเนียน นอกจากนี้ยังสามารถ override หรือเพิ่มค่าระดับบัญชีได้ด้วย ดังนั้นถ้าลูกค้าต้องการ PlanX แต่ต้องการโควตา API แบบกำหนดเอง ก็แค่ override ค่านั้นตัวเดียวลงที่บัญชีโดยตรง
จะเรียกว่าล้าสมัยก็ได้ แต่ผมไม่เข้าใจว่าทำไมเรื่องแบบนี้ต้องเอาไปจ้างบุคคลที่สาม
วิธีพื้นฐานทำได้ด้วย feature flag แต่สิทธิ์ที่เกี่ยวกับ billing และ pricing เช่น การจัดโครงสร้างและการเปลี่ยนแปลงของแพ็กเกจและ edition จะค่อย ๆ ซับซ้อนขึ้นเมื่อเวลาผ่านไปเพราะมีข้อกำหนดแวดล้อมเพิ่มขึ้นเรื่อย ๆ ลองนึกถึงการผสมกันหลากหลายแบบของฟีเจอร์, seat, กลยุทธ์แบบ usage-based/usage-metered, การสมัครสมาชิกแบบทีม, การย้ายแพ็กเกจ, แพ็กเกจ enterprise แบบครั้งเดียว, ลูกค้าที่มีหลาย subscription, ช่วงโปรโมชั่นและ subscription แบบหลายชั้น, การรวมยอดการใช้งาน, การ upsell อัตโนมัติ ฯลฯ
อย่างที่เห็นในบทความ คุณสามารถใช้ flag ที่มีค่าตัวเลขเพื่อแทนลิมิตได้ แต่โครงสร้างพื้นฐานสำหรับติดตามการใช้งาน ธุรกิจก็ยังต้องทำเองอยู่ดี ลองคิดอีกแบบว่าเอาข้อมูลการใช้งานนั้นส่งออกไปยังบริการสิทธิ์ แล้วสิทธิ์แบบ usage-based จะอัปเดตแบบเรียลไทม์ข้ามทีมได้ และสิทธิ์อื่นที่พึ่งพามันก็อาจอัปเดตตามไปด้วยได้เช่นกัน คุณอาจเลือก soft limit ที่ยังให้ใช้งานต่อได้แต่แจ้งฝ่ายขายเมื่อใกล้ถึงหรือเกินลิมิต หรือเลือก hard limit ที่แสดงคำเตือนให้อัปเกรดก็ได้
ตามเจตนาของโพสต์ต้นฉบับ เราทำงานร่วมกับโซลูชัน billing ที่มีอยู่แทนการสร้าง billing ใหม่ทั้งหมด เรากำลัง bootstrap จาก exit ที่ประสบความสำเร็จก่อนหน้านี้และกำลังทำงานกับลูกค้าชุดแรก ใครที่แค่อยากคุยเรื่องนี้ก็ติดต่อได้ที่ trent at planship.io
คุณสามารถทำทั้งการปล่อยเบต้า, การยืนยันสิทธิ์ตามบทบาท, สิทธิ์ด้าน billing, ไปจนถึงคำขอเฉพาะกิจของลูกค้าเป็น feature flag ได้ทั้งหมด feature flag ที่ดีที่สุดยังสามารถแนบค่าเพิ่มเติมได้แบบเลือกได้ ดังนั้นลิมิตของ API plan ก็กลายเป็น feature flag ได้เหมือนกัน
ถ้าถามว่านี่ดีที่สุดไหม สำหรับแต่ละ use case ก็คงไม่ใช่เสมอไป แต่พอสร้างไว้ครั้งหนึ่งแล้ว แรงดึงดูดที่จะเอาไปใช้ทุกที่มันสูงมาก
สิทธิ์ต้องเชื่อมโยงกับฟีเจอร์ที่ลูกค้ามองเห็นอย่างชัดเจน และในเชิงแนวคิดมันเป็นบล็อกฟีเจอร์ที่ใหญ่กว่ามาก ความยากของแนวทางนี้คือคุณก็ยังต้องคำนึงถึงหลายแง่มุมที่เกี่ยวกับ billing อยู่ดี เช่น การจัดการลูกค้าที่ค้างชำระ, ค่าบริการส่วนเกินเมื่อเกินลิมิตบางอย่าง, โมเดลราคาหลายแบบสำหรับฟีเจอร์เดียวกัน, การรีเซ็ตหรือยกยอดตัวนับการใช้งานเมื่อเปลี่ยนแพ็กเกจหรืออัปเกรด ซึ่งทั้งหมดนี้เพิ่มความซับซ้อนอย่างมากเมื่อเวลาผ่านไป
เพราะแบบนั้น ที่ Wingback เราจึงเลือกให้มีสิทธิ์ฟีเจอร์แยกต่างหากที่ผูกกับ billing chain และ metering อย่างใกล้ชิด ขอบอกไว้ก่อนว่าผมเป็น CTO สุดท้ายแล้วผมคิดว่าทั้งสองแนวทางใช้ได้ดี ขึ้นอยู่กับความซับซ้อนของแพ็กเกจราคาและคุณลงทุนกับ feature flag ไปมากแค่ไหน ถ้ามีการ gating ฟีเจอร์สำหรับลูกค้า มันจะทำให้การ provision บัญชีลูกค้าและการจัดแพ็กเกจแบบกำหนดเองง่ายขึ้นมาก
โครงตรรกะประมาณว่า “ระบบ X ซับซ้อนมาก ดังนั้นอย่าสร้างเอง ให้ใช้โซลูชันสำเร็จรูป” โดยรวมแล้วผมรู้สึกคล้อยตามได้ยาก
คำตอบทั่วไปของ X อาจยากและซับซ้อนมากก็จริง แต่ใน use case ของผม ต้องการแค่บางส่วนของความซับซ้อนเท่านั้น ดังนั้นผมจึงสร้างวิธีแก้แบบทำเองที่รองรับเฉพาะความซับซ้อนที่ต้องใช้ได้ และมันอาจง่ายกว่าเครื่องมือสำเร็จรูปมาก
ผมยึดแนวคิดนี้เต็มที่กับเรื่อง วันที่และเวลา วิธีจัดการวันที่และเวลาของผมต้องการให้ไลบรารีมีแค่สองฟังก์ชันเท่านั้น: ฟังก์ชันแปลง epoch time เป็นสตริงเวลาแบบ ISO ใน time zone ที่กำหนด และฟังก์ชันย้อนกลับจากนั้น โดยไม่แตะโค้ดอื่นของไลบรารีเลย ส่วนการจัดการเวลาอื่น ๆ ที่เหลือก็ทำในโค้ดของผมโดยอิงจากสองฟังก์ชันนี้
ตั้งแต่แรกคุณต้องเข้าใจสิ่งที่ควรและไม่ควรทำในการจัดการข้อมูลส่วนบุคคล, รอบเวลาและวงจรชีวิตของตัวเลือก billing แบบต่าง ๆ, ขีดจำกัดของการคืนเงิน, การรองรับ idempotency, การจัดการ database transaction ที่สมเหตุสมผลพร้อมโมเดลที่เหมาะกับงาน, การออก invoice และการเปิดให้ลูกค้าเห็น เป็นต้น
คุณอาจยังไม่ต้องใช้ทั้งหมดในคราวเดียว แต่แม้แต่ implementation แรกที่พอใช้งานได้ ก็อย่างน้อยต้องมีสักครึ่งหนึ่ง
มันให้ความรู้สึกประมาณ “14 ความเจ็บปวดของการข้ามถนน และทำไมคุณควรซื้อหนังสือของฉันมาอ่าน”
หลายคนคิดว่าการหลับตาแล้วเริ่มเดินไปก็ดีเหมือนกัน จึงลงเอยด้วยการบาดเจ็บก่อนเวลาอันควรหรือถึงตาย
กฎการข้ามถนนต่างกันไปในแต่ละประเทศ หรือแม้แต่แต่ละเมือง คุณอาจยังไม่รู้ แต่ต้องมองทั้งสองทาง บางคนไม่รู้ว่าตัวเองตาบอดสี แยกไฟแดงกับเขียวไม่ออก เลยตายหรือบาดเจ็บ คุณอาจมองซ้ายขวาแล้ว แต่เคยมองขึ้นข้างบนไหม? ในเมืองอาจมีของตกจากหน้าต่าง ในชนบทอาจมีนกบินเหนือหัว และขยะอวกาศก็กำลังตกลงสู่โลกมากขึ้นเรื่อย ๆ วัตถุสามารถมาจากได้หลายทิศทาง
ไม่ได้บอกว่าบทความนี้แย่ขนาดนั้น แต่ถ้ามันถูกเขียนเป็น บทความเชิงวิธีการ ก็น่าจะดีกว่านี้ ผมอยากอ่านอะไรแบบนั้นมากกว่าบทความที่วางกรอบเชิงลบ
มันคือต้นแบบของโปรเจกต์มุกประมาณ “มันจะยากแค่ไหนกันเชียว?” และปัญหาคือทุกอย่างในนั้นเป็นเรื่องจริงทั้งหมด
ยกตัวอย่างได้ไม่รู้จบ แต่ถ้าคุณเข้าหาปัญหานี้ผิดทาง ไม่นานก็จะชนกับคำถามว่า “ลูกค้าควรจ่ายเท่าไร?” แล้วต่อด้วย “ทำไมเราถึงเรียกเก็บเงินจำนวนนี้ ไม่ใช่อีกจำนวนหนึ่ง?” ถ้าเรื่องแบบนี้เกิดบ่อยเกินไป ทีมการเงินก็จะเดินเข้ามาถามว่าคุณไปทำอะไรไว้ เพราะมันทำให้รายงานการดำเนินงานของบริษัทไม่น่าเชื่อถือ หรือกระทั่งรายงานที่ใช้ตัดสินใจเรื่องการเลิกจ้างคนเลยทีเดียว