为何Stripe Webhook的dataObjectDeserializer.object返回空Optional?
问题原因及解决方法
可能的原因
库与API版本不兼容
Stripe Java SDK 24.12.0对应的API版本是2024-06-20,如果你的Stripe后台Webhook端点配置的API版本和这个不一致,会导致数据结构不匹配,反序列化失败,最终deserialiser.object返回空Optional。错误的反序列化判断逻辑
你当前代码直接判断deserialiser.object != null,但正确的流程应该先检查deserialiser.isSuccess()——如果反序列化失败,object必然是空,且可以通过deserialiser.error获取具体错误信息,这能帮你定位问题。请求体处理问题
Spring Boot默认的@RequestBody String body可能会对请求体做隐性修改(比如编码转换、多余转义),虽然签名验证通过了,但可能破坏了Stripe SDK反序列化所需的原始JSON结构。
解决步骤
1. 确认API版本匹配
登录Stripe后台,检查Webhook端点的API版本是否与SDK版本对应(24.12.0对应2024-06-20),如果不一致,要么升级/降级SDK,要么修改Webhook的API版本。
2. 修正反序列化逻辑
使用Stripe SDK提供的正确方式提取Charge对象,示例代码如下:
@ResponseBody @PostMapping("/stripewebhook") fun index( @RequestHeader(value = "Stripe-Signature") stripeSecret: String, @RequestBody body: String ): HttpStatus = try { val event = Webhook.constructEvent(body, stripeSecret, ourEndpointSecret) val deserializer = event.dataObjectDeserializer if (deserializer.isSuccess) { when (event.type) { "charge.succeeded" -> { val charge = deserializer.getObject(Charge::class.java) // 处理Charge对象 receiveReceipt(charge, body) } else -> { log.error("无效的事件类型: ${event.type}") HttpStatus.BAD_REQUEST } } } else { log.error("Stripe对象反序列化失败: ${deserializer.error}") HttpStatus.BAD_REQUEST } } catch (e: SignatureVerificationException) { log.error("签名验证失败", e) HttpStatus.BAD_REQUEST } catch (e: JSONException) { log.error("请求体解析失败", e) HttpStatus.BAD_REQUEST } catch (e: Exception) { log.error("支付处理异常", e) HttpStatus.INTERNAL_SERVER_ERROR }
3. 确保获取原始请求体(可选)
如果上述步骤无效,尝试获取原始字节数组来避免Spring的隐性修改:
@ResponseBody @PostMapping("/stripewebhook", consumes = [MediaType.APPLICATION_JSON_VALUE]) fun index( @RequestHeader(value = "Stripe-Signature") stripeSecret: String, request: HttpServletRequest ): HttpStatus = try { val body = request.inputStream.bufferedReader().use { it.readText() } // 后续逻辑同上 } catch (e: Exception) { // 异常处理 }
内容的提问来源于stack exchange,提问作者Michael NGV
相关产品推荐
相关产品推荐

