Lompat ke konten utama

Contoh Implementasi Web Hook yang Praktis: Panduan Keamanan yang Terjamin

Temukan contoh web hook lengkap dengan code untuk Node.js, Python, dan Go. Pelajari cara memverifikasi tanda tangan dengan aman, mencegah serangan ulang, dan debug endpoint Anda.

Martin Donadieu

Martin Donadieu

Content Marketer

Contoh Web Hook yang Praktis: Panduan Implementasi Keamanan

Anda memiliki layanan yang perlu bereaksi ketika sesuatu terjadi di tempat lain. Pembayaran terkonfirmasi. Rekaman pelanggan berubah. Repo menerima push. Anda bisa memeriksa API setiap menit dan menghabiskan siklus dengan bertanya-tanya “apakah ada yang baru?” secara berulang-ulang, atau Anda bisa membiarkan sistem sumber memanggil Anda ketika event terjadi.

Itu di mana artikel contoh web hook biasanya berhenti. Mereka menampilkan sebuah route, mencetak tubuh JSON, mengembalikan, dan menganggapnya selesai. Versi tersebut berfungsi dengan baik hingga seseorang mengirimkan permintaan palsu, memulihkan permintaan yang valid, atau handler Anda rusak karena framework memproses tubuh sebelum verifikasi tanda tangan. 200Panduan ini mengambil jalur yang akan digunakan di produksi. Contoh-contoh tersebut kecil sehingga dapat dicopy, tetapi mereka termasuk bagian yang penting: penanganan tubuh mentah, verifikasi HMAC, pengecekan timestamp, pengakuan cepat, dan debugging yang praktis.

Daftar Isi

Apa Itu Webhook dan Mengapa Menggunakannya

Apa itu Webhook dan Mengapa Menggunakannya?

Pemberi tagihan Anda menandai faktur sebagai dibayar pada pukul 02:13. Jika aplikasi Anda mengetahui tentang itu pada pukul 02:14, pelanggan mendapatkan akses segera. Jika aplikasi Anda mengetahui tentang itu pada siklus polling berikutnya, mereka menunggu, dukungan mendapatkan tiket, dan log Anda penuh dengan kebisingan yang tidak perlu. Webhook menyelesaikan masalah waktu dengan mengirimkan panggilan balik HTTP ketika event terjadi.

Dalam istilah praktis, sebuah webhook adalah POST berdasarkan event dari satu sistem ke sistem lain. Pemberi mendeteksi perubahan, seperti invoice.paid, order.created, atau push, dan mengirimkan data event ke URL yang Anda kendalikan. Hal itu menghilangkan loop

This pattern shows up in real systems because it maps cleanly to business events. Stripe posts payment outcomes. GitHub posts repository activity. Shopify posts order updates. The shape is simple, but production behavior is not. A webhook that updates money, access, or inventory deserves the same care as any public API endpoint, especially once retries, duplicates, and untrusted traffic enter the picture.

Polanya muncul dalam sistem nyata karena memetakan dengan jelas ke event bisnis. Stripe mengirimkan hasil pembayaran. __CAPGO_KEEP_0__ mengirimkan aktivitas repositori. Shopify mengirimkan update pesanan. Bentuknya sederhana, tapi perilaku produksi tidak.

Polanya membantu mental Anda

  • Cara yang berguna untuk menggambarkan alur webhook adalah empat bagian yang bekerja bersama:Sumber sistem
  • . Layanan yang mendeteksi event.Tujuan endpoint
  • . Jalur HTTP Anda yang menerima event tersebut. Event. Perubahan yang dinamai yang terjadi, seperti invoice.paid atau push.
  • Payload. Tubuh permintaan dengan detail yang dibutuhkan oleh code Anda.

Pemasok mengirim fakta tentang sesuatu yang sudah terjadi. Tugas Anda adalah untuk memverifikasi pengirim, memastikan permintaan masih segar, dan menerapkan perubahan sekali. Bagian terakhir itu lebih penting daripada banyak tutorial dasar yang mengakui.

Aturan praktis: Gunakan webhooks untuk pembaruan berdasarkan acara. Gunakan polling untuk baca yang dijadwalkan, backfills, atau penyedia yang tidak menawarkan acara keluar.

Untuk tim yang membangun lebih luas integrasi otomatis alur kerja dan data, webhooks biasanya menjadi lapisan acara yang menjaga sistem tetap sinkron tanpa lalu lintas permintaan yang tidak perlu. Jika Anda bekerja pada layanan yang berat integrasi, Capgo’s artikel pengembangan backend bisa menjadi konteks yang berguna karena masalah inti muncul di sekitar retries, antrian, observabilitas, dan pengelolaan gagal.

What bekerja dan apa yang gagal di produksi

