00:00
我们已经对支付通知当中的通知参数以及通知应答进行了一个处理,那么接下来呢,我们来对签名的验证做一下处理。签名验证呢,在我们的微信支付当中呢,有两种场景,第一种场景呢是。如果这个请求是由我们商户端向微信支付端发送的话,那么微信支付端呢,会给我们一个响应,那么在这个响应接收的过程当中,我们首先呢,要对这个响应进行签名验证,这个呢咱们之前讲过了,并且呢分析了签名验证的源代码,那么在响应返回的过程当中呢,这个签名验证呢,是微信的SDK封装好了,已经自动帮助我们实现了的。还有一种签名验证的情景呢,就是现在的这种微信的服务器端呢,会给我们发送一个通知啊,然后呢,我们要对这个通知呢也进行签名验证,那么签名验证的流程呢,和针对之前的响应进行签名验证的流程呢,是一模一样的,只不过呢,响应呢是针对response对象,而请求的签名验证呢是针对request对象,那么。
01:16
针对响应进行签名验证的时候呢,我们要从response对象里面呢,获取相应的响应头,同样针对请求进行签名验证的时候呢,我们要从request对象里面获取相应的请求头。好,那接下来呢,我们就来看一看这个请求的签名验证,那因为呢,微信支付端并没有给我们提供默认的集成在SDK内部的啊,一个不用我们自己亲自去编写的这么一个签名验证。所以呢,我们要自己编写一下针对请求的签名验证的相关的代码。那么我们来看一下。我们之前的针对响应的签名验证的一个签名验证的工具。
02:08
啊,之前我们分析的是这个类啊,这个类呢,实际上就是。进行签名验证的,那么这里面呢,有一个核心的方法叫validate,那这个方法呢,对参数首先进行一系列的处理,然后呢,再从响应头当中拿出相应的信息,比如说平台证书序列号啊,比如说平台那面的响应头当中携带的签名啊等等啊,那最终呢,调用very fair,然后调用里面的very fair方法来进行一个签名的验证,好,那现在我们针对请求进行签名呢,也是一样的,只不过呢,我们需要把这个response呢改造成request。所以呢,我们要做的事情呢,就是把这个复制一下,然后复制到我们的应用程序当中。改造成for quest,好,然后接下来呢,我们需要改造这个核心的签名验证的方法,把它呢改成。
03:09
Http request。好,那么这个类呢,原始的是实现了一个接口的,而这个接口里面的抽象方法呢,是专门针对response对象进行签名验证的,所以呢,我们就不需要去实现这个接口了。然后我们把这个呢删掉。好,那么来到验签的第一个步骤的时候呢,我们首先呢,要处理请求参数,好,也就是处理request的参数,那我们把request传递进来,然后接下来呢,我们来到处理request参数的这个方法当中,首先我们把这个地方呢改成。HTTP。
04:01
Request。然后接下来呢,我们从request当中呢,获取它的请求头当中的request ID,但是呢,实际上微信给我们的响应当中是有这个请求头的,也就是携带了这个request ID,但是他给我们的支付通知当中是没有这个请求头的,那他的这个支付通知当中的这个ID唯一标识在哪呢?在它的请求体当中啊,前面我们从我们的回调通知函数当中的request对象当中啊,曾经拿出过它的请求体,那么在请求体当中呢,有一个参数叫做ID,那这个ID呢,就是我们支付通知的唯一的ID了,那实际上呢,我们也可以从之前的我们支付通知的API文档当中看到。是在请求体当中有这样的一个通知参数的,所以呢,我们可以。
05:05
通过这个request ID。来代替这个request ID,所以呢,我们在我们的这个类的构造函数当中添加一个参数。然后在成员当中也添加这样的一个参数。好,然后呢,在构造函数当中,对这个参数呢进行赋值。好,那这样的话呢,我们未来在这个地方啊,使用这个类进行签名验证的时候,我们在创建这个类的对象的时候,我们呢,就可以。去传递very fair和request ID这两个参数了,这样的话呢,能够把这个类的实例对象给它初始化出来,所以呢,这面呢,我们的very来呢,我们的very是之前我们在con微信这个地方。
06:12
已经定义出来的这么一个可以定时更新平台证书的签名验证器对象,所以呢,在这面我们可以呢,把刚才那个very呢先注入进来。Private刚才那个它实现了一个接口啊,就叫做,所以我们直接注入这个接口就可以了,然后呢,在这个地方啊,要进行签名验证的时候,我们构造这个对象的时候呢,我们在构造函数当中传递very fair和上面的这个。Request ID,我们把这个request ID呢,不知道这个位置。好,这样的话呢,我们就得到了一个wet pay valid for request这么一个对象,然后接下来呢,我们就可以利用这个对象里面,刚才我们改造的这个validate方法呢进行验签了,因为quest好,那么这个方法呢,它的返回值呢是不值,所以呢,在这面我们可以把它放在我们的if条件判断当中。
07:24
好,那么如果他的验签不通过的话。我们呢,就可以有一个失败的应答了。像这样。好,那么这面呢,我们可以写通知验签失败,好,然后接下来呢,上面这块我们可以直接写一个在控制台上的一个错误日志log点通知。验签失败,好,那这块其实就是我们签名验证的过程了,当然了,目前为止呢,我们写的自己写的这个工具类呢,我们还要再完善一下。
08:06
那在这面我们呢,继续来修改我们的valid方法。在我们的验签的过程当中,还有一个非常重要的步骤,就是构造这个验签名串哈。从我们的请求头或者是响应头当中拿到这样的信息,然后构造成这样的格式,然后呢,在验签的时候呢,会对它做摘要,还记得吧,好,所以呢,我们这个方法就是构造验签名串的方法,只不过现在呢,我们要从请求当中获取,然后接下来我们把它改成HTTP。那么这面也是一样,都给它改造成,然后这面呢,就是get了。好到直接就是字符串。然后这面呢,直接就得到时间戳和随机数的字符串形式,那么包呢,我们可以从这个地方拿到。
09:09
这个地方就是我们的body了啊,那有的同学说,那可不可以在我们的。这个呃,工具方法当中直接用这种形式。来获取我们request当中的这个请求题呢,那么理论上是可以的哈,但是实际上你运行的时候呢,它会报告错误啊,为什么会报告错误呢?因为这个瑞这个方法呢,是从request里面获取数据流,那么这个数据流一旦获取成功了之后呢,这个BR啊这个。Buff分它就会被关闭掉,这个buff分一旦被关闭掉了的话,下一次你再从request里面拿数据就拿不出来了,所以呢,这种情况我们这个方法呢,针对同一个request对象只能调用一次,那这样的话,如果我们在这个地方已经写过了,那意味着在这个地方就不能再次的出现这句话了,啊,意味request对象是同一个,所以呢,我们可以。
10:13
还是利用这个构造函数?把这个给它传递进来。好,然后接下来呢,我们还是需要再完善这个构造函数。嗯。好,那么接下来呢?我们的这个就可以直接利用成员。啊,来构建了。那这是我们的。构造签名的过程,好,接下来呢,我们从请求头当中。
11:07
拿到平台证书序列号,Get header。然后再从请求头当中。拿到我们的请求当中携带的签名。最后利用这个对象,也就是在这个地方。我们注入进来的这个对象哈。这个对象。那进行验签的具体的工作,所以呢,把前面我们拿到的像验签名串啊,还有序列号啊,还有这个我们拿到的。签名啊,都给它传递进来,如果验签成功了的话,那么就会继续向下执行,返回处如果验签失败了的话,那么就会抛出异常,并且告诉你是由哪一个具体的请求抛出异常,所以这个地方呢,我们给它改成request ID。
12:09
好,那这块呢,就是我们的validate方法当中一个验签的一个处理,所以这块呢是验签。好,那我们再来检查一下这个类哈,那刚才的这个valid parameters当中呢,也就是说。第一个步骤。处理请求参数这个步骤当中呢,我们也需要把相应的response改成request,那因为这句话呢,主要是获取这个request ID,然后最终呢一下是否存在到这个request ID当中,下面呢,是针对这个request ID的一个使用的地方,那你会发现其实也都是报错信息当中使用的这个快ID对不对,所以实际上呢,我们可以把它直接删掉。啊,然后呢,让这个request ID呢,直接我们前面我们的成员变量当中获取就可以了。
13:04
然后接下来呢,就是这个位置对我们的请求头当中的这几个请求头的具体的内容做一个非空判断,因为我们整个验签的流程就是要通过这几个内容进行验签哈,好,那所以呢,便利这这几个请求头的见值,然后呢,从请求头当中。这块就是字符串类型的了啊,拿到这几个值之后呢,进行一个非空的判断,如果不为空的话呢,那么就继续。继续这个是做什么呢?这个是value,这个呢是基于刚才的这个便利到最后一个请求的内容,那我们这面最后一个请求头呢,是这个时间戳。所以呢,他就取到这个最后一个请求头的内容,好吧,时间戳取出来,时间戳取出来干什么呢?要判断请求是否过期。
14:09
好,那么如果过期的话,我们就拒绝过期的请求,好,那么我们再来回顾一下,这面呢,是通过这个时间戳创建一个基于时间戳那个时间的时间对象,然后接下来呢,我们再创建一个基于此时此刻的时间对象,将这两个时间对象呢啊用duration between方法呢进行比较,看一看呢,是否大于。五分钟,如果大于五分钟了的话呢,我们就会认为这是一个过期的请求,那么我们就把它拒绝就好了,所以这块呢,是对参数进行判断的过程了,好,那这面呢,就是我们的完整的一个验签的方法的一个实现了,所以实现了验签这个方法之后呢,我们在微信pay controller这个里面呢进行调用,我们在。
15:04
刚才的这个位置。就调用了我们编写的这个valid的方法,并且传递了request对象,最后判断验签是否成功就可以了,好,那现在整个验签的流程呢,我们已经写好了,那我们对整个的这个验签呢,进行一个测试,如果验签失败,那么他就会走这个if语句,那同样如果验签成功。他就会走if语句,接下来的那个好,我们重新启动一下服务器。好服务呢,已经启动成功了。我们来刷新一下我们的项目啊,那同样呢,我们需要把我们之前的这些订单呢,都给它删掉。
16:15
那我呢,进行一个扫码支付。好,支付成功了,我们来看一下这面有没有验签成功的通知,好,这面呢,通知验签成功,所以呢,我们现在对我们在。看一下刚才这个图啊,对我们在异步回调当中,微信给我们发过来的通知也进行了签名验证。
我来说两句