ข้ามไปยังเนื้อหาหลัก

การทดสอบเวบฮุก

คำแนะนำที่สมบูรณ์สำหรับการทดสอบการจัดส่งเวบฮุก, การใช้งานตัวจัดการเวบฮุก, การแก้ไขปัญหาเหตุการณ์เวบฮุก และการตั้งค่าการทดสอบเวบฮุกแบบอัตโนมัติสำหรับการผสานรวม Omise ของคุณ

ภาพรวม

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

เหตุใดจึงต้องทดสอบเวบฮุก

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

กลยุทธ์การทดสอบเวบฮุก

  1. การทดสอบในเครื่อง: ใช้ ngrok เพื่อทดสอบเวบฮุกบนเครื่องท้องถิ่นของคุณ
  2. การทดสอบด้วย Mock: ใช้บริการการทดสอบเวบฮุกสำหรับการทดสอบอย่างรวดเร็ว
  3. การทดสอบแบบอัตโนมัติ: เขียนการทดสอบสำหรับตัวจัดการเวบฮุกของคุณ
  4. การทดสอบการผสานรวม: ทดสอบลำดับการไหลของเวบฮุกแบบปลายต่อปลาย
  5. การตรวจสอบการผลิต: ตรวจสอบการจัดส่งและการประมวลผลเวบฮุก

การตั้งค่าการทดสอบเวบฮุก

การกำหนดค่าจุดสิ้นสุดเวบฮุก

ก่อนอื่น, ให้กำหนดค่าจุดสิ้นสุดเวบฮุกของคุณในแดชบอร์ด Omise:

  1. ไปที่ การตั้งค่า > เวบฮุก
  2. คลิก เพิ่มจุดสิ้นสุดเวบฮุก
  3. ป้อน URL เวบฮุกของคุณ
  4. เลือกเหตุการณ์เพื่อรับ
  5. บันทึกการกำหนดค่า

สำหรับการพัฒนาในเครื่อง, ใช้ ngrok เพื่อสร้าง URL สาธารณะ

ความเข้าใจในเหตุการณ์เวบฮุก

Omise ส่งเวบฮุกสำหรับเหตุการณ์เหล่านี้:

เหตุการณ์คำอธิบาย
charge.createประจำที่สร้าง
charge.completeประจำสำเร็จแล้ว
charge.expireประจำหมดอายุโดยไม่มีการชำระเงิน
refund.createการคืนเงินสร้าง
transfer.createการโอนสร้าง
transfer.payการโอนออก
customer.createลูกค้าสร้าง
customer.updateลูกค้าอัปเดต
customer.destroyลูกค้าลบ
card.createบัตรสร้าง
card.updateบัตรอัปเดต
card.destroyบัตรลบ
dispute.createข้อพิพาทสร้าง
dispute.updateข้อพิพาทอัปเดต

การทดสอบด้วย ngrok

การติดตั้ง ngrok

ngrok สร้างอุโมงค์ที่ปลอดภัยสู่ localhost ของคุณ, ช่วยให้ Omise สามารถส่งเวบฮุกไปยังเครื่องพัฒนาของคุณ

การติดตั้ง:

# macOS (Homebrew)
brew install ngrok

# Windows (Chocolatey)
choco install ngrok

# Linux (โหลดตรง)
wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
unzip ngrok-stable-linux-amd64.zip
sudo mv ngrok /usr/local/bin/

# ตรวจสอบการติดตั้ง
ngrok version

ลงทะเบียนและตรวจสอบสิทธิ์:

# ลงทะเบียนที่ https://dashboard.ngrok.com/signup
# รับโทเค็นการตรวจสอบสิทธิ์จาก https://dashboard.ngrok.com/get-started/your-authtoken

ngrok config add-authtoken YOUR_AUTH_TOKEN

การใช้ ngrok สำหรับการทดสอบเวบฮุก

เริ่มต้นอุโมงค์ ngrok:

# ส่งต่อไปยังพอร์ต 3000 ในเครื่อง
ngrok http 3000

# ด้วยโดเมนย่อยที่กำหนดเอง (แผนที่จ่ายเงิน)
ngrok http -subdomain=myapp 3000

