关注

云南区块链商户平台发票助手成品

允许腾讯云用户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

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--