;(function (global) { "use strict"; function isFileLike(v) { return (typeof File !== "undefined" && v instanceof File) || (typeof Blob !== "undefined" && v instanceof Blob); } function fileToDataURL(file) { return new Promise(function (resolve, reject) { var reader = new FileReader(); reader.onload = function () { resolve(reader.result); }; reader.onerror = reject; reader.readAsDataURL(file); }); } async function normalizeImageInput(input) { if (typeof input === "string") { return { image_base64: input, filename: "upload_base64", content_type: null }; } if (isFileLike(input)) { var dataURL = await fileToDataURL(input); return { image_base64: dataURL, filename: input.name || "upload_file", content_type: input.type || null }; } throw new Error("只支持 base64 字符串、File 或 Blob"); } async function parseJSONResponse(resp) { var text = await resp.text(); var data = null; try { data = text ? JSON.parse(text) : null; } catch (e) { data = text; } if (!resp.ok) { var msg = data && data.detail ? data.detail : text || ("HTTP " + resp.status); throw new Error(msg); } return data; } function normalizeSign(rawSign, fallbackAppId) { if (rawSign === undefined || rawSign === null || rawSign === "") { throw new Error("sign 不能为空,必须由客户后端传入签名字符串或对象"); } var data = rawSign; if (typeof rawSign === "string") { try { data = JSON.parse(rawSign); } catch (e) { throw new Error('sign 字符串必须是 JSON 字符串,例如 {"timestamp":"1718123456","signature":"xxxx"}'); } } if (!data || typeof data !== "object") { throw new Error("sign 必须是对象,或可解析为对象的 JSON 字符串"); } var appId = data.app_id || data.appId || fallbackAppId; var timestamp = data.timestamp; var signature = data.signature; if (!appId || !timestamp || !signature) { throw new Error("sign 必须包含 timestamp 和 signature;app_id 可省略并回退到 config.appId"); } return { app_id: String(appId), timestamp: String(timestamp), signature: String(signature) }; } function PassportOCRClient(config) { this.apiBase = (config.apiBase || "").replace(/\/+$/, ""); this.appId = config.appId || ""; this.sign = config.sign; if (!this.apiBase) { throw new Error("apiBase 不能为空"); } if (!this.appId) { throw new Error("appId 不能为空"); } } PassportOCRClient.prototype.setSign = function (sign) { this.sign = sign; return this; }; PassportOCRClient.prototype.getSignature = function (signOverride) { var rawSign = signOverride !== undefined ? signOverride : this.sign; return normalizeSign(rawSign, this.appId); }; PassportOCRClient.prototype.callOCR = async function (path, input, options) { options = options || {}; var imageInfo = await normalizeImageInput(input); var payload = { filename: options.filename || imageInfo.filename, content_type: options.content_type || imageInfo.content_type, image_base64: imageInfo.image_base64, text_rec_score_thresh: options.text_rec_score_thresh ?? 0.3, mrz_text_rec_score_thresh: options.mrz_text_rec_score_thresh ?? 0.0, mrz_top_ratio: options.mrz_top_ratio ?? 0.68, return_debug: !!options.return_debug, auto_rotate: options.auto_rotate ?? true }; var signed = this.getSignature(options.sign); var resp = await fetch(this.apiBase + path, { method: "POST", headers: { "Content-Type": "application/json", "X-App-Id": signed.app_id, "X-Timestamp": signed.timestamp, "X-Signature": signed.signature }, body: JSON.stringify(payload) }); return await parseJSONResponse(resp); }; PassportOCRClient.prototype.recognizePassport = function (input, options) { return this.callOCR("/ocr/passport/base64", input, options); }; PassportOCRClient.prototype.recognizeMRZ = function (input, options) { return this.callOCR("/ocr/mrz/base64", input, options); }; PassportOCRClient.prototype.recognizeIdCard = function (input, options) { return this.callOCR("/ocr/idcard/base64", input, options); }; PassportOCRClient.prototype.recognizeVisaNumber = function (input, options) { return this.callOCR("/ocr/visa-number/base64", input, options); }; global.PassportOCRSDK = { create: function (config) { return new PassportOCRClient(config || {}); } }; })(window);