# ด้วยภูมิภาคที่กำหนดเอง
ngrok http -region=ap 3000

ผลลัพธ์ ngrok:

Session Status                online
Account your@email.com
Version 3.0.0
Region Asia Pacific (ap)
Web Interface http://127.0.0.1:4040
Forwarding https://abc123.ap.ngrok.io -> http://localhost:3000

ใช้ URL ส่งต่อในแดชบอร์ด Omise:

Webhook URL: https://abc123.ap.ngrok.io/webhooks

การทดสอบด้วย Webhook.site

การใช้ Webhook.site

Webhook.site มี URL ชั่วคราวสำหรับการทดสอบเวบฮุกโดยไม่ต้องเขียนโค้ด

ขั้นตอน:

  1. ไปที่ https://webhook.site
  2. คัดลอก URL ที่ไม่ซ้ำกันของคุณ (เช่น https://webhook.site/abc-123)
  3. เพิ่ม URL นี้เข้าไปในเวบฮุก Omise Dashboard
  4. เรียกใช้เหตุการณ์ทดสอบใน Omise
  5. ดูคำขอแบบเรียลไทม์บน webhook.site

ฟีเจอร์:

  • ดู headers, body และ query parameters ของคำขอ
  • ตรวจสอบสถานะการตอบสนองและ body
  • แก้ไขและปรับแต่งการตอบสนอง
  • ส่งออกข้อมูลคำขอ
  • แชร์ URL เวบฮุกกับทีม

การทดสอบแบบอัตโนมัติ

การทดสอบด้วย Jest (JavaScript/Node.js)

// webhook.test.js - Jest tests สำหรับตัวจัดการเวบฮุก
const request = require('supertest');
const crypto = require('crypto');
const app = require('./app'); // แอป Express ของคุณ

describe('Webhook Handler', () => {
const SECRET_KEY = 'skey_test_xxxxxxxxxx';

function generateSignature(payload) {
return crypto
.createHmac('sha256', SECRET_KEY)
.update(JSON.stringify(payload))
.digest('hex');
}

describe('POST /webhooks', () => {
test('ควรยอมรับเวบฮุกที่ถูกต้องพร้อมลายเซ็นที่ถูกต้อง', async () => {
const payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_123',
amount: 100000,
currency: 'THB',
status: 'successful'
}
};

const signature = generateSignature(payload);

const response = await request(app)
.post('/webhooks')
.set('X-Omise-Signature', signature)
.send(payload);

expect(response.status).toBe(200);
expect(response.body).toEqual({ received: true });
});

test('ควรปฏิเสธเวบฮุกที่มีลายเซ็นไม่ถูกต้อง', async () => {
const payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_123',
amount: 100000,
currency: 'THB',
status: 'successful'
}
};

const response = await request(app)
.post('/webhooks')
.set('X-Omise-Signature', 'invalid_signature')
.send(payload);

expect(response.status).toBe(401);
expect(response.body).toHaveProperty('error');
});

test('ควรจัดการเหตุการณ์ charge.complete', async () => {
const payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_123',
amount: 100000,
currency: 'THB',
status: 'successful'
}
};

const signature = generateSignature(payload);

const response = await request(app)
.post('/webhooks')
.set('X-Omise-Signature', signature)
.send(payload);

expect(response.status).toBe(200);

// ตรวจสอบว่าเหตุการณ์ได้รับการประมวลผล
// ตรวจสอบฐานข้อมูล, บันทึก ฯลฯ
});

test('ควรจัดการเวบฮุกที่ซ้ำกันอย่างสมมาตร', async () => {
const payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_125',
amount: 100000,
currency: 'THB',
status: 'successful'
}
};

const signature = generateSignature(payload);

// ส่งเวบฮุกเดียวกันสองครั้ง
const response1 = await request(app)
.post('/webhooks')
.set('X-Omise-Signature', signature)
.send(payload);

const response2 = await request(app)
.post('/webhooks')
.set('X-Omise-Signature', signature)
.send(payload);

expect(response1.status).toBe(200);
expect(response2.status).toBe(200);