Konfigurasi yang dapat bertahan lama biasanya dirancang untuk menjadi menarik. Berlangganan hanya ke event yang Anda butuhkan. Simpan endpoint yang terbatas oleh penyedia atau keluarga event. Simpan ID event untuk menghindari pengiriman ulang efek samping. Kembalikan respons cepat 2xx setelah permintaan diverifikasi dan dikirim, kemudian lakukan logika bisnis yang lebih lambat secara asinkron.

Versi yang rapuh mudah dikenali. Satu endpoint umum mengelola segalanya. Pengecekan tanda tangan dibatalkan selama pengujian awal dan tidak pernah kembali. Pengolah menulis langsung ke tabel kritis sebelum memeriksa apakah event tersebut autentik atau sudah kadaluarsa. Hal ini berfungsi dalam demo dan gagal di bawah badai ulang, gangguan penyedia, atau penyerang yang merekam permintaan lama.

Perbandingan ini menentukan sisa panduan ini. Versi

hello world

Before writing code, it helps to look at the request as raw HTTP instead of as a framework object. A typical webhook is just an HTTP POST to a public endpoint with headers and a JSON body.

Anatomi Permintaan Webhook HTTP

POST /webhooks/orders HTTP/1.1
Host: your-app.example
Content-Type: application/json
User-Agent: Provider-Webhooks/1.0
X-Webhook-Signature: sha256=abc123example
X-Webhook-Timestamp: 1712345678

{
  "event": "order.created",
  "id": "evt_123",
  "data": {
    "order_id": "ord_456",
    "status": "created"
  }
}

Sebelum menulis __CAPGO_KEEP_0__, membantu untuk melihat permintaan sebagai HTTP mentah daripada sebagai objek framework. Webhook biasanya hanya sebuah permintaan HTTP POST ke endpoint publik dengan header dan tubuh JSON.

  • Permintaan sederhana mentahBagian pentingnya jelas:
  • Metode . Dalam prakteknya, pengiriman webhook biasanya adalah permintaan POST.
  • User-Agent. Bermanfaat untuk debugging, tapi tidak cukup untuk membangun kepercayaan.
  • Signature header. Mengandung pengecekan autentikasi penyedia.
  • Timestamp header. Digunakan untuk menolak permintaan yang sudah kadaluarsa atau direplay.

Mengapa bentuk tubuh penting

Objek code Anda biasanya tidak peduli dengan setiap bidang. Ia peduli dengan jenis event, identifikasi event, dan objek bisnis di dalamnya data. Oleh karena itu, pengelolaan yang baik hanya memproses apa yang dibutuhkan dan merekam yang lain untuk memecahkan masalah.

OpenAPI sekarang menggambarkan pola ini secara langsung. OpenAPI 3.1.0 menambahkan dukungan webhook dengan kelas pertama dengan top-level webhooks objek, di mana setiap webhook dijelaskan seperti Item Jalur tetapi diaktifkan oleh penyedia. Contoh yang umum menggunakan newPet webhook dengan post operasi, sebuah tubuh permintaan JSON, dan 200 respons untuk menunjukkan penerimaan, seperti yang ditunjukkan dalam contoh webhook OpenAPI Jika Anda sedang mendokumentasikan kontrak penerima atau penyedia sendiri, contoh yang kuat lebih berguna daripada prosa skema abstrak. Saya suka menggunakan referensi seperti.

contoh dokumen SheetMergy’s __CAPGO_KEEP_0__ SheetMergy’s API doc examples Webhook sederhana pada lapisan transportasi. Banyak kegagalan datang dari kesalahpahaman tentang kepala, pengkodean tubuh, atau aturan tanda tangan.

Bagaimana Mengamankan Tanda Tangan Webhook

Webhook yang ditandatangani menjawab satu pertanyaan: apakah payload ini berasal dari orang yang tahu rahasia bersama?

Hal itu berbeda dari bertanya apakah permintaan itu baru atau apakah Anda sudah memprosesnya. Verifikasi tanda tangan adalah pintu gerbang pertama, bukan yang terakhir.

Infografis yang menggambarkan proses enam langkah untuk mengamankan tanda tangan webhook untuk memastikan keaslian dan keamanan permintaan.

Alur verifikasi tanda tangan webhooks untuk memastikan keaslian dan keamanan permintaan.

Infografis menggambarkan alur verifikasi tanda tangan webhooks untuk memastikan keaslian dan keamanan permintaan.

Alur HMAC biasa terlihat seperti ini:

  1. Baca tanda tangan dari header penyedia.
  2. Baca badan permintaan mentah dengan tepat seperti yang diterima.
  3. Muat rahasia webhook Anda dari konfigurasi yang aman.
  4. Rekomputasi HMAC yang diharapkan menggunakan algoritma yang sama.
  5. Bandingkan tanda tangan yang diterima dan tanda tangan yang dihitung dengan perbandingan aman waktu.
  6. Tolak permintaan jika mereka tidak cocok.

