Spring Boot @RestController से webhook endpoint आसान बनाता है, पर Spring Security CSRF और JSON converter handler से पहले payload ब्लॉक या बदल सकते हैं। लोकल टेस्टिंग raw byte[] एक्सेस, webhook path पर CSRF छूट और untouched bytes पर सिग्नेचर सत्यापन साबित करे।
@RestController webhook endpoint बनाएँ
Webhook controller पतले रखें। Raw bytes लें, सिग्नेचर सत्यापित करें, फिर deserialize:
@RestController
@RequestMapping("/webhooks")
public class StripeWebhookController {
@PostMapping("/stripe")
public ResponseEntity handle(
@RequestBody byte[] payload,
@RequestHeader("Stripe-Signature") String signature) {
if (!verifier.isValid(payload, signature)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
JsonNode event = objectMapper.readTree(payload);
handler.process(event);
return ResponseEntity.ok().build();
}
}
@RequestBody byte[] Tomcat द्वारा मिला सटीक payload रखता है — जब provider raw JSON साइन करता है तो आदर्श।
HttpServletRequest से raw body पढ़ें
वैकल्पिक: servlet request से सीधे पढ़ें:
byte[] body = request.getInputStream().readAllBytes();
String sig = request.getHeader("Stripe-Signature");
पहले POJO या Map bind न करें — Jackson reserialize HMAC तोड़ता है। सिग्नेचर सत्यापन गाइड देखें।
केवल webhook path पर CSRF बंद करें
Spring Security डिफ़ॉल्ट CSRF चालू करता है। server-to-server छूट के बिना webhook POST 403 देते हैं:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.ignoringRequestMatchers("/webhooks/**"));
return http.build();
}
}
ignore को /webhooks/** तक सीमित रखें — CSRF globally बंद न करें।
बिज़नेस लॉजिक से पहले सिग्नेचर header सत्यापित करें
Provider header पढ़ें, raw byte array से digest बनाएँ, constant-time compare करें। गलत पर 401, सफल पर तेज़ 200।
लोकल टनल workflow
- चलाएँ:
./mvnw spring-boot:runपोर्ट 8080। - Tomcat expose:
npx portpreview 8080। - टनल URL + path डैशबोर्ड में पेस्ट करें।
- टेस्ट इवेंट भेजें और logs देखें।
- Idempotency के लिए same event ID replay — retry पैटर्न।
आम जाल
Filter क्रम और body consumption
Controller से पहले stream पढ़ने वाले filter खाली stream छोड़ते हैं। ज़रूरत हो तो ContentCachingRequestWrapper।
Global @RequestBody binding
जल्दी JSON parse करने वाला @ControllerAdvice bytes बदल सकता है। Webhook byte[] से अलग रखें।
धीमे handler retry trigger करते हैं
जल्दी ACK, async process, event ID से dedupe।
और पढ़ें
मूल बातें पढ़ें localhost टनलिंग और लोकल webhook डिबगिंग. सिग्नेचर मैकेनिक्स के लिए देखें सिग्नेचर सत्यापन गाइड. डुप्लिकेट-सुरक्षित हैंडलर के लिए पढ़ें retry और idempotency पैटर्न. PortPreview मुफ़्त शुरू करें.
![embedded Tomcat पर Spring Boot RestController लोकल टनल से मिले raw byte[] payload से webhook सिग्नेचर header सत्यापित करता है।](/_next/image?url=%2Fimages%2Farticles%2Fspring-boot-webhook-local-testing%2Fcover.png&w=3840&q=75)