// ตรวจสอบว่าเหตุการณ์ได้รับการประมวลผลเพียงครั้งเดียว
// ตรวจสอบฐานข้อมูลเพื่อดูบันทึกเดียว
});
});
});

การทดสอบด้วย Pytest (Python)

# test_webhooks.py - Pytest tests สำหรับตัวจัดการเวบฮุก
import pytest
import json
import hmac
import hashlib
from flask import Flask
from app import app # แอป Flask ของคุณ

@pytest.fixture
def client():
"""สร้างไคลเอนต์ทดสอบ"""
app.config['TESTING'] = True
with app.test_client() as client:
yield client

@pytest.fixture
def secret_key():
"""คีย์ลับทดสอบ"""
return 'skey_test_xxxxxxxxxx'

def generate_signature(payload, secret_key):
"""สร้างลายเซ็น HMAC สำหรับเวบฮุก"""
payload_str = json.dumps(payload)
signature = hmac.new(
secret_key.encode('utf-8'),
payload_str.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature

class TestWebhookHandler:
"""ทดสอบตัวจัดการเวบฮุก"""

def test_valid_webhook_with_correct_signature(self, client, secret_key):
"""ควรยอมรับเวบฮุกที่ถูกต้องพร้อมลายเซ็นที่ถูกต้อง"""
payload = {
'key': 'charge.complete',
'data': {
'id': 'chrg_test_123',
'amount': 100000,
'currency': 'THB',
'status': 'successful'
}
}

signature = generate_signature(payload, secret_key)

response = client.post(
'/webhooks',
data=json.dumps(payload),
headers={
'Content-Type': 'application/json',
'X-Omise-Signature': signature
}
)

assert response.status_code == 200
assert response.json['received'] == True

def test_reject_invalid_signature(self, client):
"""ควรปฏิเสธเวบฮุกที่มีลายเซ็นไม่ถูกต้อง"""
payload = {
'key': 'charge.complete',
'data': {'id': 'chrg_test_123'}
}

response = client.post(
'/webhooks',
data=json.dumps(payload),
headers={
'Content-Type': 'application/json',
'X-Omise-Signature': 'invalid_signature'
}
)

assert response.status_code == 401
assert 'error' in response.json

def test_handle_charge_complete(self, client, secret_key):
"""ควรจัดการเหตุการณ์ charge.complete"""
payload = {
'key': 'charge.complete',
'data': {
'id': 'chrg_test_123',
'amount': 100000,
'currency': 'THB',
'status': 'successful'
}
}

signature = generate_signature(payload, secret_key)

response = client.post(
'/webhooks',
data=json.dumps(payload),
headers={
'Content-Type': 'application/json',
'X-Omise-Signature': signature
}
)

assert response.status_code == 200
# ตรวจสอบว่าเหตุการณ์ได้รับการประมวลผลอย่างถูกต้อง
# ตรวจสอบฐานข้อมูล, บันทึก ฯลฯ

@pytest.mark.parametrize('event_key,expected_status', [
('charge.complete', 200),
('charge.expire', 200),
('refund.create', 200),
('transfer.create', 200),
])
def test_handle_different_events(self, client, secret_key, event_key, expected_status):
"""ควรจัดการประเภทเหตุการณ์ที่แตกต่างกัน"""
payload = {
'key': event_key,
'data': {'id': 'test_123'}
}

signature = generate_signature(payload, secret_key)

response = client.post(
'/webhooks',
data=json.dumps(payload),
headers={
'Content-Type': 'application/json',
'X-Omise-Signature': signature
}
)

assert response.status_code == expected_status

การทดสอบด้วย RSpec (Ruby)

# spec/webhooks_spec.rb - RSpec tests สำหรับตัวจัดการเวบฮุก
require 'rails_helper'
require 'openssl'
require 'json'

RSpec.describe 'Webhooks', type: :request do
let(:secret_key) { 'skey_test_xxxxxxxxxx' }

def generate_signature(payload)
OpenSSL::HMAC.hexdigest(
OpenSSL::Digest.new('sha256'),
secret_key,
payload.to_json
)
end

describe 'POST /webhooks' do
context 'ด้วยลายเซ็นที่ถูกต้อง' do
it 'ยอมรับเวบฮุกและส่งกลับ 200' do
payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_123',
amount: 100_000,
currency: 'THB',
status: 'successful'
}
}