Langkah itu raw-body adalah di mana banyak implementasi yang baik lainnya gagal. Jika kerangka kerja Anda memparse JSON terlebih dahulu, mereformat spasi putih, atau mengubah detail pengkodean sebelum hashing, tanda tangan yang dihitung Anda tidak akan cocok dengan penyedia.

Apa yang perlu diperhatikan dalam code yang nyata

Berikut adalah kesalahan yang paling sering saya lihat:

  • Menghashing JSON yang diproses. Jangan melakukan JSON.stringify(req.body) dan harapkan itu akan cocok.
  • Menggunakan kesamaan string normal. Gunakan perbandingan aman waktu.
  • Mengkodekan rahasia. Simpan mereka di variabel lingkungan atau manajer rahasia.
  • Mengandalkan header sendiri. Header tanda tangan hanya berarti jika Anda memverifikasinya.

Untuk tim yang memperketat penanganan rahasia di antara layanan, panduan Capgo tentang API keamanan kunci untuk kinerja toko aplikasi relevant karena disiplin yang sama berlaku di sini. Rotasi rahasia, akses yang dipetakan, dan menghindari kebocoran di log semua penting untuk penerima webhook juga.

A contoh verifikasi umum

const crypto = require('crypto');

function verifySignature(rawBody, receivedSignature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  const a = Buffer.from(receivedSignature, 'utf8');
  const b = Buffer.from(expected, 'utf8');

  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

Contoh ini sengaja umum. Pemasok nyata seringkali menambahkan tanda tangan, menggabungkan waktu menjadi konten yang ditandatangani, atau mengkodekan digest secara berbeda. Aturan tetap sama. Ikuti format penandatanganan pemasok secara tepat, dan selalu verifikasi terhadap payload mentah.

Mencegah Serangan Ulang

Webhook yang ditandatangani masih berbahaya jika sampai beberapa jam kemudian dan handler Anda menganggapnya sebagai yang baru. Hal itu lebih sering terjadi daripada tim yang diharapkan. Proksi merekam lalu lintas, isi pesan permintaan bocor ke tempat yang salah, atau pemasok mengulangi setelah gagal jaringan dan endpoint Anda memproses event yang sama dua kali.

Daftar Periksa untuk Mencegah Serangan Ulang

Pengverifikasi tanda tangan menjawab satu pertanyaan: apakah pengirim menciptakan payload ini dengan rahasia yang sama? Perlindungan ulang menjawab pertanyaan yang berbeda: apakah permintaan ini masih diterima sekarang? Penerima produksi membutuhkan kedua-duanya.

Periksa yang Paling Minim yang Benar-Benar Penting

Pertahanan ulang yang praktis dimulai dengan tanda tangan waktu. Pemasok mencantumkan waktu dalam header atau dalam pesan yang ditandatangani, dan penerima Anda menolak permintaan yang jatuh di luar jendela toleransi yang kecil.

Alur yang Harus Terlihat seperti Ini:

  • Baca waktu dari lokasi yang ditentukan pemasokJangan menebak nama header.
  • Parse sebagai bilangan bulat atau tanggal RFC-formatberdasarkan spesifikasi penyedia.
  • Bandingkan dengan jam server Anda.
  • Tolak permintaan yang terlalu tua atau terlalu jauh di masa depan.
  • Verifikasi tanggal sebagai bagian dari skema tanda tangan ketika penyedia mendukungnya.

Titik itu penting. Jika tanggal tidak tertutup oleh tanda tangan, seorang penyerang dapat mengganti tanggal segar dan memulai ulang tubuh asli. Saya selalu memeriksa format tanda tangan penyedia secara tepat sebelum saya percaya logika tanggal.

Apa yang harus dipilih untuk jendela toleransi

Limabelenit menit adalah default umum. Ini cukup pendek untuk mengurangi jendela serangan, tetapi cukup lama untuk bertahan melawan perbedaan jam kecil dan keterlambatan jaringan normal.

Ada perbandingan di sini. Jendela 30 detik terdengar lebih aman, tetapi lebih sering gagal dalam sistem nyata, terutama ketika ulang, antrian, atau keterlambatan regional terlibat. Jendela 30 menit lebih mudah dioperasikan, tetapi memberikan penyerang waktu yang lebih lama jika permintaan yang ditandatangani terbuka.

Pertahanan ulang bukan hanya pengecekan tanggal

Pengecekan tanggal memblokir permintaan yang ketinggalan. Ini tidak menghentikan pengolahan duplikat di dalam jendela yang valid. Jika event yang ditandatangani yang sama disampaikan dua kali dalam jendela itu, aplikasi Anda masih perlu mengenali.

Pertahankan lapisan kedua:

  • Melacak ID event atau ID pengiriman dalam penyimpanan sementara yang singkat seperti Redis.
  • Tangani handler sebagai idempoten agar pengiriman yang diulang tidak menciptakan pesanan, email, atau aksi tagihan yang sama.
  • Log permintaan yang ditolak yang sudah kadaluarsa dengan kode alasan, tetapi tidak pernah log rahasia atau muatan sensitif penuh.
  • Kembalikan respons yang cepat setelah validasi dan pekerjaan antrian berat di tempat lain.

Tim yang sudah berpikir tentang jendela kedaluwarsa dan revokasi akan mengenali pola ini. Capgo’s panduan untuk pola revokasi token di aplikasi Capacitor menutupi ide operasional yang sama. Suatu kredit atau permintaan yang sah sekali tidak boleh dipercaya selamanya.

Yang ditandatangani dan kadaluarsa masih berbahaya.

Building a Webhook Receiver in Node.js

Mengembangkan Penerima Webhook di Node.js

A laptop on a wooden desk displaying Node.js receiver code in a VS Code editor environment.

Fotografi laptop di atas meja kayu menampilkan penerima Node.js __CAPGO_KEEP_0__ di lingkungan editor VS __CAPGO_KEEP_1__.

const express = require('express');
const crypto = require('crypto');

const app = express();
const PORT = process.env.PORT || 3000;
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

// Capture raw body for signature verification
app.use(
  express.json({
    verify: (req, res, buf) => {
      req.rawBody = buf;
    },
  })
);

function safeEqual(a, b) {
  const aBuf = Buffer.from(a, 'utf8');
  const bBuf = Buffer.from(b, 'utf8');
  if (aBuf.length !== bBuf.length) return false;
  return crypto.timingSafeEqual(aBuf, bBuf);
}

function verifySignature(rawBody, secret, receivedSignature) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  return safeEqual(expected, receivedSignature);
}

