ฟอร์ม HTML
หนึ่งในวิธีเพิ่มการชำระเงินคริปโตให้กับเว็บไซต์ ร้านค้าออนไลน์ หรือบอท ลูกค้ากดปุ่ม แล้วหน้าชำระเงินพร้อมใบแจ้งหนี้จะเปิดขึ้น
ฟอร์มส่งได้เฉพาะแบบ POST ไปยัง https://dash.bitsby.app/invoices/form และประกอบด้วยสองฟิลด์:
| ฟิลด์ | เก็บอะไร |
|---|---|
data | base64url ของ JSON ที่มีฟิลด์ของใบแจ้งหนี้ |
signature | HMAC-SHA256 ของสตริง data ความยาว 64 ตัวอักษร hex |
ในแต่ละขณะ โปรเจกต์หนึ่งมีใบแจ้งหนี้ที่ยังไม่ชำระซึ่งสร้างด้วยวิธีนี้ได้ไม่เกิน 50 ใบ
ตัวอย่างฟอร์ม
<form method="post" action="https://dash.bitsby.app/invoices/form" target="_blank">
<input type="hidden" name="data" value="eyJwcm9qZWN0SWQiOiJhMWIyYzNkNC01ZTZm...">
<input type="hidden" name="signature" value="f77d6da1be35bd2900e0bfed9f202b04...">
<button type="submit">Pay</button>
</form>
เซิร์ฟเวอร์ของร้านค้าเป็นผู้กรอกค่าทั้งสองตอนเรนเดอร์หน้า ส่วนคีย์ลับไม่ปรากฏในมาร์กอัปเลย
แอตทริบิวต์ target="_blank" ไม่บังคับ: เมื่อใช้ ตะกร้าสินค้าจะยังเปิดอยู่ในแท็บเดิม
วิธีสร้างคอนเทนเนอร์
- สร้างออบเจ็กต์ JSON ที่มีฟิลด์ของใบแจ้งหนี้
- เข้ารหัสเป็น base64url ผลลัพธ์คือสตริง
data - คำนวณ
signature = HMAC-SHA256(data, formSecret)
สตริง data ถูกเซ็นทั้งก้อน ดังนั้นลำดับคีย์ใน JSON การเยื้อง และรูปแบบการ escape อักขระ Unicode จึงไม่มีผล ฝั่งผู้รับยังยอมรับ base64 มาตรฐานด้วย ทั้งแบบมีและไม่มี padding
อย่าสร้าง data ใหม่หลังจากเซ็นแล้ว: หากมีแม้แต่ไบต์เดียวเปลี่ยนไป ต้องคำนวณลายเซ็นใหม่
วิธีคำนวณลายเซ็น พร้อมตัวอย่างสำเร็จรูปในสี่ภาษา อธิบายไว้ในลายเซ็นฟอร์ม HTML
คีย์ภายใน data
| คีย์ | จำเป็น | เก็บอะไร |
|---|---|---|
projectId | ใช่ | ID ของโปรเจกต์จากการตั้งค่าในแดชบอร์ด เป็น uuid |
amountFiat | ใช่ | จำนวนเงินตั้งแต่ 1 ถึง 100,000 ทศนิยมไม่เกินสองตำแหน่ง ส่งเป็นสตริง "10.50" หรือตัวเลข 10.5 ก็ได้ |
currencyFiat | ใช่ | สกุลเงินเฟียต: USD, EUR หรือ RUB |
timeToPay | ใช่ | กำหนดเวลาชำระเงินเป็นชั่วโมง: 0.5, 1, 3, 6, 12 ส่งเป็นสตริงหรือตัวเลขก็ได้ |
description | ไม่ | คำอธิบายสำหรับลูกค้า ยาวได้ไม่เกิน 1,000 ตัวอักษร |
serviceData | ไม่ | ตัวระบุคำสั่งซื้อฝั่งร้านค้า ยาวได้ไม่เกิน 1,000 ตัวอักษร ไม่แสดงให้ลูกค้าเห็นแต่มองเห็นได้ในซอร์สโค้ดของฟอร์ม — อย่าใส่ข้อมูลอ่อนไหวไว้ที่นี่ |
output | ไม่ | errors — แสดงรายละเอียดของข้อผิดพลาดการตรวจสอบ |
คีย์ที่ไม่บังคับจะละไว้จาก JSON ก็ได้ — มีผลเหมือนสตริงว่าง คีย์เรียงลำดับใดก็ได้ ส่วนคีย์ที่ไม่รู้จักผู้รับจะไม่สนใจ
ค่าเป็นสตริงหรือตัวเลขของ JSON ส่วน Boolean อาร์เรย์ และออบเจ็กต์ซ้อนไม่ถือเป็นค่าฟิลด์ และจะมาถึงเป็นสตริงว่าง
ตัวอย่างเนื้อหาของ data:
{
"projectId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"amountFiat": 10.5,
"currencyFiat": "USD",
"timeToPay": 1,
"description": "Order #7, delivery",
"serviceData": "order-7"
}
ในตัวอย่างนี้ จำนวนเงินและกำหนดเวลาชำระเงินส่งเป็นตัวเลข จะส่งเป็นสตริงก็ยอมรับเช่นกัน ส่วนคีย์ output ที่ไม่บังคับไม่ได้ตั้งค่าไว้เลย
รูปแบบจำนวนเงิน
ใช้ได้เฉพาะตัวเลขและจุดทศนิยม ทศนิยมไม่เกินสองตำแหน่ง: 10, 10.00, 1000.50 ช่องว่างหัวท้ายจะถูกตัดออก
รูปแบบอื่นถูกปฏิเสธทั้งหมด — ตัวคั่นหลักพัน จุลภาคแทนจุด สัญกรณ์เลขชี้กำลัง เครื่องหมายหน้าเลข สัญลักษณ์สกุลเงิน ไม่มีการปัดเศษ: ทศนิยมตำแหน่งที่สามไม่ถูกตัดทิ้ง แต่ทำให้ถูกปฏิเสธ
คีย์ลับของฟอร์ม
คีย์ลับนี้อยู่ในการตั้งค่าโปรเจกต์ในแดชบอร์ด ในฟิลด์คีย์ลับของฟอร์ม (Form secret) เซิร์ฟเวอร์เป็นผู้ออกให้ตอนสร้างโปรเจกต์ คุณตั้งค่าเองไม่ได้ ทำได้เพียงออกคีย์ลับใหม่ — เช่น ในกรณีที่คีย์รั่วไหล
คีย์ลับต้องอยู่บนเซิร์ฟเวอร์ของร้านค้าเท่านั้น หากไปปรากฏใน HTML หน้าร้าน ลายเซ็นก็หมดความหมาย
คีย์ลับของฟอร์มกับคีย์ลับของ Webhook เป็นคนละคีย์กัน อย่าสับสน
ตัวระบุคำสั่งซื้อ
กรอก serviceData เสมอ: ใส่ตัวระบุคำสั่งซื้อของคุณเองไว้ที่นั่น ค่านี้จะถูกส่งกลับมาในการแจ้งเตือนการชำระเงิน — ร้านค้าใช้ค่านี้ค้นหาคำสั่งซื้อ
serviceData ที่กรอกไว้ช่วยป้องกันใบซ้ำ การส่งฟอร์มซ้ำหรือดับเบิลคลิกปุ่มจะไม่สร้างใบแจ้งหนี้ใบที่สอง: ลูกค้าจะถูกพาไปยังใบเดิมที่ยังไม่ชำระ การจับคู่พิจารณาจากฟิลด์ของคำสั่งซื้อ — โปรเจกต์ จำนวนเงิน สกุลเงิน คำอธิบาย และ serviceData — ไม่ใช่จากไบต์ของ data
ค่านี้ต้องไม่ซ้ำกันในแต่ละคำสั่งซื้อ หากใช้ค่าเดียวกัน ลูกค้าคนที่สองจะไปเจอใบแจ้งหนี้ที่ยังไม่ชำระของลูกค้าคนแรก
serviceData ที่ว่างเปล่าทำให้การป้องกันนี้หายไป: ไม่มีอะไรให้ใช้จดจำการส่งซ้ำ และการส่งทุกครั้งจะสร้างใบแจ้งหนี้ใหม่ ใบซ้ำกินโควตา 50 ใบที่ยังไม่ชำระ และเมื่อมีการชำระใบใดใบหนึ่ง ร้านค้าก็ไม่มีอะไรใช้ผูกการชำระเงินเข้ากับคำสั่งซื้อ
ข้อผิดพลาดและโหมดดีบัก
ฟอร์มผ่านการตรวจสอบสองขั้น: ขั้นแรกคือลายเซ็นและคอนเทนเนอร์ จากนั้นคือค่าของฟิลด์
| เกิดอะไรขึ้น | บริการแสดงอะไร |
|---|---|
| ลายเซ็นไม่ตรง คอนเทนเนอร์อ่านไม่ได้ โปรเจกต์เป็นของคนอื่นหรือไม่มีอยู่ | ข้อผิดพลาดทั่วไป ไม่ระบุสาเหตุ |
| ลายเซ็นตรง แต่ฟิลด์กรอกไม่ถูกต้อง | ข้อผิดพลาดทั่วไป หากใช้ "output":"errors" — ข้อผิดพลาดแบบละเอียด |
| ผ่านทั้งสองขั้น | หน้าชำระเงินพร้อมใบแจ้งหนี้ |
การตรวจสอบขั้นแรกไม่เปิดเผยสาเหตุเลย ไม่ว่าตั้งค่าอย่างไร
คู่ "output":"errors" ใน JSON เปิดรายละเอียดของการตรวจสอบขั้นที่สอง: บริการจะระบุชื่อฟิลด์ แสดงรายการค่าที่อนุญาต และแจ้งเมื่อถึงเพดาน 50 ใบที่ยังไม่ชำระ คีย์นี้อยู่ภายในคอนเทนเนอร์ที่เซ็นแล้ว จึงไม่มีใครแทรกจากภายนอกได้
ระหว่างตั้งค่าฟอร์ม ให้ใส่ "output":"errors" ไว้ใน JSON เมื่อตั้งค่าเสร็จแล้ว ให้ลบคีย์นี้ออกและสร้างคอนเทนเนอร์ใหม่
หากลายเซ็นเองไม่ตรง ให้เทียบ data และลายเซ็นของคุณกับชุดอ้างอิงในลายเซ็นฟอร์ม HTML
ขั้นตอนถัดไป
ใบแจ้งหนี้ที่สร้างด้วยฟอร์มได้รับการประมวลผลแบบเดียวกับใบที่สร้างผ่าน API หรือแดชบอร์ด:
- การยืนยันการชำระเงินจะมาถึงที่ Webhook URL ตรวจสอบลายเซ็นของการแจ้งเตือนด้วยคีย์ลับของ Webhook และส่งมอบคำสั่งซื้อโดยอิงจากการแจ้งเตือนนี้เท่านั้น
- การพาลูกค้ากลับไปยังเว็บไซต์ของคุณตั้งค่าผ่าน URL เมื่อสำเร็จ (Successful URL) และ URL เมื่อไม่สำเร็จ (Unsuccessful URL) — ดูส่วน “การพาลูกค้ากลับไปยังเว็บไซต์ร้านค้า” บนหน้าวงจรชีวิตของใบแจ้งหนี้ การมาถึง URL เหล่านี้ไม่ใช่การยืนยันการชำระเงิน
- สถานะใบแจ้งหนี้และหน้าต่างค้นหาการชำระเงินอธิบายไว้ในวงจรชีวิตของใบแจ้งหนี้
- ลูกค้าโอนเงินผิดจำนวน — ดูการจับคู่การชำระเงินและยอดเงินไม่ตรงกัน