@authme/identity-verification 2.8.3 → 2.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -7,7 +7,7 @@ import 'core-js/modules/es.promise.js';
7
7
  import { getTranslateInstance, EventListenerService, TrackingEvent, generateStatus, StatusDescription, AuthmeError, ErrorCode, Feature, StatusEvent, StatusView, StatusAction, setRequestLoggingFunc, setAccessToken, getCustomerState } from '@authme/core';
8
8
  import { EAuthMeFASServiceStatus, EAuthMeIDCardAntiFraudStage as EAuthMeIDCardAntiFraudStage$1, EAuthMeCardClass as EAuthMeCardClass$1, AuthmeFunctionModule, MlEngine, EngineModule, EAuthMeEngineReturnCode, AuthmeEngineModuleBase } from '@authme/engine';
9
9
  import { IdRecognitionCardType, CountryCode, EAuthMeCardClass, EAuthMeIDCardAntiFraudStatus, EAuthMeIDCardAntiFraudStage, thicknessDefaultConfig, mapCardtypeToAuthmeClass, getRecognitionColumnOrder, cardTypeTitle, cardTypeConfirmTitle, cardTypeHeader, EAuthMeCardOCRStatus, EAuthMeMRZServiceStatus, saveExtraDoc, initScanDocumentResourceBase64, MRZService, option, themeUI, initScan, initScanDocument, ResourceImageType, uploadFrameBase64, finishScanDocument, CardOCR, IdCardAntiFraudService, twoWayAuthmeCardClassMap, RecognitionFileType, recognizeBase64, getCardSubTypes, getCardTypes, confirmScan } from '@authme/id-recognition';
10
- import { getCssVariable, RGBToLottieColor, colorToRGB, Storage, useState, uiThemeText, uiThemeHint, clearCanvas, getImageData, isMobile, hidePopup, showPopup, waitTime, TIME_UNIT, AuthmeError as AuthmeError$1, ErrorCode as ErrorCode$1, uiThemeButton, uiThemeSmallButton, requestCamera, showElement, asyncOnLineShowErrorMessage, getCanvasSize, startSpinner, stopSpinner, themeConfigDefault, fontWeight, hideElement, dataURItoBlob, showErrorMessage, checkOnlineStatus, UintArrayToBlob, isIphone14proOrProMax, cropByRatio, switchCamera, asyncShowPopup, retryPromiseWithCondition, asyncShowErrorMessage, hideErrorMessage, uploadModal, backgroundRequest, debugTools, showErrorMessageEventName, RUN_FUNCTION_NAME, STORAGE_KEY, splitResult, combineResult, startLoadingSDK, stopLoadingSDK } from '@authme/util';
10
+ import { getCssVariable, RGBToLottieColor, colorToRGB, Storage, useState, uiThemeText, uiThemeHint, clearCanvas, getImageData, isMobile, hidePopup, showPopup, waitTime, TIME_UNIT, AuthmeError as AuthmeError$1, ErrorCode as ErrorCode$1, uiThemeButton, uiThemeSmallButton, requestCamera, showElement, asyncOnLineShowErrorMessage, getCanvasSize, startSpinner, stopSpinner, themeConfigDefault, fontWeight, hideElement, dataURItoBlob, showErrorMessage, checkOnlineStatus, dropMenu, UintArrayToBlob, isIphone14proOrProMax, cropByRatio, switchCamera, asyncShowPopup, retryPromiseWithCondition, asyncShowErrorMessage, hideErrorMessage, uploadModal, backgroundRequest, debugTools, showErrorMessageEventName, RUN_FUNCTION_NAME, STORAGE_KEY, splitResult, DEVICE_TYPE, combineResult, startLoadingSDK, stopLoadingSDK } from '@authme/util';
11
11
  import { mergeMap, animationFrames, filter, tap, map, from, catchError, EMPTY, of, merge, fromEvent, concatAll, takeUntil, Subject, defer, switchMap, throttleTime, raceWith, concatMap, throwError, finalize, timer, Observable, take, interval, mapTo, firstValueFrom, shareReplay, switchMapTo, takeWhile as takeWhile$1, race } from 'rxjs';
12
12
  import 'core-js/modules/es.regexp.to-string.js';
13
13
  import { FasRecognitionResult, EAuthMeFASServiceStage, FasService, LivenessAPI, EAuthMeMouthStatus, LivenessResultStatus } from '@authme/liveness';
@@ -28,6 +28,8 @@ import 'core-js/modules/es.typed-array.fill.js';
28
28
  import 'core-js/modules/es.typed-array.set.js';
29
29
  import 'core-js/modules/es.typed-array.sort.js';
30
30
  import 'core-js/modules/es.typed-array.to-locale-string.js';
31
+ import 'core-js/modules/es.string.pad-start.js';
32
+ import 'core-js/modules/es.regexp.constructor.js';
31
33
  import 'core-js/modules/es.typed-array.uint8-array.js';
32
34
 
