这可能是全网唯一一篇国税局查税接口破解的教程(当然也有可能是我没搜到而已),因为目前国税局通过第三方公司乐税对此查税接口进行收费,所以我就没法公开代码了,不过在这里我会将所有流程全部详细说说,并且告诉你两个强行访问接口的解决方案,其实跟公开代码区别也不大......
首先,让我们用IE打开国税局查税接口的网站,为什么说要用Internet打开呢?是因为安全证书的原因,谷歌和火狐的安全证书需要特定浏览器版本才能使用
然后我们点击安装证书,安装完后,我们再找一张发票将发票代码和发票号码进行输入
好了,返回的数据是验证码和一些其他之后还要返回给服务器,以保证一次性的参数,我们先来分析下发给服务器获取验证码的这个url
https://fpcyweb.tax.sh.gov.cn:1001/WebQuery/yzmQuery?callback=jQuery110204014181644806747_1536650783691&fpdm=031001600311&fphm=06071721&r=0.5805669505833084&v=V1.0.06_001&nowtime=1536651021375&area=3100&publickey=9E4AB45195C512D5C35D02B45ECC2B16&_=1536650783692
1: fpcyweb.tax.sh.gov.cn 这个代表我们查询的这张发票属于上海区域,这里说一句,国税局只是在前端对各个地方和省份的查票接口进行了一个聚合,这也是为什么我们要输入发票代码和号码才能出现验证码的原因
2: callback=jQuery110204014181644806747_1536650783691 这个是jsonp ajax跨域的一个回调函数名,所以不用管它.
3: fpdm=031001600311&fphm=06071721这个就是我们输入的发票代码和号码
4: r=0.5805669505833084&v=V1.0.06_00 随机数和当前版本号,这个主要是为了保证查询的唯一性
5: nowtime=1536651021375&area=3100&publickey=9E4AB45195C512D5C35D02B45ECC2B16&_=1536650783692 第一个参数,时间戳,不过要注意,这个时间戳有点心机的,并不是当前时间,area参数则是地区编码,代表上海,publickey就是典型的加密公钥,最后一个参数不用管,只是一个在一个窗口生命期递增的数字
Ok,分析完了请求参数,我们再来看看响应数据,因为数据太多,浏览器的抓包窗口实在不好截图,所以我弄到了本地文件里
key1:验证码数据被base64编码后的数据.key2:当前查询时间,k3,k4和k5则是区别发票类型的,在js文件里做判断的
分析完了后我们再直接进行查询一次
额,我们直接看第一个请求就行了,其它的都是静态文件,这里我们可以看到返回的数据是乱码的,原因是服务器返回的数据是gbk编码,而我们的抓包工具是utf-8进行编码,所以乱码了,这个不影响
我们再来分析下请求的url
https://fpcyweb.tax.sh.gov.cn:1001/WebQuery/vatQuery?callback=jQuery110204014181644806747_1536650783691&key1=031001600311&key2=06071721&key3=20180322&key4=288598&fplx=10&yzm=%E5%A4%96y&yzmSj=2018-09-11+15%3A50%3A07&index=173d4147add27195a2611a261ebc5caa&area=3100&publickey=2E037FCE5CAFFC1A384447A26195BF69&_=1536650783695
1: fpcyweb.tax.sh.gov.cn这个我在上面解释过了
2:key1=031001600311&key2=06071721&key3=20180322&key4=288598&fplx=10&yzm=%E5%A4%96y&yzmSj=2018-09-11+15%3A50%3A07这些参数分别是我填的发票代码,号码,日期,校验码,验证码,以及发票类型10代表增值税电子普通发票(这个是根据发票代码代码里判断的)
3:index=173d4147add27195a2611a261ebc5caa&area=3100&publickey=2E037FCE5CAFFC1A384447A26195BF69&_=1536650783695 这些的话除了area还有最后一个参数外都是js代码自动生成的
分析完了,那我们现在在理一下思路,首先,我们要下载证书,然后输入发票代码和号码获取验证码,最后输入验证码以及其它参数点击查询便可以获取到数据了.
那我们现在的难题是在哪里呢?
1:没有证书发请求别人直接就拒绝了(请看https原理),我们要怎么把证书弄到服务器里去,毕竟我们是要用服务器直接调接口的
2:那些网站里随机生成的参数还有公钥怎么办?我们没法通过数字本身找到规律
OK,只要明确了问题剩下的就很简单了,
问题1的解决方案: 将证书下载下来导入jvm的证书库中,这个可以百度,java导入https证书,再使用httpclient模拟IE浏览器(额,user-agent了解一哈)
问题2的解决方案: 我们将他们的加密和随机生成参数的js文件下载下来
这个是加密和生成秘钥的js
这个是根据参数生成类型的js
解析返回结果的js
但是这样一来又出现了一个新的问题: 如果我们按照方案2的做法,那我们就没证书可以导了,那我们就算能发请求又有什么用呢?根本通不过啊.
问题的解决方案: 在客户端生成请求,但是这个请求我们作为字符串,将其转发给我们的服务器,之后服务器再使用证书模拟IE将请求直接发送.
最后有一点要注意的是,每个省的服务器对于请求头的拦截都是不同的,还有,最好将你在第一次请求验证码时返回的cookie给拿到,然后再存到httpclient的header里发出去,因为像江苏这些网站对cookie是有做验证的,还有有些还对refersh也做验证,如果不是自己省财务或者国税局财务网站发来的,就直接在nginx层拦掉
这样一来,你就会开心的拿到发票数据了.什么?你觉得很麻烦?好吧,selenium+phantomjs+任务队列了解一下,我没使用这几个的原因是因为窗口句柄切换太麻烦,而且速度也不快,但如果你没看懂上面的,那就用它们吧,简单易操作.