Integration และ Webhook
หน้าจอนี้เป็น control plane ที่เปิดใช้จริงสำหรับ Merchant ของผู้ใช้ที่ล็อกอินอยู่เท่านั้น White Label และ Agent ใช้ scope_id ของลูกข่ายมาอ่านหรือแก้แทนไม่ได้
GET /v1/bo/integrations?scope_id=<merchant_uuid>
PUT /v1/bo/webhooks/<webhook_uuid>อ่านสถานะ
GET /v1/bo/integrations ต้องมีทั้ง settings:read และ webhooks:read พร้อม contracts settings และ webhooks ระบบคืน integrations_v1 แบบ Cache-Control: no-store
Response ตั้งใจปกปิด URL เต็ม, path, secret, private key, raw payload และ response body โดยแสดงเฉพาะ host ที่มีผลจริง, มี path หรือไม่, fallback route, จำนวน delivery และสถานะ sender
| สถานะ sender | ความหมาย |
|---|---|
healthy | scheduler, queue consumer, DNS/fetch policy, DB sender RPC และคู่กุญแจพร้อม |
degraded | sender พร้อม แต่มี delivery ค้างเกินเกณฑ์ |
unavailable | ปิดการส่งแบบ fail closed พร้อม reason ที่ไม่เปิดเผยข้อมูลลับ |
Reason แบบปิดมีเพียง queue_binding_unavailable, scheduler_composition_unavailable, signing_key_mismatch, database_function_unavailable, dns_policy_unavailable และ delivery_backlog
Preview อ่านได้อย่างเดียว
หน้า preview ของ theme เรียกข้อมูลตัวอย่างได้ แต่ห้ามส่ง mutation หรือถือ credential ที่เขียนข้อมูลจริง
สร้างหรือเปลี่ยน endpoint
PUT ใช้ cookie session แบบ same-origin, role merchant_owner, capability webhooks:manage และ fresh configuration step-up ที่ผูกกับ operation webhook.endpoint.upsert รวมถึง method, canonical path, body digest, request digest, Idempotency-Key, correlation ID และ If-Match
PUT /v1/bo/webhooks/4f8d85f0-1f3a-4fc5-9888-24c70fc70a6a
Content-Type: application/json
Idempotency-Key: wh_cfg_01K3M7Y9RS5TQ0WH2E7XKJ4C6B
If-Match: "0"
X-Correlation-Id: cfg_01K3M7Y9RS5TQ0WH2E7XKJ4C6B
X-Step-Up-Token: <request-bound-token>{
"scope_id": "5f6dcff9-4463-4908-adce-5fc6bc3b4b25",
"label": "Production events",
"api_version": "2026-08-01",
"deposit_url": "https://hooks.merchant.co/paygate/deposits",
"withdrawal_url": null,
"account_url": null,
"enabled": true,
"reason_code": "MERCHANT_CONFIG_UPDATE"
}- ใช้
If-Match: "0"ตอนสร้าง และ ETag/current version ตอนแก้; ทุกครั้งสร้าง immutable revision ใหม่ withdrawal_url=nullและaccount_url=nullจะ fallback ไปdeposit_url- exact replay คืน receipt เดิม; idempotency key เดิมแต่ body ต่างกันถูกปฏิเสธ
- เปลี่ยน URL หรือปิด endpoint จะยกเลิก binding ที่ยังไม่ terminal ทั้งหมดของ revision เก่าและตัด lease/retry เดิมทันที คำขอที่ส่งออกไปแล้วก่อนบันทึกอาจจบที่ปลายทางได้หนึ่งครั้ง แต่จะไม่ถูก retry อีก โดยไม่แก้ event bytes, attempt history หรือ terminal binding
URL ที่รับได้
URL ต้องเป็น lowercase ASCII https:// DNS hostname แบบ public และใช้ port ปกติหรือ :443 เท่านั้น (:443 จะถูก canonicalize ออก) path จะไม่ใส่ก็ได้ หรือใช้ ASCII pchar เท่านั้น
ระบบปฏิเสธ userinfo, IP literal, punycode/Unicode host, suffix ภายในหรือสงวน, percent encoding ทุกชนิด, query, fragment, backslash, control/space, // ซ้ำ และ path segment . หรือ .. การบันทึกไม่ยิง DNS; sender จะตรวจทั้ง A และ AAAA ผ่าน public DNS อีกครั้งก่อนส่งและปฏิเสธ private/reserved/mixed answers
สัญญาการส่งที่ตรึงไว้
- Event ที่ sender ชุดนี้รองรับ:
deposit.settled,withdrawal.partial_fill,withdrawal.terminal - เซ็น raw body bytes ด้วย Ed25519; ตรวจ keyset และ test vector ก่อนเปิดส่ง
- สำเร็จเฉพาะ
200,201,202,204;410เป็น permanent failure - ไม่ตาม redirect และมี total timeout 15 วินาที
- ส่งสูงสุด 11 ครั้งตาม delay (วินาที):
0, 10, 60, 300, 1800, 7200, 21600, 43200, 86400, 86400, 86400 - เก็บ event อย่างน้อย 30 วัน; queue มีเพียง opaque pointer ส่วน DB lease เป็น authoritative
