वेबहुक टेस्टिंग
Webhook एक HTTP callback है: जब किसी system (provider) में कोई event होता है, तो वह एक HTTP request, आम तौर पर JSON body वाला POST, उस URL पर भेजता है जिसे दूसरे system (consumer) ने पहले से register किया हो। उदाहरण: card payment सफल होने पर payment provider payment.succeeded event को https://shop.example/webhooks/payments पर post करता है, और shop order 1042 को paid mark करके एक receipt email करती है।
Webhook testing इस call के दोनों पक्ष जाँचती है। Provider को documented event signed रूप में भेजना है और delivery fail होने पर retry करना है। Consumer, जिस पर आम तौर पर tester का ध्यान रहता है, को forged requests reject करनी हैं, असली requests acknowledge करनी हैं और हर event का असर सिर्फ़ एक बार होने देना है, चाहे वह देर से, दो बार या उल्टे क्रम में आए।
यह क्यों ज़रूरी है
Webhooks बिना किसी के देखे चलते हैं। कोई webhook खो जाए या दो बार process हो जाए, तो आम तौर पर कोई screen error नहीं दिखाती: paid order "pending" ही रहता है, stock दो बार घटता है या customer को दो receipts मिलती हैं। Defect अक्सर कई दिन बाद सामने आता है, जब उसे reproduce करना मुश्किल होता है।
Webhook endpoint एक public URL भी है। जिसे भी यह मिल जाए वह नकली "payment succeeded" event भेज सकता है, इसलिए signature verification एक security control है, और इसे गलत implement करना आसान है। इसे टेस्ट करने का मतलब है forged और बदली हुई deliveries भेजना, सिर्फ़ उन systems पर जो आपके अपने हैं या जिन्हें टेस्ट करने की आपके पास लिखित अनुमति है।
Callbacks, acknowledgement और retries
REST lessons में client पूछता था और server जवाब देता था। Webhook भूमिकाएँ उलट देता है: provider का server client है, और consumer का endpoint request receive करता है। Consumer delivery को जल्दी 2xx status लौटाकर acknowledge करता है; कोई भी दूसरा status (3xx, 4xx, 5xx), timeout या refused connection आम तौर पर failed delivery माना जाता है।
इसके बाद कई providers attempts के बीच बढ़ते अंतराल के साथ, एक सीमित अवधि तक retry करते हैं; कुछ लगातार fail होने वाले endpoint को disable कर देते हैं, और कुछ retry करते ही नहीं, बल्कि manual redelivery देते हैं। Failure के नियम, timeout और schedule हर provider में अलग होते हैं, इसलिए provider का webhook documentation आपका test basis है।
Retries का मतलब है कि delivery "at least once" होती है: अगर consumer ने काम कर दिया लेकिन उसका response खो गया या बहुत धीमा था, तो वही event फिर आता है। आम तौर पर हर event का एक id होता है जो हर retry में वही रहता है (कुछ providers हर attempt का अलग id भी जोड़ते हैं), और इसी id से duplicate पहचाना जाता है। आम तौर पर क्रम की भी guarantee नहीं होती: retry हुआ payment.succeeded उसके बाद हुए payment.refunded के भी बाद पहुँच सकता है।
Idempotency: हर event का असर सिर्फ़ एक बार
Processing idempotent तब है जब किसी event को दो बार handle करने का असर एक बार handle करने जैसा ही हो, जैसे idempotent HTTP methods में। आम design: event id को unique constraint वाली table में store करें; unique constraint database का एक नियम है जो उसी value वाली दूसरी row को मना कर देता है। अगर id पहले से मौजूद है, तो consumer कुछ नहीं करता और फिर भी 2xx लौटाता है; error status लौटाने से provider बस उस event को retry करता रहेगा जो पहले ही handle हो चुका है। यह भी पूछें कि id store होने के बाद काम ही fail हो जाए तो क्या होता है: तब retry को duplicate मानकर छोड़ना नहीं चाहिए, वरना event खो जाता है।
एक event की दो copies एक ही पल में दो server instances पर भी आ सकती हैं। Code में "पहले check, फिर insert" दोनों को निकल जाने दे सकता है; database का unique constraint दूसरी को रोकता है। गलत क्रम से बचने के लिए consumer event की तुलना current state से करता है, ताकि refunded order कभी वापस paid न बने।
- पेमेंट provider भेजता है और retry करता है
- शॉप का webhook endpoint verify, record, acknowledge
- शॉप का डेटाबेस event id पर unique key
- 1 पेमेंट provider से शॉप का webhook endpoint तक: Attempt 1: signed event POST करें
id: evt_7f3a91 - 2 शॉप का webhook endpoint आंतरिक रूप से: signature और timestamp verify करें पास
- 3 शॉप का webhook endpoint से शॉप का डेटाबेस तक: event id insert करें, order 1042 को PAID करें एक receipt queue में जाती है
- 4 शॉप का webhook endpoint से पेमेंट provider तक: response खो गया या timeout के बाद पहुँचा जवाब provider इसे failed delivery मानता है फ़ेल
- 5 पेमेंट provider आंतरिक रूप से: रुकें, फिर retry करें attempts के बीच बढ़ता अंतराल सावधानी
- 6 पेमेंट provider से शॉप का webhook endpoint तक: Attempt 2: वही event दोबारा वही event id, नया timestamp और signature
id: evt_7f3a91 - 7 शॉप का webhook endpoint आंतरिक रूप से: signature और timestamp verify करें पास
- 8 शॉप का webhook endpoint से शॉप का डेटाबेस तक: वही event id insert करें
- 9 शॉप का डेटाबेस से शॉप का webhook endpoint तक: पहले से stored: unique key इसे रोकती है जवाब दूसरी receipt नहीं, order में कोई बदलाव नहीं
- 10 शॉप का webhook endpoint से पेमेंट provider तक: 200 OK: duplicate acknowledge हुआ जवाब पास
परिणाम: दो बार deliver, एक बार process: order 1042 paid है और customer को ठीक एक receipt मिलती है। पास
Signature की जाँच
कई providers हर delivery को HMAC (RFC 2104) से sign करते हैं: यह secret key के साथ calculate किया गया hash है, इसलिए सही value सिर्फ़ key वाला ही बना सकता है, और message का एक byte बदलने से value पूरी तरह बदल जाती है। आम तौर पर यह HMAC-SHA256 होता है, एक ऐसे secret से जो सिर्फ़ provider और consumer जानते हैं, ठीक उसी raw body पर, अक्सर आगे timestamp (Unix time: 1 जनवरी 1970 UTC से बीते seconds) जोड़कर। Consumer मिले हुए bytes पर HMAC दोबारा calculate करके तुलना करता है। मेल खाने का मतलब है कि sender secret जानता है और body बदली नहीं गई; पुराने timestamps reject करने से capture की गई request का replay सीमित होता है। Providers आम तौर पर हर attempt को नए सिरे से sign करते हैं, इसलिए घंटों बाद आया retry नया timestamp लेकर आता है। Verification raw bytes पर ही करें: जो handler पहले JSON को फिर से serialise करता है, वह असामान्य spacing या key order वाली valid deliveries reject कर देता है। नीचे की scheme सिर्फ़ उदाहरण है: हर provider अपने headers और format खुद document करता है।
secret shared value from the provider settings (test mode)
timestamp 1790000000, sent in the Pay-Timestamp header
input "1790000000." + raw body bytes, exactly as received
signature hex( HMAC-SHA256(secret, input) ), sent in Pay-Signature
consumer recomputes over the raw bytes it received, compares with the
header, and rejects a timestamp outside the tolerance windowCapture endpoint से टेस्टिंग
Capture endpoint, जिसे अक्सर request bin कहते हैं, एक temporary public URL है जो उस पर आने वाली हर request record करता है। इसे provider के test mode में webhook URL के रूप में register करें, कोई event trigger करें, और आपको असली delivery दिखेगी: method, headers, raw body और timing। इससे consumer बनने से पहले ही provider side टेस्ट हो जाती है: payload को documentation से मिलाएँ और test secret से उसका signature verify करें।
फिर captured delivery consumer के लिए test data बन जाती है। इसे replay करें, यानी वही method, headers और raw body फिर से भेजें, उदाहरण के लिए cURL से: duplicates टेस्ट करने के लिए बिना बदले और timestamp window के अंदर, stale deliveries का rejection टेस्ट करने के लिए window बीतने के बाद, और rejection टेस्ट करने के लिए एक byte बदलकर। Window के अंदर सिर्फ़ वही चीज़ गलत होती है जो आपने बदली; उसके बाहर अकेला पुराना timestamp ही rejection का कारण बन जाता है। HMAC tool से अपने variants sign करें। Retries देखने के लिए delivery जानबूझकर fail करवाएँ (consumer रोक दें, उससे 503 लौटवाएँ, या provider को ऐसे endpoint पर point करें जो 5xx status लौटाता है) और provider के delivery log में attempts पढ़ें।
- Capture endpoint आम तौर पर हर चीज़ पर
200लौटाता है: यह साबित करता है कि provider ने क्या भेजा, यह नहीं कि आपका consumer काम करता है। - सिर्फ़ test mode, test secrets और synthetic data इस्तेमाल करें, क्योंकि captures कुछ समय तक किसी server पर stored रहते हैं। कोई secret leak हो जाए तो उसे rotate करवाएँ।
आज़माएँ: Webhook टेस्टर आज़माएँ: Webhook इंस्पेक्टर आज़माएँ: Webhook पेलोड फ़ॉर्मेटर आज़माएँ: API स्टेटस कोड सिम्युलेटर
Worked example: payment webhook के tests
Requirement: "Valid payment.succeeded event आने पर order को paid mark करें और एक receipt भेजें। Deliveries timestamp और body पर HMAC-SHA256 से signed हैं; 300 seconds से पुराने timestamps reject होते हैं। Provider हर non-2xx response और 10 seconds से धीमे हर response पर retry करता है।" एक captured delivery:
- W1: valid नई delivery → 10 seconds के अंदर
2xx, order 1042 PAID, एक receipt। - W2: वही delivery replay, और W3: एक साथ दो copies →
2xx, फिर भी एक receipt और एक stored event id। - W4: बिना re-sign किए amount "1.00" कर दिया, signature नहीं, या दूसरा secret →
4xx, order वैसा ही, rejection logged। - W5: valid signature, timestamp 300 और 301 seconds पुराना → accept, reject (2-value boundary value analysis: "300 से पुराना" वाले नियम में 300 accepted partition में रहता है)। Request के रास्ते में रहते age बढ़ती है, इसलिए पूछें कि उसे कैसे मापा और round किया जाता है।
- W6: retry वाला
payment.succeededआने से पहलेpayment.refundedprocess हो चुका → order REFUNDED ही रहे। - W7: पहले attempt पर
503→ provider retry करे, retry सफल हो, एक receipt।
POST /webhooks/payments HTTP/1.1
Host: shop.example
Content-Type: application/json
Pay-Timestamp: 1790000000
Pay-Signature: sha256=<hex HMAC-SHA256 of "1790000000." + raw body>
{
"id": "evt_7f3a91",
"type": "payment.succeeded",
"data": { "order_id": 1042, "amount": "190.00", "currency": "SAR" }
}आम गलतियाँ
- एक साफ़ delivery टेस्ट करना और duplicate, parallel copy, गलत क्रम वाला event या fail हुआ पहला attempt कभी टेस्ट न करना।
- Duplicate पर error status की उम्मीद करना: provider उसे फिर retry करेगा। Duplicate को
2xxमिलता है और उसे ignore किया जाता है। - Response time नज़रअंदाज़ करना: जवाब से पहले धीमा काम (emails, PDFs, दूसरी services) provider को timeout तक पहुँचाता है और वह handle हो चुके event को retry करता है। Verify, record, acknowledge, फिर process।
- सिर्फ़ यह टेस्ट करना कि valid signature pass होता है, यह नहीं कि बदली हुई, unsigned, पुरानी या गलत secret से signed deliveries fail होती हैं।
- असली customer data या live secret किसी public capture endpoint पर भेजना, या उसे bug report में paste करना।
QA का नज़रिया
Integration plan होते ही शुरू करें। Provider का webhook documentation माँगें (event types, payload schema, signature scheme, timeout, retry schedule, ordering) और developers से पूछें: idempotency key कौन-सा id है? कोई downstream service बंद हो तो handler क्या लौटाता है? Retries ख़त्म होने पर किसे alert जाता है?
Test cases और bug reports में ये record करें: event id, attempt का समय, secrets mask करके headers, raw body, consumer का status और response time, और नतीजे वाली state: rows, emails, stock। Signature bugs अक्सर सिर्फ़ exact bytes से reproduce होते हैं, इसलिए raw capture attach करें।
अभ्यास
Shipment webhook के tests design करें
एक delivery company आपकी shop को shipment.delivered webhooks भेजती है; उसका documentation नीचे है। Shop को order "delivered" mark करना है और customer को एक notification भेजना है। Test cases लिखें और बताएँ कि हर एक को कैसे चलाएँगे।
Webhooks: shipment events
- POST, JSON body; हर event का unique "id"; retries में वही id रहता है।
- Header Ship-Signature: timestamp + "." + raw body का hex HMAC-SHA256,
timestamp Ship-Timestamp में (Unix seconds); 300 s से पुराना reject होता है।
हर attempt, retries समेत, नए timestamp के साथ sign होता है।
- 10 s में 2xx नहीं = failure। 24 घंटों में अधिकतम 8 retries।
- Events एक से ज़्यादा बार और किसी भी क्रम में आ सकते हैं।- Captured delivery पर जो checks कर सकते हैं, उनकी list बनाएँ।
- Duplicates, ordering, signatures और retries के लिए consumer cases लिखें, expected response और state के साथ।
- हर case के लिए लिखें कि उसे test mode में असली provider, replay या edit किया गया capture, या नई signed request चाहिए।
- Developers के लिए कम से कम दो सवाल लिखें।
मॉडल उत्तर दिखाएँ
Test mode में captured delivery: POST, Content-Type: application/json, दोनों headers मौजूद, body fields documentation के अनुसार, और signature test secret से verify होता है।
Consumer: (1) valid नया event → 10 s में 2xx, DELIVERED, एक notification; (2) replay → 2xx, दूसरी notification नहीं; (3) दो parallel copies → एक notification; (4) body का एक byte बदला → 4xx, कोई बदलाव नहीं; (5) signature नहीं या गलत secret → 4xx; (6) timestamp 300 s और 301 s पुराना → accept, reject (2-value BVA); (7) shipment.delivered के बाद shipment.in_transit → DELIVERED ही रहे; (8) पहले attempt पर 503, और (9) 10 s से धीमा handler → retry होता है, फिर भी एक notification।
असली provider: 1, 8 और 9 (उसका delivery log पढ़ें)। Replay किया गया capture: 2 और 3। Edit किया गया capture: 4, और header हटाकर 5। Cases 2 से 5 capture के 300 s के अंदर भेजें, वरना rejection की वजह test की जा रही condition नहीं, पुराना timestamp होगा। HMAC tool और अपने चुने timestamp से नई signed request: गलत secret वाला 5, 6 और 7।
सवाल: Timestamp की age कैसे मापी और round की जाती है, और क्या ठीक 300 seconds पुराना timestamp accept होता है? Idempotency key कौन-सा id है, और क्या उस पर unique constraint है? Notification 2xx से पहले भेजी जाती है या बाद में?
अक्सर पूछे जाने वाले सवाल
Webhook और API की polling में क्या फ़र्क़ है?
Polling में consumer बार-बार provider की API call करके पूछता है कि कुछ बदला या नहीं। Webhook में event होते ही provider consumer को call करता है। Webhooks देरी और बेकार calls घटाते हैं, लेकिन इनके लिए public endpoint, signature checks और duplicate handling चाहिए; कई integrations छूटे हुए events की भरपाई के लिए API से भी data पढ़ते हैं।
Webhook endpoint को कौन-सा status code लौटाना चाहिए?
Delivery verify और सुरक्षित रूप से record होते ही 2xx, आम तौर पर 200 या 204, पहले से handle हुए duplicate के लिए भी। Reject की गई delivery के लिए, जैसे गलत signature वाली, 4xx। Provider का documentation देखें: कई providers हर non-2xx response पर retry करते हैं, इसलिए 4xx से retries शायद न रुकें।
क्या provider मेरे localhost पर webhooks भेज सकता है?
नहीं। Provider के servers आपके private network की machine तक नहीं पहुँच सकते। Delivery को public capture endpoint पर capture करके अपने local consumer पर replay करें, team द्वारा approved tunnel इस्तेमाल करें, या अगर provider देता हो तो test events forward करने वाला command-line tool इस्तेमाल करें।
अगर endpoint HTTPS इस्तेमाल करता है, तो क्या signature फिर भी ज़रूरी है?
हाँ। HTTPS request को रास्ते में सुरक्षित रखता है, लेकिन कोई भी public HTTPS URL पर request भेज सकता है। Signature साबित करता है कि sender shared secret जानता है और body बदली नहीं गई; यह बात अकेला HTTPS consumer को नहीं बताता।
संदर्भ
- RFC 9110: HTTP SemanticsHTTP मेथड, हेडर फ़ील्ड, स्टेटस कोड और कंटेंट निगोशिएशन के अर्थ, वायर वर्ज़न से स्वतंत्र।
- RFC 2104: HMAC: Keyed-Hashing for Message AuthenticationHMAC संरचना: एक सीक्रेट की और हैश फ़ंक्शन मिलकर मैसेज ऑथेंटिकेशन कोड कैसे बनाते हैं।
- ISTQB Certified Tester Foundation Level (CTFL) v4.0सॉफ़्टवेयर टेस्टिंग का फ़ाउंडेशन पाठ्यक्रम: टेस्ट स्तर और प्रकार, टेस्ट डिज़ाइन तकनीकें, टेस्ट प्रबंधन और टूल।
Mutqan tools से अभ्यास करें
एक अनोखा URL पाएँ, उस पर webhook भेजें और method, हेडर, बॉडी तथा टाइमिंग रीयल टाइम में जाँचें।
कैप्चर की गई webhook डिलीवरी गहराई से जाँचें: हेडर, signature, JSON बॉडी, टाइमिंग और replay डेटा।
अपने secret से webhook signature (HMAC-SHA256/SHA1, Stripe, GitHub, Shopify, Slack शैली) सत्यापित करें — लोकल रूप से।
वेबहुक और API रिक्वेस्ट साइनिंग के लिए HMAC सिग्नेचर (SHA-256/384/512/SHA-1) बनाएँ।
Stripe, GitHub, Shopify, Slack, Twilio और अन्य के webhook पेलोड फ़ॉर्मेट करें, सुंदर बनाएँ और उन पर व्याख्या पाएँ।
ऐसा सार्वजनिक endpoint पाएँ जो कोई भी HTTP स्टेटस कोड लौटाए, वैकल्पिक देरी और कस्टम JSON बॉडी के साथ, ताकि क्लाइंट की error हैंडलिंग टेस्ट हो सके।
और गहराई से
इस topic में आपकी प्रगति
प्रगति ट्रैक करने के लिए साइन इन करें
Topics पूर्ण चिह्नित करें, जहाँ छोड़ा था वहीं से जारी रखें और specialisation परीक्षाएँ खोलें।