WebHooks

หัวข้อทั้งหมดในหน้านี้

Webhooks

ภาพรวม

Webhook คือ HTTP POST request ที่ส่งจากเซิร์ฟเวอร์ของเราไปยัง HTTPS endpoint ที่คุณกำหนด เมื่อเกิดเหตุการณ์เฉพาะขึ้นบนบัญชีของคุณ แต่ละ request จะมีอ็อบเจกต์ event ที่มีข้อมูล payload สำหรับการดำเนินการที่เป็นตัวกระตุ้น

Webhook ช่วยให้สามารถรับการแจ้งเตือนแบบอะซิงโครนัสและเรียลไทม์เมื่อเกิดเหตุการณ์สำคัญบนบัญชีของคุณ แทนที่จะต้องส่ง request ซ้ำๆ ไปยัง API เพื่อตรวจสอบการเปลี่ยนแปลงสถานะ Webhook จะพุชการแจ้งเตือนไปยังเซิร์ฟเวอร์ของคุณโดยตรงในทันทีที่เหตุการณ์เกิดขึ้น

ประโยชน์หลัก:

  • ประสิทธิภาพ: ขจัดความจำเป็นในการ polling อย่างต่อเนื่อง ลด API call และภาระเซิร์ฟเวอร์ที่ไม่จำเป็น
  • การอัปเดตแบบเรียลไทม์: รับการแจ้งเตือนทันทีเมื่อเกิดเหตุการณ์ เช่น การชำระเงินสำเร็จ การคืนเงิน หรือการโต้แย้ง
  • การทำงานอัตโนมัติ: เรียกใช้เวิร์กโฟลว์อัตโนมัติในแอปพลิเคชันของคุณทันทีเมื่อได้รับเหตุการณ์ เช่น การอัปเดตสถานะคำสั่งซื้อ การส่งอีเมลให้ลูกค้า หรือการกระทบยอดบัญชี
  • ความน่าเชื่อถือ: รับประกันว่าคุณจะไม่พลาดเหตุการณ์สำคัญ แม้ในช่วงที่แอปพลิเคชันของคุณไม่ได้ตรวจสอบการอัปเดตอยู่

การตั้งค่า

ตั้งค่า Webhook endpoint แยกต่างหากสำหรับโหมดทดสอบและโหมดจริง:

การดูข้อมูล Event

เข้าถึงข้อมูล event ของ Webhook ทั้งหมดได้ผ่าน:

  • แดชบอร์ดในหัวข้อ Events คลิกไอคอน Account ที่แผงด้านขวาและเลือก Events
  • Events API

การ Serialize ข้อมูล

อ็อบเจกต์ event ใน POST request (หรือที่ส่งคืนผ่าน Events API) จะถูก serialize ตามค่าเริ่มต้นเวอร์ชัน API ณ เวลาที่เกิดเหตุการณ์เสมอ โดยไม่คำนึงถึงค่าของ header Omise-Version ที่ส่งมาใน request ที่เป็นตัวกระตุ้น

ตัวอย่าง

สำหรับบัญชีที่ตั้งค่าเวอร์ชันเป็น 2017-11-02:

  1. สร้าง charge โดยใช้ curl พร้อม -H "Omise-Version: 2019-05-29"
  2. Request ดังกล่าวสร้าง event charge.create ที่มีอ็อบเจกต์ charge ฝังอยู่
  3. อ็อบเจกต์จะถูก serialize ตามเวอร์ชัน 2017-11-02 ของCharge API ไม่ใช่ เวอร์ชัน 2019-05-29
  4. แม้หลังจากอัปเดตบัญชีเป็นเวอร์ชัน 2019-05-29 แล้ว event ก็ยังคง serialize ตามเวอร์ชัน 2017-11-02 อยู่

ข้อกำหนดและแนวปฏิบัติที่ดี

ข้อกำหนดทางเทคนิค

  • URL ต้อง ใช้ HTTPS
  • URL ต้อง ใช้ SSL certificate ที่ถูกต้อง (ไม่รองรับ self-signed certificate)
  • ตรวจสอบ SSL certificate ด้วย SSL Labs
  • สำหรับ SSL certificate ฟรี ไปที่ Let's Encrypt

แนวปฏิบัติด้านความปลอดภัย

