| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- package com.muzhi.lemeng.common.tencent;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.tencentcloudapi.common.Credential;
- import com.tencentcloudapi.common.exception.TencentCloudSDKException;
- import com.tencentcloudapi.common.profile.ClientProfile;
- import com.tencentcloudapi.common.profile.HttpProfile;
- import com.tencentcloudapi.ocr.v20181119.OcrClient;
- import com.tencentcloudapi.ocr.v20181119.models.*;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang.StringUtils;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Component;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.HashMap;
- import java.util.Map;
- @Slf4j
- @Component
- public class TencentInvoice {
- private static String secretId;
- private static String secretKey;
- private static String region;
- // 创建一个非静态的 Setter 方法,加上 @Value
- // Spring 启动时会调用这个方法,将配置文件值传入
- @Value("${myapp.tengxun.secretId}")
- public void setSecretId(String value) {
- TencentInvoice.secretId = value; // 赋值给静态变量
- }
- @Value("${myapp.tengxun.secretKey}")
- public void setSecretKey(String value) {
- TencentInvoice.secretKey = value; // 赋值给静态变量
- }
- @Value("${myapp.tengxun.region}")
- public void setRegion(String value) {
- TencentInvoice.region = value; // 赋值给静态变量
- }
- // 创建请求描述
- private static ClientProfile doRequest(String endPoint) {
- HttpProfile httpProfile = new HttpProfile();
- httpProfile.setEndpoint(endPoint);
- ClientProfile clientProfile = new ClientProfile();
- clientProfile.setHttpProfile(httpProfile);
- return clientProfile;
- }
- /**
- * 通用票据识别(高级版)
- * REMARK 接口文档地址:https://cloud.tencent.com/document/product/866/37835
- *
- * @param invoiceUrl 发票文件公网URL
- */
- public static JSONObject doRecognizeGeneralInvoice(String invoiceUrl) throws TencentCloudSDKException{
- Credential cred = new Credential(secretId, secretKey);
- ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
- OcrClient client = new OcrClient(cred, region, clientProfile);
- RecognizeGeneralInvoiceRequest req = new RecognizeGeneralInvoiceRequest();
- if (invoiceUrl.startsWith("http")) {
- req.setImageUrl(invoiceUrl);
- } else {
- req.setImageBase64(invoiceUrl);
- }
- req.setEnableMultiplePage(true); // PDF多页识别, 仅支持返回文件前30页
- req.setEnableCutImage(false); // 返回切割图片base64
- RecognizeGeneralInvoiceResponse resp = client.RecognizeGeneralInvoice(req);
- String result = MixedInvoiceOCRResponse.toJsonString(resp);
- JSONObject jsonObject = JSON.parseObject(result);
- log.debug("请求响应, {}", result);
- return jsonObject;
- }
- /**
- * 发票验真[新版]
- * REMARK 接口文档地址:https://cloud.tencent.com/document/product/866/73674
- *
- * @param invoiceKind 票种类型
- * @param invoiceCode 发票代码
- * @param invoiceNo 发票号码
- * @param invoiceDate 开票日期
- * @param amount 价税合计金额
- * @param checkCode 校验码
- * @param excludingTax 不含税金额
- * @param gmfName 购买方名称
- * @param gmfNo 购买方纳税人识别号
- */
- public static JSONObject doVatInvoiceVerifyNew(String invoiceKind, String invoiceCode, String invoiceNo, String invoiceDate, String amount, String checkCode, String excludingTax, String gmfName, String gmfNo) throws TencentCloudSDKException {
- Credential cred = new Credential(secretId, secretKey);
- ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
- OcrClient client = new OcrClient(cred, region, clientProfile);
- // 一些特殊发票校验码只有5位, 兼容
- if (StringUtils.isNotBlank(checkCode) && checkCode.length() > 6) {
- checkCode = checkCode.substring(checkCode.length() - 6);
- }
- VatInvoiceVerifyNewRequest req = new VatInvoiceVerifyNewRequest();
- req.setInvoiceNo(invoiceNo);
- req.setInvoiceDate(invoiceDate);
- req.setInvoiceCode(invoiceCode);
- req.setCheckCode(checkCode);
- // ppExt: 全电票, 新版本识别接口, 返回名称为: 电子发票(普通发票) 不包含全电标识, 发类型为: 全电发票. 注意取值
- if (invoiceKind.contains("全电")) {
- // 全电票, 需要价税合计且无发票代码与校验码
- req.setCheckCode(null);
- req.setInvoiceCode(null);
- req.setAmount(amount);
- } else {
- req.setAmount(null);
- req.setAmount(excludingTax);
- }
- log.debug("发票验真, {}, {}", invoiceKind, JSON.toJSONString(req));
- String result = null;
- String message = null;
- try {
- VatInvoiceVerifyNewResponse resp = client.VatInvoiceVerifyNew(req);
- result = VatInvoiceVerifyNewResponse.toJsonString(resp);
- }catch (TencentCloudSDKException e){
- e.printStackTrace();
- message = e.getMessage();
- log.error("发票验真失败: " + e.getMessage());
- }
- log.info("发票验真, {}, {}", invoiceKind, result);
- // 1. 获取当前日期时间对象
- LocalDateTime now = LocalDateTime.now();
- // 2. 定义格式化器 (yyyy-MM-dd HH:mm:ss)
- // 注意:HH 代表24小时制,mm 代表分钟,ss 代表秒
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
- // 3. 格式化输出
- String formattedDate = now.format(formatter);
- System.out.println("当前时间: " + formattedDate);
- Map invoiceMapResult = new HashMap();
- if (result != null){
- JSONObject jsonObject = JSON.parseObject(result);
- // 因全电票取值, 取值价税合计, 单独校验金额
- JSONObject invoice = jsonObject.getJSONObject("Invoice");
- if (invoiceCode == null){
- invoiceCode = "";
- }
- if (checkCode == null){
- checkCode = "";
- }
- String fpdm = invoice.getString("Code");
- System.out.println("发票代码: " + fpdm);
- String fphm = invoice.getString("Number");
- System.out.println("发票号码: " + fphm);
- String kprq = invoice.getString("Date");
- System.out.println("开票日期: " + kprq);
- float hsje = invoice.getFloat("AmountWithTax");
- System.out.println("含税金额: " + hsje);
- float bhsje = invoice.getFloat("AmountWithoutTax");
- System.out.println("不含税金额: " + bhsje);
- //将含税金额、不含税金额从文本转成数字
- float amountFloat = Float.parseFloat(amount);
- float excludingTaxFloat = Float.parseFloat(excludingTax);
- String gmfmc = invoice.getString("BuyerName");
- System.out.println("购方名称: " + gmfmc);
- String gmfnsrsbh = invoice.getString("BuyerTaxCode");
- System.out.println("购方纳税人识别号: " + gmfnsrsbh);
- if (invoiceCode.equals(fpdm) && invoiceNo.equals(fphm) && invoiceDate.equals(kprq) && amountFloat == hsje && excludingTaxFloat == bhsje && gmfmc.equals(gmfName) && gmfnsrsbh.equals(gmfNo)){
- invoiceMapResult.put("state", "验真成功");
- invoiceMapResult.put("message", "✅发票验真成功!执行时间:" + formattedDate);
- }else {
- invoiceMapResult.put("state", "验真失败");
- invoiceMapResult.put("message", "⚠️发票存在疑问!执行时间:" + formattedDate);
- }
- }else {
- invoiceMapResult.put("state", "验真失败");
- invoiceMapResult.put("message", "⚠️发票存在疑问!执行时间:" + formattedDate + "【失败原因:" + message + "】");
- }
- String jsonString = JSON.toJSONString(invoiceMapResult);
- JSONObject invoiceJsonObject = JSONObject.parseObject(jsonString);
- log.info("发票验真结果: {}", invoiceJsonObject);
- return invoiceJsonObject;
- }
- }
|