分类
科技文章

电子发票解析结构化数据说明

输出示例:

{
  "发票代码": "031001900111",
  "发票号码": "96803177",
  "开票日期": "2020-06-04",
  "校验码": "15821 43303 58801 56335",
  "机器编号": "499099827029",
  "发票名称": "上海增值税电子普通发票",
  "购买方": {
    "名称": "上海少侠网络科技有限公司",
    "纳税人识别号": "91310230MA1K2X93X0",
    "地址、电话": "",
    "开户行及账号": ""
  },
  "密码": [
    "032821682*+*-9*36*6338+915<<",
    ">46</76>0/40351+19066>6434-5",
    "045292/12+/64-+352822/3>48<*",
    "796349569<01+2761949>/>0*+74"
  ],
  "项目": [
    [
      "货物或应税劳务、服务名称",
      "*信息技术服务*信息系统增值服务",
      "*广告代理服务*广告代理费",
      "合计"
    ],
    [
      "规格型号"
    ],
    [
      "单位",
      "次",
      "次"
    ],
    [
      "数量",
      "1",
      "1"
    ],
    [
      "单价",
      "863.21",
      "80.19"
    ],
    [
      "金额",
      "863.21",
      "80.19",
      "¥943.40"
    ],
    [
      "税率",
      "6%",
      "6%"
    ],
    [
      "税额",
      "51.79",
      "4.81",
      "¥56.60"
    ]
  ],
  "合计": [
    "壹仟元整",
    "¥1000.00"
  ],
  "销售方": {
    "名称": "百度在线网络技术(北京)有限公司上海软件技术分公司",
    "纳税人识别号": "91310000772120643P",
    "地址、电话": "上海市嘉定区汇荣路468号2幢2层B区021-39005678",
    "开户行及账号": "招商银行上海分行曹家渡支行215081392810001"
  },
  "备注": [],
  "收款人": "百度",
  "复核": "",
  "开票人": "百度",
  "fileId": "dc20c6e07d858fdca9468055e05b54f8"
}

数据结构根节点为对象,对象的key基本上都是发票票面上的字段和字段值。

开票日期统一格式化为YYYY-MM-DD格式,可能跟票面实际文本略有差异。

购买方销售方下各有4个字段。

密码字段是数组结构,解析正确时都有4个元素,按顺序对应发票票面密码区从上到下4行密码文本。

项目字段是二维数组结构。表示“货物或应税劳务、服务名称”表格的内容,包括表头。项目一级数组有8个元素,对应表格的8列。二级数组中包含当前列的所有文本字段,包括表头。

合计是价税合计一行的文本,是数组结构,一定包含大写文本和小写金额。

备注是数组结构,包含发票票面备注区域的文本。

分类
科技文章

QQ音乐flac文件封面

从QQ音乐下载的无损flac文件,在索尼等MP3播放设备上,是无法显示封面的,原因是QQ音乐把封面图片存储在了不正确的文件位置中,也就是非标准flac格式,所以索尼等设备使用标准flac格式就无法读取封面。

提供一个免费工具可以自己重新设置flac文件封面:FLAC标签编辑器,欢迎大家使用

分类
科技文章

Node.js unable to verify the first certificate

在node.js中使用request、superagent之类的请求https地址有可能会遇到

unable to verify the first certificate

这个问题是intermediate certificate导致的:the intermediate certificate wasn’t bundled along with the server certificate, you’ll need to fix that

npm上有个package专门可以修复这个问题https://www.npmjs.com/package/ssl-root-cas,网上有很多方法是禁用ssl校验来规避问题,但是这种方法并不安全

其实这个问题很有可能是服务器配置有疏漏导致的,如果是Apache2可以检查一下有没有配置SSLCertificateChainFile

分类
科技文章

php intval的一个小坑

var_dump(intval('19.90' * 100)); // 1989
var_dump(intval(floatval(1990))); // 1990

计算得来的float 1990和直接声明得来的 float 1990,在intval取整的时候结果会不一样的

跟float存储方式有关,一不小心可能就掉坑了。

// 解决办法
var_dump(intval(round('19.90' * 100))); // 1990
分类
科技文章

FLAC标签编辑器

FLAC代表免费无损音频编解码器,它是一种类似于MP3的音频格式,但是无损,这意味着音频在FLAC中进行了压缩而没有任何质量损失。

FLAC音频支持音乐作者、专辑、封面等媒体标签,但是市面上少见能自主编辑这些标签的软件。

FLAC标签编辑器,是一款免费的在线标签编辑器。可以让你实现编辑标签,添加封面图片等功能。

分类
科技文章

使用shell命令删除指定时间前的文件

显示20分钟前的文件

find /home/prestat/bills/test -type f -mmin +20 -exec ls -l {} \;

删除20分钟前的文件

find /home/prestat/bills/test -type f -mmin +20 -exec rm {} \;

显示20天前的文件

find /home/prestat/bills/test -type f -mtime +20 -exec ls -l {} \;

删除20天前的文件

find /home/prestat/bills/test -type f -mtime +20 -exec rm {} \;
分类
科技文章

html input九宫格数字键盘

<input type="number">

这种用法,在安卓系统上可以调出九宫格,但是iOS系统需要加上pattern=”\d*”

<input type="number" pattern="\d*">
分类
科技文章

App交付AppStoreConnect之后消失的坑

使用Transporter或者其他方式上传App到AppStoreConnect之后,在Transporter中会显示已经交付,这时在App Store Connect的“活动”列表中也会看到上传的版本

但是:有可能过一会儿列表中的版本就会消失…

原因是如果上传的二进制文件有问题,列表里就会直接消失,可以查看一下开发者账号的邮箱,成功失败,苹果都会给你发一封邮件。

这个交互,真的让新手摸不到头脑…

分类
科技文章

electron的一个小坑

const pkg = require('../package.json');
const something = pkg.build.something;

以上这段代码,在dev状态是不会报错的,但是build之后的包,运行起来就会报错。原因是electron-builder在打包时把package.json的内容精简了,只留了name, version等少数内容,所以以下代码是不会报错的:

const pkg = require('../package.json');
const version = pkg.version;

这个问题只在打包后才会报错,还挺不好排查的。

分类
科技文章

nodejs文件md5

const fs = require('fs');
const crypto = require('crypto');

module.exports = (filename) => {
    return new Promise((resolve) => {
        const hash = crypto.createHash('md5');
        const input = fs.createReadStream(filename);
        input.on('readable', () => {
            const data = input.read();
            if (data)
                hash.update(data);
            else {
                resolve(hash.digest('hex'));
            }
        });
    });
};