R92 A2 修复发票 OCR provider 与二进制写库

这个提交包含在:
2026-05-05 22:16:13 +08:00
父节点 fced77a567
当前提交 abba3371dd
共修改 7 个文件,包含 113 行新增和 17 行删除
+29 -8
查看文件
@@ -1,20 +1,39 @@
const crypto = require("node:crypto");
function decodeMarker(imageBase64) {
function decodeImageBase64(imageBase64) {
try {
return Buffer.from(imageBase64, "base64").toString("utf8");
return Buffer.from(imageBase64, "base64");
} catch {
return "";
return Buffer.alloc(0);
}
}
function buildInvoiceKey(markerText) {
function isTextLike(value) {
if (!value) {
return false;
}
const sample = value.slice(0, 256);
const controlChars = sample.match(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g) ?? [];
return controlChars.length === 0;
}
function decodeMarker(buffer) {
const text = buffer.toString("utf8");
if (!isTextLike(text)) {
return "";
}
return text.replace(/[\u0000-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim();
}
function buildInvoiceKey(buffer, markerText) {
const duplicateMatch = markerText.match(/MOCK_DUP:([A-Za-z0-9_-]+)/);
if (duplicateMatch?.[1]) {
return `dup:${duplicateMatch[1]}`;
}
const hash = crypto.createHash("sha256").update(markerText || "mock-empty").digest("hex");
const hash = crypto.createHash("sha256").update(buffer.length ? buffer : "mock-empty").digest("hex");
return `hash:${hash.slice(0, 20)}`;
}
@@ -40,12 +59,13 @@ function toAmount(seedHex, fallback) {
}
async function runMockOcr({ ocrType, imageBase64 }) {
const markerText = decodeMarker(imageBase64);
const buffer = decodeImageBase64(imageBase64);
const markerText = decodeMarker(buffer);
if (markerText.includes("MOCK_OCR_FAIL")) {
throw new Error("mock_ocr_failed");
}
const invoiceKey = buildInvoiceKey(markerText);
const invoiceKey = buildInvoiceKey(buffer, markerText);
const hash = crypto.createHash("sha256").update(invoiceKey).digest("hex");
const invoiceCode = `MOCK${hash.slice(0, 8).toUpperCase()}`;
const invoiceNumber = hash.slice(8, 16).toUpperCase();
@@ -62,7 +82,8 @@ async function runMockOcr({ ocrType, imageBase64 }) {
raw: {
provider: "mock",
invoiceKey,
marker: markerText.slice(0, 128),
marker: markerText ? markerText.slice(0, 128) : null,
sourceSha256: crypto.createHash("sha256").update(buffer).digest("hex"),
},
};