function isFresh(timestampHeader, toleranceSeconds = 300) {
  const timestamp = Number(timestampHeader);
  if (!Number.isFinite(timestamp)) return false;

  const now = Math.floor(Date.now() / 1000);
  return Math.abs(now - timestamp) <= toleranceSeconds;
}

app.post('/webhooks/example', async (req, res) => {
  const signature = req.get('x-webhook-signature');
  const timestamp = req.get('x-webhook-timestamp');

  if (!WEBHOOK_SECRET) {
    return res.status(500).send('Webhook secret is not configured');
  }

  if (!signature || !timestamp) {
    return res.status(400).send('Missing required security headers');
  }

  if (!isFresh(timestamp)) {
    return res.status(401).send('Stale webhook');
  }

  const valid = verifySignature(req.rawBody, WEBHOOK_SECRET, signature);
  if (!valid) {
    return res.status(401).send('Invalid signature');
  }

  // Acknowledge quickly
  res.status(200).send('OK');

  // Process after acknowledgement
  try {
    const event = req.body;
    console.log('Accepted event:', event.event, event.id);
    // enqueueJob(event)
  } catch (err) {
    console.error('Post-ack processing failed:', err);
  }
});

app.listen(PORT, () => {
  console.log(`Webhook receiver listening on ${PORT}`);
});

Contoh produksi yang bijak menggunakan Express

Mengapa struktur ini tetap stabil

  • Pilihan-pilihan di sini adalah sengaja:Pemangkasan tubuh mentah terjadi di middleware
  • . Hal itu mempertahankan byte asli untuk hashing.Timestamp dicek sebelum logika bisnis
  • . Tidak ada gunanya melakukan pekerjaan untuk lalu lintas yang ketinggalan zaman. 200 Rute kembali dengan cepat. Tugas berjalan lama harus dimasukkan ke dalam antrian atau tugas latar belakang.
  • Post-ack processing dipisahkan. Bahkan jika logika hilir gagal, jalur penerima tetap kecil.

Rahasia adalah titik lemah dalam banyak implementasi webhook. Jangan simpan mereka di sumber, jangan tempel mereka ke fixture uji, dan jangan echo mereka di log. Jika Anda membutuhkan proses yang lebih luas seputar rotasi dan pengelolaan CI, Capgo’s guide to menangani rahasia di pipeline CI/CD menutup sisi operasional dengan baik.

Langkah-langkah singkat membantu jika Anda ingin melihat bagian-bagian yang bergerak secara langsung:

Apa yang saya ubah untuk sistem hidup

Untuk integrasi penyedia yang sebenarnya, saya akan menambahkan deduplikasi ID event di penyimpanan persisten, log struktur dengan ID permintaan, dan antrian di belakang jalur pengakuan. Saya juga akan menghindari endpoint umum yang satu jika penyedia-penyedia lain menggunakan format tanda tangan yang berbeda. Penggunaan handler yang terpisah lebih mudah untuk dipahami dan lebih sulit untuk rusak.

