支付宝 v3 验签如何实现

上次给大家介绍了 支付宝 v3 自签名如何实现,这次顺便再把验签也写一下。

为什么要验签

说起为什么要验签,如果要详细一点解释的话,可以写很多很多......

我们就简单一点来解释:验签可以证明接收到的信息是支付宝给我的,不是被人中途拦截篡改数据之后再发给我的。

支付宝的通知分为 「同步通知 」和 「异步通知 」:

  • 「同步通知 」就是我们请求支付宝之后,支付宝返回的数据。
  • 「异步通知 」是到达某些条件之后,支付宝主动发的;更详细内容可以参考之前我写的 [手把手|支付宝异步通知如何使用]。

对于这两种通知我们都需要进行验签处理,才能保证数据的准确性!(⚠️ 很重要!!)

其实支付宝给的 SDK 里面也封装了验签的方法,并且对同步通知都经过了验签的处理,同步验签不过的话,接口会直接抛出异常 [sign check fail: check Sign and Data Fail]。

另外 v3 SDK 里面提供的验签方法名跟 v2 版本是一样的,大家不想麻烦的话可以直接查看 [SDK如何实现验签]。

(大家凑合看,v3 版本好像还没有完整的验签示例代码,也可能是我没找到 😢)

虽然给了这么多简单的方法,但是我就是要自!己!写!一!遍!╭(╯^╰)╮

如何验签

验签的流程比加签要简单一点,下面用支付宝同步通知的数据做验签例子

步骤一、接收支付宝返回的信息

首先就是要接收到支付宝返回的信息,因为是同步验签的数据,直接拿之前自签名的代码改一下

验签我们所需要的数据有:

  • aliapy-signature:支付宝生成的签名内容。
  • alipay-timestamp:支付宝应答时间戳。
  • alipay-nonce:支付宝应答随机串。
  • httpResponseBody:响应报文内容,自签名的 resData 数据。
接收代码
//获取响应的请求头head
Header[] responseHeader = response.getAllHeaders();
//待验签数据head:aliapy-signature、alipay-timestamp、alipay-nonce
String alipaysignature = response.getFirstHeader("alipay-signature").getValue();
String alipaytimestamp = response.getFirstHeader("alipay-timestamp").getValue();
String alipaynonce = response.getFirstHeader("alipay-nonce").getValue();	
获取到的响应值
httpResponseBody:{"out_trade_no":"20181128763521373251698","qr_code":"https://qr.alipay.com/bax04870evi3w2dlaeai2502"}
aliapy-signature:M/6yx2OajiQD0mM9Tk9ShsduFERtmj+xI0BN8QiZk8BMUCvMQCne1n/VIbMZ738k4No8nsE1DC0saPe2NqtmgxC3B+TmWgrhJ+4JOVEc7K4/LcIDWN2PaPCw5g5+oUQRIGCbo0+f9yqSew4NwETV2RiVIw91q+kJ4OeIpauSnGQAuwOxqciDM52k7gUhij8G+evhK7xn6TNhiQgRk0RjkyhEEp/00lYb5xI2d9Oj5KgsDC9KTRo9SO0SJaH0SbfNHU40XUkkomuj6jiOEeccfB6Fofzq5jfL3u24Ev9SxTDf2kYZzffShLrYhlrI8947VqC3h8/F6O8y4K/PQl3LCw==
alipay-timestamp:1703576825544
alipay-nonce:73b3422127c9996ad405e77091eef6f4

