Appearance
ภาพรวม Webhook
GameSO ส่ง webhook notification ไปยัง Merchant เมื่อ order มีการเปลี่ยนแปลงสถานะ ช่วยให้ Merchant รับทราบผลลัพธ์แบบ real-time โดยไม่ต้อง poll API
Webhook Events
| Event | เมื่อไหร่ |
|---|---|
order.completed | เมื่อทุก item ใน order เสร็จสมบูรณ์ |
order.failed | เมื่อ order ล้มเหลว |
ขั้นตอนการทำงาน
1. Merchant สร้าง order
│
▼
2. ระบบประมวลผล items
│
▼
3. Order เสร็จ/ล้มเหลว
│
▼
4. GameSO ส่ง POST request ไปยัง Webhook URL ของ Merchant
│
▼
5. Merchant ตอบกลับ HTTP 200ข้อกำหนดของ Webhook Endpoint
Merchant ต้องมี HTTP endpoint ที่:
- รับ
POSTrequest - ตอบกลับ
HTTP 200ภายใน 30 วินาที - รองรับ
Content-Type: application/json - แนะนำให้ใช้ HTTPS
WARNING
หาก endpoint ตอบกลับช้าเกิน 30 วินาที หรือตอบกลับ status code ที่ไม่ใช่ 2xx ระบบจะถือว่า delivery ล้มเหลว
Retry Policy
หาก webhook delivery ล้มเหลว ระบบจะ retry อัตโนมัติ:
| Retry | หลังจาก |
|---|---|
| ครั้งที่ 1 | 1 นาที |
| ครั้งที่ 2 | 5 นาที |
| ครั้งที่ 3 | 30 นาที |
หลังจาก retry ครบ 3 ครั้งแล้วยังล้มเหลว ระบบจะหยุด retry
ตัวอย่าง Webhook Handler
javascript
const express = require("express");
const crypto = require("crypto");
const app = express();
app.use(express.json());
app.post("/webhooks/gameso", (req, res) => {
// 1. ตรวจสอบ signature ก่อน
const signature = req.headers["x-webhook-signature"];
const payload = JSON.stringify(req.body);
const secret = process.env.GAMESO_WEBHOOK_SECRET;
const expectedSig = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
if (signature !== `sha256=${expectedSig}`) {
return res.status(401).json({ error: "Invalid signature" });
}
// 2. ประมวลผล event
const { event, data } = req.body;
if (event === "order.completed") {
console.log(`Order ${data.order_number} completed!`);
// อัพเดทสถานะในระบบของคุณ
} else if (event === "order.failed") {
console.log(
`Order ${data.order_number} failed: ${data.failure_message}`,
);
// จัดการ error
}
// 3. ตอบกลับ 200 ทันที
res.status(200).json({ received: true });
});python
import hmac
import hashlib
import json
import os
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhooks/gameso', methods=['POST'])
def gameso_webhook():
# 1. ตรวจสอบ signature
signature = request.headers.get('X-Webhook-Signature', '')
payload = request.get_data(as_text=True)
secret = os.environ['GAMESO_WEBHOOK_SECRET']
expected = 'sha256=' + hmac.new(
secret.encode(), payload.encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return jsonify({'error': 'Invalid signature'}), 401
# 2. ประมวลผล event
body = request.json
event = body['event']
data = body['data']
if event == 'order.completed':
print(f"Order {data['order_number']} completed!")
# อัพเดทสถานะในระบบของคุณ
elif event == 'order.failed':
print(f"Order {data['order_number']} failed: {data['failure_message']}")
# 3. ตอบกลับ 200
return jsonify({'received': True}), 200php
<?php
// 1. ตรวจสอบ signature
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
$secret = getenv('GAMESO_WEBHOOK_SECRET');
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($signature, $expected)) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
exit;
}
// 2. ประมวลผล event
$body = json_decode($payload, true);
$event = $body['event'];
$data = $body['data'];
if ($event === 'order.completed') {
// อัพเดทสถานะในระบบของคุณ
error_log("Order {$data['order_number']} completed!");
} elseif ($event === 'order.failed') {
error_log("Order {$data['order_number']} failed: {$data['failure_message']}");
}
// 3. ตอบกลับ 200
http_response_code(200);
echo json_encode(['received' => true]);ขั้นตอนถัดไป
- Webhook Payload & Signature Verification — รายละเอียด payload และวิธีตรวจสอบ signature