Membangun Penerima Webhook di Python

Flask adalah pilihan yang baik untuk contoh webhook yang bersih karena pengelolaan permintaan yang eksplisit dan Python’s library standar sudah memberikan apa yang Anda butuhkan untuk HMAC.

Hal utama yang perlu diingat adalah sama seperti di Node. Verifikasi terhadap byte permintaan asli, bukan kamus JSON yang diparsing.

A Contoh Flask dengan pengecekan tanda tangan dan timestamp

import os
import time
import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = os.environ.get("WEBHOOK_SECRET", "")

def is_fresh(timestamp_header, tolerance_seconds=300):
    try:
        timestamp = int(timestamp_header)
    except (TypeError, ValueError):
        return False

    now = int(time.time())
    return abs(now - timestamp) <= tolerance_seconds

def verify_signature(raw_body, secret, received_signature):
    expected = hmac.new(
        secret.encode("utf-8"),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, received_signature)

@app.route("/webhooks/example", methods=["POST"])
def webhook():
    if not WEBHOOK_SECRET:
        return "Webhook secret is not configured", 500

    signature = request.headers.get("X-Webhook-Signature")
    timestamp = request.headers.get("X-Webhook-Timestamp")

    if not signature or not timestamp:
        return "Missing required security headers", 400

    if not is_fresh(timestamp):
        return "Stale webhook", 401

    raw_body = request.get_data()

    if not verify_signature(raw_body, WEBHOOK_SECRET, signature):
        return "Invalid signature", 401

    payload = request.get_json(silent=True) or {}

    # Acknowledge receipt
    response = jsonify({"status": "ok"})

    # In production, queue payload here instead of heavy sync work
    print("Accepted event:", payload.get("event"), payload.get("id"))

    return response, 200

if __name__ == "__main__":
    app.run(port=5000, debug=True)

Detail khusus Flask yang berpengaruh

request.get_data() adalah panggilan utama di sini. Ia memberikan Anda byte mentah dari tubuh. Jika Anda langsung melompat ke request.json, Anda telah melangkah melewati garis di mana kesalahan tanda tangan menjadi bingung.

Catatan implementasi beberapa hal:

  • Pakai hmac.compare_digest bukalh perbandingan sederhana.
  • Tangani kepala yang hilang sebagai gagal klien dan tolak awal.
  • Pakai silent=True untuk parsing JSON jika Anda ingin mengontrol pengelolaan kesalahan daripada membiarkan Flask mengangkatnya.
  • Jaga rute tipis. Tambahkan pekerjaan jika payload memicu sesuatu yang mahal.

Tidak debug kesalahan tanda tangan dengan menurunkan cek keamanan. Debug mereka dengan mencetak secara tepat apa saja byte yang di-hash dan apa saja format yang diharapkan penyedia.

Dimana tim biasanya terjebak

Jalan kegagalan yang umum adalah melakukan pengujian dengan JSON yang dibangun tangan, kemudian beralih ke penyedia nyata dan menemukan tanda tangan tidak lagi cocok. Biasanya berarti salah satu dari tiga hal: penyedia menandatangani amplop yang bertanggal, tanda tangan dikodekan berbeda dari yang Anda asumsikan, atau middleware mengubah tubuh sebelum verifikasi.

Ketika itu terjadi, hentikan mengubah crypto code secara acak. Tangkap header mentah dan tubuh mentah, reproduksi hash dalam skrip terisolasi yang kecil, dan baru kemudian masukkan kembali ke dalam rute Flask.

Membangun Penerima Webhook di Go

Go adalah pilihan yang bagus untuk penerima webhook karena library standar sudah cukup. Anda tidak memerlukan framework untuk mendapatkan handler kecil yang dapat diandalkan, dan code mudah untuk menjaga kejujuran.

Satu hal yang perlu diwaspadai adalah pengelolaan tubuh. r.Body adalah aliran. Baca sekali, hash byte yang Anda dapat, dan kemudian unmarshalling dari byte yang sama.

Contoh library standar

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"crypto/subtle"
	"encoding/hex"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"time"
)

type WebhookPayload struct {
	Event string          `json:"event"`
	ID    string          `json:"id"`
	Data  json.RawMessage `json:"data"`
}

func isFresh(timestampHeader string, toleranceSeconds int64) bool {
	ts, err := strconv.ParseInt(timestampHeader, 10, 64)
	if err != nil {
		return false
	}

	now := time.Now().Unix()
	diff := now - ts
	if diff < 0 {
		diff = -diff
	}

	return diff <= toleranceSeconds
}

func verifySignature(rawBody []byte, secret string, received string) bool {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write(rawBody)
	expected := hex.EncodeToString(mac.Sum(nil))

	if len(expected) != len(received) {
		return false
	}

	return subtle.ConstantTimeCompare([]byte(expected), []byte(received)) == 1
}