แนะนำ: การตรวจสอบลายเซ็น

เราแนะนำอย่างยิ่งให้นำการตรวจสอบลายเซ็นมาใช้เป็นมาตรการรักษาความปลอดภัยหลักเพื่อรับรองความถูกต้องของ Webhook การตรวจสอบลายเซ็นยืนยันทางการเข้ารหัสว่า request มาจาก Omise และไม่ได้ถูกดัดแปลง ซึ่งให้การป้องกันที่แข็งแกร่งที่สุดจากผู้ไม่ประสงค์ดีที่พยายามส่ง Webhook ปลอมไปยัง endpoint ของคุณ ดูรายละเอียดการนำไปใช้งานได้ที่หัวข้อการปกป้อง Endpoint

ทางเลือก: การตรวจสอบ Event

หากการตรวจสอบลายเซ็นไม่สามารถนำไปใช้ได้ในการติดตั้งของคุณ ให้ใช้การตรวจสอบ event เป็นทางเลือก เมื่อได้รับ Webhook event (เช่น charge.complete) ให้ใช้ resource ID เพื่อส่ง GET request อิสระเพื่อยืนยันสถานะ โปรดทราบว่าวิธีนี้ไม่ได้ป้องกัน endpoint ของคุณจากการรับ request ปลอม แต่ช่วยให้คุณตรวจสอบความถูกต้องของข้อมูล event ได้หลังจากได้รับแล้วเท่านั้น

ตัวอย่างเวิร์กโฟลว์การตรวจสอบ event:

1. รับ Webhook `charge.complete`
2. ดึง Charge ID จาก Webhook payload
3. ส่ง GET request ไปที่ `/charges/{CHARGE_ID}`
4. ตรวจสอบสถานะ charge อย่างอิสระ

Event ที่รองรับ

Event บัตร

ชื่อ Event ตัวกระตุ้น
card.destroy บัตรถูกลบแล้ว
card.update บัตรถูกอัปเดตแล้ว

Event Charge

ชื่อ Event ตัวกระตุ้น
charge.capture Charge ถูก capture แล้ว (เฉพาะการ capture ด้วยตนเอง)
charge.complete Charge เสร็จสมบูรณ์แล้ว (หมายเหตุ: การทำ charge บัตรที่ไม่ใช่ 3DS ให้สำเร็จจะไม่ทริกเกอร์ Webhook นี้)
charge.create Charge ถูกสร้างแล้ว
charge.expire Charge หมดอายุแล้ว (เฉพาะ Barcode Alipay)
charge.reverse Charge ถูกยกเลิกแล้ว (เฉพาะการยกเลิกด้วยตนเอง)
charge.update Charge ถูกอัปเดตแล้ว

Event ลูกค้า

ชื่อ Event ตัวกระตุ้น
customer.create ลูกค้าถูกสร้างแล้ว
customer.destroy ลูกค้าถูกลบแล้ว
customer.update ลูกค้าถูกอัปเดตแล้ว
customer.update.card บัตรถูกอัปเดตโดยอัตโนมัติผ่านลูกค้า

Event การโต้แย้ง

ชื่อ Event ตัวกระตุ้น
dispute.accept การโต้แย้งได้รับการยอมรับแล้ว
dispute.close การโต้แย้งถูกปิดแล้ว
dispute.create การโต้แย้งถูกเปิดแล้ว
dispute.update การโต้แย้งถูกอัปเดตแล้ว

Event ผู้รับเงิน

ชื่อ Event ตัวกระตุ้น
recipient.activate ผู้รับเงินถูกเปิดใช้งานแล้ว
recipient.create ผู้รับเงินถูกสร้างแล้ว
recipient.deactivate ผู้รับเงินถูกปิดใช้งานแล้ว
recipient.destroy ผู้รับเงินถูกลบแล้ว
recipient.update ผู้รับเงินถูกอัปเดตแล้ว
recipient.verify ผู้รับเงินได้รับการยืนยันแล้ว

Event การคืนเงิน

ชื่อ Event ตัวกระตุ้น
refund.create การคืนเงินถูกสร้างแล้ว

Event กำหนดการ

