You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby 2.5.5 + Rails 5.2环境下Paddle Webhook验证失败排查

问题分析与修复方案

我帮你排查一下Paddle Webhook验证失败的问题,大概率是签名生成的格式不对,咱们一步步拆解来看:

1. 核心错误:用JSON序列化替代了Paddle要求的键值拼接格式

Paddle的签名验证规则不是基于JSON的!你现在用data_sorted.to_json生成待验证字符串的方式完全不符合要求,这是导致verified始终为false的主要原因。

Paddle要求的正确格式是:把排序后的键值对逐个格式化为key=value,然后直接拼接所有字符串(没有任何分隔符)。

2. 其他需要确认的细节

  • 公钥格式要准确:确保你的公钥完整保留-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----标识,中间的密钥内容没有多余换行、空格或截断(你示例里的FAKE要替换成Paddle提供的真实公钥)。如果公钥格式有误,OpenSSL::PKey::RSA.new(public_key)可能生成无效密钥,导致验证失败。
  • 数据类型转换要彻底:你把所有值转成String的操作是对的,但要确保转换后的字符串和Paddle发送的完全一致(比如数字转字符串时不要加前导零,URL参数不要额外编码)。
  • 排序规则没问题:你用sort_by{|key, value| key}是正确的,Paddle要求按键名的ASCII升序排序,Ruby默认的字符串排序正好符合这个规则。

修正后的完整代码

data = { "alert_id"=>"1", "alert_name"=>"alert_created", "cancel_url"=>"https://...", "checkout_id"=>"1", "user_id"=>"1", "p_signature"=>"fwWXqR9C..." }
public_key = "-----BEGIN PUBLIC KEY----- 替换为你的真实公钥内容 -----END PUBLIC KEY-----"

# 提取并解码签名
signature = Base64.decode64(data['p_signature'])
data.delete('p_signature')

# 确保所有值都是字符串类型
data.each { |key, value| data[key] = String(value) }

# 按键名ASCII升序排序
data_sorted = data.sort_by { |key, _| key }

# 按Paddle规则拼接待验证字符串
data_serialized = data_sorted.map { |key, value| "#{key}=#{value}" }.join

# 执行签名验证
digest = OpenSSL::Digest::SHA1.new
pub_key = OpenSSL::PKey::RSA.new(public_key)
verified = pub_key.verify(digest, signature, data_serialized)

puts verified # 现在应该返回true了

额外调试建议

如果还是验证失败,可以试试这两步:

  • 打印出data_serialized,对比Paddle官方文档里的示例格式是否一致;
  • 用Paddle提供的测试Webhook事件和测试公钥做验证,排除真实数据的干扰。

内容的提问来源于stack exchange,提问作者userden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:33:30