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
相关产品推荐
相关产品推荐