ชื่อ Event ตัวกระตุ้น
schedule.create กำหนดการถูกสร้างแล้ว
schedule.destroy กำหนดการถูกลบแล้ว
schedule.expire กำหนดการหมดอายุแล้ว
schedule.expiring กำหนดการใกล้หมดอายุแล้ว
schedule.suspend กำหนดการถูกระงับแล้ว

Event การโอนเงิน

ชื่อ Event ตัวกระตุ้น
transfer.create การโอนเงินถูกสร้างแล้ว
transfer.destroy การโอนเงินถูกลบแล้ว
transfer.fail การโอนเงินถูกทำเครื่องหมายว่าล้มเหลว
transfer.pay การโอนเงินถูกทำเครื่องหมายว่าชำระแล้ว
transfer.send การโอนเงินถูกทำเครื่องหมายว่าส่งแล้ว
transfer.update การโอนเงินถูกอัปเดตแล้ว

Dynamic Webhook

บัญชี Omise ทุกบัญชีมี endpoint Webhook แบบ static ที่ตั้งค่าได้หนึ่งรายการ โดยค่าเริ่มต้น การแจ้งเตือน event ทั้งหมดจะถูกส่งไปยัง endpoint นี้

ฟีเจอร์ Dynamic Webhook ช่วยให้คุณระบุ endpoint Webhook แบบกำหนดเองในแต่ละ charge ได้ โดยส่งพารามิเตอร์ webhook_endpoints เมื่อสร้าง charge

การทำงาน

เมื่อระบุ webhook_endpoints:

  • Event ทั้งหมดสำหรับ charge นั้นจะถูกส่งไปยัง webhook_endpoints ที่ระบุ
  • Event จะไม่ถูกส่งไปยัง Webhook แบบ static

เมื่อไม่ได้ระบุ webhook_endpoints:

  • การแจ้งเตือน event จะถูกส่งไปยัง Webhook แบบ static ของบัญชี

การปกป้อง Endpoint

Omise ใช้อัลกอริทึม HMAC-SHA256 ในการลงนาม Webhook payload ทางการเข้ารหัส เมื่อมีการตั้งค่า Webhook secret ในบัญชีของคุณ ลายเซ็นดิจิทัลจะถูกรวมอยู่ใน Webhook header ตรวจสอบลายเซ็นเพื่อรับรองความถูกต้องและความครบถ้วนของ Webhook request

Header ลายเซ็น Webhook

Header คำอธิบาย
Omise-Signature ลายเซ็น HMAC ที่เข้ารหัสเป็น Hex ที่สร้างโดย Omise ระหว่างการหมุนเวียน secret header จะมีลายเซ็นสองรายการคั่นด้วยเครื่องหมายจุลภาค โดยแต่ละรายการสอดคล้องกับ secret แต่ละรายการ
Omise-Signature-Timestamp Unix timestamp เมื่อสร้างลายเซ็น

ตัวอย่าง header:

Omise-Signature: 072cc0d8b49d49ce7119857279b1e36a9efa25fadb468d0126628064d4062c83
Omise-Signature-Timestamp: 1758696391

// ระหว่างการหมุนเวียน
Omise-Signature: 072cc0d8b49d49ce7119857279b1e36a9efa25fadb468d0126628064d4062c83,4bb1e14023f53d076e598245e5e16fd96a94d46072149c483815718eecf2a38d

วิธีตรวจสอบลายเซ็น Webhook

ขั้นตอนที่ 1: ดึงลายเซ็น

ดึง header Omise-Signature และ Omise-Signature-Timestamp จาก Webhook request

ขั้นตอนที่ 2: เตรียม payload สำหรับลงนาม

สร้าง payload สำหรับการสร้างลายเซ็น HMAC โดยการต่อข้อมูลต่อไปนี้:

  1. ค่าของ header Omise-Signature-Timestamp
  2. จุด (.)
  3. raw body ของ Webhook request ที่เข้ารหัสเป็น UTF-8

รูปแบบ:

<TIMESTAMP>.<RAW_BODY>

ขั้นตอนที่ 3: ถอดรหัส Webhook Secret

Webhook secret คือ HMAC secret key ที่เข้ารหัสเป็น Base64 ถอดรหัสก่อนดำเนินการขั้นตอนถัดไป

ขั้นตอนที่ 4: คำนวณลายเซ็นที่คาดหวัง