signature = generate_signature(payload)

post '/webhooks',
params: payload.to_json,
headers: {
'Content-Type' => 'application/json',
'X-Omise-Signature' => signature
}

expect(response).to have_http_status(:ok)
expect(JSON.parse(response.body)['received']).to be true
end
end

context 'ด้วยลายเซ็นไม่ถูกต้อง' do
it 'ปฏิเสธเวบฮุกและส่งกลับ 401' do
payload = {
key: 'charge.complete',
data: { id: 'chrg_test_123' }
}

post '/webhooks',
params: payload.to_json,
headers: {
'Content-Type' => 'application/json',
'X-Omise-Signature' => 'invalid_signature'
}

expect(response).to have_http_status(:unauthorized)
end
end

context 'การจัดการเหตุการณ์ charge.complete' do
it 'ประมวลผลการทำให้ประจำเสร็จสิ้น' do
payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_123',
amount: 100_000,
currency: 'THB',
status: 'successful'
}
}

signature = generate_signature(payload)

expect {
post '/webhooks',
params: payload.to_json,
headers: {
'Content-Type' => 'application/json',
'X-Omise-Signature' => signature
}
}.to change { ProcessedWebhook.count }.by(1)

expect(response).to have_http_status(:ok)
end
end

context 'การจัดการเวบฮุกที่ซ้ำกัน' do
it 'ประมวลผลเวบฮุกเพียงครั้งเดียว' do
payload = {
key: 'charge.complete',
data: {
id: 'chrg_test_125',
amount: 100_000,
currency: 'THB',
status: 'successful'
}
}

signature = generate_signature(payload)

# ส่งเวบฮุกสองครั้ง
2.times do
post '/webhooks',
params: payload.to_json,
headers: {
'Content-Type' => 'application/json',
'X-Omise-Signature' => signature
}

expect(response).to have_http_status(:ok)
end

# ตรวจสอบว่าประมวลผลเพียงครั้งเดียว
expect(ProcessedWebhook.where(event_id: payload[:data][:id]).count).to eq(1)
end
end
end
end

การผสานรวม CI/CD

GitHub Actions สำหรับการทดสอบเวบฮุก

# .github/workflows/test-webhooks.yml
name: ทดสอบเวบฮุก

on:
push:
branches: [main, develop]
pull_request:
branches: [main]

jobs:
test-webhooks:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:13
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- uses: actions/checkout@v3

- name: ตั้งค่า Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'

- name: ติดตั้งความต้องการ
run: npm ci

- name: ตั้งค่าฐานข้อมูลทดสอบ
run: npm run db:setup
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db

- name: เรียกใช้การทดสอบเวบฮุก
run: npm test -- --testPathPattern=webhooks
env:
OMISE_SECRET_KEY: ${{ secrets.OMISE_SECRET_KEY_TEST }}
NODE_ENV: test

- name: อัปโหลดผลการทดสอบ
if: always()
uses: actions/upload-artifact@v3
with:
name: webhook-test-results
path: test-results/

แนวทางปฏิบัติที่ดี

1. ตรวจสอบลายเซ็นเวบฮุก

ตรวจสอบลายเซ็นเวบฮุกเสมอเพื่อป้องกันการปลอมแปลง:

<?php
// PHP - การตรวจสอบลายเซ็นเวบฮุก
function verifyWebhookSignature($payload, $signature, $secretKey) {
$expectedSignature = hash_hmac('sha256', $payload, $secretKey);

// ใช้การเปรียบเทียบที่ปลอดภัยจากการกำหนดเวลา
return hash_equals($expectedSignature, $signature);
}

// การใช้งาน
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_OMISE_SIGNATURE'] ?? '';

if (!verifyWebhookSignature($payload, $signature, $secretKey)) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
exit;
}

// ประมวลผลเวบฮุก
$event = json_decode($payload, true);
processWebhook($event);

http_response_code(200);
echo json_encode(['received' => true]);
?>

2. ประมวลผลเวบฮุกแบบไม่ซิงโครนัส