33
35
  /******************************************************************************
@@ -101,7 +103,8 @@ const defaultLivenessConfig = {
101
103
  subtitle: null,
102
104
  uploadFullFrame: false,
103
105
  passive: false,
104
- compareCustomerClientId: null
106
+ compareCustomerClientId: null,
107
+ deviceType: null
105
108
  };
106
109
  const defaultIdRecognitionConfig = {
107
110
  icon: DEFAULT_ICON_URI,
@@ -125,7 +128,8 @@ const defaultIdRecognitionConfig = {
125
128
  captureTimeout: -1,
126
129
  resultImageFormat: 'jpg',
127
130
  confirmPageEnabled: true,
128
- isFraudIntroEnable: false
131
+ isFraudIntroEnable: false,
132
+ deviceType: null
129
133
  };
130
134
 
131
135
  function setCorrectViewHeight() {
@@ -27896,7 +27900,7 @@ const setStatusTextTop = params => {
27896
27900
  const _maskTop = maskTop !== null && maskTop !== void 0 ? maskTop : window.innerHeight / 2 - maskHeight / 2;
27897
27901
  const _maskBotton = _maskTop + maskHeight;
27898
27902
  titleTextPanel.style.top = `${_maskTop - MASK_STYLE.MASK_TITLE_MARGIN - MASK_STYLE.TITLE_TEXT_FONT_SIZE}px`;
27899
- statusTextPanel.style.top = `${_maskBotton + MASK_STYLE.MASK_TITLE_MARGIN}px`;
27903
+ statusTextPanel.style.top = `${_maskBotton + MASK_STYLE.MASK_TITLE_MARGIN + 60}px`;
27900
27904
  };
27901
27905
 
27902
27906
  const limitFPS = fps => {
@@ -27915,7 +27919,9 @@ const limitFPS = fps => {
27915
27919
  };
27916
27920
  const sendFrame = (canvasSizeInfo, canvas, video, frameCallback, fps, bas64Format, imageType, cardType, flags, type) => source$ => {
27917
27921
  let received = true;
27918
- const ctx = canvas.getContext('2d');
27922
+ const ctx = canvas.getContext('2d', {
27923
+ willReadFrequently: true
27924
+ });
27919
27925
  return source$.pipe(mergeMap(() => animationFrames().pipe(limitFPS(fps), filter(() => received && !(flags === null || flags === void 0 ? void 0 : flags.animating)), tap(() => received = false), tap(() => clearCanvas(canvas)), map(() => getImageData(canvas, ctx, video, canvasSizeInfo, bas64Format, imageType)), mergeMap(imageData => from(frameCallback(imageData.data, imageData.base64, cardType, type)).pipe(catchError(e => {
27920
27926
  // send to fast, ignore
27921
27927
  if (e instanceof AuthmeError && e.code === ErrorCode.RECOGNITION_NOT_AVAILABLE) {
@@ -28224,7 +28230,6 @@ function startLiveness(config) {
28224
28230
  // }
28225
28231
  function makeSDKFlowTimeout(expiredIn) {
28226
28232
  return timer(expiredIn * TIME_UNIT.SECOND).pipe(switchMap(() => new Observable(observer => {
28227
- console.log('makeSDKFlowTimeout observer');
28228
28233
  config.onDestroy();
28229
28234
  popupView({
28230
28235
  title: translateService.translate('sdk.general.error.timeout.title'),
@@ -28759,7 +28764,6 @@ const renderCameraSwitch = config => {
28759
28764
  };
28760
28765
  const renderOCRUI = config => {
28761
28766
  const uiThemeConfig = Storage.getItem('themeConfig');
28762
- console.log('uiThemeConfig', uiThemeConfig);
28763
28767
  const translateService = getTranslateInstance();
28764
28768
  const createTextPanel = () => {
28765
28769
  const ele = document.createElement('div');
@@ -29914,7 +29918,9 @@ const imageDataToBase64 = (data, width, height, mimeType = 'image/png') => {
29914
29918
  const canvas = document.createElement('canvas');
29915
29919
  canvas.width = width;
29916
29920
  canvas.height = height;
29917
- const ctx = canvas.getContext('2d');
29921
+ const ctx = canvas.getContext('2d', {
29922
+ willReadFrequently: true
29923
+ });
29918
29924
  // 2. 建立 ImageData,填充像素數據
29919
29925
  const imgData = ctx.createImageData(width, height);
29920
29926
  imgData.data.set(new Uint8ClampedArray(data)); // 確保格式正確
@@ -29926,7 +29932,9 @@ const videoToBase64 = (video, sizeInfo) => __awaiter(void 0, void 0, void 0, fun
29926
29932
  const canvas = document.createElement('canvas');
29927
29933
  canvas.width = sizeInfo.canvasWidth;
29928
29934
  canvas.height = sizeInfo.canvasHeight;
29929
- const ctx = canvas.getContext('2d');
29935
+ const ctx = canvas.getContext('2d', {
29936
+ willReadFrequently: true
29937
+ });
29930
29938
  if (!ctx) {
29931
29939
  throw new Error('Failed to get 2d context from canvas');
29932
29940
  }
@@ -30342,7 +30350,6 @@ const toast = arg => {
30342
30350
  };
30343
30351
 
30344
30352
  const confirmPopup = arg => {
30345
- console.log('confirmPopup', arg);
30346
30353
  const authmeContainer = document.querySelector('.authme-container');
30347
30354
  if (!authmeContainer) {
30348
30355
  console.error('confirmPopup: authmeContainer not found');
@@ -30534,6 +30541,343 @@ const fraudScanIntroPage = arg => {
30534
30541
  authmeContainer.appendChild(domModal);
30535
30542
  };
30536
30543
 
30544
+ const ocrResultModal = arg => {
30545
+ let modifiedDetails = {};
30546
+ const authmeContainer = document.querySelector('.authme-container');
30547
+ if (!authmeContainer) {
30548
+ console.error('modal: authmeContainer not found');
30549
+ return;
30550
+ }
30551
+ const translateService = getTranslateInstance();
30552
+ const uiThemeConfig = Storage.getItem('themeConfig');
30553
+ function removeOcrResultModal() {
30554
+ var _a;
30555
+ (_a = document.querySelector('.video-container__ocrResultModal')) === null || _a === void 0 ? void 0 : _a.remove();
30556
+ }
30557
+ function formatTime(seconds) {
30558
+ const m = Math.floor(seconds % 3600 / 60);
30559
+ const s = seconds % 60;
30560
+ return [m, s].map(unit => String(unit).padStart(2, '0')).join(':');
30561
+ }
30562
+ function groupInput({
30563
+ name,
30564
+ label,
30565
+ value
30566
+ }) {
30567
+ const domGroupItem = document.createElement('div');
30568
+ domGroupItem.classList.add('video-container__ocrResultModal-group-item');
30569
+ domGroupItem.id = name;
30570
+ const domLabel = document.createElement('label');
30571
+ const domInput = document.createElement('input');
30572
+ const domError = document.createElement('div');
30573
+ domLabel.classList.add('video-container__ocrResultModal-label');
30574
+ domInput.classList.add('video-container__ocrResultModal-input');
30575
+ domError.classList.add('video-container__ocrResultModal-error');
30576
+ domError.classList.add('hidden');
30577
+ domLabel.innerText = `${label}`;
30578
+ domInput.type = 'text';
30579
+ domInput.value = value;
30580
+ domError.innerText = `${label}格式不符`;
30581
+ domInput.addEventListener('input', () => {
30582
+ validateFields() ? btnConfirmStatus(false) : btnConfirmStatus(true);
30583
+ // btnConfirmStatus(Object.values(validateMap).some((i: any) => i.validate === false));
30584
+ });
30585
+
30586
+ domGroupItem.appendChild(domLabel);
30587
+ domGroupItem.appendChild(domInput);
30588
+ domGroupItem.appendChild(domError);
30589
+ return domGroupItem;
30590
+ }
30591
+ function groupDropMenu({
30592
+ name,
30593
+ label,
30594
+ value,
30595
+ selections
30596
+ }) {
30597
+ const domGroupItem = document.createElement('div');
30598
+ domGroupItem.classList.add('video-container__ocrResultModal-group-item');
30599
+ domGroupItem.id = name;
30600
+ const domLabel = document.createElement('label');
30601
+ domLabel.classList.add('video-container__ocrResultModal-label');
30602
+ domLabel.innerText = `${label}`;
30603
+ const domDropMenu = document.createElement('div');
30604
+ domDropMenu.classList.add('drop_menu_container');
30605
+ const domDropMenuTitle = document.createElement('div');
30606
+ domDropMenuTitle.classList.add('drop_menu_title');
30607
+ domDropMenuTitle.setAttribute('data-value', value);
30608
+ domDropMenuTitle.innerHTML = `<span class="ellipsis">${selections.find(i => i.value === value) ? selections.find(i => i.value === value).name : '請選擇'}</span>
30609
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 7L10.07 14L17 7" stroke="#343434" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
30610
+ const domError = document.createElement('div');
30611
+ domError.classList.add('video-container__ocrResultModal-error');
30612
+ domError.classList.add('hidden');
30613
+ domError.innerText = `${label}格式不符`;
30614
+ let domDropMenuCancel = null;
30615
+ if (window.innerWidth < 1440) {
30616
+ // mobile
30617
+ domDropMenuCancel = document.createElement('div');
30618
+ domDropMenuCancel.classList.add('drop_menu_cancel');
30619
+ domDropMenuCancel.innerText = arg.cancelText;
30620
+ }
30621
+ const domDropMenuulSection = document.createElement('section');
30622
+ domDropMenuulSection.classList.add('drop_menu_ul_section');
30623
+ const domDropMenuUlContainer = document.createElement('div');
30624
+ domDropMenuUlContainer.classList.add('drop_menu_ul_container');
30625
+ const domDropMenuUl = document.createElement('ul');
30626
+ domDropMenuulSection.classList.add('hide');
30627
+ selections.forEach(selection => {
30628
+ const domDropMenuLi = document.createElement('li');
30629
+ domDropMenuLi.classList.add('drop_menu_item');
30630
+ if (selection.value === value) {
30631
+ domDropMenuLi.classList.add('active');
30632
+ }
30633
+ domDropMenuLi.setAttribute('data-value', selection.value);
30634
+ domDropMenuLi.innerHTML = `<span>${selection.name}</span>`;
30635
+ domDropMenuUl.appendChild(domDropMenuLi);
30636
+ });
30637
+ domDropMenu.appendChild(domDropMenuTitle);
30638
+ domDropMenuUlContainer.appendChild(domDropMenuUl);
30639
+ if (domDropMenuCancel) {
30640
+ domDropMenuUlContainer.appendChild(domDropMenuCancel);
30641
+ }
30642
+ domDropMenuulSection.appendChild(domDropMenuUlContainer);
30643
+ domDropMenu.appendChild(domDropMenuulSection);
30644
+ dropMenu(domDropMenu, dom => {
30645
+ domDropMenuTitle.setAttribute('data-value', dom.getAttribute('data-value'));
30646
+ validateFields() ? btnConfirmStatus(false) : btnConfirmStatus(true);
30647
+ });
30648
+ domGroupItem.appendChild(domLabel);
30649
+ domGroupItem.appendChild(domDropMenu);
30650
+ domGroupItem.appendChild(domError);
30651
+ return domGroupItem;
30652
+ }
30653
+ function formatDate(dateString, format) {
30654
+ // 解析日期字串為 Date 物件
30655
+ const date = new Date(dateString);
30656
+ const year = date.getFullYear(); // 取得年份
30657
+ const month = (date.getMonth() + 1).toString().padStart(2, '0'); // 取得月份並補齊兩位
30658
+ const day = date.getDate().toString().padStart(2, '0'); // 取得日期並補齊兩位
30659
+ // 根據傳入的 format 來替換字串
30660
+ return format.replace('YYYY', year.toString()) // 替換 "YYYY" 為年份
30661
+ .replace('yyyy', year.toString()) // 替換 "yyyy" 為年份
30662
+ .replace('MM', month) // 替換 "MM" 為月份
30663
+ .replace('dd', day) // 替換 "dd" 為日期
30664
+ .replace('yyyy', year.toString()); // 處理 "yyyy" 格式
30665
+ }
30666
+
30667
+ function isValidDateFormat(dateStr) {
30668
+ const regex = /^\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])$/;
30669
+ return regex.test(dateStr);
30670
+ }
30671
+ function checkModifiedData() {
30672
+ const items = domModal.querySelectorAll('.video-container__ocrResultModal-group-item');
30673
+ items.forEach(item => {
30674
+ const input = item.querySelector('input');
30675
+ if (input) {
30676
+ const key = item.id;
30677
+ const value = input.value;
30678
+ let valueOrigin = arg.items.find(i => i.name === key).value;
30679
+ const dateFormat = arg.items.find(i => i.name === key).dateFormat;
30680
+ if (dateFormat) {
30681
+ valueOrigin = formatDate(valueOrigin, dateFormat);
30682
+ }
30683
+ modifiedDetails[key] = {
30684
+ isModified: value !== valueOrigin ? true : false,
30685
+ value
30686
+ };
30687
+ } else if (item.querySelector('.drop_menu_title')) {
30688
+ // drop menu
30689
+ const key = item.id;
30690
+ const value = item.querySelector('.drop_menu_title').getAttribute('data-value');
30691
+ const valueOrigin = arg.items.find(i => i.name === key).value;
30692
+ modifiedDetails[key] = {
30693
+ isModified: value !== valueOrigin ? true : false,
30694
+ value
30695
+ };
30696
+ }
30697
+ });
30698
+ }
30699
+ function btnConfirmStatus(flag) {
30700
+ domConfirm.disabled = flag;
30701
+ uiThemeButton(domConfirm, uiThemeConfig.majorButton, flag);
30702
+ }
30703
+ function validateFields() {
30704
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
30705
+ for (const key in validateMap) {
30706
+ const item = validateMap[key];
30707
+ const domItem = domModal.querySelector(`#${key}`);
30708
+ if (domItem) {
30709
+ const input = domItem.querySelector('input');
30710
+ if (input && item.regex) {
30711
+ if (item.regex.test(input.value)) {
30712
+ item.validate = true;
30713
+ (_a = domItem.querySelector('.video-container__ocrResultModal-input')) === null || _a === void 0 ? void 0 : _a.classList.remove('error');
30714
+ (_b = domItem.querySelector('.video-container__ocrResultModal-error')) === null || _b === void 0 ? void 0 : _b.classList.add('hidden');
30715
+ } else {
30716
+ item.validate = false;
30717
+ (_c = domItem.querySelector('.video-container__ocrResultModal-input')) === null || _c === void 0 ? void 0 : _c.classList.add('error');
30718
+ (_d = domItem.querySelector('.video-container__ocrResultModal-error')) === null || _d === void 0 ? void 0 : _d.classList.remove('hidden');
30719
+ }
30720
+ } else if (item.regex) {
30721
+ // drop menu
30722
+ const domDropMenu = domItem.querySelector('.drop_menu_title');
30723
+ if (domDropMenu) {
30724
+ if (domDropMenu.getAttribute('data-value') !== '') {
30725
+ item.validate = true;
30726
+ domDropMenu.classList.remove('error');
30727
+ (_e = domItem.querySelector('.video-container__ocrResultModal-error')) === null || _e === void 0 ? void 0 : _e.classList.add('hidden');
30728
+ } else {
30729
+ item.validate = false;
30730
+ domDropMenu.classList.add('error');
30731
+ (_f = domItem.querySelector('.video-container__ocrResultModal-error')) === null || _f === void 0 ? void 0 : _f.classList.remove('hidden');
30732
+ }
30733
+ }
30734
+ } else if (input && item.dateFormat) {
30735
+ if (isValidDateFormat(input.value)) {
30736
+ // if (item.dateFormat.test(input.value)) {
30737
+ item.validate = true;
30738
+ (_g = domItem.querySelector('.video-container__ocrResultModal-input')) === null || _g === void 0 ? void 0 : _g.classList.remove('error');
30739
+ (_h = domItem.querySelector('.video-container__ocrResultModal-error')) === null || _h === void 0 ? void 0 : _h.classList.add('hidden');
30740
+ } else {
30741
+ item.validate = false;
30742
+ (_j = domItem.querySelector('.video-container__ocrResultModal-input')) === null || _j === void 0 ? void 0 : _j.classList.add('error');
30743
+ (_k = domItem.querySelector('.video-container__ocrResultModal-error')) === null || _k === void 0 ? void 0 : _k.classList.remove('hidden');
30744
+ }
30745
+ }
30746
+ }
30747
+ }
30748
+ const isPass = Object.values(validateMap).every(item => item.validate === true);
30749
+ return isPass;
30750
+ }
30751
+ modifiedDetails = arg.items.reduce((acc, item) => {
30752
+ acc[item.name] = {
30753
+ isModified: false,
30754
+ value: item.value
30755
+ };
30756
+ return acc;
30757
+ }, {});
30758
+ let timer = Math.floor((arg.countDownTime - new Date().getTime()) / 1000);
30759
+ const validateMap = {};
30760
+ const domModal = document.createElement('div');
30761
+ const domHeaderContainer = document.createElement('div');
30762
+ const domBodyContainer = document.createElement('div');
30763
+ const domBody = document.createElement('div');
30764
+ const domTitle = document.createElement('div');
30765
+ const domSubtitle = document.createElement('div');
30766
+ const domFooterContainer = document.createElement('div');
30767
+ const domCountDownContainer = document.createElement('div');
30768
+ const domCountDown = document.createElement('div');
30769
+ const domHint = document.createElement('div');
30770
+ const domClose = document.createElement('div');
30771
+ const domConfirm = document.createElement('button');
30772
+ domModal.classList.add('video-container__ocrResultModal');
30773
+ domHeaderContainer.classList.add('video-container__ocrResultModal-header-container');
30774
+ domBodyContainer.classList.add('video-container__ocrResultModal-body-container');
30775
+ domBody.classList.add('video-container__ocrResultModal-body');
30776
+ domTitle.classList.add('video-container__ocrResultModal-title');
30777
+ domSubtitle.classList.add('video-container__ocrResultModal-subtitle');
30778
+ domFooterContainer.classList.add('video-container__ocrResultModal-footer-container');
30779
+ domCountDownContainer.classList.add('video-container__ocrResultModal-countdown-container');
30780
+ domCountDown.classList.add('video-container__ocrResultModal-countdown');
30781
+ domHint.classList.add('video-container__ocrResultModal-hint');
30782
+ domClose.classList.add('video-container__ocrResultModal-close');
30783
+ domConfirm.classList.add('video-container__ocrResultModal-confirm');
30784
+ btnConfirmStatus(true);
30785
+ // uiThemeButton(domConfirm, uiThemeConfig.majorButton);
30786
+ uiThemeText(domTitle, uiThemeConfig.resultTitle);
30787
+ uiThemeText(domSubtitle, uiThemeConfig.resultBody);
30788
+ domTitle.innerText = arg.title;
30789
+ domSubtitle.innerText = arg.subtitle;
30790
+ domHint.innerHTML = arg.hintText;
30791
+ domCountDownContainer.innerHTML = `${arg.countDown1Text} <span class="video-container__ocrResultModal-countdown" style="color: ${uiThemeConfig.resultTime};font-size:${uiThemeConfig.fontSize}px;font-weight:${fontWeight[uiThemeConfig.textWeight]}"> ${formatTime(timer)} </span> ${arg.countDown2Text}`;
30792
+ domConfirm.innerText = arg.confirmText;
30793
+ domClose.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19.1943 6.41714C19.6393 5.97216 19.6393 5.2507 19.1943 4.80571C18.7493 4.36073 18.0278 4.36073 17.5829 4.80571L12 10.3886L6.41714 4.80572C5.97216 4.36073 5.2507 4.36073 4.80571 4.80571C4.36073 5.2507 4.36073 5.97216 4.80571 6.41714L10.3886 12L4.80571 17.5829C4.36073 18.0278 4.36073 18.7493 4.80571 19.1943C5.2507 19.6393 5.97216 19.6393 6.41714 19.1943L12 13.6114L17.5829 19.1943C18.0278 19.6393 18.7493 19.6393 19.1943 19.1943C19.6393 18.7493 19.6393 18.0278 19.1943 17.5829L13.6114 12L19.1943 6.41714Z" fill="${uiThemeConfig.nonEkycCloseButton.contentColor}" fill-opacity="${uiThemeConfig.nonEkycCloseButton.contentOpacity}" /></svg>`;
30794
+ const countdownInterval = setInterval(() => {
30795
+ timer -= 1;
30796
+ const countdownEl = domModal.querySelector('.video-container__ocrResultModal-countdown');
30797
+ if (countdownEl) {
30798
+ countdownEl.innerHTML = formatTime(timer);
30799
+ }
30800
+ if (timer <= 0) {
30801
+ clearInterval(countdownInterval);
30802
+ }
30803
+ }, 1000);
30804
+ // form start
30805
+ arg.items.sort((a, b) => {
30806
+ var _a, _b;
30807
+ return ((_a = a.order) !== null && _a !== void 0 ? _a : Infinity) - ((_b = b.order) !== null && _b !== void 0 ? _b : Infinity);
30808
+ });
30809
+ arg.items.forEach(item => {
30810
+ // init validateMap
30811
+ if (item.regex) {
30812
+ validateMap[item.name] = {
30813
+ validate: false,
30814
+ regex: new RegExp(item.regex.slice(1, -1))
30815
+ };
30816
+ } else if (item.selections) {
30817
+ validateMap[item.name] = {
30818
+ validate: false,
30819
+ regex: /\S+/
30820
+ };
30821
+ } else if (item.dateFormat) {
30822
+ validateMap[item.name] = {
30823
+ validate: false,
30824
+ dateFormat: new RegExp(item.dateFormat.slice(1, -1))
30825
+ };
30826
+ }
30827
+ // init UI
30828
+ if (!item.hidden) {
30829
+ if (item.selections) {
30830
+ const domDropMenu = groupDropMenu({
30831
+ name: item.name,
30832
+ label: item.name === 'issueReason' ? translateService.translate('sdk.ocr.verify.result.issueType') : translateService.translate(`sdk.ocr.verify.result.${item.name}`),
30833
+ value: item.value,
30834
+ selections: item.selections
30835
+ });
30836
+ domBody.appendChild(domDropMenu);
30837
+ } else {
30838
+ const domGroupItem = groupInput({
30839
+ name: item.name,
30840
+ label: item.name === 'issueReason' ? translateService.translate('sdk.ocr.verify.result.issueType') : translateService.translate(`sdk.ocr.verify.result.${item.name}`),
30841
+ value: item.dateFormat ? formatDate(item.value, item.dateFormat) : item.value
30842
+ });
30843
+ domBody.appendChild(domGroupItem);
30844
+ }
30845
+ }
30846
+ });
30847
+ // form end
30848
+ domHeaderContainer.appendChild(domTitle);
30849
+ domHeaderContainer.appendChild(domSubtitle);
30850
+ domModal.appendChild(domHeaderContainer);
30851
+ domModal.appendChild(domClose);
30852
+ domModal.appendChild(domBodyContainer);
30853
+ // domBodyContainer.appendChild(domTitle);
30854
+ // domBodyContainer.appendChild(domSubtitle);
30855
+ domBodyContainer.appendChild(domBody);
30856
+ domModal.appendChild(domFooterContainer);
30857
+ domFooterContainer.appendChild(domCountDownContainer);
30858
+ domFooterContainer.appendChild(domHint);
30859
+ domFooterContainer.appendChild(domConfirm);
30860
+ authmeContainer.appendChild(domModal);
30861
+ validateFields() ? btnConfirmStatus(false) : btnConfirmStatus(true);
30862
+ return new Promise(resolve => {
30863
+ domClose.addEventListener('click', () => __awaiter(void 0, void 0, void 0, function* () {
30864
+ if (arg.onClose) {
30865
+ yield arg.onClose();
30866
+ }
30867
+ removeOcrResultModal();
30868
+ resolve('close');
30869
+ }));
30870
+ domConfirm.addEventListener('click', () => __awaiter(void 0, void 0, void 0, function* () {
30871
+ checkModifiedData();
30872
+ if (arg.onConfirm) {
30873
+ yield arg.onConfirm(modifiedDetails);
30874
+ }
30875
+ removeOcrResultModal();
30876
+ resolve(modifiedDetails);
30877
+ }));
30878
+ });
30879
+ };
30880
+
30537
30881
  const initEvenTrackingStatus = ocrConfig => {
30538
30882
  setFeature$1(ocrConfig.needAntiFraud ? Feature.OCRFraud : Feature.OCR);
30539
30883
  };
@@ -30544,6 +30888,7 @@ function startOCR(config) {
30544
30888
  const timeout$ = new Subject();
30545
30889
  // let sdkFlowTimeout: NodeJS.Timeout;
30546
30890
  let sdkFlowTimeout = null;
30891
+ let countDownTime = 0;
30547
30892
  let deviceMetas;
30548
30893
  // anti fraud
30549
30894
  let currentAntiFraudStage;
@@ -30773,7 +31118,6 @@ function startOCR(config) {
30773
31118
  // }
30774
31119
  function makeSDKFlowTimeout(expiredIn) {
30775
31120
  return timer(expiredIn * TIME_UNIT.SECOND).pipe(switchMap(() => new Observable(observer => {
30776
- console.log('makeSDKFlowTimeout observer');
30777
31121
  config.onDestroy();
30778
31122
  popupView({
30779
31123
  title: translateService.translate('sdk.general.error.timeout.title'),
@@ -30927,6 +31271,7 @@ function startOCR(config) {
30927
31271
  buttonDisable$(cardMatchROI);
30928
31272
  }
30929
31273
  if (ocrEngineConfig.expiredIn && !sdkFlowTimeout) {
31274
+ countDownTime = new Date().getTime() + ocrEngineConfig.expiredIn * TIME_UNIT.SECOND;
30930
31275
  sdkFlowTimeout = makeSDKFlowTimeout(ocrEngineConfig.expiredIn);
30931
31276
  }
30932
31277
  })), sendFrame(canvasSizeInfo, uiComponentOCR.image, uiComponentBasic.video, config.onAntiFraudFrame, ocrEngineConfig.fraudMaxFps, false, 'jpg', undefined), map(x => x.result), tap(x => {
@@ -31164,7 +31509,9 @@ function startOCR(config) {
31164
31509
  let ocrSendFrameAnimation = false;
31165
31510
  const handleOcrSendFrame = (canvasSizeInfo, canvas, video, frameCallback, fps, bas64Format, imageType, cardType, type) => source$ => {
31166
31511
  let received = true;
31167
- const ctx = canvas.getContext('2d');
31512
+ const ctx = canvas.getContext('2d', {
31513
+ willReadFrequently: true
31514
+ });
31168
31515
  return source$.pipe(mergeMap(() => animationFrames().pipe(limitFPS(fps), filter(() => received && !ocrSendFrameAnimation), tap(() => received = false), tap(() => clearCanvas(canvas)), map(() => getImageData(canvas, ctx, video, canvasSizeInfo, bas64Format, imageType)), mergeMap(imageData => from(frameCallback(imageData.data, imageData.base64, cardType, type)).pipe(catchError(e => {
31169
31516
  // send to fast, ignore
31170
31517
  if (e instanceof AuthmeError && e.code === ErrorCode.RECOGNITION_NOT_AVAILABLE) {
@@ -31232,6 +31579,7 @@ function startOCR(config) {
31232
31579
  return init(retry).pipe(tap(() => {
31233
31580
  setStatusView(StatusView.Running);
31234
31581
  if (ocrEngineConfig.expiredIn && !sdkFlowTimeout) {
31582
+ countDownTime = new Date().getTime() + ocrEngineConfig.expiredIn * TIME_UNIT.SECOND;
31235
31583
  sdkFlowTimeout = makeSDKFlowTimeout(ocrEngineConfig.expiredIn);
31236
31584
  }
31237
31585
  }), switchMap(canvasSizeInfo => {
@@ -31422,26 +31770,66 @@ function startOCR(config) {
31422
31770
  }), switchMap(() => config.onSuccess()), tap(() => {
31423
31771
  setStatusEvent$1(cardClassResultMapping(config.acceptTypes[config.acceptTypes.length - 1]));
31424
31772
  stopSpinner();
31425
- uiComponentBasic.container.style.display = 'none';
31773
+ // only for TWN IDCard handle ocr result page
31774
+ if (config.cardTypes[0].includes(IdRecognitionCardType.IDCard) && config.cardTypes[0].includes(CountryCode.TWN)) ; else {
31775
+ uiComponentBasic.container.style.display = 'none';
31776
+ }
31426
31777
  }), concatMap(result => __awaiter(this, void 0, void 0, function* () {
31427
31778
  setStatusView(StatusView.Confirm);
31428
31779
  let modifiedData = result2ModifiedData(result.details);
31429
31780
  if (config.ocrConfig.displayResultPage) {
31430
- modifiedData = yield renderConfirmUI({
31431
- cardType: config.ocrConfig.type,
31432
- items: {
31433
- columns: Object.keys(result.details).sort((a, b) => {
31434
- const aScore = getRecognitionColumnOrder(a);
31435
- const bScore = getRecognitionColumnOrder(b);
31436
- return aScore - bScore || a.localeCompare(b);
31437
- }),
31438
- details: result.details
31439
- },
31440
- options: {
31441
- headerIcon: config.ocrConfig.icon,
31442
- translate: key => translateService.translate(key)
31781
+ // only for TWN IDCard
31782
+ if (config.cardTypes[0].includes(IdRecognitionCardType.IDCard) && config.cardTypes[0].includes(CountryCode.TWN)) {
31783
+ const keyMapping = {
31784
+ [IdRecognitionCardType.IDCard]: 'idCard',
31785
+ [IdRecognitionCardType.DriverLicense]: 'driverLicense',
31786
+ [IdRecognitionCardType.HealthCard]: 'HealthCard',
31787
+ [IdRecognitionCardType.ResidentCard]: 'residentCard',
31788
+ [IdRecognitionCardType.Passport]: 'passport'
31789
+ };
31790
+ const res = yield ocrResultModal({
31791
+ title: `${'請確認'}${translateService.translate(config.ocrConfig.type ? `sdk.ocr.verify.result.title.${keyMapping[config.ocrConfig.type]}` : '')}`,
31792
+ subtitle: '若資料有錯誤,可點擊內容進行修改',
31793
+ items: result.ocrResultFilds,
31794
+ confirmText: translateService.translate('sdk.general.confirm'),
31795
+ hintText: '逾時將自動轉跳至選單頁並無法保存此次紀錄',
31796
+ countDown1Text: '請在',
31797
+ countDown2Text: '內完成確認',
31798
+ countDownTime,
31799
+ cancelText: translateService.translate('sdk.general.cancel'),
31800
+ onConfirm: result => {
31801
+ modifiedData = result;
31802
+ },
31803
+ onClose: () => {
31804
+ // console.log('onClose');
31805
+ }
31806
+ });
31807
+ if (res === 'close') {
31808
+ const cancelResultObj = {
31809
+ isSuccess: false,
31810
+ code: `${ErrorCode.USER_CANCEL}`,
31811
+ message: new AuthmeError(ErrorCode.USER_CANCEL).message,
31812
+ data: {}
31813
+ };
31814
+ return cancelResultObj;
31443
31815
  }
31444
- });
31816
+ } else {
31817
+ modifiedData = yield renderConfirmUI({
31818
+ cardType: config.ocrConfig.type,
31819
+ items: {
31820
+ columns: Object.keys(result.details).sort((a, b) => {
31821
+ const aScore = getRecognitionColumnOrder(a);
31822
+ const bScore = getRecognitionColumnOrder(b);
31823
+ return aScore - bScore || a.localeCompare(b);
31824
+ }),
31825
+ details: result.details
31826
+ },
31827
+ options: {
31828
+ headerIcon: config.ocrConfig.icon,
31829
+ translate: key => translateService.translate(key)
31830
+ }
31831
+ });
31832
+ }
31445
31833
  }
31446
31834
  flags.onConfirm = true;
31447
31835
  Storage.setItem('scanId', result.scanId);
@@ -31875,6 +32263,7 @@ function startOCR(config) {
31875
32263
  sdkFlowTimeout.unsubscribe();
31876
32264
  sdkFlowTimeout = null;
31877
32265
  }
32266
+ countDownTime = 0;
31878
32267
  eventListenerService$1.stop();
31879
32268
  hidePopup();
31880
32269
  uiComponentBasic.container.remove();
@@ -32368,7 +32757,9 @@ class LivenessVerifyModule {
32368
32757
  const result = yield this.fasService.recognition(data);
32369
32758
  if (this.canvas) {
32370
32759
  const debugData = yield (_c = this.fasService) === null || _c === void 0 ? void 0 : _c.getDebugImageData(data);
32371
- const ctx = this.canvas.getContext('2d');
32760
+ const ctx = this.canvas.getContext('2d', {
32761
+ willReadFrequently: true
32762
+ });
32372
32763
  this.canvas.width = frameWidth;
32373
32764
  this.canvas.height = frameHeight;
32374
32765
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -32555,7 +32946,7 @@ class LivenessModule {
32555
32946
  try {
32556
32947
  const result = yield firstValueFrom(yield startLiveness({
32557
32948
  getOptionConfig: () => __awaiter(this, void 0, void 0, function* () {
32558
- const res = yield LivenessAPI.IdentityVerification.option();
32949
+ const res = yield LivenessAPI.IdentityVerification.option(config.deviceType);
32559
32950
  const themeId = res.themeId;
32560
32951
  if (!themeId) {
32561
32952
  return {};
@@ -32615,7 +33006,9 @@ class LivenessModule {
32615
33006
  const result = yield this.fasService.recognition(data);
32616
33007
  if (this.canvas) {
32617
33008
  const debugData = yield (_b = this.fasService) === null || _b === void 0 ? void 0 : _b.getDebugImageData(data);
32618
- const ctx = this.canvas.getContext('2d');
33009
+ const ctx = this.canvas.getContext('2d', {
33010
+ willReadFrequently: true
33011
+ });
32619
33012
  this.canvas.width = frameWidth;
32620
33013
  this.canvas.height = frameHeight;
32621
33014
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -33113,7 +33506,9 @@ class MRZModule {
33113
33506
  const mrzResult = yield this.mrzService.recognition(data);
33114
33507
  if (this.canvas) {
33115
33508
  const debugData = yield (_d = this.mrzService) === null || _d === void 0 ? void 0 : _d.getDebugImageData(data);
33116
- const ctx = this.canvas.getContext('2d');
33509
+ const ctx = this.canvas.getContext('2d', {
33510
+ willReadFrequently: true
33511
+ });
33117
33512
  this.canvas.width = frameWidth;
33118
33513
  this.canvas.height = frameHeight;
33119
33514
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -33274,7 +33669,8 @@ class MRZModule {
33274
33669
  yield waitTime(1000);
33275
33670
  return {
33276
33671
  scanId: scanId,
33277
- details: latestTField !== null && latestTField !== void 0 ? latestTField : {}
33672
+ details: latestTField !== null && latestTField !== void 0 ? latestTField : {},
33673
+ ocrResultFilds: []
33278
33674
  };
33279
33675
  }),
33280
33676
  onDestroy: () => __awaiter(this, void 0, void 0, function* () {
@@ -33527,6 +33923,7 @@ class OCRModule {
33527
33923
  let backImage = null;
33528
33924
  let frontCropImage = null;
33529
33925
  let backCropImage = null;
33926
+ let ocrResultFilds = [];
33530
33927
  const {
33531
33928
  getDebugLogsLength,
33532
33929
  modifyDeubgLog,
@@ -33616,8 +34013,7 @@ class OCRModule {
33616
34013
  cardTypeConfigs: cardTypeConfigs,
33617
34014
  ocrConfig: config,
33618
34015
  getOptionConfig: () => __awaiter(this, void 0, void 0, function* () {
33619
- const res = yield option();
33620
- console.log('themeId:', res.themeId);
34016
+ const res = yield option(config.deviceType);
33621
34017
  const themeId = res.themeId;
33622
34018
  if (!themeId) {
33623
34019
  return {};
@@ -34048,7 +34444,9 @@ class OCRModule {
34048
34444
  }
34049
34445
  if (this.canvas) {
34050
34446
  const debugData = yield (_f = this.antiFraudInstance) === null || _f === void 0 ? void 0 : _f.getDebugImageData(data);
34051
- const ctx = this.canvas.getContext('2d');
34447
+ const ctx = this.canvas.getContext('2d', {
34448
+ willReadFrequently: true
34449
+ });
34052
34450
  this.canvas.width = frameWidth;
34053
34451
  this.canvas.height = frameHeight;
34054
34452
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -34175,7 +34573,9 @@ class OCRModule {
34175
34573
  });
34176
34574
  if (this.canvas) {
34177
34575
  const debugData = yield _service === null || _service === void 0 ? void 0 : _service.getDebugImageData(data);
34178
- const ctx = this.canvas.getContext('2d');
34576
+ const ctx = this.canvas.getContext('2d', {
34577
+ willReadFrequently: true
34578
+ });
34179
34579
  this.canvas.width = frameWidth;
34180
34580
  this.canvas.height = frameHeight;
34181
34581
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -34214,7 +34614,6 @@ class OCRModule {
34214
34614
  // downloadImage(image, `${frameIndex}-${docInfos[type as EAuthMeCardClass].docId}-${new Date().getTime().toString()}.jpg`)
34215
34615
  frameIndex++;
34216
34616
  backgroundRequest(() => __awaiter(this, void 0, void 0, function* () {
34217
- console.log('recognition', docInfos[cardType !== null && cardType !== void 0 ? cardType : ''].docId);
34218
34617
  if (docInfos[eClass].docId === '') {
34219
34618
  console.warn('didnt find docid, retry');
34220
34619
  return false;
@@ -34373,7 +34772,7 @@ class OCRModule {
34373
34772
  throw 'recognition failed';
34374
34773
  }
34375
34774
  result = unionMerge(result, resp && resp.details || {});
34376
- yield SendRequestWithRetry(() => __awaiter(this, void 0, void 0, function* () {
34775
+ const res = yield SendRequestWithRetry(() => __awaiter(this, void 0, void 0, function* () {
34377
34776
  const postData = {
34378
34777
  scanDocumentId: docId,
34379
34778
  details: resp === null || resp === void 0 ? void 0 : resp.details,
@@ -34394,7 +34793,11 @@ class OCRModule {
34394
34793
  // needFraudOption ? this.fraudResult : null
34395
34794
  // )
34396
34795
  );
34397
-
34796
+ // ocrResultFilds = res.fields.concat(ocrResultFilds);
34797
+ ocrResultFilds = ocrResultFilds.map(item1 => {
34798
+ const item2 = res.fields.find(item => item.name === item1.name);
34799
+ return item2 ? Object.assign(Object.assign({}, item1), item2) : item1;
34800
+ }).concat(res.fields.filter(item2 => !ocrResultFilds.some(item1 => item1.name === item2.name)));
34398
34801
  delete docInfos[option.cardType];
34399
34802
  return true;
34400
34803
  } catch (error) {
@@ -34570,7 +34973,9 @@ class OCRModule {
34570
34973
  }
34571
34974
  if (this.canvas) {
34572
34975
  const debugData = yield (_j = this.antiFraudInstance) === null || _j === void 0 ? void 0 : _j.getDebugImageData(data);
34573
- const ctx = this.canvas.getContext('2d');
34976
+ const ctx = this.canvas.getContext('2d', {
34977
+ willReadFrequently: true
34978
+ });
34574
34979
  this.canvas.width = frameWidth;
34575
34980
  this.canvas.height = frameHeight;
34576
34981
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -34717,7 +35122,8 @@ class OCRModule {
34717
35122
  frontImage,
34718
35123
  backImage,
34719
35124
  frontCropImage,
34720
- backCropImage
35125
+ backCropImage,
35126
+ ocrResultFilds
34721
35127
  };
34722
35128
  }),
34723
35129
  onDestroy: () => __awaiter(this, void 0, void 0, function* () {
@@ -34779,7 +35185,7 @@ function renderCardTypeAndCountryConfig(config) {
34779
35185
  currentCardTypeAndCountry = Object.assign(Object.assign({}, currentCardTypeAndCountry), {
34780
35186
  country
34781
35187
  });
34782
- countrySelectDropdownText.innerText = translate(`sdk.home.selectCountry.${country}`);
35188
+ countrySelectDropdownText.innerText = translate(`sdk.general.country.${country}`);
34783
35189
  };
34784
35190
  const dropdownSwitch = switchTarget => {
34785
35191
  const closeDropdown = () => {
@@ -34816,7 +35222,7 @@ function renderCardTypeAndCountryConfig(config) {
34816
35222
  <label class="country-select-label">${translate('sdk.home.selectCountry')}</label>
34817
35223
  <div class="country-select-dropdown">
34818
35224
  <div class="country-select-dropdown-frame">
34819
- <div class="country-select-dropdown-text">${translate(`sdk.home.selectCountry.${config.defaultCountry}`)}</div>
35225
+ <div class="country-select-dropdown-text">${translate(`sdk.general.country.${config.defaultCountry}`)}</div>
34820
35226
  <div class="country-select-dropdown-icon"></div>
34821
35227
  </div>
34822
35228
  <div class="dropdown-country-list"></div>
@@ -34847,7 +35253,7 @@ function renderCardTypeAndCountryConfig(config) {
34847
35253
  countryDom.classList.add('dropdown-country-list-item');
34848
35254
  countryDom.innerHTML = `
34849
35255
  <div class="dropdown-country-list-item-frame">
34850
- <div class="dropdown-country-list-item-text">${translate(`sdk.home.selectCountry.${country}`)}</div>
35256
+ <div class="dropdown-country-list-item-text">${translate(`sdk.general.country.${country}`)}</div>
34851
35257
  </div>
34852
35258
  `;
34853
35259
  countryDom.addEventListener('click', event => {
@@ -34952,6 +35358,7 @@ class AuthmeIdentityVerification extends AuthmeFunctionModule {
34952
35358
  super(...arguments);
34953
35359
  this.isAuth = false;
34954
35360
  this.tearDownPromise = undefined;
35361
+ this.DEVICE_TYPE = DEVICE_TYPE;
34955
35362
  }
34956
35363
  // livenessVerify 可能是過時的產物,暫時不支援 LIVENESS_VERIFY module。
34957
35364
  preloadAsync(modules) {
@@ -35234,8 +35641,8 @@ class AuthmeIdentityVerification extends AuthmeFunctionModule {
35234
35641
  }
35235
35642
 
35236
35643
  var name = "authme/sdk";
35237
- var version$1 = "2.8.3";
35238
- var date = "2025-03-05T06:16:55+0000";
35644
+ var version$1 = "2.8.5";
35645
+ var date = "2025-03-17T05:56:00+0000";
35239
35646
  var packageInfo = {
35240
35647
  name: name,
35241
35648
  version: version$1,