## 소스맵 노출 차단 (공개 이슈 )
배포본에 .map 이 포함돼 원본 TS/TSX 전문(sourcesContent, 한글 주석 포함)이
그대로 노출됐다. 생성·서빙·저장소 유입 3계층을 모두 막는다.
- 빌드 config 15곳(코어 3 + _bundled 12): sourcemap 하드코딩 제거.
G7_BUILD_SOURCEMAP 판정식으로 교체 — 미설정(로컬 npm run build)이면 생성해
개발 디버깅 경험을 보존하고, 0 이면 미생성.
- Build{Core,Module,Plugin,Template}Command: 죽어 있던 --production 플래그 복구.
$productionMode 를 콘솔 문자열에만 쓰고 npm 프로세스에 env 를 넘기지 않아
산출물이 개발 빌드와 동일했다. runNpmCommand 에 $env 를 추가해 주입
(--watch 에는 미주입). Symfony Process 는 부모 환경에 병합하므로 PATH 유실 없음.
- Allowed{Module,Plugin}FileType / {Module,Plugin}Service::getMimeType:
허용 확장자 map 제거 — 익명 200 서빙 차단(템플릿은 원래 미허용, 3종 정책 일치).
- ExtensionBundleService: CSS 번들의 /*# sourceMappingURL=... */ strip 추가.
CSS 는 블록 주석이라 JS 의 //# 패턴으로는 검출되지 않던 구멍.
- 추적 .map 13개 삭제 + .gitignore 전역 *.map 규칙(경로 한정 시 새 확장에서 누락).
실측: 산출 JS 의 sourceMappingURL 13 → 0, 추적 .map 13 → 0,
확장 디렉토리 npm run build 는 여전히 map 생성(개발 경험 회귀 없음).
## 관리자 환경설정 탭 지연 로딩
코어/이커머스/게시판 환경설정 화면이 진입 즉시 전 탭의 데이터소스를 한꺼번에
호출했다. 각 데이터소스에 활성 탭 조건(if)을 걸어 해당 탭에서만 fetch 하도록
변경하고, 결제 플러그인 3종의 테스트모드 상태 조회도 주문설정 탭으로 한정.
## 동반 결함 수정 (무관 결함 — 재발 방지 목적으로 같은 세션 처리)
- 나이스페이먼츠: 체크아웃 캐시 프리페치가 라우트를 가리지 않아 플러그인 번들이
로드되는 모든 페이지(홈/게시판/로그인)에서 주문서를 조회 → 비회원 매번 422.
형제 플러그인(kginicis)의 기존 가드 패턴을 적용해 체크아웃 경로로 한정.
- admin smoke 8건: 대부분 구현이 아니라 테스트 결함이었다 — URL 오타(단수 board),
존재하지 않는 권한키, 앱 로케일이 en 인데 한국어 라벨 로케이터, DataGrid 버튼을
먼저 잡던 휴리스틱 로케이터. 레이아웃에는 sticky className / 안정 id 를 부여.
- PHPDoc ↔ Pint 충돌 3건: 설명 없는 @param 은 no_superfluous_phpdoc_tags 가
삭제해 audit phpdoc-public-method 와 무한 충돌. 한국어 설명을 붙여 양쪽 충족
(리스너 3종의 설명 누락 메서드도 전수 보강).
- Log::spy 500 3건: spy 가 Log::channel('activity') 를 null 로 만들고
logActivity 가 null->info 로 \Error → 같은 줄 catch(\Exception) 은 못 잡아
통과. 운영에선 채널이 항상 로거이므로 제품 무결 → 테스트에 activity 채널
보존 헬퍼 추가.
- NhnKcpApiServiceTest 5건: 스텁이 Unix 바이너리만 만들어 Windows 분기
(pp_cli_exe.exe)에서만 실패. #!/bin/sh 는 Windows 실행 불가 → 파일 내 기존
컨벤션대로 skip 가드.
## 테스트
- 소스맵 범위 130 passed (신규: BuildCommandSourcemapEnv, NoSourcemapArtifacts,
ExtensionBundleService CSS strip, Allowed*FileType 반전, 자산 서빙 거부)
- 결제 3플러그인 505 passed / 0 failed (skipped 9 = Windows 전용 CLI, 사유 명시)
- 나이스페이먼츠 프론트 38 passed (가드 제거 시 red 실증 후 복원)
- E2E: production-sourcemap-exposure.spec.ts 6건 + 시나리오 매니페스트
버전: sirsoft-admin_basic 1.0.2 → 1.0.3, sirsoft-board 1.0.1 → 1.0.2
(각 manifest/package/lock/composer 동기화). 코어 7.0.4 는 미출시 누적.
18 lines
44 KiB
JavaScript
18 lines
44 KiB
JavaScript
(function(){"use strict";function tt(e){return/^https?:\/\//i.test(e)||e.startsWith("/api/")?e:e.startsWith("/plugins/")?`/api${e}`:e.startsWith("plugins/")?`/api/${e}`:e}function nt(e){return e.trim().slice(0,160)}function rt(e){if(e)return e.replace(/\/payment\/close-report$/,"/payment/retry")}async function ce(e,t,n=!1){const r=window.G7Core?.api;if(typeof r?.post=="function"){await r.post(e,t);return}const a=await fetch(tt(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:n});if(!a.ok){let o=`NHN KCP payment request failed (${a.status})`;try{const i=await a.json(),s=Array.isArray(i?.errors?.message)?i.errors.message[0]:i?.error??i?.message;typeof s=="string"&&s.trim()!==""&&(o=s)}catch{}throw new Error(o)}}async function at(e){const t=rt(e.closeReportUrl);t&&await ce(t,{oid:e.oid,price:Number(e.price),buyer_email:e.buyer_email??"",buyer_phone:e.buyer_phone??"",payment_method:e.payment_method??""})}async function ot(e,t="kcp-window-closed"){if(!e.closeReportUrl)return;const n={oid:e.oid,price:Number(e.price),buyer_email:e.buyer_email??"",buyer_phone:e.buyer_phone??"",payment_method:e.payment_method??"",reason:nt(t)||"kcp-window-closed"};try{await ce(e.closeReportUrl,n,!0)}catch(r){console.warn("[sirsoft-pay_nhnkcp] failed to report payment window close",r)}}const it="nhnkcp_applepay";function M(e){return e===it}function S(){if(typeof navigator>"u")return!1;const e=navigator,t=(e.userAgent||"").toLowerCase(),n=((e.userAgentData?.platform??e.platform)||"").toLowerCase(),r=e.maxTouchPoints??0;return/iphone|ipad|ipod/.test(t)||/iphone|ipad|ipod|ios/.test(n)?!0:/macintosh|mac os x/.test(t)&&r>1}function H(){return((typeof document<"u"?document.documentElement.lang:"")||"").toLowerCase().startsWith("ko")?"애플페이는 IOS 기기에 모바일결제만 가능합니다.":"Apple Pay is available only for mobile payments on iOS devices."}function B(e){return(e??"KRW").trim().toUpperCase()||"KRW"}function st(e){return B(e)==="KRW"}function ct(e){const t=B(e);return((typeof document<"u"?document.documentElement.lang:"")||"").toLowerCase().startsWith("ko")?`NHN KCP는 KRW 결제만 지원합니다. (${t})`:`NHN KCP supports KRW payments only. (${t})`}function dt(e){const t=Math.max(0,Math.round(Number(e.amount??0))),n=Math.min(Math.max(0,Math.round(Number(e.tax_free_amount??0))),t);if(n<=0)return{};const r=Math.max(0,Math.round(Number(e.tax_amount??0))),a=Math.max(0,Math.round(Number(e.vat_amount??0))),o=Math.max(0,t-n),i=o>0&&r>0&&a>0?Math.min(o,Math.round(o*(a/r))):0,s=o-i;return{tax_flag:"TG03",comm_tax_mny:String(s),comm_vat_mny:String(i),comm_free_mny:String(n)}}class D extends Error{constructor(t){super(t??"결제가 취소되었습니다."),this.name="KcpCancelledError"}}const lt={card:"100000000000",bank_transfer:"010000000000",virtual_account:"001000000000",mobile:"000010000000",bank:"010000000000",vbank:"001000000000",phone:"000010000000"},de={nhnkcp_payco:{payco_direct:"Y"},nhnkcp_naverpay:{naverpay_direct:"Y"},nhnkcp_naverpay_point:{naverpay_direct:"Y",naverpay_point_direct:"Y"},nhnkcp_kakaopay:{kakaopay_direct:"Y"},nhnkcp_applepay:{applepay_direct:"Y"}};function ut(e,t){const n=e.toLowerCase();return!t||!Object.prototype.hasOwnProperty.call(de,n)?{}:{param_opt_1:n,nhnkcp_easy_pay_method:n}}function pt(e){if(!e.isConnected)return!0;const t=window.getComputedStyle(e);if(t.display==="none"||t.visibility==="hidden")return!0;const n=e.getBoundingClientRect();return n.width<=0||n.height<=0}function mt(e,t){let n=!1,r,a;const o=()=>{n=!0,a&&(a.disconnect(),a=void 0),r!==void 0&&(window.clearInterval(r),r=void 0)},i=()=>{n||!pt(e)||(o(),t())},s=document.body??document.documentElement;return s&&typeof MutationObserver<"u"&&(a=new MutationObserver(i),a.observe(s,{attributes:!0,attributeFilter:["class","hidden","style"],childList:!0,subtree:!0})),r=window.setInterval(i,300),o}function yt(){if(typeof navigator>"u")return!1;if(S())return!0;const e=navigator;if(e.userAgentData?.mobile!==void 0)return e.userAgentData.mobile;const t=(navigator.userAgent||"").toLowerCase();return!!(/android|iphone|ipod|windows phone|iemobile|blackberry|opera mini|mobile safari/.test(t)||(navigator.maxTouchPoints??0)>1&&!t.includes("windows")&&!t.includes("macintosh"))}async function le(e,t){const{pgPaymentData:n,paymentMethod:r}=e.params||{};if(!n){console.error("[sirsoft-pay_nhnkcp] pgPaymentData is required");return}const a=r??n.pay_method??"card",o=typeof a=="string"&&a.startsWith("nhnkcp_"),i=window.G7Core;let s=null;try{if(!st(n.currency)){const u=ct(n.currency);i?.state?.setLocal?.({paymentErrorMessage:u,isSubmittingOrder:!1,paymentMethod:a}),i?.modal?.open?.("nhnkcp_payment_error_modal");return}if(M(a)&&!S()){const u=H();i?.state?.setLocal?.({paymentErrorMessage:u,isSubmittingOrder:!1,paymentMethod:a}),i?.modal?.open?.("nhnkcp_payment_error_modal");return}const c=await i.api.get("/modules/sirsoft-ecommerce/payments/client-config/nhnkcp");if(!c.data){console.error("[sirsoft-pay_nhnkcp] Failed to fetch client config",c);return}const d=c.data;s={closeReportUrl:d.callback_urls.close_report,oid:n.order_number,price:Number(n.amount),buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??"",payment_method:a};const l=window.location.origin+d.callback_urls.callback;await at(s),yt()?await ft(i,n,a,o,l):await ht(d,n,a,o,l)}catch(c){if(c instanceof D){s&&await ot(s,c.message||"kcp-window-closed"),i?.state?.setLocal?.({isSubmittingOrder:!1,paymentMethod:a});return}console.error("[sirsoft-pay_nhnkcp] requestPayment error",c);const l=c?.response?.data,u=l?.errors?Object.values(l.errors)[0]?.[0]:void 0,m=l?.error??l?.message??u??(c instanceof Error?c.message:"Unknown error");i?.state?.setLocal?.({paymentErrorMessage:m,isSubmittingOrder:!1,paymentMethod:a}),i?.modal?.open?.("nhnkcp_payment_error_modal")}}async function ft(e,t,n,r,a){const o=await e.api.post("/plugins/sirsoft-pay_nhnkcp/mobile/approval-key",{order_number:t.order_number,amount:t.amount,good_name:t.order_name,pay_method:n,buyr_name:t.customer_name??"",buyr_mail:t.customer_email??"",buyr_tel1:t.customer_phone??"",ret_url:a,currency:B(t.currency)});if(!o.success||!o.data){const d=o.errors,l=d?Object.values(d)[0]?.[0]:void 0;throw new Error(o.error??o.message??l??"KCP 모바일 승인키 획득 실패")}const{pay_url:i,fields:s}=o.data,c=document.createElement("form");c.method="POST",c.action=i,c.acceptCharset="euc-kr",c.style.display="none";for(const[d,l]of Object.entries(s)){const u=document.createElement("input");u.type="hidden",u.name=d,u.value=String(l),c.appendChild(u)}document.body.appendChild(c),c.submit(),await new Promise(()=>{})}async function ht(e,t,n,r,a){const o=r?"100000000000":lt[t.pay_method??"card"]??"100000000000",s={site_cd:n==="nhnkcp_payco"?e.easy_pay_client_id??e.client_id:e.use_escrow&&!r?e.escrow_client_id??e.client_id:e.client_id,ordr_idxx:t.order_number,good_name:t.order_name,good_mny:String(t.amount),buyr_name:t.customer_name??"",buyr_mail:t.customer_email??"",buyr_tel1:t.customer_phone??"",pay_method:o,Ret_URL:a};if(Object.assign(s,dt(t)),Object.assign(s,ut(n,r)),o==="001000000000"&&(s.vcnt_expire_term=String(e.vbank_expire_days??3),s.disp_tax_yn="N"),e.use_escrow&&!r&&(s.escw_used="Y",s.pay_mod="O"),r){s.payco_direct="",s.naverpay_direct="A",s.kakaopay_direct="A",s.applepay_direct="A";const d=de[n];d&&Object.assign(s,d)}const c=Object.entries(s).map(([d,l])=>`<input type="hidden" name="${d}" value="${l.replace(/"/g,""")}">`).join("");await new Promise((d,l)=>{document.getElementById("kcp-sdk-iframe")?.remove(),document.getElementById("kcp-dim-overlay")?.remove();const u=document.createElement("div");u.id="kcp-dim-overlay",u.style.cssText="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:99998;",document.body.appendChild(u);const m=document.createElement("iframe");m.id="kcp-sdk-iframe",m.setAttribute("allowtransparency","true"),m.style.cssText="position:fixed;top:0;left:0;width:100%;height:100%;border:0;z-index:99999;background:transparent;",document.body.appendChild(m);const y=m.contentWindow;let x=!1,h,f;const se=()=>{f?.(),f=void 0,h!==void 0&&(clearTimeout(h),h=void 0),m.remove(),u.remove()},v=_=>{x||(x=!0,se(),l(_))},w=()=>{x=!0,f?.(),f=void 0,h!==void 0&&(clearTimeout(h),h=void 0)};f=mt(m,()=>{v(new D("kcp-payment-frame-closed"))}),y.m_Completepayment=function(_){const E=_.elements.res_cd?.value??"",p=_.elements.res_msg?.value??"";if(E==="0000"){w();const g=y.document.forms.namedItem("order_info"),k=g&&g!==_?g:_;if(g&&g!==_)for(let I=0;I<_.elements.length;I++){const L=_.elements[I];if(!L.name)continue;let A=g.elements.namedItem(L.name);A||(A=y.document.createElement("input"),A.type="hidden",A.name=L.name,g.appendChild(A)),A.value=L.value}k.action=a,k.method="POST",k.target="_top",y.document.body.appendChild(k),k.submit()}else{const g=E===""||E==="7777"||p.includes("취소");v(g?new D(p):new Error(`KCP 오류 [${E}]: ${p}`))}},y.__kcpFail=_=>{v(_)};const C=m.contentDocument||y.document;C.open(),C.write(`<!DOCTYPE html><html><head>
|
||
<script src="${e.sdk_url}"><\/script>
|
||
</head><body style="margin:0;padding:0;background:transparent;">
|
||
<form name="order_info">${c}</form>
|
||
<script>
|
||
try {
|
||
if (typeof KCP_Pay_Execute === 'function') {
|
||
KCP_Pay_Execute(document.forms['order_info']);
|
||
window.__kcpReady && window.__kcpReady();
|
||
} else {
|
||
window.__kcpFail && window.__kcpFail(new Error('KCP_Pay_Execute not defined'));
|
||
}
|
||
} catch(e) {
|
||
window.__kcpFail && window.__kcpFail(e);
|
||
}
|
||
<\/script>
|
||
</body></html>`),C.close(),h=window.setTimeout(()=>{v(new Error("KCP SDK load timeout"))},15e3),y.__kcpReady=()=>{h!==void 0&&(clearTimeout(h),h=void 0)}})}const _t={nhnkcp_payco:"PAYCO",nhnkcp_naverpay:"네이버페이",nhnkcp_naverpay_point:"네이버페이 포인트",nhnkcp_kakaopay:"카카오페이",nhnkcp_applepay:"Apple Pay"},gt="0 0 0 2px #ffffff, 0 0 0 5px rgba(0,0,0,0.55)";function ue(){return document.querySelector(".nhnkcp-easy-pay-btns")??null}function pe(){const e=ue();e&&e.querySelectorAll("button").forEach(t=>{t.style.boxShadow="",t.style.outline=""})}function wt(e){const t=ue();if(!t)return;const n=_t[e];t.querySelectorAll("button").forEach(r=>{r.textContent?.trim()===n?(r.style.boxShadow=gt,r.style.outline="none"):(r.style.boxShadow="",r.style.outline="")})}function Pt(e){const t=e.params?.paymentMethod;if(!t)return;const n=window.G7Core;if(M(t)&&!S()){const a=H();n?.state?.setLocal?.({paymentErrorMessage:a,isSubmittingOrder:!1}),n?.modal?.open?.("nhnkcp_payment_error_modal"),pe();return}const r=typeof t=="string"&&t.startsWith("nhnkcp_");n?.state?.setLocal?.({paymentMethod:t,serverPaymentMethod:r?"card":t}),r?wt(t):pe()}function kt(e){const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{document.execCommand("copy")}finally{t.remove()}}async function bt(e){const t=String(e.params?.text??"");if(t!==""){if(navigator.clipboard&&typeof navigator.clipboard.writeText=="function"){await navigator.clipboard.writeText(t);return}kt(t)}}const me={requestPayment:le,setPaymentMethod:Pt,copyToClipboard:bt},ye="/api/modules/sirsoft-ecommerce/user/orders",Ct="sirsoft-nhnkcp",j="sirsoft-pay_nhnkcp",fe="nhnkcp_",b={info:(...e)=>console.info(`[${j}]`,...e),warn:(...e)=>console.warn(`[${j}]`,...e),error:(...e)=>console.error(`[${j}]`,...e)};function Nt(e){return typeof e=="string"?e:e instanceof URL?e.toString():typeof Request<"u"&&e instanceof Request?e.url:String(e)}function xt(e,t){return t?.method?t.method.toUpperCase():typeof Request<"u"&&e instanceof Request?e.method.toUpperCase():"GET"}function vt(e,t){if(t!=="POST")return!1;const n=e.split("?")[0].split("#")[0];return n===ye||n.endsWith(ye)}function Et(){return window.location.pathname+window.location.search+window.location.hash}function At(e,t){const n=JSON.stringify(t);return new Response(n,{status:e.status,statusText:e.statusText,headers:e.headers})}function St(e){return new Response(JSON.stringify({success:!1,message:e,error:e,errors:{payment_method:[e]}}),{status:422,statusText:"Unprocessable Content",headers:{"Content-Type":"application/json"}})}function he(e){try{return JSON.parse(e).payment_method}catch{return}}function Kt(e,t){try{const n=JSON.parse(e);return n.payment_method=t,JSON.stringify(n)}catch{return e}}function It(){if(typeof window>"u"||typeof window.fetch!="function")return;const e="__sirsoftNhnkcpInterceptorInstalled",t=window;if(t[e])return;t[e]=!0;const n="__sirsoftPgOriginalFetch";t[n]||(t[n]=window.fetch.bind(window));const r=t[n],a=window.fetch.bind(window);window.fetch=async function(i,s){const c=Nt(i),d=xt(i,s);if(!vt(c,d))return a(i,s);let l,u=s;if(s?.body&&typeof s.body=="string"){const p=he(s.body);typeof p=="string"&&p.startsWith(fe)&&(l=p,u={...s,body:Kt(s.body,"card")},b.info(`easy pay detected: replacing payment_method '${p}' → 'card'`))}if(!l)try{const p=window.G7Core?.state?.getLocal?.()?.paymentMethod;typeof p=="string"&&p.startsWith(fe)&&(l=p,b.info(`easy pay detected from local state: '${p}'`))}catch{}if(M(l)&&!S()){const p=H();return b.warn(p),St(p)}const y=await(l?r:a)(i,u);let x;try{x=y.clone()}catch{return y}let h=null;try{h=await x.json()}catch{return y}const f=h?.data;if(!f)return y;const se=f.requires_pg_payment===!0,v=f.pg_provider===Ct;if(!l&&(!se||!v)||l&&!f.order&&!f.pg_payment_data)return y;let w=f.pg_payment_data;if(!w&&l&&f.order){const p=f.order,g=p.options,k=g?.[0]?.product_name??String(p.order_number??""),I=(g?.length??0)>1?`${k} 외 ${(g?.length??0)-1}건`:k;w={order_number:p.order_number,order_name:I,amount:Math.floor(Number(p.total_due_amount??p.total_amount??0)),currency:"KRW",customer_name:p.orderer_name??null,customer_email:p.orderer_email??null,customer_phone:String(p.orderer_phone??"").replace(/[^0-9]/g,"")},b.info("pg_payment_data constructed from order (기본 PG가 타 PG)",{order_number:w.order_number,amount:w.amount})}if(!w)return b.warn("nhnkcp order detected but pg_payment_data missing"),y;b.info("intercepted order create response — opening PG popup");const C=f.order?{tax_amount:f.order.total_tax_amount??0,vat_amount:f.order.total_vat_amount??0,tax_free_amount:f.order.total_tax_free_amount??0}:{},_=!l&&u?.body&&typeof u.body=="string"?(()=>{const p=he(u.body);return p?{...w,pay_method:p,...C}:{...w,...C}})():{...w,...C};le({params:{pgPaymentData:_,paymentMethod:l}});const E={...h,data:{...f,requires_pg_payment:!1,redirect_url:Et()}};return At(y,E)},b.info("order response interceptor installed")}const Y="sirsoft-pay_nhnkcp",_e="__kcpOcReceiptInjectorInstalled",ge="kcp-oc-receipt-btn",Mt=/^\/shop\/orders\/([^/]+)\/complete$/;function we(){return localStorage.getItem("auth_token")}async function Tt(e){const t=we();if(!t)return null;try{const n=await fetch(`/api/modules/sirsoft-ecommerce/user/orders/${e}`,{headers:{Authorization:`Bearer ${t}`,Accept:"application/json"}});return n.ok?(await n.json())?.data?.payment??null:null}catch{return null}}async function q(e){const t=we();if(!t)return null;try{const n=await fetch(`/api/plugins/${Y}/user/orders/${e}/receipt`,{headers:{Authorization:`Bearer ${t}`,Accept:"application/json"}});return n.ok?await n.json():null}catch{return null}}function Pe(e,t,n){const r=document.createElement("button");return r.type="button",r.className=t,r.textContent=e,r.addEventListener("click",()=>n(r)),r}function $t(e){if(!e)return!1;const t=Array.from(document.querySelectorAll("div"));for(const n of t){const r=Array.from(n.children).filter(i=>i instanceof HTMLElement&&i.tagName==="SPAN");if(r.length<2)continue;const a=r[0].textContent?.trim();if(a!=="결제 방법"&&a!=="결제수단"&&a!=="결제 방식")continue;const o=r[r.length-1];return o.textContent?.trim()===e?(n.dataset.nhnkcpPaymentMethodRow="true",!0):(o.textContent=e,o.dataset.nhnkcpPaymentMethodPatched="true",n.dataset.nhnkcpPaymentMethodRow="true",!0)}return!1}async function Rt(e){if(document.getElementById(ge))return;const t=await Tt(e);if(!t||t.pg_provider!=="nhnkcp"||!t.transaction_id||!t.paid_at)return;const n=Array.from(document.querySelectorAll('button[type="button"]')).find(c=>c.className.includes("bg-blue-600"));if(!n?.parentElement)return;const r=await q(e);$t(r?.payment_method_display_label);const a=n.parentElement,o=Pe("영수증 조회",n.className.replace(/bg-blue-\d+/g,"bg-green-600").replace(/hover:bg-blue-\d+/g,"hover:bg-green-700"),async c=>{c.disabled=!0,c.textContent="로딩 중...";const d=await q(e);if(c.disabled=!1,c.textContent="영수증 조회",d){const l=window.KcpReceiptPopup;l&&new l({url:d.receipt_url??void 0})}});o.id=ge;const i=a.lastElementChild;a.insertBefore(o,i);const s="kcp-oc-cash-receipt-btn";if(!document.getElementById(s)&&(t.payment_method==="vbank"||t.payment_method==="bank_transfer")){const c=Pe("현금영수증 조회",o.className.replace(/bg-green-\d+/g,"bg-teal-600").replace(/hover:bg-green-\d+/g,"hover:bg-teal-700"),async d=>{d.disabled=!0,d.textContent="로딩 중...";const l=await q(e);if(d.disabled=!1,d.textContent="현금영수증 조회",l){const u=window.KcpReceiptPopup;u&&new u({cash_url:l.cash_receipt_url??void 0})}});c.id=s,a.insertBefore(c,i)}console.info(`[${Y}] receipt button injected on order complete page`)}function Ot(){const t=location.pathname.match(Mt);t&&Rt(t[1])}function Lt(){if(typeof window>"u")return;const e=window;if(e[_e])return;e[_e]=!0,console.info(`[${Y}] order complete receipt injector installed`);const t=(r=1200)=>setTimeout(Ot,r);document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>t()):t();const n=history.pushState.bind(history);history.pushState=(...r)=>{n(...r),t()},window.addEventListener("popstate",()=>t(500))}const P="sirsoft-pay_nhnkcp",ke="__kcpMpShowInjectorInstalled",F="kcp-mp-vbank-row",G="kcp-mp-receipt-row",T="kcp-mp-mock-deposit",Ht=/^\/mypage\/orders\/([^/]+)$/;function Bt(e){try{const n=window.G7Core?.getState,o=n?.()?.currentDataContext?.order?.data;return!o||o.order_number!==e?null:o}catch{return null}}function be(){return localStorage.getItem("auth_token")}async function Ce(e){const t=be();if(!t)return null;try{const n=await fetch(`/api/plugins/${P}/user/orders/${e}/receipt`,{headers:{Authorization:`Bearer ${t}`,Accept:"application/json"}});return n.ok?await n.json():null}catch{return null}}async function Ne(e){const t=be();if(!t)return null;try{const n=await fetch(`/api/plugins/${P}/user/orders/${e}/vbank-mock-deposit-info`,{headers:{Authorization:`Bearer ${t}`,Accept:"application/json"}});return n.ok?await n.json():null}catch{return null}}function xe(e){const t=document.createElement("div");t.id=T,t.className="pt-4 mt-2 border-t border-dashed border-orange-300 dark:border-orange-700";const n=document.createElement("div");n.className="flex items-center gap-2 mb-3";const r=document.createElement("span");r.className="inline-flex items-center px-2 py-0.5 rounded text-xs font-bold bg-orange-100 text-orange-700 dark:bg-orange-900/40 dark:text-orange-300 border border-orange-300 dark:border-orange-700",r.textContent="TEST";const a=document.createElement("p");a.className="text-sm font-semibold text-orange-700 dark:text-orange-300",a.textContent="모의입금처리",n.appendChild(r),n.appendChild(a);const o=document.createElement("form");o.method="POST",o.action=e.mock_url??"",o.target="_blank",o.className="space-y-2";const i=[{label:"KCP 거래번호",name:"e_trade_no",value:e.trade_no??""},{label:"입금계좌",name:"deposit_no",value:e.account_no??""},{label:"입금자명",name:"req_name",value:"NHN KCP",editable:!0},{label:"입금통보 URL",name:"noti_url",value:e.notify_url??""}];for(const d of i){const l=document.createElement("div");l.className="flex items-center gap-2 text-sm";const u=document.createElement("span");u.className="w-28 flex-shrink-0 text-gray-500 dark:text-gray-400 text-xs",u.textContent=d.label;const m=document.createElement("input");m.type="text",m.name=d.name,m.value=d.value,m.readOnly=!d.editable,m.className=d.editable?"flex-1 px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-white font-mono":"flex-1 px-2 py-1 text-xs border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800 text-gray-700 dark:text-gray-300 font-mono",l.appendChild(u),l.appendChild(m),o.appendChild(l)}const s=document.createElement("div");s.className="pt-1";const c=document.createElement("button");if(c.type="submit",c.className="w-full py-1.5 text-xs font-semibold rounded border border-orange-400 dark:border-orange-600 bg-orange-50 dark:bg-orange-900/30 text-orange-700 dark:text-orange-300 hover:bg-orange-100 dark:hover:bg-orange-900/50 transition-colors",c.textContent="입금통보 테스트",s.appendChild(c),o.appendChild(s),t.appendChild(n),t.appendChild(o),e.is_admin_view){const d=document.createElement("p");d.className="mt-2 text-xs text-center text-orange-500 dark:text-orange-400 font-medium",d.textContent="관리자에게만 출력되는 내용",t.appendChild(d)}return t}function ve(){const e=document.getElementById("order_payment_info_panel");if(e)return Array.from(e.children).find(o=>o.className?.includes("space-y"))??e;const t=Array.from(document.querySelectorAll("h3")).find(a=>a.textContent?.includes("결제 정보"));if(!t)return null;const n=t.parentElement?.parentElement;return n?Array.from(n.children).find(a=>a.className?.includes("space-y"))??n:null}function K(e,t,n="font-medium text-gray-900 dark:text-white"){const r=document.createElement("div");r.className="flex items-center justify-between text-sm";const a=document.createElement("span");a.className="text-gray-500 dark:text-gray-400",a.textContent=e;const o=document.createElement("span");return o.className=n,o.textContent=t,r.appendChild(a),r.appendChild(o),r}function Dt(e,t){if(!t)return!1;const n=Array.from(e.querySelectorAll("div"));for(const r of n){const a=Array.from(r.children).filter(s=>s instanceof HTMLElement&&s.tagName==="SPAN");if(a.length<2)continue;const o=a[0].textContent?.trim();if(o!=="결제 방법"&&o!=="결제수단"&&o!=="Payment Method")continue;const i=a[a.length-1];return i.textContent?.trim()===t?(r.dataset.nhnkcpPaymentMethodRow="true",!0):(i.textContent=t,i.dataset.nhnkcpPaymentMethodPatched="true",r.dataset.nhnkcpPaymentMethodRow="true",!0)}return!1}function jt(e,t){const n=document.createElement("div");n.id=F,n.className="pt-4 mt-2 border-t border-gray-200 dark:border-gray-700 space-y-3";const r=document.createElement("p");r.className="text-sm font-semibold text-gray-800 dark:text-gray-200",r.textContent="가상계좌 입금 안내";const a=document.createElement("div");a.className="space-y-1.5",a.appendChild(K("은행",e.vbank_name??"")),a.appendChild(K("계좌번호",e.vbank_number??"","font-medium text-gray-900 dark:text-white font-mono tracking-wide")),a.appendChild(K("예금주",e.vbank_holder??"")),a.appendChild(K("입금 금액",t)),e.due_date_formatted&&a.appendChild(K("입금 기한",e.due_date_formatted));const o=document.createElement("p");return o.className="text-xs text-amber-600 dark:text-amber-400",o.textContent="입금 기한 내에 입금하지 않으시면 주문이 자동 취소됩니다.",n.appendChild(r),n.appendChild(a),n.appendChild(o),n}function Yt(e){const t=document.createElement("div");t.id=G,t.className="pt-4 mt-2 border-t border-gray-200 dark:border-gray-700";const n=document.createElement("div");n.className="flex items-center justify-between";const r=document.createElement("span");r.className="text-gray-500 dark:text-gray-400 text-sm",r.textContent="영수증";const a=document.createElement("button");return a.type="button",a.className="inline-flex items-center gap-1 text-sm text-blue-600 dark:text-blue-400 hover:underline disabled:opacity-50",a.textContent="영수증 조회",a.addEventListener("click",async()=>{a.disabled=!0,a.textContent="로딩 중...";const o=await Ce(e);if(a.disabled=!1,a.textContent="영수증 조회",o){const i=window.KcpReceiptPopup;i&&new i({url:o.receipt_url,cash_url:o.cash_receipt_url})}}),n.appendChild(r),n.appendChild(a),t.appendChild(n),t}async function qt(e){const t=Bt(e);if(!t){if(!document.getElementById(T)){const m=ve();if(!m)return!1;const y=await Ne(e);y?.available&&(m.appendChild(xe(y)),console.info(`[${P}] mock deposit form injected on mypage order show`))}return!0}const{payment:n}=t;if(!n||n.pg_provider!=="nhnkcp")return!0;const r=n.payment_method==="vbank"&&!!n.vbank_name,a=!!n.transaction_id&&!!n.paid_at,o=n.payment_method==="vbank"&&!!n.vbank_number,i=!r||!!document.getElementById(F),s=!a||!!document.getElementById(G),c=!o||!!document.getElementById(T);if(i&&s&&c)return!0;const d=ve();if(!d)return!1;const l=a?await Ce(e):null,u=Dt(d,l?.payment_method_display_label);if(!document.getElementById(F)&&r)return d.appendChild(jt(n,t.total_amount_formatted??"")),console.info(`[${P}] vbank info injected on mypage order show`),!1;if(!document.getElementById(G)&&a)return d.appendChild(Yt(e)),console.info(`[${P}] receipt button injected on mypage order show`),!1;if(u&&console.info(`[${P}] payment method display patched on mypage order show`),!document.getElementById(T)&&o){const m=await Ne(e);if(m?.available)d.appendChild(xe(m)),console.info(`[${P}] mock deposit form injected on mypage order show`);else return!0}return!0}function Ft(e){let t=0;const n=setInterval(()=>{t++,qt(e).then(r=>{(r||t>=30)&&clearInterval(n)})},400)}function Gt(){const e=location.pathname.match(Ht);e&&Ft(e[1])}function Wt(){if(typeof window>"u")return;const e=window;if(e[ke])return;e[ke]=!0,console.info(`[${P}] mypage order show injector installed`);const t=(r=1500)=>setTimeout(Gt,r);document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>t()):t();const n=history.pushState.bind(history);history.pushState=(...r)=>{n(...r),t(600)},window.addEventListener("popstate",()=>t(500))}const Ut="sirsoft-pay_nhnkcp",Ee="__kcpCheckoutEasyPayInjectorInstalled",zt=/^\/shop\/checkout\/?$/,Ae="__kcpCheckoutEasyPaySyncListenerAttached",Vt=200,Jt=120,Se=[{id:"nhnkcp_payco",configKey:"PAYCO",labels:["PAYCO (NHN KCP)","PAYCO NHN KCP 간편결제","PAYCO로 결제 (NHN KCP)","Pay with PAYCO (NHN KCP)"],ko:{heading:"PAYCO",description:"PAYCO로 결제 (NHN KCP)",title:"PAYCO로 결제 (NHN KCP)"},en:{heading:"PAYCO",description:"Pay with PAYCO (NHN KCP)",title:"Pay with PAYCO (NHN KCP)"},markText:"P",markClassName:"bg-red-500 text-white"},{id:"nhnkcp_naverpay",configKey:"NAVERPAY",labels:["네이버페이 (NHN KCP)","네이버페이 신용카드로 결제 (NHN KCP)","NaverPay NHN KCP 간편결제","Naver Pay (NHN KCP)","NaverPay (NHN KCP)","Pay by Naver Pay credit card (NHN KCP)"],ko:{heading:"네이버페이 (카드)",description:"네이버페이 신용카드로 결제 (NHN KCP)",title:"네이버페이 신용카드로 결제 (NHN KCP)"},en:{heading:"Naver Pay (Card)",description:"Pay by Naver Pay credit card (NHN KCP)",title:"Pay by Naver Pay credit card (NHN KCP)"},markText:"N",markClassName:"bg-green-500 text-white"},{id:"nhnkcp_naverpay_point",configKey:"NAVERPAY POINT",labels:["네이버페이 포인트 (NHN KCP)","네이버페이 머니/포인트로 결제 (NHN KCP)","NaverPay 포인트 NHN KCP 포인트 간편결제","Naver Pay Point (NHN KCP)","NaverPay Point (NHN KCP)","Pay with Naver Pay Money/Points (NHN KCP)"],ko:{heading:"네이버페이 (포인트)",description:"네이버페이 머니/포인트로 결제 (NHN KCP)",title:"네이버페이 머니/포인트로 결제 (NHN KCP)"},en:{heading:"Naver Pay (Point)",description:"Pay with Naver Pay Money/Points (NHN KCP)",title:"Pay with Naver Pay Money/Points (NHN KCP)"},markText:"NP",markClassName:"bg-green-600 text-white"},{id:"nhnkcp_kakaopay",configKey:"KAKAOPAY",labels:["카카오페이 (NHN KCP)","카카오페이로 결제 (NHN KCP)","KakaoPay NHN KCP 간편결제","Kakao Pay (NHN KCP)","KakaoPay (NHN KCP)","Pay with Kakao Pay (NHN KCP)"],ko:{heading:"카카오페이",description:"카카오페이로 결제 (NHN KCP)",title:"카카오페이로 결제 (NHN KCP)"},en:{heading:"Kakao Pay",description:"Pay with Kakao Pay (NHN KCP)",title:"Pay with Kakao Pay (NHN KCP)"},markText:"K",markClassName:"bg-yellow-400 text-gray-950"},{id:"nhnkcp_applepay",configKey:"APPLEPAY",labels:["애플페이 (NHN KCP)","애플페이로 결제 (NHN KCP)","Apple Pay NHN KCP 간편결제","Apple Pay (NHN KCP)","Pay with Apple Pay (NHN KCP)"],ko:{heading:"애플페이",description:"애플페이로 결제 (NHN KCP)",title:"애플페이로 결제 (NHN KCP)"},en:{heading:"Apple Pay",description:"Pay with Apple Pay (NHN KCP)",title:"Pay with Apple Pay (NHN KCP)"},markText:"A",markClassName:"bg-gray-900 text-white"}];let Ke=null,$=null,W=!1;function Qt(){return window}function U(){return zt.test(window.location.pathname)}function Xt(e){return(e??"").replace(/\s+/g," ").trim()}function Zt(){return(document.documentElement.lang||navigator.language||"").toLowerCase().startsWith("ko")}function en(e){return Zt()?e.ko:e.en}function Ie(e){return e.replaceAll("네이버페이","네이버페이").replaceAll("카카오페이","카카오페이").replaceAll("Naver Pay","Naver Pay").replaceAll("Kakao Pay","Kakao Pay")}function Me(e){return Se.find(t=>t.id===e)??null}function tn(e){const t=Me(e.dataset.nhnkcpEasyPayMethod);if(t)return t;const n=Xt(e.textContent);return Se.find(r=>r.labels.some(a=>n.includes(a)))??null}function Te(e){return e.querySelector(".flex.items-center.gap-2, .flex.items-center.gap-3")??e.querySelector(".flex.items-center")}function nn(e,t,n){e.style.textAlign="left";const r=Te(e);r&&(r.style.justifyContent="flex-start",r.style.textAlign="left",r.style.width="100%");const a=t?.parentElement??n?.parentElement;a instanceof HTMLElement&&(a.style.textAlign="left",a.style.minWidth="0")}function rn(e){const t=document.createElement("span");return t.dataset.nhnkcpEasyPayMark="true",t.dataset.nhnkcpEasyPayMethod=e.id,t.setAttribute("aria-hidden","true"),t.className=`inline-flex items-center justify-center rounded-lg text-xs font-bold ${e.markClassName}`,t.style.width="32px",t.style.height="32px",t.style.flex="0 0 32px",t.textContent=e.markText,t}function an(e){delete e.dataset.kginicisBrandPaymentButton,delete e.dataset.kginicisBrandPaymentMethod,delete e.dataset.kginicisNaverpayBrandButton,e.querySelectorAll('[data-kginicis-brand-payment-mark="true"], [data-kginicis-naverpay-mark="true"]').forEach(t=>{t.remove()}),e.querySelectorAll("[data-kginicis-brand-payment-heading], [data-kginicis-brand-payment-description], [data-kginicis-naverpay-heading], [data-kginicis-naverpay-description]").forEach(t=>{delete t.dataset.kginicisBrandPaymentHeading,delete t.dataset.kginicisBrandPaymentDescription,delete t.dataset.kginicisNaverpayHeading,delete t.dataset.kginicisNaverpayDescription})}function on(e){return e.querySelector('[data-kginicis-brand-payment-mark="true"], [data-kginicis-naverpay-mark="true"]')??e.querySelector('[data-nhnkcp-easy-pay-mark="true"]')??e.querySelector("svg")??e.querySelector('i[class*="fa-"], i[role="img"], i')}function sn(e,t){const n=e.querySelector('[data-nhnkcp-easy-pay-mark="true"]');if(n){n.dataset.nhnkcpEasyPayMethod=t.id,n.className=`inline-flex items-center justify-center rounded-lg text-xs font-bold ${t.markClassName}`,n.textContent=t.markText;return}const r=rn(t),a=on(e);if(a&&a.parentElement){a.replaceWith(r);return}Te(e)?.prepend(r)}function cn(e,t){const n=Array.from(e.querySelectorAll("p")),r=en(t),a=Ie(r.heading),o=Ie(r.description),i=n[0],s=n[1];i&&i.textContent!==a&&(i.textContent=a),i&&(i.setAttribute("aria-label",r.heading),i.style.textAlign="left",i.style.whiteSpace="normal",i.style.wordBreak="keep-all",i.style.overflowWrap="anywhere"),s&&s.textContent!==o&&(s.textContent=o),s&&(s.style.textAlign="left",s.style.fontSize="12px",s.style.lineHeight="1rem",s.style.whiteSpace="normal",s.style.wordBreak="keep-all",s.style.overflowWrap="anywhere"),nn(e,i,s),e.title=r.title}function $e(e,t){if(M(t.id)&&!S()){e.hidden=!0,e.disabled=!0,e.style.display="none",e.setAttribute("aria-hidden","true"),e.dataset.nhnkcpEasyPayMethod=t.id,e.dataset.nhnkcpEasyPayHidden="true",delete e.dataset.nhnkcpEasyPayVisible;return}e.hidden&&(e.hidden=!1),e.disabled&&(e.disabled=!1),e.style.display==="none"&&e.style.removeProperty("display"),e.removeAttribute("aria-hidden"),e.dataset.nhnkcpEasyPayMethod=t.id,e.dataset.nhnkcpEasyPayVisible="true",delete e.dataset.nhnkcpEasyPayHidden,an(e),sn(e,t),cn(e,t)}function dn(e){const t={kginicis_naverpay:["nhnkcp_naverpay","nhnkcp_naverpay_point"],kginicis_kakaopay:["nhnkcp_kakaopay"]};let n=!1;return Object.entries(t).forEach(([r,a])=>{Array.from(e.querySelectorAll(`button[data-kginicis-brand-payment-method="${r}"]`)).filter(i=>!i.dataset.nhnkcpEasyPayMethod).slice(1).forEach((i,s)=>{const c=Me(a[s]);c&&($e(i,c),n=!0)})}),n}async function z(e=document){if(typeof window>"u"||typeof document>"u"||!U())return!1;let t=!1;return e.querySelectorAll("button").forEach(n=>{const r=tn(n);r&&($e(n,r),t=!0)}),dn(e)&&(t=!0),t}function ln(){W||(W=!0,window.setTimeout(()=>{W=!1,z()},0))}function Re(){$!==null&&(window.clearInterval($),$=null)}function V(){if(!U())return;Re(),z();let e=0;$=window.setInterval(()=>{e+=1,z(),e>=Jt&&Re()},Vt);const t=document.body;t[Ae]||(t[Ae]=!0,Ke=new MutationObserver(()=>ln()),Ke.observe(document.body,{childList:!0,subtree:!0,characterData:!0}))}function Oe(){U()&&V()}function un(){if(typeof window>"u"||typeof document>"u")return;const e=Qt();if(e[Ee])return;e[Ee]=!0,console.info(`[${Ut}] checkout easy pay method sync installed`),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>V()):V();const t=history.pushState.bind(history);history.pushState=(...n)=>{t(...n),window.setTimeout(()=>Oe(),200)},window.addEventListener("popstate",()=>window.setTimeout(()=>Oe(),200))}const pn="sirsoft-pay_nhnkcp",Le="__kcpAdminApplePayNoticeInjectorInstalled",mn=/^\/admin\/ecommerce\/settings\/?$/,He="__kcpAdminApplePayNoticeListenerAttached",yn="애플페이는 IOS 기기에 모바일결제만 가능합니다.",fn="Apple Pay is available only for mobile payments on iOS devices.";let Be=null,R=null,J=!1;function hn(){return window}function Q(){if(!mn.test(window.location.pathname))return!1;const e=new URLSearchParams(window.location.search).get("tab");return e===null||e==="order_settings"}function De(){return(document.documentElement.lang||navigator.language||"").toLowerCase().startsWith("ko")?yn:fn}function je(e){return(e??"").replace(/\s+/g," ").trim()}function _n(e){const t=je(e.textContent);return t==="애플페이"||t==="Apple Pay"}function gn(){const e=document.createElement("span");return e.dataset.nhnkcpAdminApplePayNotice="true",e.className="text-label-subtle",e.style.display="block",e.style.width="100%",e.style.flexBasis="100%",e.style.marginTop="2px",e.style.fontSize="12px",e.style.lineHeight="1rem",e.textContent=De(),e}function X(e=document){if(typeof window>"u"||typeof document>"u"||!Q()||je(document.body?.innerText??document.body?.textContent).includes(De()))return!1;const n=Array.from(e.querySelectorAll("span, p, div")).find(_n);return n?(n.insertAdjacentElement("afterend",gn()),!0):!1}function wn(){J||(J=!0,window.setTimeout(()=>{J=!1,X()},0))}function Ye(){R!==null&&(window.clearInterval(R),R=null)}function Z(){if(!Q())return;Ye(),X();let e=0;R=window.setInterval(()=>{e+=1,(X()||e>=50)&&Ye()},200);const t=document.body;t[He]||(t[He]=!0,Be=new MutationObserver(()=>wn()),Be.observe(document.body,{childList:!0,subtree:!0,characterData:!0}))}function qe(){Q()&&Z()}function Pn(){if(typeof window>"u"||typeof document>"u")return;const e=hn();if(e[Le])return;e[Le]=!0,console.info(`[${pn}] admin Apple Pay notice injector installed`),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>Z()):Z();const t=history.pushState.bind(history);history.pushState=(...n)=>{t(...n),window.setTimeout(()=>qe(),200)},window.addEventListener("popstate",()=>window.setTimeout(()=>qe(),200))}const kn="sirsoft-pay_nhnkcp",Fe="__nhnkcpAdminPaymentMethodBrandInjectorInstalled",Ge="__nhnkcpAdminPaymentMethodBrandSyncListenerAttached",bn=/^\/admin\/ecommerce\/settings\/?$/,We='[data-nhnkcp-admin-payment-brand-mark="true"]',Cn=200,Nn=120,xn=[{id:"nhnkcp_payco",labels:["PAYCO (NHN KCP)","PAYCO로 결제 (NHN KCP)","Pay with PAYCO (NHN KCP)"],shortLabels:["PAYCO"],markLines:["P"],markClassName:"bg-red-500 text-white"},{id:"nhnkcp_naverpay",labels:["네이버페이 (NHN KCP)","네이버페이 신용카드로 결제 (NHN KCP)","Naver Pay (NHN KCP)","Pay by Naver Pay credit card (NHN KCP)"],shortLabels:["네이버페이 (카드)","Naver Pay (Card)"],markLines:["N"],markClassName:"bg-green-500 text-white"},{id:"nhnkcp_naverpay_point",labels:["네이버페이 포인트 (NHN KCP)","네이버페이 머니/포인트로 결제 (NHN KCP)","Naver Pay Point (NHN KCP)","Pay with Naver Pay Money/Points (NHN KCP)"],shortLabels:["네이버페이 (포인트)","Naver Pay (Point)"],markLines:["NP"],markClassName:"bg-green-600 text-white"},{id:"nhnkcp_kakaopay",labels:["카카오페이 (NHN KCP)","카카오페이로 결제 (NHN KCP)","Kakao Pay (NHN KCP)","Pay with Kakao Pay (NHN KCP)"],shortLabels:["카카오페이","Kakao Pay"],markLines:["K"],markClassName:"bg-yellow-400 text-gray-950"},{id:"nhnkcp_applepay",labels:["애플페이 (NHN KCP)","애플페이로 결제 (NHN KCP)","Apple Pay (NHN KCP)","Pay with Apple Pay (NHN KCP)"],shortLabels:["애플페이","Apple Pay"],markLines:["A"],markClassName:"bg-gray-900 text-white"}];let Ue=null,O=null,ee=!1;function vn(){return window}function te(){if(!bn.test(window.location.pathname))return!1;const e=new URLSearchParams(window.location.search).get("tab");return e===null||e===""||e==="order_settings"}function En(e){return e instanceof HTMLElement?e.className:""}function ze(e){return(e??"").replace(/\u200B/g,"").replace(/\s+/g," ").trim()}function An(e){const t=En(e);return t.includes("excel-card")||t.includes("flex-center")&&t.includes("border")&&t.includes("gap-4")}function Ve(e){return e.querySelector(".font-medium")}function Sn(e){const t=ze(Ve(e)?.textContent),n=ze(e.textContent);return xn.find(r=>r.shortLabels.some(a=>t===a)||r.labels.some(a=>n.includes(a)))??null}function Kn(e){return Array.from(e.querySelectorAll("div")).filter(An)}function In(e){return Array.from(e.querySelectorAll("svg, [data-icon], i")).find(n=>!n.closest("[data-drag-handle]")&&!n.closest(We)&&!n.closest('.row-stack, .excel-card-body, button, select, [role="switch"]'))??null}function Je(e,t){e.dataset.nhnkcpAdminPaymentBrandMark="true",e.dataset.nhnkcpAdminPaymentMethod=t.id,e.setAttribute("aria-hidden","true"),e.className=`inline-flex items-center justify-center rounded-lg font-bold ${t.markClassName}`,e.style.width="32px",e.style.height="32px",e.style.flex="0 0 32px",e.style.lineHeight="1",e.style.fontSize=t.markLines.join("").length>2?"9px":"12px";const n=t.markLines.join("");e.textContent!==n&&(e.replaceChildren(),t.markLines.length>1?(e.style.flexDirection="column",t.markLines.forEach(r=>{const a=document.createElement("span");a.style.lineHeight="1",a.textContent=r,e.appendChild(a)})):(e.style.removeProperty("flex-direction"),e.textContent=t.markLines[0]??""))}function Mn(e){const t=document.createElement("span");return Je(t,e),t}function Tn(e,t){const n=e.querySelector(We);if(n instanceof HTMLSpanElement)return e.dataset.nhnkcpAdminPaymentMethod=t.id,Je(n,t),!0;const r=Mn(t),a=In(e);if(a&&a.parentElement)return e.dataset.nhnkcpAdminPaymentMethod=t.id,a.replaceWith(r),!0;const o=Ve(e);return o&&o.parentElement?(e.dataset.nhnkcpAdminPaymentMethod=t.id,o.parentElement.insertBefore(r,o),!0):!1}function ne(e=document){if(typeof window>"u"||typeof document>"u"||!te())return!1;let t=!1;return Kn(e).forEach(n=>{const r=Sn(n);r&&Tn(n,r)&&(t=!0)}),t}function $n(){ee||(ee=!0,window.setTimeout(()=>{ee=!1,ne()},0))}function re(){O!==null&&(window.clearInterval(O),O=null)}function ae(){if(!te())return;re(),ne();let e=0;O=window.setInterval(()=>{e+=1,ne(),e>=Nn&&re()},Cn);const t=document.body;t[Ge]||(t[Ge]=!0,Ue=new MutationObserver(()=>$n()),Ue.observe(document.body,{childList:!0,subtree:!0,characterData:!0}))}function Qe(){if(te()){ae();return}re()}function Rn(){if(typeof window>"u"||typeof document>"u")return;const e=vn();if(e[Fe])return;e[Fe]=!0,console.info(`[${kn}] admin payment method brand sync installed`),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>ae()):ae();const t=history.pushState.bind(history);history.pushState=(...n)=>{t(...n),window.setTimeout(()=>Qe(),200)},window.addEventListener("popstate",()=>window.setTimeout(()=>Qe(),200))}const oe="sirsoft-pay_nhnkcp",Xe="__nhnkcpAdminPaymentDisplayInjectorInstalled",On=/^\/admin\/ecommerce\/orders\/([^/]+)$/;function Ln(){return localStorage.getItem("auth_token")}async function Hn(e){const t=Ln();if(!t)return null;try{const n=await fetch(`/api/plugins/${oe}/admin/orders/${e}/transaction-status`,{headers:{Authorization:`Bearer ${t}`,Accept:"application/json"}});if(!n.ok)return null;const r=await n.json();return("data"in r?r.data:r)??null}catch{return null}}function Bn(e){return Array.from(e.children).filter(t=>t instanceof HTMLElement)}function Dn(e,t){let n=!1;const r=Array.from(e.querySelectorAll("div"));for(const a of r){const o=Bn(a),i=o.findIndex(u=>u.textContent?.trim()==="결제수단");if(i<0)continue;const s=o.slice(i+1).find(u=>u.textContent?.trim()&&u.textContent.trim()!=="결제수단");if(!s)continue;const c=o.slice(i+2).find(u=>/^\(.+\)$/.test(u.textContent?.trim()??"")),d=c?.textContent?.trim().replace(/^\(|\)$/g,"")??"",l=d&&t.endsWith(")")?t.replace(/\)$/,`, ${d})`):t;s.textContent?.trim()!==l&&(s.textContent=l,s.dataset.nhnkcpPaymentMethodPatched="true"),a.dataset.nhnkcpPaymentMethodRow="admin-order",c&&d&&(c.textContent="",c.style.display="none",c.dataset.nhnkcpPaymentInstallmentHidden="true"),n=!0}return n}function jn(e,t,n){const a=Array.from(e.querySelectorAll("span")).filter(o=>o.textContent?.trim()===t).find(o=>{const i=typeof o.className=="string"?o.className:"";return i.includes("rounded-full")||i.includes("font-medium")});return a?(a.textContent=n,a.dataset.nhnkcpPaymentMethodPatched="true",a.dataset.nhnkcpPaymentMethodBadge="admin-order",!0):!1}function Yn(e,t){const n=t?._pay_method_label,r=t?._embedded_pg_provider_label,a=t?._base_pay_method_label;if(!n||!r)return!1;const o=Dn(e,n),i=a?jn(e,a,r):!1;return o||i}async function qn(e){const t=document.getElementById("section_payment_info")??document.getElementById("payment_info_card");if(!t)return!1;const n=await Hn(e);return n&&Yn(t,n)&&console.info(`[${oe}] payment method display patched on admin order detail`),!0}function Fn(e){let t=0;const n=setInterval(()=>{t++,qn(e).then(r=>{(r||t>=30)&&clearInterval(n)})},400)}function Gn(){const e=location.pathname.match(On);e&&Fn(e[1])}function Wn(){if(typeof window>"u")return;const e=window;if(e[Xe])return;e[Xe]=!0,console.info(`[${oe}] admin order payment display injector installed`);const t=(r=1500)=>setTimeout(Gn,r);document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>t()):t();const n=history.pushState.bind(history);history.pushState=(...r)=>{n(...r),t(600)},window.addEventListener("popstate",()=>t(500))}class Un{constructor(t){const n="width=800,height=600,scrollbars=yes,resizable=yes,toolbar=no,menubar=no";t.url&&window.open(t.url,"kcp_receipt",n),t.cash_url&&window.open(t.cash_url,"kcp_cash_receipt",n)}}window.KcpReceiptPopup=Un;const N="sirsoft-pay_nhnkcp",ie={info:(...e)=>console.info(`[${N}]`,...e),warn:(...e)=>console.warn(`[${N}]`,...e),error:(...e)=>console.error(`[${N}]`,...e)};function Ze(){const e=window.G7Core;if(!e)return 0;const t=e.getActionDispatcher;if(typeof t!="function")return 0;const n=t();if(!n||typeof n.registerHandler!="function")return 0;let r=0;for(const[a,o]of Object.entries(me)){const i=`${N}.${a}`;n.registerHandler(i,o,{category:"plugin",source:N}),r++}return r}function et(){const e=()=>{const t=Ze();if(t>0){ie.info(`${t} handler(s) registered`);return}let n=0;const r=50,a=setInterval(()=>{n++;const o=Ze();if(o>0){clearInterval(a),ie.info(`${o} handler(s) registered (after ${n} retries)`);return}n>=r&&(clearInterval(a),ie.warn("ActionDispatcher not available after timeout"))},100)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e):e()}It(),Lt(),Wt(),un(),Pn(),Rn(),Wn(),et(),window.__SirsoftNhnkcp={identifier:N,handlers:Object.keys(me),initPlugin:et}})();
|