คำนวณ HMAC-SHA256 digest ของ payload สำหรับลงนามโดยใช้ secret ที่ถอดรหัสแล้ว จากนั้นเข้ารหัสผลลัพธ์เป็นสตริง hexadecimal

ขั้นตอนที่ 5: เปรียบเทียบลายเซ็น

  1. วนซ้ำลายเซ็นทั้งหมดใน header Omise-Signature
  2. เปรียบเทียบลายเซ็นแต่ละรายการกับลายเซ็นที่คาดหวัง
  3. ปฏิเสธ Webhook request หากไม่มีลายเซ็นใดตรงกัน
  4. หากลายเซ็นตรงกัน คุณสามารถดำเนินการประมวลผล Webhook ได้ทันที หรือเลือกตรวจสอบ timestamp ก่อนเพื่อความปลอดภัยเพิ่มเติมจากการโจมตีแบบ replay

ข้อควรพิจารณาด้านความปลอดภัยที่สำคัญ:

  • การป้องกัน timing attack: ใช้อัลกอริทึมการเปรียบเทียบสตริงแบบ constant-time เมื่อเปรียบเทียบลายเซ็นเพื่อป้องกันการโจมตีแบบ timing
  • การป้องกัน replay attack (ไม่บังคับ): เพื่อความปลอดภัยที่เพิ่มขึ้น ให้ตรวจสอบ timestamp โดยคำนวณความแตกต่างระหว่างเวลาระบบปัจจุบันกับ timestamp ที่ได้รับ ปฏิเสธ Webhook หากความแตกต่างเกินกว่าที่ยอมรับได้ (เช่น 5 นาที) เพื่อป้องกันการโจมตีแบบ replay การตรวจสอบ timestamp เป็นตัวเลือกเสริม การที่ลายเซ็นตรงกันเพียงอย่างเดียวก็ยืนยันความถูกต้องของ Webhook ได้แล้ว

ตัวอย่างการนำไปใช้งาน

const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json({
  verify: (req, res, buf) => {
    req.rawBody = buf;
  }
}));

function verifySignature({ req }) {
  // ขั้นตอนที่ 1: ดึงลายเซ็น
  const signatureHeader = req.headers['omise-signature'];
  const timestampHeader = req.headers['omise-signature-timestamp'];

  // ขั้นตอนที่ 2: เตรียม payload สำหรับลงนาม
  const rawBody = req.rawBody.toString('utf8');
  const signedPayload = `${timestampHeader}.${rawBody}`;

  // ขั้นตอนที่ 3: ถอดรหัส Webhook secret
  const secret = Buffer.from('<YOUR_WEBHOOK_SECRET>', 'base64');

  // ขั้นตอนที่ 4: คำนวณลายเซ็นที่คาดหวัง
  const expectedBuffer = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest();

  // ขั้นตอนที่ 5: เปรียบเทียบกับลายเซ็นทั้งหมดใน header
  const signatures = signatureHeader.split(',');
  for (const sig of signatures) {
    const sigBuffer = Buffer.from(sig, 'hex');
    if (crypto.timingSafeEqual(sigBuffer, expectedBuffer)) {
      // ไม่บังคับ: เพิ่มการตรวจสอบ timestamp ได้ที่นี่
      return true;
    }
  }
  return false;
}

app.post('/webhook', (req, res) => {
  if (!verifySignature({ req })) {
    return res.status(401).send('Invalid signature');
  }

  // หากตรวจสอบแล้ว ส่ง 200 หลังจากประมวลผล Webhook
  res.status(200).send('OK');
});

การจัดการ Webhook Secret

คุณสามารถดู สร้าง และจัดการ Webhook secret ได้ในส่วนการตั้งค่า Webhook ของแดชบอร์ด Omise Secret เป็นแบบเฉพาะสภาพแวดล้อม โดย secret ของโหมดทดสอบแยกจาก secret ของโหมดจริง

⚠ ข้อควรระวัง: Webhook secret เป็นข้อมูลที่ต้องรักษาเป็นความลับ ให้จัดการเหมือนข้อมูลประจำตัวที่ละเอียดอ่อน อย่าเปิดเผยใน client-side code, repository สาธารณะ หรือแชร์ในสภาพแวดล้อมที่ไม่ปลอดภัยเป็นอันขาด