func webhookHandler(secret string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
			return
		}

		signature := r.Header.Get("X-Webhook-Signature")
		timestamp := r.Header.Get("X-Webhook-Timestamp")

		if signature == "" || timestamp == "" {
			http.Error(w, "missing required security headers", http.StatusBadRequest)
			return
		}

		if !isFresh(timestamp, 300) {
			http.Error(w, "stale webhook", http.StatusUnauthorized)
			return
		}

		rawBody, err := io.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "failed to read body", http.StatusBadRequest)
			return
		}

		if !verifySignature(rawBody, secret, signature) {
			http.Error(w, "invalid signature", http.StatusUnauthorized)
			return
		}

		var payload WebhookPayload
		if err := json.Unmarshal(rawBody, &payload); err != nil {
			http.Error(w, "invalid json", http.StatusBadRequest)
			return
		}

		w.WriteHeader(http.StatusOK)
		w.Write([]byte("OK"))

		log.Printf("accepted event=%s id=%s", payload.Event, payload.ID)
	}
}

func main() {
	secret := os.Getenv("WEBHOOK_SECRET")
	if secret == "" {
		log.Fatal("WEBHOOK_SECRET is not set")
	}

	http.HandleFunc("/webhooks/example", webhookHandler(secret))

	log.Println("listening on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

Mengapa Go terasa solid di sini

Beberapa manfaat yang menonjol:

  • Pengaturan handler jelas. Tidak ada sihir middleware yang disembunyikan.
  • Menggunakan tipe membantu di tepi. Parsing header, konversi timestamp, dan dekripsi JSON semua gagal dengan jelas.
  • Paket kriptografi standar sudah cukup. Tidak perlu dependensi tambahan untuk verifikasi HMAC dasar.

Catatan Operasional

Jika volume webhook tumbuh, model konkurensi Go memberikan ruang untuk membagi pekerjaan latar belakang tanpa mengubah pintu masuk HTTP Anda. Bahkan saat itu, tetaplah menerima yang sempit. Terima, validasi, konfirmasi, lalu tukarkan.

Pengaturan Webhook Go yang kuat biasanya tetap sederhana. Mereka tidak mencampur verifikasi transportasi dengan logika bisnis, dan mereka tidak melakukan pekerjaan basis data berat sebelum respons dikembalikan.

Teknik Debugging yang Paling Penting

Biasanya, bug webhook muncul sebagai pesan dukungan, bukan tumpukan jejak. Pemberi mengatakan mereka telah mengirimkan event. Endpoint Anda mengatakan tidak ada yang mencapai aplikasi, atau verifikasi tanda tangan gagal pada permintaan yang terlihat valid pada pandangan pertama. Pada titik itu, debugging adalah tentang merekonstruksi pertukaran HTTP yang tepat, byte per byte, dan membuktikan di mana itu gagal.

Daftar lima alat dan teknik penting untuk debugging webhook dalam lingkungan pengembangan perangkat lunak.

Kit Debugging Praktis

Mulai dengan format kabel.

Jika periksa tanda tangan gagal, tangkap tubuh permintaan mentah secara tepat seperti yang diterima, bersama dengan header yang digunakan untuk verifikasi. Pada kenyataannya, bug sering kali membosankan. Suatu kerangka memproses JSON sebelum hashing, suatu proxy mengubah encoding, atau suatu ulang tayang tes melewatkan timestamp asli header. Mencetak objek yang diproses tidak cukup. Anda memerlukan byte asli dan input verifikasi.

Alat-alat ini membantu mengisolasi masalah cepat:

  • Perekaman permintaan mentah. Log header, jenis konten, panjang konten, dan tubuh yang tidak dimodifikasi selama penyelidikan.
  • Endpoint Inspeksi Permintaan. Layanan seperti webhook.site membantu memastikan apa yang dikirimkan pengirim.
  • Tunneling Lokal. ngrok dan alat-alat serupa memungkinkan Anda menguji terhadap penerima lokal sambil menjaga penyedia dalam jalur.
  • Manual replay. Rebuild permintaan dengan curl atau menggunakan Postman dengan tubuh dan header yang sama. Itu adalah cara tercepat untuk memastikan apakah code atau payload penyedia adalah masalah.
  • Catatan pengiriman penyedia. Dashboard pengirim sering kali mencakup kode respons, riwayat ulang, dan identifikasi permintaan yang dapat Anda sesuaikan dengan log Anda.

Polanya penting. Kerja dari luar ke dalam. Pertama, verifikasi apakah penyedia mengirimkan apa yang Anda harapkan. Kemudian, verifikasi apakah server Anda menerima byte yang sama. Kemudian, verifikasi apakah code menghash byte yang sama dengan aturan dan timestamp yang sama.

Pengaturan log yang bermanfaat

Log webhook yang baik harus menjawab tiga pertanyaan dalam satu pencarian:

PertanyaanBidang log yang berguna
Apakah permintaan sampai?rute, metode, received_at
Mengapa itu ditolak?__CAPGO_KEEP_0__
Apakah saya bisa menghubungkannya kemudian?__CAPGO_KEEP_0__, __CAPGO_KEEP_1__

Bidang keempat membantu dalam sistem nyata. Tambahkan sebuah lokal request_id __CAPGO_KEEP_0__ yang dihasilkan oleh penerima Anda sehingga Anda bisa mengikuti permintaan melalui log aplikasi, antrian, dan log pekerja.

Pilihlah dengan selektif apa yang disimpan. Tidak pernah log rahasia. Hindari membuang payload produksi penuh jika mereka termasuk data pelanggan, token akses, atau detail tagihan. Pola yang lebih aman adalah log metadata plus hash tubuh singkat. Itu masih memungkinkan Anda membandingkan ulang dan memastikan apakah dua pengiriman identik.

Reproduksi gagal dengan input asli

Bagian ini adalah yang dasar tutorial abaikan. Jika Anda tidak bisa merekam permintaan gagal secara tepat, Anda hanya menebak.

Simpan webhook gagal sebagai:

  • byte byte tubuh asli
  • semua header terkait tanda tangan
  • Waktu permintaan
  • Jenis konten
  • ID permintaan penyedia

Kemudian ulangi itu terhadap endpoint pengujian. Jika ulangan itu berhasil, bandingkan apa yang berubah selama transit. Pemicu umum termasuk middleware yang menyederhanakan tubuh permintaan, kesalahan pengkodean karakter, dan load balancer yang menghilangkan atau menulis ulang header. Saya juga telah melihat gagal karena tim menyalin beban dari tampilan dashboard yang diprint dengan cantik daripada tubuh permintaan asli. Perbedaan whitespace saja sudah cukup untuk memecahkan verifikasi HMAC.

Untuk rilis yang lebih luas dan troubleshooting transportasi mobile, disiplin debugging yang sama muncul dalam panduan Capgo untuk Alat-alat untuk debugging pembaruan OTA di CapacitorTransportasi yang berbeda, pelajaran yang sama. Tangkap jalur permintaan asli sebelum mengubah aplikasi code.

Jika verifikasi tanda tangan gagal, inspect byte-byte yang asli, header yang tepat yang digunakan dalam verifikasi, dan nilai timestamp sebelum menyentuh kriptografi code.

Daftar Periksa untuk Webhook yang Siap Produksi

Pengolah webhook biasanya terlihat baik di pengujian sampai badai ulangan pertama, beban yang rusak, atau kesalahan tanda tangan pada pukul 2 pagi. Batas produksi lebih tinggi. Penerima harus menolak permintaan palsu, menerima ulangan yang sah, dan memberikan signal yang cukup kepada operator untuk debug gagal tanpa mengungkapkan data sensitif.

Pemeriksaan keamanan dan korektif

  • Verifikasi setiap tanda tangan permintaan. URL endpoint terbuka. URL tes dibagikan di obrolan. Verifikasi tanda tangan adalah kontrol yang memberitahu Anda bahwa pengirim mengetahui rahasia yang disepakati.
  • Tolak permintaan lama. Tanda tangan yang valid pada payload lama masih dapat direplay. Tetapkan toleransi waktu yang sesuai dengan model ulang provider.
  • Hashkan tubuh mentah, bukan JSON yang diparsing. Middleware dapat mengurutkan kunci, normalisasi spasi, atau mengubah encoding. Verifikasi harus berjalan terhadap byte yang tepat yang datang.
  • Tetapkan rahasia tanda tangan di luar code. Variabel lingkungan adalah dasar. Manajer rahasia lebih baik jika Anda memutar kredential secara berkala atau menjalankan di beberapa lingkungan.
  • Gagal tutup pada kesalahan autentikasi. Jika header tanda tangan hilang, rusak, atau menggunakan skema yang tidak terduga, tolak permintaan dan log alasan.

Pengecekan keandalan

  • Konfirmasi cepat. Provider biasanya menganggap 2xx apa pun sebagai kesuksesan, jadi validasi permintaan, simpan apa yang Anda butuhkan, dan lakukan pekerjaan yang lambat ke dalam antrian atau pekerjaan.
  • Buat handler idempoten. Acara yang sama mungkin datang lebih dari sekali. Angkat efek sampingan dari ID acara, ID pengiriman, atau identifikasi penyedia stabil lainnya.
  • Kembalikan kode error yang dapat diprediksi. Gunakan 400 untuk masukan yang rusak, 401 atau 403 untuk verifikasi gagal, dan 5xx hanya ketika sistem Anda adalah masalah. Hal ini membuat perilaku ulang penyedia lebih mudah dipahami.
  • Tetapkan batasan sebelum memparse. Batasi ukuran permintaan Cap, jenis konten, dan jumlah header awal. Ini mencegah endpoint webhook berubah menjadi lubang pengingesan umum.
  • Tetapkan kontrak sempit. Terima hanya bidang dan jenis acara yang Anda dukung. Pemparse yang longgar terasa nyaman pada awalnya dan menjadi mahal selama penyedia API berubah.

Periksaan Observabilitas

Operasi webhook yang baik terlihat membosankan. Tim dapat menjawab tiga pertanyaan dengan cepat: Apakah kita menerima itu? Apakah kita memverifikasi itu? Apakah proses downstream berhasil?

Pakai standar:

  • Ikuti penerimaan, verifikasi, dan pengolahan sebagai hasil yang terpisah.
  • Tandai ID permintaan, ID event, status tanda tangan, dan pergeseran waktu.
  • Ukur delay antrian, latensi pengolah, dan volume ulang coba.
  • Tetapkan jalur ulang main yang aman untuk alur kerja staging atau redelivery.
  • Peringatkan perubahan polaseperti lonjakan kegagalan tanda tangan atau pengiriman duplikat.

Capgo adalah contoh yang berguna dari titik operasional yang lebih luas. Ini termasuk alat sekitar pengiriman rilis dan observabilitas dalam alur kerja pembaruan, dan bagian dari ekosistemnya juga menyentuh alur-alur terkait webhook. Pelajaran ini sangat praktis. Sistem pengiriman membutuhkan visibilitas dari penerimaan hingga selesai.

Jika tim menutupi periksaan di atas, penerima webhook biasanya dalam keadaan baik untuk produksi. Jika ada item yang hilang, celah tersebut cenderung muncul selama insiden, bukan selama demo.

Frequently Asked Questions About Webhooks

Apa status code yang harus saya kembalikan?

Kembalikan sebuah 2xx ketika Anda telah menerima webhook. Jika validasi gagal, kembalikan sebuah kesalahan klien atau autentikasi yang sesuai dengan kegagalan, seperti 400 untuk input yang rusak atau 401 untuk data autentikasi yang tidak valid. Pastikan logika tersebut konsisten sehingga dashboard penyedia lebih mudah dipahami.

Apakah saya harus memproses webhook secara sinkron?

Biasanya tidak. Validasi, konfirmasi, lalu push pekerjaan sebenarnya ke antrian atau pekerja latar belakang. Hal ini menjaga jalur pengiriman tetap cepat dan mengurangi ulang coba yang disebabkan oleh proses downstream yang lambat.

Bagaimana saya harus menghandle ulang coba?

Anggap mereka akan terjadi. Bangun ketahanan idempotensi ke dalam handler Anda sehingga menerima event yang sama lagi tidak akan menimbulkan efek sampingan yang berulang. ID event atau ID pengiriman penyedia biasanya digunakan sebagai anker untuk itu.

Apa jika event tiba-tiba tidak berurutan?

Desain handler untuk toleran terhadap urutan ketika Anda bisa. Jika proses bisnis memerlukan urutan, simpan cukup state untuk mendeteksi transisi yang ketinggalan waktu daripada menganggap urutan pengiriman menunjukkan urutan event.

How do I menghadapi perubahan versi webhook?

Versi logika pengolah Anda secara sengaja. Pegang parsing spesifik penyedia terisolasi, hindari menyebarkan asumsi payload melalui kodebase Anda, dan tambahkan tes dengan contoh sampel yang nyata sebelum meluncurkan dukungan untuk format baru.


Jika tim Anda mengirimkan Capacitor atau aplikasi Electron, Capgo adalah hal yang perlu diketahui karena alasan yang terkait. Ini memberikan tim cara yang terkendali untuk menyampaikan pembaruan web yang ditandatangani, mengamati perilaku pengiriman, dan pulih dari insiden tanpa menunggu tinjauan aplikasi toko, yang sesuai dengan insting insinyur yang sama di balik desain webhook yang solid: validasi input, jaga jalur rilis teramati, dan lakukan pemulihan dengan cepat.

Pembaruan langsung untuk aplikasi Capacitor

Ketika bug layer web masih aktif, kirimkan perbaikan melalui Capgo bukan menunggu hari-hari untuk persetujuan toko aplikasi. Pengguna mendapatkan pembaruan di latar belakang sementara perubahan native tetap dalam jalur review normal.

Mulai Sekarang

Terbaru dari Blog Kami

Capgo memberikan Anda wawasan terbaik yang Anda butuhkan untuk membuat aplikasi mobile yang profesional.