5.4. 签名原理
研究底层:开启 debug 日志
debug 启动项目,查看日志
(1)构造签名串
(2)计算签名值
使用商户私钥对签名串进行 SHA-256 with RSA 签名,并对结果进行 Base64 编码,得到签名值
(3)设置 HTTP 头
通过HTTP Authorization头来传递签名,由认证类型和签名信息两个部分组成
(4)发送请求代码
(5)找源码
找到构造签名串的类 WechatPay2Credentials
源码位置:External Libraries 外部库
打断点检查是否定位成功
(6)源码分析
① 计算随机数
步入查看
② 获取时间戳
步入
③ 构造签名串
步入,返回请求方法、url、时间戳、随机串、请求体
④ 计算签名值
步入,使用 SHA-256 with RSA 加密算法
⑤ 生成 HTTP 头的签名信息部分
⑥ 调用这个 getToken 的方法(在方法堆栈中找调用的上一个方法)
携带签名执行远程请求的发送方法 executeWithSignature
最终其实就是由步骤(4)中的完成签名并执行请求方法调用的
5.5. 验签原理源码分析
(1)获取平台证书
① 在获取签名验证器的方法中断点调试
② 步入构造函数,参数:身份认证对象(商户号+商户私钥),对称加密密钥
③ 步入初始化证书管理器,参数同上
参数校验通过后进行初始化,第三个参数 60 表示每隔 60mins 检查是否有新的平台证书,有的话会进行下载
tip:singleton 表示单例模式,确保一个类只有一个实例
④ 步入初始化单例的证书管理器方法,参数校验后对实例进行初始化
executor:执行定时任务的执行器对象
certificates:商户证书列表对象
⑤ 步入初始化证书方法,方法中执行证书的下载和更新
⑥ 步入下载和更新证书方法,创建 httpClient 对象发送远程请求
获取响应体,用对称加密密钥解密响应体中的内容,生成证书列表
⑦ 回到初始化单例的证书管理器方法,初始化证书后,启动定时更新证书任务
该任务由 executor 对象定时执行
(2)验签方法 validate 的调用
① 调试运行后打断点,前端点击确认支付,查看方法调用栈
② 前端点击确认支付后,首先会来到 controller 层的 nativePay 方法,接下来会调用 service 层的 nativePay
③ 最终执行的是 wxPayClient 的 execute 方法
④ 接着一层层地向上执行
⑤ 在 executeWithSignature 方法中对应答进行验签,由此找到 validate 验签方法的调用位置
前面部分的代码是签名和发送请求流程
⑥ validate 验签方法首先会对所有响应数据进行校验:各数据是否为空,且响应时间不超过 5 分钟
(3)正常验签流程
① 构造验签串
步入
② 获取应答签名,通过 HTTP 头 Wechatpay-Signature 传递
在响应头中获取平台证书的序列号
获取应答签名
③ verify 方法验证签名
步入:参数校验 -> 获取最新的平台证书 -> 验签
步入:获取平台证书 -> verify
步入:构建 sign 对象设置验签需要的算法 -> 从平台证书中解析出平台公钥 -> 在 sign 中放入验签串
步入:获取公钥
sign 对象中包含了验签算法、平台公钥、验签串
用 sign 对象对 Base64 解码后的应答签名进行验签
连续步入
步入:判断签名字符串的长度是否正确 -> 摘要比对