ตอบสนองต่อเวบฮุกอย่างรวดเร็วและประมวลผลแบบไม่ซิงโครนัส:

# Python - การประมวลผลเวบฮุกแบบไม่ซิงโครนัส
from flask import Flask, request, jsonify
import threading
import queue

app = Flask(__name__)
webhook_queue = queue.Queue()

def process_webhooks_async():
"""คนงานพื้นหลังเพื่อประมวลผลเวบฮุก"""
while True:
try:
event = webhook_queue.get()

# ประมวลผลเหตุการณ์
process_webhook_event(event)

webhook_queue.task_done()
except Exception as e:
print(f'Error processing webhook: {e}')

# เริ่มคนงานพื้นหลัง
worker_thread = threading.Thread(target=process_webhooks_async, daemon=True)
worker_thread.start()

@app.route('/webhooks', methods=['POST'])
def handle_webhook():
# ตรวจสอบลายเซ็น
if not verify_signature(request):
return jsonify({'error': 'Invalid signature'}), 401

# เข้าคิวสำหรับประมวลผล
event = request.json
webhook_queue.put(event)

# ตอบสนองทันที
return jsonify({'received': True}), 200

def process_webhook_event(event):
"""ประมวลผลเหตุการณ์เวบฮุก (ทำงานในพื้นหลัง)"""
event_key = event.get('key')
data = event.get('data', {})

try:
if event_key == 'charge.complete':
handle_charge_complete(data)
elif event_key == 'refund.create':
handle_refund_create(data)
# จัดการเหตุการณ์อื่นๆ...

except Exception as e:
print(f'Error in webhook processing: {e}')
# บันทึกข้อผิดพลาด, ส่งการแจ้งเตือน ฯลฯ

3. บันทึกเหตุการณ์เวบฮุก

บันทึกอย่างครอบคลุมเพื่อการแก้ไขปัญหา:

// JavaScript - การบันทึกเวบฮุก
const winston = require('winston');

const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'webhooks-error.log', level: 'error' }),
new winston.transports.File({ filename: 'webhooks.log' })
]
});

app.post('/webhooks', (req, res) => {
const event = req.body;
const signature = req.headers['x-omise-signature'];

// บันทึกเวบฮุกที่ได้รับ
logger.info('Webhook received', {
event_key: event.key,
event_id: event.data?.id,
timestamp: new Date().toISOString(),
signature: signature
});

try {
// ตรวจสอบลายเซ็น
if (!verifySignature(req.body, signature)) {
logger.error('Invalid webhook signature', {
event_key: event.key,
signature: signature
});
return res.status(401).json({ error: 'Invalid signature' });
}

// ประมวลผลเวบฮุก
processWebhook(event);

logger.info('Webhook processed successfully', {
event_key: event.key,
event_id: event.data?.id
});

res.json({ received: true });

} catch (error) {
logger.error('Webhook processing failed', {
event_key: event.key,
error: error.message,
stack: error.stack
});

res.status(500).json({ error: 'Processing failed' });
}
});

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

ปัญหาทั่วไป

ปัญหา: เวบฮุกไม่ได้รับ

สาเหตุที่เป็นไปได้:

  • URL เวบฮุกไม่ได้กำหนดค่าในแดชบอร์ด Omise
  • ไฟร์วอลล์บล็อกคำขอ
  • อุโมงค์ ngrok ไม่ทำงาน
  • เซิร์ฟเวอร์ไม่รับฟังบนพอร์ตที่ถูกต้อง

วิธีแก้ไข:

  1. ตรวจสอบ URL เวบฮุกในแดชบอร์ด Omise
  2. ตรวจสอบบันทึกเซิร์ฟเวอร์สำหรับคำขอขาเข้า
  3. ทดสอบด้วย webhook.site ก่อน
  4. ตรวจสอบว่า ngrok ทำงานอยู่: curl http://localhost:4040/api/tunnels

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

สาเหตุที่เป็นไปได้:

  • ใช้คีย์ลับไม่ถูกต้อง
  • เปรียบเทียบกับรูปแบบเพย์โหลดไม่ถูกต้อง
  • ปัญหาการเข้ารหัส