การหมุนเวียน Secret

หากคุณต้องการอัปเดต secret (เช่น เพื่อปฏิบัติตามข้อกำหนดด้านความปลอดภัย หรือเนื่องจาก secret ถูกเปิดเผย) Omise มีขั้นตอนการหมุนเวียนที่ไม่ต้องหยุดให้บริการ:

  • การหมุนเวียน Secret: เมื่อคุณ Roll secret ใหม่จะถูกสร้างขึ้นทันที เพื่อป้องกันการหยุดชะงักของบริการ secret เดิมจะยังคงใช้งานได้อีก24 ชั่วโมง
  • ลายเซ็นคู่: ในช่วงเปลี่ยนผ่าน 24 ชั่วโมงนี้ Omise จะลงนาม Webhook ทุกรายการด้วยทั้ง secret ใหม่และเก่า header Omise-Signature จะมีลายเซ็นสองรายการคั่นด้วยเครื่องหมายจุลภาค
  • การเพิกถอนด้วยตนเอง: คุณไม่สามารถลบ secret ที่ใช้งานอยู่หลักได้ อย่างไรก็ตาม คุณสามารถเพิกถอน secret ที่กำลังจะหมดอายุด้วยตนเองได้ตลอดเวลาในช่วง 24 ชั่วโมงเพื่อสิ้นสุดช่วงเปลี่ยนผ่านทันที
  • จำนวนสูงสุด: คุณสามารถมี secret ที่ใช้งานอยู่พร้อมกันได้สูงสุดสองรายการ (รายการปัจจุบันและรายการที่กำลังจะหมดอายุ) หาก secret ที่กำลังจะหมดอายุยังใช้งานอยู่ คุณต้องรอให้หมดอายุหรือเพิกถอนด้วยตนเองก่อนจึงจะ Roll secret ได้อีกครั้ง

การทดสอบ

เราแนะนำให้ใช้โหมดทดสอบเพื่อตรวจสอบตรรกะการตรวจสอบลายเซ็นก่อนเปลี่ยนไปใช้โหมดจริง

  • การจำลองที่ปลอดภัย: การหมุนเวียนหรือเพิกถอน secret ในโหมดทดสอบไม่มีผลกระทบต่อสภาพแวดล้อมการใช้งานจริงของโหมดจริง
  • การตรวจสอบตรรกะการหมุนเวียน: เราแนะนำอย่างยิ่งให้ทดสอบขั้นตอน การหมุนเวียน Secret ในโหมดทดสอบ เพื่อให้แน่ใจว่าโค้ดของคุณจัดการกับพฤติกรรมลายเซ็นคู่ได้อย่างถูกต้องก่อนที่จะหมุนเวียนในสภาพแวดล้อมการใช้งานจริง

การแก้ไขปัญหา

ปัญหาที่พบบ่อย

ไม่ได้รับ Webhook:

  • ตรวจสอบว่า URL ของ endpoint เป็น HTTPS พร้อม SSL certificate ที่ถูกต้อง
  • ตรวจสอบว่า firewall อนุญาต request ขาเข้าจาก IP ของเซิร์ฟเวอร์ Webhook Omise ต่อไปนี้:
    • 54.169.118.227
    • 52.74.199.175
    • 18.139.13.19
  • ยืนยันว่า endpoint เข้าถึงได้และตอบสนองต่อ request

การตรวจสอบลายเซ็นล้มเหลว:

  • ยืนยันว่าคุณใช้ Webhook secret ที่ถูกต้องสำหรับสภาพแวดล้อมของคุณ (ทดสอบ vs จริง)
  • ตรวจสอบว่าคุณใช้ raw request body โดยไม่มีการแก้ไขใดๆ
  • ตรวจสอบให้แน่ใจว่าถอดรหัส Base64 ของ Webhook secret อย่างถูกต้อง

Event ถูกส่งไปยัง endpoint ผิด:

  • ตรวจสอบว่ามีการระบุพารามิเตอร์ webhook_endpoints ระหว่างการสร้าง charge หรือไม่
  • ตรวจสอบการตั้งค่า Webhook แบบ static ในแดชบอร์ด

คำถามที่พบบ่อย

สามารถตั้งค่า endpoint Webhook แบบ static หลายรายการได้หรือไม่?

