云南区块链商户平台发票助手成品
允许腾讯云用户UID:2561063转发自腾讯云
https://cloud.tencent.com/developer/user/2561063
目录
- 1 概述
- 2 功能对比
- 3 项目演示图
- 4 核心逻辑
-
- 4.1智能赋码
- 4.2 解密方法
- 4.3 登录与检测
- 4.4 发票金额大写转换
- 4.5 检查登录是否失效
- 4.6 验证码识别
- 5 演示效果
- 6 项目部署
-
- 6.1 Web站点部署
-
- 6.1.1 环境
- 6.1.2 前端
- 6.1.3 后端
- 6.2 Docker部署
-
- 6.2.1 构建镜像
- 6.2.2 创建容器
- 6.3.3 访问项目域名
- 附件下载
1 概述
云南区块链商户平台是一款提供给云南省商户使用的开票工具,由于自身使用仅限于电脑端,没有移动端,且设计理念存在问题使用非常不便,于是打算通过制作一个发票助手完善一些核心功能模块,主要是对商户的使用流程顺序进行简化,以及对原产品的便捷性进行了提升,能不让商户进行操作的尽量全自动化
前面的几篇博文云南区块链商户平台:抓包技术自制开票工具(三)
、云南区块链商户平台:抓包技术自制开票工具(二)
、云南区块链商户平台:抓包技术自制开票工具(一)
已经介绍了制作发票助手的一些功能模块,经测试使用了半个月后完善了本次项目
本项目对接了增值税票务OCR识别
、51商品税收编码识别
接口,前面的博文中提到了第三方识别平台,虽然免费可是效果太差,在最后的修改中废弃掉了,采用《基于DdddOcr通用验证码离线本地识别SDK搭建个人云打码接口Api》本地接口,对于第三方API接口,都是通过抓包分析的,第三方接口可以稳定使用,后续考虑将第三方接口单独拿出来供大家对接使用。
2 功能对比
优点:免去每次需要登陆,采用自动登录,历史记忆留存更便捷开票信息填入,自动下载到手机,为广大云南商户开票提供便捷等
缺点:目前因业务需要,未进行税率调整操作,默认免税商品编码入库,有能力的可以自己修改后端接口,前端新增税率调整或通过api接口进行输入
3 项目演示图
可以便捷搜索商户平台原有商品库存,若没有该商品可以自动查询该商品的
税收编码,点击可以一键添加到商户平台库存,方便下次使用
,商品名采用模糊搜索,键入一定字符串就可以识别对应的商品,极大的简化了原平台全文输入模式
联网识别
税收分类编码以及该分类介绍、类目等信息,帮助用户快速识别该商品的税收编码,点击即可添加入库,而传统的方式,需要商户自行搜索,该商品属于的类目,需要对分类进行一定的筛选和信息检索,该功能极大简化了用户操作的时间成本
首次可免密登录,下次启动保留账号自动识别登录,自动检查更新token
,商户无需再次输入繁琐的账户和密码,开票就两步骤:1、打开软件 2、填入开票公司信息纳税识别号以及开票商品数据 简化了操作流程
4 核心逻辑
4.1智能赋码
全平台找了个遍,没有直接就能用的,需要自行解密抓包,税码识别来自51发票,通过商品关键词得出结果,可以根据选择人群最多的选择
流程:随机获取验证码并存储验证码id,通过本地ddddocr识别后将验证码与验证码id一起提交即可。
4.2 解密方法
登录的数据是经过aes加密的,想学习的可参考文章《云南区块链商户平台:抓包技术自制开票工具(二)》,不再赘述
<?phpheader(\'Content-Type: text/html;charset=utf-8\');header(\'Access-Control-Allow-Origin:*\'); // *代表允许任何网址请求header(\'Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE\'); // 允许请求的类型header(\'Access-Control-Allow-Credentials: true\'); // 设置是否允许发送 cookiesheader(\'Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin\'); // 设置允许自定义请求头的字段header(\"Content-type:text/html;charset=utf-8\");//字符编码设置function encrypt($plaintext, $key_text, $iv_text) { // 使用PKCS7填充 $block_size = 16; $pad_length = $block_size - (strlen($plaintext) % $block_size); $plaintext .= str_repeat(chr($pad_length), $pad_length); // 如果IV不足16字节,使用空字节填充至16字节 $iv_length = strlen($iv_text); if ($iv_length < 16) { $iv_text = str_pad($iv_text, 16, \"\\0\"); } // 创建AES加密器 $ciphertext = openssl_encrypt($plaintext, \'aes-128-cbc\', $key_text, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv_text); // 将加密结果进行Base64编码 $encrypted_base64 = base64_encode($ciphertext); return $encrypted_base64;}// // 设置参数// $key_text = \'1BEF7826AB87631D\';// $iv_text = \'ABCDEF1234123412\';// $plaintext = \'ABCDABCD1234567\';// $encoding = \'utf-8\';// // 调用加密函数// $encrypted_base64 = encrypt($plaintext, $key_text, $iv_text);// echo \"加密后的Base64编码结果:\".$encrypted_base64.\"\\n\";?>
4.3 登录与检测
4.4 发票金额大写转换
观察发票,当合计金额为整数时,大写的合计也是xxx整,当合计金额有小数等(非整)不加’整’
将代码封装,需要使用调用即可
<?php function toChineseNumber($money){ $money = round($money, 2); $cnynums = array(\"零\",\"壹\",\"贰\",\"叁\",\"肆\",\"伍\",\"陆\",\"柒\",\"捌\",\"玖\"); $cnyunits = array(\"圆\",\"角\",\"分\"); $cnygrees = array(\"拾\",\"佰\",\"仟\",\"万\",\"拾\",\"佰\",\"仟\",\"亿\"); list($int, $dec) = explode(\".\", $money, 2); $dec = array_filter(array($dec[1], $dec[0])); $ret = array_merge($dec, array(implode(\"\", cnyMapUnit(str_split($int), $cnygrees)), \"\")); $ret = implode(\"\", array_reverse(cnyMapUnit($ret, $cnyunits))); // 检查是否是整数,若是整数则加上\'整\'字 if ($money == round($money)) { $ret .= \'整\'; } return str_replace(array_keys($cnynums), $cnynums, $ret); }function cnyMapUnit($list, $units) { $ul = count($units); $xs = array(); foreach (array_reverse($list) as $x) { $l = count($xs); if ($x != \"0\" || !($l % 4)) $n = ($x == \'0\' ? \'\' : $x).($units[($l - 1) % $ul]); else $n = is_numeric($xs[0][0]) ? $x : \'\'; array_unshift($xs, $n); } return $xs; }
使用方法
$chinese= toChineseNumber($totalAmount);
4.5 检查登录是否失效
<?php$token=$_POST[\'token\'];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, \'https://yunnan-cloud-backend.wetax.com.cn/v3/user/user-info?token=\'.$token);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, \'GET\');curl_setopt($ch, CURLOPT_HTTPHEADER, [ \'accept: application/json, text/plain, */*\', \'accept-language: zh,zh-CN;q=0.9\', \'cache-control: no-cache\', \'origin: https://yunnan-cloud.wetax.com.cn\', \'pragma: no-cache\', \'referer: https://yunnan-cloud.wetax.com.cn/\', \'sec-ch-ua: \"Google Chrome\";v=\"123\", \"Not:A-Brand\";v=\"8\", \"Chromium\";v=\"123\"\', \'sec-ch-ua-mobile: ?0\', \'sec-ch-ua-platform: \"Windows\"\', \'sec-fetch-dest: empty\', \'sec-fetch-mode: cors\', \'sec-fetch-site: same-site\', \'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\',]);$response = curl_exec($ch);echo($response);curl_close($ch);
4.6 验证码识别
使用Ddddocr服务器版本通过Docker搭建的api接口,以下为临时服务器项目3个月后失效
<?phpheader(\'Content-Type: text/html;charset=utf-8\');header(\'Access-Control-Allow-Origin:*\'); // *代表允许任何网址请求header(\'Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE\'); // 允许请求的类型header(\'Access-Control-Allow-Credentials: true\'); // 设置是否允许发送 cookiesheader(\'Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin\'); // 设置允许自定义请求头的字段header(\"Content-type:text/html;charset=utf-8\");//字符编码设置function ddddocr($base64_content) { // 设置主机地址 $host = \"http://120.55.79.6:32770\"; // 构建 API URL $api_url = $host . \"/ocr/b64/text\"; // 使用 cURL 发送 POST 请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $api_url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $base64_content); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); // 检查响应状态码 $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http_code == 200) { return $response; } else { return \"Failed to call the API: \" . $http_code; }}// 示例 base64 编码的图片内容// $base64_content = \"\";// 调用函数并打印结果// $result = ddddocr($base64_content);// echo($result);?>
5 演示效果
6 项目部署
6.1 Web站点部署
下载附件进行解压,前端留在本地桌面,后端上传服务器
6.1.1 环境
php7.0+Nginx1.18+mysql5.6
6.1.2 前端
解压前端压缩包,到uniapp打开项目,替换所有vue页面的apiurl为你自己的域名(注意/)
6.1.3 后端
将后端文件夹下的压缩包上传至服务器站点解压,导入数据库,修改config.php配置文件,能访问任意接口即可(非404)
6.2 Docker部署
如果你只是简单的使用,可以通过docker部署,但是接口都在我的演示服务器里,但这不影响使用,接口不收集其他信息,主要是录入了开票公司名用于下拉选择,介意请自己更换接口即可
解压docker.zip将dockerfile和YunnanCloud文件夹同级存放,使用dockerfile构建镜像文件,创建运行容器,访问指定端口即可
6.2.1 构建镜像
6.2.2 创建容器
6.3.3 访问项目域名