วิธีแก้ไข:

// ลายเซ็นการแก้ไขข้อบกพร่อง
const receivedSignature = req.headers['x-omise-signature'];
const payload = JSON.stringify(req.body);
const secretKey = process.env.OMISE_SECRET_KEY;

const expectedSignature = crypto
.createHmac('sha256', secretKey)
.update(payload)
.digest('hex');

console.log('Received:', receivedSignature);
console.log('Expected:', expectedSignature);
console.log('Match:', receivedSignature === expectedSignature);

ปัญหา: เวบฮุกหมดเวลา

สาเหตุ: การประมวลผลใช้เวลานานเกินไป

วิธีแก้ไข: ประมวลผลแบบไม่ซิงโครนัส:

# ตอบสนองอย่างรวดเร็ว, ประมวลผลแบบไม่ซิงโครนัส
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
event = request.json

# เข้าคิวสำหรับประมวลผลในพื้นหลัง
celery_app.send_task('process_webhook', args=[event])

# ตอบสนองทันที
return jsonify({'received': True}), 200

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

Omise รอตอบสนองเวบฮุกนานแค่ไหน

Omise รอ 30 วินาทีเพื่อให้จุดสิ้นสุดของคุณตอบสนอง หากไม่มีการตอบสนองภายใน 30 วินาที, เวบฮุกจะถูกทำเครื่องหมายว่าล้มเหลวและจะลองใหม่

ฉันต้องตรวจสอบลายเซ็นเวบฮุกหรือไม่

ใช่, ตรวจสอบลายเซ็นเวบฮุกเสมอเพื่อป้องกันการปลอมแปลง Omise ลงนามในเวบฮุกทั้งหมดด้วย HMAC-SHA256 โดยใช้คีย์ลับของคุณ

ฉันสามารถทดสอบเวบฮุกในโหมดทดสอบได้หรือไม่

ใช่, โหมดทดสอบส่งเวบฮุกเช่นเดียวกับการผลิต กำหนดค่าจุดสิ้นสุดเวบฮุกโหมดทดสอบแยกต่างหากในแดชบอร์ด Omise

ฉันสามารถเล่นเวบฮุกใหม่ได้หรือไม่

ใช่, คุณสามารถเล่นเวบฮุกใหม่ได้จากแดชบอร์ด Omise ไปที่ การตั้งค่า > เวบฮุก, ค้นหาเหตุการณ์ และคลิก "ส่งใหม่"

ฉันควรจัดการเวบฮุกที่ซ้ำกันอย่างไร

ใช้ ID เหตุการณ์เพื่อติดตามเหตุการณ์ที่คุณประมวลผลแล้ว เก็บ ID เหตุการณ์ที่ประมวลผลแล้วในฐานข้อมูลของคุณและข้ามการประมวลผลซ้ำ

ทรัพยากรที่เกี่ยวข้อง

ขั้นตอนถัดไป

  1. ตั้งค่า ngrok สำหรับการทดสอบเวบฮุกในเครื่อง
  2. ใช้การตรวจสอบลายเซ็น ในตัวจัดการเวบฮุกของคุณ
  3. เพิ่มการจัดการความสามารถในการเป็นปัญหาเดียวกัน เพื่อป้องกันการประมวลผลซ้ำ
  4. เขียนการทดสอบแบบอัตโนมัติ สำหรับตัวจัดการเวบฮุกของคุณ
  5. ประมวลผลเวบฮุกแบบไม่ซิงโครนัส เพื่อประสิทธิภาพที่ดีขึ้น
  6. เพิ่มการบันทึกที่ครอบคลุม เพื่อการแก้ไขปัญหา
  7. ตั้งค่าการตรวจสอบสุขภาพเวบฮุก สำหรับโหมดการผลิต
  8. ทดสอบเหตุการณ์เวบฮุกทั้งหมด ที่แอปพลิเคชันของคุณจัดการ

พร้อมปรับใช้งาน ดูรายการตรวจสอบการทำงานเพื่อไปใช้งาน

ต้องการข้อมูลทดสอบ ดูเลขบัตรทดสอบและข้อมูล