今天是在公司的最后一天,早上完成工作后大佬还没时间给我安排新的工作,现在就有点时间来写下博客了,前段时间都没写的博客,哎!感觉这个习惯很难养成。

今天来讲讲之前做的一个东西,就是要生成国税局的发票二维码,即 使用程序代码生成相应信息的二维码需要跟 税局发票助手 生成的二维码携带的信息是一样的。我使用的是 php 语言,一开始就上网百度了下 php 生成二维码的方法,一下子就能找出 phpqrcode 这个库(地址:http://phpqrcode.sourceforge.net/),下载后直接引入主要的文件 phpqrcode.php 再百度下 demo 代码即可生成(带 logo 的二维码),当然如果是生成普通的二维码的话上面就可以了,但是生成国税局发票的二维码还是不简单滴,涉及到 了 CRC-16 加密算法,百度了一篇博文讲解了国税总局发票助手二维码生成的CRC计算和便捷开票二维码编码内容格式,点击打开链接,如下图:

可以看出,最最主要的就是计算这个 CRC 了,不过上面的这篇博文给出的代码不仅是 java 版本的,关键的是代码不完整,变量初值没给出来。这就很尴尬了。于是继续百度,发现 php 官网上有计算 crc16 的算法例子(点击打开链接),或直接见以下代码(我只拿了其中一份简洁的代码例子如下):

<?php
function crc16($string) { $crc = 0xFFFF; for ($x = 0; $x < strlen ($string); $x++) { $crc = $crc ^ ord($string[$x]); for ($y = 0; $y < 8; $y++) { if (($crc & 0x0001) == 0x0001) { $crc = (($crc >> 1) ^ 0xA001); } else { $crc = $crc >> 1; } } } return $crc;
}
?>

于是迫不及待尝试计算存储在二维码中的信息构成的 crc16 的值,结果计算出来的始终与 税局发票助手(可以下载然后用来测试)生成的 crc16 不一样。。还是贴下测试的代码:

<?phpfunction crc16($string) { $crc = 0xFFFF; for ($x = 0; $x < strlen ($string); $x++) { $crc = $crc ^ ord($string[$x]); for ($y = 0; $y < 8; $y++) { if (($crc & 0x0001) == 0x0001) { $crc = (($crc >> 1) ^ 0xA001); } else { $crc = $crc >> 1; } } } return $crc;
}$string = '广东xx网络有限公司</>91442000***3</>中山市石岐区xxx 0760-88888888</>中国建设银行中山兴中道支行 4400***0</>';$s = @pack('H*', $string);
$t = @crc16($s);
@printf('%02x%02x', $t%256, floor($t/256));

狠尴尬。。百度了好久也不造确切原因额。。

接下来只能寄希望于最初那篇博文的源代码了,于是继续百度百度百度,最后终于找到了一个说根据那段残缺代码然后去测试,慢慢推出来了那两个变量的初值,不容易啊!牛~花了2积分下了他的代码自行研究,毕竟是 java 版本的,还是得改成 php 版本的先。

主要的 java 版本的代码如下所示:

public class TestCrc  {public static void main(String[] args){String input = "北京国税123456789</>9XXxx123456789XXxx</>北京市通州区正在大厦123456789</>中国银行123456789</>";  try {byte[] inputs = input.getBytes("GBK");  for (int i = 0; i < inputs.length; i ++) {  div(inputs[i]);  }  byte r = 0;  div(r);  div(r); String crc3=Integer.toHexString(a);System.out.println(Integer.toHexString(a));String jm=getBase64(input+crc3.toUpperCase());//base64加密String s="$01"+jm+"$";String a="5YyX5Lqs5Zu956iOMTIzNDU2Nzg5PC8+OVhYeHgxMjM0NTY3ODlYWHh4PC8+5YyX5Lqs5biC6YCa5bee5Yy65q2j5Zyo5aSn5Y6mMTIzNDU2Nzg5PC8+5Lit5Zu96ZO26KGMMTIzNDU2Nzg5PC8+MjAxQQ==";System.out.println(s);String jmh1=getFromBase64(a);System.out.println(jmh1);} catch (Exception e) {e.printStackTrace();}  }static int a=0x0000;static int crc16=0x8005;private static void div(byte input) {//算法 int temp=0;  int data = input;  for (int i = 0; i < 8; i ++) {  temp = a & 0x8000;  a = a << 1;  a = a & 0x0000ffff;  int numIn = data & 0x80;  numIn = numIn >> 7;  a = a ^ numIn;  if (temp == 0x8000) {  a = a ^ crc16;  }  data = data << 1;  a = a & 0x0000ffff ; } }public static String getBase64(String str) {  //加密byte[] b = null;  String s = null;  try {  b = str.getBytes("utf-8");  } catch (UnsupportedEncodingException e) {  e.printStackTrace();  }  if (b != null) {  s = new BASE64Encoder().encode(b);  }  return s;  } public static String getFromBase64(String s) {  //解密byte[] b = null;  String result = null;  if (s != null) {  BASE64Decoder decoder = new BASE64Decoder();  try {  b = decoder.decodeBuffer(s);  result = new String(b, "utf-8");  } catch (Exception e) {  e.printStackTrace();  }  }  return result;  }
}

只能使用上述的生成 crc16 的算法了,经过研究改成 php 版本的代码如下:

<?php
class TestCrc  {public static function getBytes($string) {/* 获取字节流数组(ASCII码) */$bytes = array(); for($i = 0; $i < strlen($string); $i++){ $bytes[] = ord($string[$i]); } return $bytes; }public static function test($input){/* 传递参数为填写在国税发票助手的内容拼成的二维码存储内容格式,返回的是存入二维码的内容 */
                        $inputs = iconv('utf-8', 'gbk', $input);
$inputs = array_map('ord', str_split($inputs));for ($i = 0; $i < count($inputs); $i++) {  self::div($inputs[$i]);  }$r = 0;self::div($r);self::div($r);$crc = sprintf("%04X",self::$a); /* 输出4位16进制数(不足四位用0占位) */$QRcodeContent = $input.$crc;return '$01'.base64_encode($QRcodeContent).'$';}public static $a=0x0000;public static $crc16=0x8005; private static function div($input) {/* 算法 */$temp=0;  $data = $input;  for ($i = 0; $i < 8; $i ++) {  $temp = self::$a & 0x8000;  self::$a = self::$a << 1;  self::$a = self::$a & 0x0000ffff;  $numIn = $data & 0x80;  $numIn = $numIn >> 7;  self::$a = self::$a ^ $numIn;  if ($temp == 0x8000) {  self::$a = self::$a ^ self::$crc16;  }$data = $data << 1;  self::$a = self::$a & 0x0000ffff ; } }
}

测试代码:

        $content = "广东xx网络有限公司</>91442000***3</>中山市石岐区xxx 0760-88888888</>中国建设银行中山兴中道支行 4400***0</>";
$qrcodeContent = TestCrc::test($content);

结果发现结果还是与税局发票助手的生成的 crc16 结果不一样,后来一想直接不要将输入的内容转 gbk 格式试试看,结果就可以了,主要将上述代码修改如下:

修改 test 函数的前两行代码为:

      $inputs = self::getBytes($input);

即可顺利生成与税局发票助手一致的二维码了(存储的 base64 内容一致)。快去试试吧!

感觉很多东西一开始很陌生,会有种惧怕的感觉,但是一旦尝试深入解决,只要坚持,我相信大部分(不可能是全部)难题都可以被你解决的!

好了,Java 版本的代码地址如下:

点击打开链接

php 版本的 demo 地址如下:

点击打开链接

php 生成国税局二维码相关推荐

  1. EFQRCode:自动生成花式二维码

    原文链接:https://github.com/EyreFree/EFQRCode EFQRCode:自动生成花式二维码.# 为开源点赞# -- 由SwiftLanguage分享 EFQRCode i ...

  2. 程序员的乐趣,生成自定义二维码,5 行 Python 代码就搞定

    选自 | towardsdatascience 作者 | Arindom Bhattacharjee 转自 | 机器之心 参与 | 杜伟.小舟 随处可见的二维码是怎么生成的?自己做一个试试吧. 随着互 ...

  3. 支付宝支付 第六集:生成支付二维码

    支付宝支付 第六集:生成支付二维码 一.资源 支付宝沙箱显示APP-ID错误:我的原因是支付宝网关地址写错了 支付宝沙箱环境报 invalid-app-id 错误原因: 无效的AppID参数 错误 支 ...

  4. Android应用--QR的生成(二维码)

    二维码的定义: 二维码 (2-dimensional bar code),是用某种特定的几何图形按一定规律在平面(二维方向上) 分布的黑白相间的图形记录数据符号信息的. 在许多种类的二维条码中,常用的 ...

  5. python小工具myqr生成动态二维码

    python小工具myqr生成动态二维码 (一)安装 (二)使用 (一)安装 命令: pip install myqr 安装完成后,就可以在命令行中输入 myqr 查看下使用帮助: myqr --he ...

  6. 分享几个在线生成网址二维码的API接口

    现在很多大网站都有这样的一个功能,使用手机扫描一下网页上的二维码便可快速在手机上访问网站.想要实现这样的功能其实很简单,下面麦布分享几个在线生成网址二维码的API接口.都是采用http协议接口,无需下 ...

  7. qrcode方法生成的二维码安卓手机长按不识别

    qrcode生成的二维码,在苹果等手机上长按可识别,在华为手机上长按没有反应,截图保存下来长按又可以识别. #问题原因 浏览器兼容问题 qrcode在页面生成二维码时,会生成一个canvas标签和一个 ...

  8. python生成动态二维码实例_python生成动态个性二维码(示例代码)

    1 安装工具 2 生成普通二维码 3 带图片的二维码 4 动态 GIF 二维码 5 在Python程序中使用 一.安装 首先在python环境下运行, 打开cmd进入python27 进入script ...

  9. ThinkPHP-保存生成的二维码

    通过TP框架引入Qrcode插件,然后调用插件生成二维码,并保存 1.引入qrcode插件: 2.功能页面-生成二维码按钮: 3.生成二维码-代码: 4.后台代码-通过vendor方法引入: //下载 ...

最新文章

  1. ps aux|grep
  2. 黄聪:使用srvany.exe将任何程序作为Windows服务运行
  3. linux的备份和恢复命令,Linux基本命令——备份与恢复文档
  4. 神策数据荣登 2020 IDC 中国 Fintech 50 强榜单
  5. SpringBoot学习系列之一
  6. hive.ql.exec.DDLTask. MetaException(message:java.io.IOException: Attempt to start meta tracker faile
  7. python中turtle画树_python中turtle可以画树吗?怎么画?
  8. php的变量、传值、传址、销毁变量
  9. win7下wifi密码的保存路径
  10. mysql架构 三级主从同步_MySQL 主从同步架构中你不知道的“坑”
  11. java中criteria类_java – Criteria API:按类类型过滤
  12. linux设备驱动 注册 命令6,Linux设备驱动调试
  13. mysql public权限_MySQL · 引擎特性 · Binlog encryption 浅析
  14. Python全栈之路Day16
  15. Skyline Web 二次开发- 1.地图显示、Position、AttachEvent
  16. 模拟退火算法_Simulated Annealing 模拟退火算法
  17. 视频教程-VBA从入门到精通(控件+类模块+ADO+SQL数据库)-Office/WPS
  18. 如何批量查询手机号码归属地
  19. html 锚文本,什么是锚文本,锚文本链接对SEO的影响!
  20. 视频教程-Ps教程之神奇的Photoshop自动化技术-Photoshop

热门文章

  1. 一个互联网技术从业者的管理认知思考
  2. UCI计算机工程必修专业课,UCI大学尖端专业学科盘点
  3. 修改UINavigationItem标题字体
  4. LCD12864液晶显示
  5. binlog回滚mysql误操作数据
  6. HTML5期末大作业:轮滑运动体育类人物介绍主题网站设计(12页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计
  7. SQL注入学习日记(一)
  8. 教你如何更改U盘图标
  9. 抖音快手如何快速涨粉技巧整理
  10. mysql使用结巴语句_结巴分词 java 高性能实现,是 huaban jieba 速度的 2倍