TXYImplInvoice.java 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package com.malk.xzkj.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.malk.server.common.McException;
  4. import com.malk.utils.UtilMap;
  5. import com.malk.utils.UtilNumber;
  6. import com.malk.xzkj.config.TXYConf;
  7. import com.malk.xzkj.service.TXYInvoice;
  8. import com.tencentcloudapi.common.Credential;
  9. import com.tencentcloudapi.common.exception.TencentCloudSDKException;
  10. import com.tencentcloudapi.common.profile.ClientProfile;
  11. import com.tencentcloudapi.common.profile.HttpProfile;
  12. import com.tencentcloudapi.ocr.v20181119.OcrClient;
  13. import com.tencentcloudapi.ocr.v20181119.models.*;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.apache.commons.lang3.StringUtils;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.stereotype.Service;
  18. import java.util.Map;
  19. @Slf4j
  20. @Service
  21. public class TXYImplInvoice implements TXYInvoice {
  22. @Autowired
  23. private TXYConf txyConf;
  24. // 创建请求描述
  25. private ClientProfile doRequest(String endPoint) {
  26. HttpProfile httpProfile = new HttpProfile();
  27. httpProfile.setEndpoint(endPoint);
  28. ClientProfile clientProfile = new ClientProfile();
  29. clientProfile.setHttpProfile(httpProfile);
  30. return clientProfile;
  31. }
  32. /**
  33. * 混贴票据识别
  34. *
  35. * @apiNote https://cloud.tencent.com/document/product/866/37835
  36. */
  37. @Override
  38. public Map doMixedInvoiceOCR(String image) throws TencentCloudSDKException {
  39. Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
  40. ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
  41. OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
  42. MixedInvoiceOCRRequest req = new MixedInvoiceOCRRequest();
  43. if (image.startsWith("http")) {
  44. req.setImageUrl(image);
  45. } else {
  46. req.setImageBase64(image);
  47. }
  48. req.setReturnMultiplePage(true); // PDF多页识别, 仅支持返回文件前30页
  49. //log.debug("请求参数, {}", JSON.toJSONString(req));
  50. MixedInvoiceOCRResponse resp = client.MixedInvoiceOCR(req);
  51. String result = MixedInvoiceOCRResponse.toJsonString(resp);
  52. log.debug("请求响应, {}", result);
  53. return (Map) JSON.parse(result);
  54. }
  55. /**
  56. * 通用票据识别(高级版)
  57. *
  58. * @apiNote https://cloud.tencent.com/document/api/866/90802
  59. */
  60. @Override
  61. public Map doRecognizeGeneralInvoice(String image) throws TencentCloudSDKException {
  62. Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
  63. ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
  64. OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
  65. RecognizeGeneralInvoiceRequest req = new RecognizeGeneralInvoiceRequest();
  66. if (image.startsWith("http")) {
  67. req.setImageUrl(image);
  68. } else {
  69. req.setImageBase64(image);
  70. }
  71. req.setEnableMultiplePage(true); // PDF多页识别, 仅支持返回文件前30页
  72. req.setEnableCutImage(false); // 返回切割图片base64
  73. RecognizeGeneralInvoiceResponse resp = client.RecognizeGeneralInvoice(req);
  74. String result = MixedInvoiceOCRResponse.toJsonString(resp);
  75. log.debug("请求响应, {}", result);
  76. return (Map) JSON.parse(result);
  77. }
  78. /**
  79. * 发票验真[新版]
  80. *
  81. * @apiNote https://cloud.tencent.com/document/product/866/73674
  82. */
  83. @Override
  84. public Map doVatInvoiceVerifyNew(String invoiceKind, String invoiceCode, String invoiceNo, String invoiceDate, String amount, String checkCode, String excludingTax, String tips) throws TencentCloudSDKException {
  85. Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
  86. ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
  87. OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
  88. // 一些特殊发票校验码只有5位, 兼容
  89. if (StringUtils.isNotBlank(checkCode) && checkCode.length() > 6) {
  90. checkCode = checkCode.substring(checkCode.length() - 6);
  91. }
  92. VatInvoiceVerifyNewRequest req = new VatInvoiceVerifyNewRequest();
  93. req.setInvoiceNo(invoiceNo);
  94. req.setInvoiceDate(invoiceDate);
  95. req.setInvoiceCode(invoiceCode);
  96. req.setCheckCode(checkCode);
  97. // ppExt: 全电票, 新版本识别接口, 返回名称为: 电子发票(普通发票) 不包含全电标识, 发类型为: 全电发票. 注意取值
  98. if (invoiceKind.contains("全电")) {
  99. // 全电票, 需要价税合计且无发票代码与校验码
  100. req.setCheckCode(null);
  101. req.setInvoiceCode(null);
  102. req.setAmount(amount);
  103. } else {
  104. req.setAmount(null);
  105. req.setAmount(excludingTax);
  106. }
  107. log.debug("发票验真, {}, {}", invoiceKind, JSON.toJSONString(req));
  108. VatInvoiceVerifyNewResponse resp = client.VatInvoiceVerifyNew(req);
  109. String result = VatInvoiceVerifyNewResponse.toJsonString(resp);
  110. Map rsp = (Map) JSON.parse(result);
  111. // 因全电票取值, 取值价税合计, 单独校验下金额
  112. Map invoice = (Map) rsp.get("Invoice");
  113. if (StringUtils.isBlank(tips)) {
  114. tips = "发票有疑问";
  115. }
  116. log.debug("请求响应, {}", result);
  117. McException.assertAccessException(!UtilNumber.equalBigDecimal(UtilMap.getString(invoice, "AmountWithTax"), amount), tips + ", 价税合计金额不匹配!");
  118. // ppExt: 增值税卷票: 票面无税率, 税额. 但接口验证返回或本质上发票是有税率, 税额. 因此取消后置判断
  119. McException.assertAccessException(!invoiceKind.contains("卷票") && !UtilNumber.equalBigDecimal(UtilMap.getString(invoice, "AmountWithoutTax"), excludingTax), tips + ", 不含税金额不匹配!");
  120. return rsp;
  121. }
  122. /**
  123. * 名片识别
  124. *
  125. * @apiNote https://console.cloud.tencent.com/api/explorer?Product=ocr&Version=2018-11-19&Action=BusinessCardOCR
  126. */
  127. @Override
  128. public Map doBusinessCardOCR(String image) throws TencentCloudSDKException {
  129. Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
  130. ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
  131. OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
  132. BusinessCardOCRRequest req = new BusinessCardOCRRequest();
  133. if (image.startsWith("http")) {
  134. req.setImageUrl(image);
  135. } else {
  136. req.setImageBase64(image);
  137. }
  138. req.setConfig(JSON.toJSONString(UtilMap.map("RetImageType", "PROPROCESS")));
  139. //log.debug("请求参数, {}", JSON.toJSONString(req));
  140. BusinessCardOCRResponse resp = client.BusinessCardOCR(req);
  141. String result = BusinessCardOCRResponse.toJsonString(resp);
  142. log.debug("请求响应, {}", result);
  143. return (Map) JSON.parse(result);
  144. }
  145. }