ไม่ได้ แต่ละบัญชี Omise รองรับ endpoint Webhook แบบ static เพียงหนึ่งรายการ หากต้องการส่ง event ไปยังหลายปลายทางในแต่ละ charge ให้ใช้ฟีเจอร์Dynamic Webhook และส่ง URL หลายรายการในพารามิเตอร์ webhook_endpoints เมื่อสร้าง charge

จะได้รับ Webhook สำหรับทุก event type โดยอัตโนมัติหรือไม่?

ใช่ โดยค่าเริ่มต้น endpoint Webhook แบบ static จะรับการแจ้งเตือนสำหรับ event type ที่รองรับทั้งหมด ปัจจุบันยังไม่มีตัวเลือกในการกรอง event type เฉพาะในระดับบัญชีสำหรับ endpoint แบบ static

endpoint ควรส่งคืน HTTP response code อะไร?

endpoint ควรส่งคืน response 200 OK หลังจากรับและประมวลผล Webhook สำเร็จ การส่งคืน status code ที่ไม่ใช่ 2xx อาจทำให้ Omise ถือว่าการส่งล้มเหลว

Omise จะลองส่ง Webhook ซ้ำเมื่อล้มเหลวหรือไม่?

Omise ไม่รับประกันการลองส่งซ้ำอัตโนมัติสำหรับการส่งที่ล้มเหลวในปัจจุบัน เพื่อให้แน่ใจว่าคุณไม่พลาด event ให้นำเวิร์กโฟลว์การตรวจสอบ event มาใช้เป็น fallback หรือ poll Events API สำหรับ event ที่คุณอาจพลาดไป

ทำไมจึงไม่ได้รับ Webhook สำหรับ charge บัตรที่ไม่ใช่ 3DS ที่เสร็จสมบูรณ์?

event charge.complete จะไม่ถูกทริกเกอร์สำหรับ charge บัตรที่ไม่ใช่ 3DS เฉพาะ charge ที่ผ่านกระบวนการยืนยันตัวตน 3DS หรือวิธีการชำระเงินแบบอะซิงโครนัสอื่นๆ เท่านั้นที่จะสร้าง Webhook charge.complete

สามารถใช้ endpoint Webhook เดียวกันสำหรับทั้งโหมดทดสอบและโหมดจริงได้หรือไม่?

ได้ แต่ไม่แนะนำ โหมดทดสอบและโหมดจริงใช้ Webhook secret ที่แตกต่างกัน ดังนั้น endpoint ของคุณจะต้องจัดการทั้งสองอย่าง การรักษา endpoint แยกต่างหากสำหรับแต่ละสภาพแวดล้อมจะปลอดภัยและจัดการได้ง่ายกว่า

จะจัดการการหมุนเวียน Webhook secret โดยไม่มี downtime ได้อย่างไร?

ใช้ตัวเลือก Roll ในการตั้งค่า Webhook ในช่วงเปลี่ยนผ่าน 24 ชั่วโมง Omise จะส่งทั้งลายเซ็นเก่าและใหม่ใน header Omise-Signature อัปเดตตรรกะการตรวจสอบของคุณให้ยอมรับลายเซ็นใดลายเซ็นหนึ่งก่อนเพิกถอน secret เก่า ดูรายละเอียดที่การหมุนเวียน Secret

ควรทำอย่างไรหาก Webhook secret ถูกเปิดเผย?

Roll secret ทันทีในการตั้งค่า Webhook เพื่อสร้าง secret ใหม่ จากนั้นเพิกถอน secret ที่กำลังจะหมดอายุด้วยตนเองเพื่อสิ้นสุดช่วงเปลี่ยนผ่านทันที อัปเดตแอปพลิเคชันของคุณด้วย secret ใหม่โดยเร็วที่สุด

แหล่งข้อมูลเพิ่มเติม

เว็ปไซต์นี้มีการใช้คุกกี้เพื่อวิเคราะห์การใช้และปรับการใช้งานให้เหมาะกับท่าน เมื่อกดยอมรับหรือยังคงเข้าชมเว็บไซต์ต่อ เราถือว่าท่านยินยอมในการใช้งานคุกกี้ของเว็บไซต์ อ่านนโยบายความเป็นส่วนตัว