package foundation.ai;
|
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.util.List;
|
import java.util.Objects;
|
|
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.Logger;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
|
import foundation.ai.dao.InvoiceVerificationDao;
|
import foundation.ai.logic.OCRResultKingDee;
|
import foundation.dao.Filter;
|
import foundation.dao.Settings;
|
import foundation.data.entity.EntitySet;
|
import foundation.data.object.DataObject;
|
import foundation.util.ContentBuilder;
|
import foundation.util.MD5Utils;
|
import foundation.util.Util;
|
import okhttp3.MediaType;
|
import okhttp3.OkHttpClient;
|
import okhttp3.Request;
|
import okhttp3.RequestBody;
|
import okhttp3.Response;
|
import okhttp3.ResponseBody;
|
import sun.misc.BASE64Encoder;
|
|
public class KingdeeAIProvider extends AIProvider {
|
|
private static Logger logger;
|
|
private static String HOST = "https://api.piaozone.com";
|
private static String CLIENT_ID = "Pa0umVUNzg6EiWSEpGht";
|
private static String CLIENT_SECRET = "a3cbabd08e684413a30aae1803c773d5";
|
private static String TOKEN_PATH = "/base/oauth/token";
|
protected static String AES_KEY = "goopyi5VTKD5WIgs";
|
|
public static int TimeOut_Second_Write = 10;
|
public static int TimeOut_Second_Read = 10;
|
public static boolean Debug = true;
|
private static OkHttpClient httpClient = null;
|
|
static {
|
logger = LogManager.getLogger(KingdeeAIProvider.class);
|
}
|
|
@Override
|
protected String getName() {
|
return "金蝶AI";
|
}
|
|
@Override
|
public OCRResult executeAction(Operator operator, File file) throws Exception {
|
boolean isReal = false, isBill = false;
|
|
// 1. 得到图片的Base64
|
String base64 = imageToBase64(file);
|
if (base64 == null) {
|
logger.error("无法对图片{}进行Base64编码,无法进行AI识别", file);
|
return null;
|
}
|
|
// 2. 获取access_token
|
Response tokenResponse = getAccessToken();
|
if (!tokenResponse.isSuccessful()) {
|
return new OCRResult(operator, "error");
|
}
|
ResponseBody body = tokenResponse.body();
|
String bodyStr = body.string();
|
JSONObject tokenJson = JSONObject.parseObject(bodyStr);
|
body.close();
|
|
// 3. 创建请求
|
OperateUrl operation = OperateUrl.parse(operator);
|
Request request = new Request.Builder().url(HOST + operation.requestUrl + tokenJson.getString("access_token"))
|
.post(RequestBody.create(MediaType.parse("text/plain"), base64)).build();
|
|
// 4. 发送请求
|
String value = "";
|
try {
|
value = send(operation, request);
|
} catch (Exception e) {
|
e.printStackTrace();
|
value = "fail";
|
}
|
|
// 5.分析校验结果
|
OCRResultKingDee resultKingDee = OCRResultKingDee.parseBatch(value);
|
List<InvoiceVerificationDao> invoiceVerificationList = resultKingDee.getInvoiceVerificationList();
|
|
if(invoiceVerificationList.size()> 0 || !resultKingDee.isSuccess()) {
|
isReal = false; isBill = false;
|
}
|
|
// 5.1 发票唯一性校验
|
boolean checkDistinct = Settings.getBoolean("InvoiceDistinctCheck", false);
|
|
if (checkDistinct) {
|
for (InvoiceVerificationDao invoice : invoiceVerificationList) {
|
boolean distincCheck = distinctCheck(invoice.getCode(), invoice.getNumber());
|
invoice.setDistinct(distincCheck);
|
}
|
}
|
|
// 6. 返回结果
|
value = Util.ocrJson(value);
|
OCRResult result = new OCRResult(operator, value);
|
result.setErrcode(resultKingDee.getErrcode());
|
result.setDescription(resultKingDee.getDescription());
|
result.setTraceId(resultKingDee.getTraceId());
|
result.setIs_real(isReal);
|
result.setIs_bill(isBill);
|
result.setJsonArray(resultKingDee.getData());
|
result.setInvoiceList(invoiceVerificationList);
|
|
return result;
|
}
|
|
|
@Override
|
public OCRResult executeAction(Operator operator, Object paramObject) throws Exception {
|
boolean isReal = false, isBill = false;
|
|
// 1. 获取发票信息
|
JSONObject vatInvoiceVerify = (JSONObject) paramObject;
|
if (vatInvoiceVerify == null || Util.isEmpty(vatInvoiceVerify)) {
|
logger.error("未获取到相关发票信息,无法查询发票");
|
return null;
|
}
|
|
// 2.获取access_token
|
Response tokenResponse = getAccessToken();
|
if (!tokenResponse.isSuccessful()) {
|
return new OCRResult(operator, "error");
|
}
|
ResponseBody body = tokenResponse.body();
|
String bodyStr = body.string();
|
JSONObject tokenJson = JSONObject.parseObject(bodyStr);
|
body.close();
|
|
// 3. 创建请求
|
String value = "";
|
OperateUrl operation = OperateUrl.parse(operator);
|
JSONObject jsonBody = new JSONObject();
|
jsonBody.put("invoiceCode", vatInvoiceVerify.getString("invoiceCode"));
|
jsonBody.put("invoiceNo", vatInvoiceVerify.getString("invoiceNo"));
|
jsonBody.put("invoiceDate", vatInvoiceVerify.getString("invoiceDate"));
|
jsonBody.put("invoiceMoney", vatInvoiceVerify.getString("invoiceMoney"));
|
jsonBody.put("totalAmount", vatInvoiceVerify.getString("totalAmount"));
|
jsonBody.put("checkCode", vatInvoiceVerify.getString("checkCode"));
|
jsonBody.put("isCreateUrl", vatInvoiceVerify.getString("isCreateUrl"));
|
Request request = new Request.Builder().url(HOST + operation.requestUrl + tokenJson.getString("access_token"))
|
.post(RequestBody.create(MediaType.parse("application/json"), jsonBody.toJSONString())).build();
|
|
// 4. 发送请求
|
try {
|
value = send(operation, request);
|
} catch (Exception e) {
|
e.printStackTrace();
|
value = e.getMessage();
|
}
|
|
// 5. 分析查询结果
|
OCRResultKingDee resultKingDee = OCRResultKingDee.parseOne(value);
|
List<InvoiceVerificationDao> invoiceVerificationList = resultKingDee.getInvoiceVerificationList();
|
|
// 5.1 发票唯一性校验
|
boolean checkDistinct = Settings.getBoolean("InvoiceDistinctCheck", false);
|
|
|
if (checkDistinct) {
|
for (InvoiceVerificationDao invoice : invoiceVerificationList) {
|
boolean distincCheck = distinctCheck(invoice.getCode(), invoice.getNumber());
|
invoice.setDistinct(distincCheck);
|
}
|
}
|
|
if (Util.isEmpty(invoiceVerificationList) || !resultKingDee.isSuccess()) {
|
isReal = false;
|
isBill = false;
|
}
|
|
|
// 6. 返回结果
|
value = Util.ocrJson(value);
|
OCRResult result = new OCRResult(operator, value);
|
result.setErrcode(resultKingDee.getErrcode());
|
result.setDescription(resultKingDee.getDescription());
|
result.setTraceId(resultKingDee.getTraceId());
|
result.setIs_real(isReal);
|
result.setIs_bill(isBill);
|
result.setJsonArray(resultKingDee.getData());
|
result.setInvoiceList(invoiceVerificationList);
|
|
return result;
|
|
}
|
|
private String send(OperateUrl operation, Request request) throws IOException {
|
httpClient = new OkHttpClient();
|
String json = null;
|
|
Response response = httpClient.newCall(request).execute();
|
if (response.isSuccessful()) {
|
try {
|
json = response.body().string();
|
} catch (Exception e) {
|
e.printStackTrace();
|
} finally {
|
response.close();
|
}
|
}
|
|
return json;
|
}
|
|
private static Response getAccessToken() throws Exception {
|
httpClient = new OkHttpClient();
|
long currentTimeStamp = System.currentTimeMillis();
|
String sign = MD5Utils.MD5Encode(CLIENT_ID + CLIENT_SECRET + currentTimeStamp, "UTF-8");
|
|
JSONObject body = new JSONObject();
|
// 1. set parameter
|
body.put("client_id", CLIENT_ID);
|
body.put("client_secret", CLIENT_SECRET);
|
body.put("sign", sign);
|
body.put("timestamp", currentTimeStamp);
|
|
MediaType jsonMediaType = MediaType.get("application/json");
|
String bodyStr = JSON.toJSONString(body);
|
|
Request request = new Request.Builder().url(HOST + TOKEN_PATH).post(RequestBody.create(jsonMediaType, bodyStr))
|
.build();
|
|
// 3. do sendRequest
|
Response response = httpClient.newCall(request).execute();
|
|
return response;
|
}
|
|
private static String imageToBase64(File file) {
|
byte[] data = null;
|
|
InputStream in = null;
|
try {
|
// 1. bytes
|
in = new FileInputStream(file);
|
data = new byte[in.available()];
|
in.read(data);
|
in.close();
|
|
// 2. encode
|
BASE64Encoder encoder = new BASE64Encoder();
|
return encoder.encode(Objects.requireNonNull(data));
|
} catch (IOException e) {
|
e.printStackTrace();
|
} finally {
|
try {
|
in.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
return null;
|
}
|
|
public static boolean distinctCheck(String invoiceCode , String invoiceNumber) throws Exception {
|
DataObject dataObject = DataObject.getInstance("so_implant_invoice_list");
|
Filter filter = new Filter();
|
|
ContentBuilder builder = new ContentBuilder(", ");
|
builder.append(Util.quotedStr("input"));
|
builder.append(Util.quotedStr("cancel"));
|
builder.append(Util.quotedStr("close"));
|
|
filter.add("so_implant_invoice.code", invoiceCode);
|
filter.add("so_implant_invoice.number", invoiceNumber);
|
filter.add("so_implant.state_code", "not in ", "(" + builder.toString() + ")");
|
EntitySet entitySet = dataObject.getBrowseEntitySet(filter);
|
|
if (entitySet.size() > 0 ) {
|
return false;
|
}
|
return true;
|
}
|
}
|