允许腾讯云用户UID:2561063转发自腾讯云
https://cloud.tencent.com/developer/user/2561063
目录
1 概述
云南区块链商户平台是一款提供给云南省商户使用的开票工具,由于自身使用仅限于电脑端,没有移动端,且设计理念存在问题使用非常不便,于是打算通过制作一个发票助手完善一些核心功能模块,主要是对商户的使用流程顺序进行简化,以及对原产品的便捷性进行了提升,能不让商户进行操作的尽量全自动化
前面的几篇博文云南区块链商户平台:抓包技术自制开票工具(三)
、云南区块链商户平台:抓包技术自制开票工具(二)
、云南区块链商户平台:抓包技术自制开票工具(一)
已经介绍了制作发票助手的一些功能模块,经测试使用了半个月后完善了本次项目
本项目对接了增值税票务OCR识别
、51商品税收编码识别
接口,前面的博文中提到了第三方识别平台,虽然免费可是效果太差,在最后的修改中废弃掉了,采用《基于DdddOcr通用验证码离线本地识别SDK搭建个人云打码接口Api》本地接口,对于第三方API接口,都是通过抓包分析的,第三方接口可以稳定使用,后续考虑将第三方接口单独拿出来供大家对接使用。
2 功能对比
功能 | 原平台 | 商户平台发票助手 |
---|---|---|
自动登录 | ❌每次登陆需输入验证码 | ✅免验证码自动登录,登录状态失效自动更新检测,商户使用无感 |
商品编码识别 | ❌需商户自行判断或搜索该商品税收编码 | ✅提供本地库存和在线检测,本地没有记录自动匹配接口一键添加税收编码到商户 |
历史记忆 | ❌不会留存之前开过发票的公司信息 | ✅开过发票记录自动留存,关键字匹配公司名和纳税识别号,适用于小个体户经常给相同公司开发票 |
自动下载 | ❌发票开具成功后,需要去管理页面手动下载 | ✅开具成功后可自动发送文件到邮箱(邮箱绑定微信)也可自己下载 |
增值税票务OCR识别 | ❌只能手动输入 | ✅可通过拍照识别|图片上传识别,自动获取公司名和纳税识别号 |
辅助模式 | ❌ | ✅免输入,商品通过手动下滑选择添加,通过拍照识别开票公司信息 |
优点:免去每次需要登陆,采用自动登录,历史记忆留存更便捷开票信息填入,自动下载到手机,为广大云南商户开票提供便捷等
缺点:目前因业务需要,未进行税率调整操作,默认免税商品编码入库,有能力的可以自己修改后端接口,前端新增税率调整或通过api接口进行输入
3 项目演示图
可以便捷搜索商户平台原有商品库存,若没有该商品可以自动查询该商品的
税收编码,点击可以一键添加到商户平台库存,方便下次使用
,商品名采用模糊搜索,键入一定字符串就可以识别对应的商品,极大的简化了原平台全文输入模式
联网识别
税收分类编码以及该分类介绍、类目等信息,帮助用户快速识别该商品的税收编码,点击即可添加入库,而传统的方式,需要商户自行搜索,该商品属于的类目,需要对分类进行一定的筛选和信息检索,该功能极大简化了用户操作的时间成本
首次可免密登录,下次启动保留账号自动识别登录,自动检查更新token
,商户无需再次输入繁琐的账户和密码,开票就两步骤:1、打开软件 2、填入开票公司信息纳税识别号以及开票商品数据 简化了操作流程
4 核心逻辑
4.1智能赋码
全平台找了个遍,没有直接就能用的,需要自行解密抓包,税码识别来自51发票,通过商品关键词得出结果,可以根据选择人群最多的选择
流程:随机获取验证码并存储验证码id,通过本地ddddocr识别后将验证码与验证码id一起提交即可。
4.2 解密方法
登录的数据是经过aes加密的,想学习的可参考文章《云南区块链商户平台:抓包技术自制开票工具(二)》,不再赘述
<?php
header('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'); // 设置是否允许发送 cookies
header('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个月后失效
<?php
header('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'); // 设置是否允许发送 cookies
header('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 访问项目域名
附件下载
转载自CSDN-专业IT技术社区
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_35230125/article/details/139308243