包含之前自签名的完整代码(仅供参考)
public class V3HttpPostTest {public static void main(String args[]) throws Exception {// 发送请求的urlString url = "https://openapi.alipay.com/v3/alipay/trade/precreate";// 发送请求的内容String content = "{\"out_trade_no\":\"20181128763521373251698\",\"total_amount\":\"1\",\"subject\":\"123\",\"body\":\"body\"}";String chearset = "utf-8";// 创建请求对象:post或者getHttpPost httpPost = new HttpPost(url);// httpClient实例化CloseableHttpClient httpClient = HttpClients.createDefault();// 设置类型// "application/x-www-form-urlencoded","application/json"、multipart/form-data、text/xmlhttpPost.setHeader("Content-Type", "application/json");// 调用方的requestId,用于定位一次请求,需要每次请求保持唯一。httpPost.setHeader("alipay-request-id", "32432432432423421");httpPost.setHeader("authorization","ALIPAY-SHA256withRSA app_id=2021111111111122,timestamp=1702452177941,nonce=3246658768654544,sign=WDF6pS2qK/kEZnsJDMrhNmd/z82ClZ+VMohYxIUs3MZ2j0m+4reQtSBGa6mZyA5ffbIPPvZTRO+1DLEuuCvZRMQGK3okYSA/ASP7GEqfCDeKmkqzKV2kWrmftNfO+EiIiCnsiyJG4SQ9G7s0OtmCT6wVkphW9wgk7mfUoF5a+Wo3kzvEur3U+7ZfSgLa4HXQG2xE+z7BjmHG8j1qVoVa/3TR1lVBAqOwkodZ9cSPKceK2RxaPkk8gsFbofbuARl5xBqDwkS2caTQu27+DLXT/QJOHRHRw5VtH9v8B7nT+nrijFjktm6hD7aIHuPon6TtEgnbtWltRizEZldh+Fo1Eg==");// 支付宝根证书序列号,使用证书模式时,需要传递该值// httpPost.setHeader("alipay-root-cert-sn", "");// 组织数据StringEntity se = null;try {se = new StringEntity(content);// 设置编码格式se.setContentEncoding(chearset);// 设置数据类型se.setContentType("application/json");// post请求,将请求体填充进httpPosthttpPost.setEntity(se);// 通过执行httpPost获取实例HttpResponse response = httpClient.execute(httpPost);HttpEntity entity = response.getEntity();String resData = EntityUtils.toString(entity);System.out.println("httpResponseBody:" + resData);//获取响应的请求头headHeader[] responseHeader = response.getAllHeaders();//待验签数据head:aliapy-signature、alipay-timestamp、alipay-nonceString alipaysignature = response.getFirstHeader("alipay-signature").getValue();String alipaytimestamp = response.getFirstHeader("alipay-timestamp").getValue();String alipaynonce = response.getFirstHeader("alipay-nonce").getValue();	System.out.println("aliapy-signature:" + alipaysignature);System.out.println("alipay-timestamp:" + alipaytimestamp);System.out.println("alipay-nonce:" + alipaynonce);// 关闭httpClient资源httpClient.close();} catch (Exception e) {e.printStackTrace();}}
}

步骤二、拼接待验签内容

接收到响应数据之后,我们需要按照

${alipay-timestamp}\n
${alipay-nonce}\n
${httpResponseBody}\n

规则,将数据组装起来。

content 组装示例

【注意:\n 不要丢!】

String content = alipaytimestamp + "\n" + alipaynonce + "\n" + httpResponseBody + "\n";
返回值
1703576825544
73b3422127c9996ad405e77091eef6f4
{"out_trade_no":"20181128763521373251698","qr_code":"https://qr.alipay.com/bax08770vkyzjc0is6ep25ed"}

步骤三、进行签名比对

组装完待验签内容之后,我们就可以将数据进行验签了,其中用到的参数有:

  • content:上一步获取到的内容。
  • alipaysignature:第一步获取到的 alipaysignature。
  • publicKey:为支付宝公钥,在支付宝平台上传应用公钥后获取,参考 [如何获取支付宝公钥]。
  • charset:编码格式,代码中用的是 UTF-8。
验签代码
private static boolean doVerify(String content, String alipaysignature, String publicKey, String charset) throws Exception {try {byte[] encodedKey = publicKey.getBytes();encodedKey = Base64.getDecoder().decode(encodedKey);PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(encodedKey));java.security.Signature signature = java.security.Signature.getInstance("SHA256withRSA");signature.initVerify(pubKey);signature.update(content.getBytes(charset));boolean signVerified = signature.verify(Base64.getDecoder().decode(alipaysignature.getBytes()))System.out.println("signVerified:" + signVerified);return falg;} catch (Exception e) {String errorMessage = "验签失败,请检查公钥格式是否正确。content=" + content + " publicKey=" + publicKey + " reason="+ e.getMessage();throw new Exception(errorMessage);}}
返回值
signVerified:true

只有返回 true 才能说明验签是通过的。

写在最后

v3 验签写完之后,可以看到其实跟 v2 的验签方法没有什么区别,最大的不同点在于待验签内容,大家都可以试试看,还是挺简单的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2659728.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【信息安全原理】——拒绝服务攻击及防御(学习笔记)

📖 前言:拒绝服务攻击(Denial of Service, DoS)是一种应用广泛、难以防范、严重威胁网络安全(破坏可用性)的攻击方式。本章主要介绍DoS的基本概念、攻击原理及防御措施。 目录 🕒 1. 定义&#…

sonarqube安装踩坑记录

如果用java1.8和mysql,则sonarqube版本不能超过7.8,看这里。 sonarqube7.8安装包地址: https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.8.zip 安装步骤: 1、下载sonarqube安装包 wget https://binari…

计算机毕业设计---ssm+mysql+jsp实现的校园二手市场交易平台源码

项目介绍 本系统主要实现的功能有: 前台:(1)二手物品信息查看、搜索。 (2)学生注册登录、个人信息修改。 (3)二手物品信息发布、编辑。 (4)二手物品评论、回…

mybatisX自动生成sql语句,尝试测试方法报错

今天我使用mybatisx自定义mapper方法生成sql语句后,在测试时报错 错误是MyBatis 无法找到映射的语句(Statement)引起的 我是这样操作的,在mapper接口自定义了一个方法 然后alt加enter,自动生成sql 结果 mapper.xml文件…

手机流量卡推广分销网站php源码,多功能的号卡推广分销管理系统

源码简介 拥有多个接口,包括运营商接口,并支持无限三级代理。 最简单易用的PHP系统,它自带自动安装向导,可以让你轻松安装和部署。 该系统集成了多个第三方接口资源,能够满足你的不同需求。采用全系统双色主题&…

MYSQL 索引结构 B+树 hash索引

B-Tree树 当节点存在五个key时,中间的key向上分裂形成树 B树 所有的数据都会出现在叶子节点,叶子节点形成一个单向链表 哈希索引 优点

Vulnhub-Al-Web-1.0 靶机复现完整过程

一、信息收集 1.主机发现 arp-scan -l2.端口扫描 nmap -sV -p- 192.168.200.16PORTSTATESERVICEVERSIONMAC Address80/TCPOpenhttpApache httpd00:0C:29:C4:1B:78 (VMware) 3.目录扫描 python dirsearch.py -u http://192.168.200.16扫描出来这两个文件,首先先…

java基础-回忆性记录

java基础 Java概括 jaava是一种计算机交流的高级编程语言,1995年java衍生,詹姆斯高斯林被世人称之为java之父。 java语言具有跨平台性 java程序并非可以直接运行的,在java程序编译完成后会形成与编译无关的class文件。Java具有跨平台性&a…

ARM CCA机密计算软件架构之内存加密上下文(MEC)

内存加密上下文(MEC) 内存加密上下文是与内存区域相关联的加密配置,由MMU分配。 MEC是Arm Realm Management Extension(RME)的扩展。RME系统架构要求对Realm、Secure和Root PAS进行加密。用于每个PAS的加密密钥、调整或加密上下文在该PAS内是全局的。例如,对于Realm PA…

中国蚁剑-antSword

1.简介 蚁剑是一款开源的跨平台Webshell管理工具,它是一个开源的远程管理工具,主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。蚁剑提供了一个图形化界面,可以通过简单的操作连接和控制目标设备或系统。 蚁剑具有以下…

QT应用篇 三、QML自定义显示SpinBox的加减按键图片及显示值效果

QT应用篇 一、QT上位机串口编程 二、QML用Image组件实现Progress Bar 的效果 三、QML自定义显示SpinBox的加减按键图片及显示值效果 文章目录 QT应用篇前言一、qml需求二、使用组件1.SpinBox组件2.SpinBox中QML的使用 总结 前言 记录自己学习QML的一些小技巧方便日后查找 QT的…

企业数据可视化-亿发数据化管理平台提供商,实现一站式数字化运营

近些年来,国内企业数据化管理升级进程持续加速,以物联网建设、人工智能、大数据和5G网络等新技术的发展,推动了数字经济的蓬勃发展,成为维持经济持续稳定增长的重要引擎。如今许多国内中小型企业纷纷摒弃传统管理模式,…

《Linux系列》Linux磁盘MBR分区扩容

文章目录 Linux磁盘MBR分区扩容1.前言2.控制台磁盘扩容3.分区扩容3.1 fdisk3.2 lsblk3.3 扩容分区 4.扩容文件系统4.1 df4.2 扩容文件系统 Linux磁盘MBR分区扩容 1)参考阿里云扩容分区文档,整理MBR分区扩容 2)本文档适用于MBR分区(fdisk -lu查…

MySQL的日志管理以及备份和恢复

MySQL日志管理 mysql的日志默认保存位置为/usr/local/mysql/data vim /etc/my.cnf #开启二进制日志功能 vim /etc/my.cnf [mysqld]##错误日志,用来记录当MySQL启动、停止或运行时发生的错误信息,默认已开启 log-error/usr/local/mysql/data/mysql_…

LabVIEW的便携式车辆振动测试分析

随着计算机和软件技术的发展,虚拟仪器正逐渐成为机械工业测试领域的主流。在现代机械工程中,特别是车辆振动测试,传统的测试方法不仅设备繁杂、成本高昂,而且操作复杂。为解决这些问题,开发了一款基于美国国家仪器公司…

postman使用-03发送请求

文章目录 请求1.新建请求2.选择请求方式3.填写请求URL4.填写请求参数get请求参数在params中填写(填完后在url中会自动显示)post请求参数在body中填写,根据接口文档请求头里面的content-type选择body中的数据类型post请求参数为json-选择raw-选…

[DAU-FI Net开源 | Dual Attention UNet+特征融合+Sobel和Canny等算子解决语义分割痛点]

文章目录 概要I Introduction小结 概要 提出的架构,双注意力U-Net与特征融合(DAU-FI Net),解决了语义分割中的挑战,特别是在多类不平衡数据集上,这些数据集具有有限的样本。DAU-FI Net 整合了多尺度空间-通…

TiDB 7.1 多租户在中泰证券中的应用

本文详细介绍了中泰证券在系统国产化改造项目中采用 TiDB 多租户技术的实施过程。文章分析了中泰证券数据库系统现状以及引入 TiDB 资源管控技术的必要性,探讨了 TiDB 多租户的关键特性,并阐述了在实际应用中的具体操作步骤。通过该技术的应用&#xff0…

python学习14

前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…

【论文阅读】Resource Allocation for Text Semantic Communications

这是一篇关于语义通信中资源分配的论文。全文共5页,篇幅较短。 目录在这里 摘要关键字引言语义通信资源分配贡献公式符号 系统模型DeepSC TransmitterTransmission ModelDeepSC Receiver 语义感知资源分配策略Semantic Spectral Efficiency (S-SE&#…