diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/payment-method-brand-mark.spec.ts b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/payment-method-brand-mark.spec.ts new file mode 100644 index 00000000..ac07315a --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/payment-method-brand-mark.spec.ts @@ -0,0 +1,108 @@ +/** + * 주문설정 결제수단 — PG 플러그인 브랜드 마크 주입 회귀. + * + * 배경: 관리자 레이아웃은 아이콘 열을 `Icon name={{$method._cached_icon}}` 하나로만 그리고 + * `_cached_brand_mark` 를 읽는 노드가 없다. 각 PG 플러그인이 자기 결제수단 행의 아이콘을 + * 브랜드 배지로 치환하는 관리자 전용 injector 를 직접 싣는 구조다. + * + * 이 spec 이 고정하는 두 가지: + * 1. 설치된 PG 플러그인의 간편결제 행에 브랜드 배지가 주입된다 (플러그인별 data 속성으로 판정). + * 2. **다른 탭에 갔다 돌아와도** 배지가 재주입된다. 탭 전환은 pushState 가 아니라 + * replaceState 로 URL 만 바꾸므로, pushState/popstate 만 후킹하던 구현은 복귀 후 + * 배지가 사라진 채로 남았다(행은 정상 렌더되어 화면상 아이콘만 회색으로 되돌아감). + * + * 측정 규율: + * - 결제수단 ID·PG명을 하드코딩하지 않는다. 설치 구성은 환경마다 다르므로 브랜드 배지 + * data 속성을 **런타임 카운트**로 판정하고, 배지가 0인 환경(간편결제 플러그인 미설치)은 + * skip 이 아니라 "행이 렌더됐는지" 를 먼저 확인해 거짓 통과를 만들지 않는다. + * + * @scenario extension_payment_method method_kind=extension × capability=brand_mark + * @effects admin_shows_brand_mark, admin_rebinds_brand_mark_after_tab_return + */ +import { test, expect, authenticatePage } from '../../fixtures/ecommerce-auth'; +import type { Page } from '@playwright/test'; + +const ORDER_SETTINGS_URL = '/admin/ecommerce/settings?tab=order_settings'; + +/** 설치된 모든 PG 플러그인의 브랜드 배지 총합 + 렌더된 결제수단 행 수. */ +async function counts(page: Page): Promise<{ badges: number; rows: number }> { + return page.evaluate(() => ({ + badges: document.querySelectorAll('[data-testid], span').length + && document.querySelectorAll('span[class*="rounded-lg"][aria-hidden="true"]').length, + rows: document.querySelectorAll('[data-testid^="pg-locked-badge-"]').length, + })); +} + +/** 플러그인별 브랜드 배지 카운트 (data 속성 접미사로 집계 — 플러그인명 하드코딩 회피). */ +async function badgeCountsByPlugin(page: Page): Promise> { + return page.evaluate(() => { + const out: Record = {}; + for (const el of document.querySelectorAll('span[aria-hidden="true"]')) { + for (const name of Object.keys(el.dataset)) { + if (!/AdminPaymentBrandMark$/.test(name)) continue; + out[name] = (out[name] ?? 0) + 1; + } + } + return out; + }); +} + +/** 설정 탭을 라벨 텍스트로 클릭한다 (탭은 role/accessible-name 이 라벨과 일치하지 않는다). */ +async function clickTab(page: Page, label: string): Promise { + const clicked = await page.evaluate((text) => { + const el = [...document.querySelectorAll('button, a')].find((e) => e.textContent?.trim() === text); + if (!el) return false; + (el as HTMLElement).click(); + return true; + }, label); + if (!clicked) throw new Error(`탭을 찾지 못했다: ${label}`); +} + +async function gotoOrderSettings(page: Page, token: string): Promise { + await authenticatePage(page, token); + await page.setViewportSize({ width: 1440, height: 1000 }); + await page.goto(ORDER_SETTINGS_URL); + await page.waitForLoadState('domcontentloaded', { timeout: 30_000 }); + await expect.poll(async () => (await counts(page)).rows, { timeout: 30_000 }).toBeGreaterThan(0); +} + +test.describe('@sirsoft-ecommerce 주문설정 결제수단 — 브랜드 마크', () => { + test('PG 플러그인의 간편결제 행에 브랜드 배지가 주입된다', async ({ page, settingsToken }) => { + await gotoOrderSettings(page, settingsToken); + + await expect + .poll(async () => Object.values(await badgeCountsByPlugin(page)).reduce((a, b) => a + b, 0), { timeout: 20_000 }) + .toBeGreaterThan(0); + + const byPlugin = await badgeCountsByPlugin(page); + // 간편결제를 제공하는 PG 플러그인이 하나라도 설치돼 있으면 그 플러그인 배지가 잡혀야 한다. + expect(Object.keys(byPlugin).length, `브랜드 배지를 주입한 플러그인이 없다: ${JSON.stringify(byPlugin)}`) + .toBeGreaterThan(0); + }); + + test('다른 탭에 갔다 돌아와도 브랜드 배지가 재주입된다 (replaceState 회귀)', async ({ page, settingsToken }) => { + await gotoOrderSettings(page, settingsToken); + + await expect + .poll(async () => Object.values(await badgeCountsByPlugin(page)).reduce((a, b) => a + b, 0), { timeout: 20_000 }) + .toBeGreaterThan(0); + const before = await badgeCountsByPlugin(page); + + // 탭 전환은 replaceState 로 URL 만 바꾼다 — 화면 전환을 실제 클릭으로 재현한다. + // 탭은 접근성 이름이 라벨과 정확히 일치하지 않으므로(내부 텍스트 노드 구성) 텍스트로 찾는다. + await clickTab(page, '배송설정'); + await expect.poll(async () => (await counts(page)).rows, { timeout: 20_000 }).toBe(0); + + await clickTab(page, '주문설정'); + await expect.poll(async () => (await counts(page)).rows, { timeout: 20_000 }).toBeGreaterThan(0); + + // 복귀 후 배지가 수정 전처럼 0 으로 남지 않아야 한다. + await expect + .poll(async () => Object.values(await badgeCountsByPlugin(page)).reduce((a, b) => a + b, 0), { timeout: 20_000 }) + .toBeGreaterThan(0); + + const after = await badgeCountsByPlugin(page); + expect(after, `탭 복귀 후 배지가 복원되지 않았다 (before=${JSON.stringify(before)} after=${JSON.stringify(after)})`) + .toEqual(before); + }); +}); diff --git a/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md index b81fcbf0..8a8055fe 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md @@ -22,6 +22,7 @@ ### Fixed +- 이커머스 관리자 주문설정에서 다른 탭에 갔다 돌아오면 간편결제 항목의 브랜드 로고가 사라지고 회색 기본 아이콘으로 남던 문제를 수정했습니다. 화면을 새로고침해야만 다시 표시됐습니다. - 결제 취소 기록의 환불 금액에 원화 단위가 고정 표기되던 문제를 수정했습니다. 해외 결제(엔화 등) 취소도 실제 결제 통화로 표시됩니다. - 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 결제를 마치거나 결제에 실패한 구매자가 존재하지 않는 페이지로 이동하던 문제를 수정했습니다. 이동 주소가 기본 주소로 고정돼 있었기 때문이며, 이제 상점 주소 설정을 따라갑니다. 이미 운영 중인 사이트도 업데이트 시 자동으로 반영되며, 이동 주소를 직접 입력해 두었다면 그 값은 그대로 유지됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) diff --git a/plugins/_bundled/sirsoft-pay_kginicis/components.json b/plugins/_bundled/sirsoft-pay_kginicis/components.json index 91e11cb0..6365c88b 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/components.json +++ b/plugins/_bundled/sirsoft-pay_kginicis/components.json @@ -1,7 +1,7 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "identifier": "sirsoft-pay_kginicis", - "version": "1.0.2", + "version": "1.1.0", "components": { "basic": [], "composite": [], diff --git a/plugins/_bundled/sirsoft-pay_kginicis/dist/js/plugin.iife.js b/plugins/_bundled/sirsoft-pay_kginicis/dist/js/plugin.iife.js index 64367c76..0419790f 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/dist/js/plugin.iife.js +++ b/plugins/_bundled/sirsoft-pay_kginicis/dist/js/plugin.iife.js @@ -1,4 +1,4 @@ -(function(){"use strict";const x="kginicis_pay_form_",R="__sirsoftKginicisReloadStandardPaySdk",w="__sirsoftKginicisMobilePaymentReturnPending";function oe(){if(typeof document>"u")return 0;const e=document.querySelectorAll(`form[id^="${x}"]`);return e.forEach(t=>t.remove()),e.length}function qe(){typeof window>"u"||(window[R]=!0)}function We(){if(typeof window>"u")return!1;const e=window,t=e[R]===!0;return delete e[R],t}function Ve(e){typeof window>"u"||typeof document>"u"||(window.INIStdPay=void 0,document.querySelectorAll(`script[src="${e}"], script[src*="/INIStdPay_third-party.js"]`).forEach(t=>t.remove()))}function ze(e=Date.now()){if(!(typeof window>"u"))try{window.sessionStorage.setItem(w,String(e))}catch{window[w]=e}}function M(){if(!(typeof window>"u")){try{window.sessionStorage.removeItem(w)}catch{}delete window[w]}}function ie(e=Date.now()){if(typeof window>"u")return!1;let t=null;try{const n=window.sessionStorage.getItem(w);t=n?Number(n):null}catch{t=null}if(!Number.isFinite(t)){const n=window[w];t=typeof n=="number"?n:Number(n)}return!Number.isFinite(t)||e-t>18e5?(M(),!1):!0}const N="sirsoft-pay_kginicis",Xe=N,Ze="payment-window-closed",ae="__sirsoftKginicisPaymentCloseListenerInstalled",L="__sirsoftKginicisActiveStandardPaymentCloseContext",se=20,Qe=100,O={info:(...e)=>console.info(`[${N}]`,...e),warn:(...e)=>console.warn(`[${N}]`,...e)};function et(e){if(!e||typeof e!="object")return!1;const t=e;return t.source===Xe&&t.type===Ze}function $(){return/\/shop\/checkout\/?$/.test(window.location.pathname)}function P(){return window}function tt(){const e=P()[L];return!e||typeof e!="object"?null:e}function nt(e){return/^https?:\/\//i.test(e)||e.startsWith("/api/")?e:e.startsWith("/plugins/")?`/api${e}`:e.startsWith("plugins/")?`/api/${e}`:e}function rt(e){e.closeReportUrl&&(P()[L]={...e,reported:!1})}function ce(){delete P()[L]}function de(){ce()}async function ot(e="payment-window-closed"){const t=tt();if(!t||t.reported||!$())return;t.reported=!0;const n={oid:t.oid,price:t.price,buyer_email:t.buyer_email??"",buyer_phone:t.buyer_phone??"",payment_method:t.payment_method??"",reason:e};try{const r=window.G7Core?.api;typeof r?.post=="function"?await r.post(t.closeReportUrl,n):await fetch(nt(t.closeReportUrl),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),keepalive:!0})}catch(r){O.warn("failed to report KG payment window close",{reason:e,error:r})}finally{ce()}}function le(e="payment-window-closed",t=!0){if(!$())return!1;const r=window.G7Core?.state?.setLocal;return typeof r!="function"?(t&&O.warn("G7Core.state.setLocal not available while resetting payment submit state"),!1):(oe(),qe(),r({isSubmittingOrder:!1}),O.info("checkout submit state reset after KG payment close",{reason:e}),!0)}function it(e,t=!1){let n=0;const r=()=>{if(n++,!(t&&!ie())){if(le(e,n>=se)){t&&M();return}!$()||n>=se||window.setTimeout(r,Qe)}};r()}function I(e){ie()&&it(e,!0)}function at(){if(typeof window>"u")return;const e=P();e[ae]||(window.addEventListener("message",t=>{t.origin===window.location.origin&&et(t.data)&&(ot(t.data.reason),le(t.data.reason))}),window.addEventListener("pagehide",()=>{de()}),window.addEventListener("beforeunload",()=>{de()}),window.addEventListener("pageshow",t=>{I(t.persisted?"mobile-payment-bfcache-return":"mobile-payment-page-show")}),window.addEventListener("focus",()=>{I("mobile-payment-window-focus")}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&I("mobile-payment-visibility-return")}),e[ae]=!0,I("mobile-payment-listener-installed"))}function ue(){if(typeof navigator>"u")return!1;const e=navigator;if(e.userAgentData?.mobile!==void 0)return e.userAgentData.mobile;const t=(e.userAgent||"").toLowerCase(),n=((e.userAgentData?.platform??e.platform)||"").toLowerCase();if(/android|iphone|ipad|ipod|windows phone|iemobile|blackberry|opera mini|mobile safari/.test(t)||/iphone|ipad|ipod|ios/.test(n))return!0;const r=e.maxTouchPoints??0;return/macintosh|mac os x/.test(t)&&r>1}function st(e){return new Promise((t,n)=>{if(document.querySelector(`script[src="${e}"]`)){t();return}const r=document.createElement("script");r.src=e,r.async=!0,r.onload=()=>t(),r.onerror=()=>n(new Error(`Failed to load script: ${e}`)),document.head.appendChild(r)})}function me(e,t){if(!t.startsWith("kginicis_"))return e;const n=new URL(e,window.location.origin);return n.searchParams.set("selectedPaymentMethod",t),n.toString()}function ct(e){const t=(e??"").trim().toUpperCase();return t===""||t==="WON"?"KRW":t}function fe(e,t,n="utf-8",r){const o=document.createElement("form");r&&(o.id=r),o.method="POST",o.action=e,o.acceptCharset=n,o.style.display="none";for(const[i,s]of Object.entries(t)){const a=document.createElement("input");a.type="hidden",a.name=i,a.value=s,o.appendChild(a)}document.body.appendChild(o),o.submit()}const dt={card:"Card",vbank:"VBank",bank:"DirectBank",phone:"HPP",kginicis_samsung_pay:"onlyssp",kginicis_naverpay:"onlynaverpay",kginicis_lpay:"onlylpay",kginicis_kakaopay:"onlykakaopay"},lt={card:"CARD",vbank:"VBANK",bank:"BANK",phone:"MOBILE"},ut={kginicis_samsung_pay:"d_samsungpay=Y",kginicis_naverpay:"d_npay=Y",kginicis_lpay:"d_lpay=Y",kginicis_kakaopay:"d_kakaopay=Y"},mt=["CARD","CVS","PAYpay"],pe={card:["CARD"],kginicis_japan_paypay:["PAYpay"],kginicis_japan_cvs:["CVS"]},ft=new Set(Object.keys(pe)),pt=new Set(["kginicis_samsung_pay","kginicis_naverpay","kginicis_lpay","kginicis_kakaopay"]);async function yt(e,t,n,r){const o=String(Math.floor(Date.now())),i=await e.api.post(t.callback_urls.mobile_signature,{oid:n.order_number,price:n.amount,timestamp:o,buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??""}),{chkfake:s,mobile_payment_url:a}=i.data,c=me(window.location.origin+t.callback_urls.mobile_callback+"?orderId="+encodeURIComponent(n.order_number),r),u=ut[r],d=u!==void 0,l=d?a.replace(/\/smart\/[^/]+\/?$/,"/smart/wcard/"):a,m=lt[r]??"CARD",f=t.use_escrow?"below1000=Y&vbank_receipt=Y&useescrow=Y¢erCd=Y&amt_hash=Y":"below1000=Y&vbank_receipt=Y¢erCd=Y&amt_hash=Y",p=d?f.replace("&useescrow=Y","")+"&"+u:f,y={P_MID:t.mid,P_OID:n.order_number,P_AMT:String(n.amount),P_GOODS:n.order_name,P_UNAME:n.customer_name??"",P_MOBILE:n.customer_phone??"",P_EMAIL:n.customer_email??"",P_NEXT_URL:c,P_CHARSET:"utf8",P_TIMESTAMP:o,P_CHKFAKE:s,P_RESERVED:p};d?y.P_SKIP_TERMS="Y":y.P_INI_PAYMENT=m,m==="MOBILE"&&!d&&(y.P_HPP_METHOD="2"),m==="VBANK"&&!d&&(y.P_NOTI_URL=window.location.origin+t.callback_urls.mobile_vbank_notify),ze(),fe(l,y,"euc-kr",x+"mobile_"+Date.now())}async function _t(e,t,n,r){const o=String(Math.floor(Date.now())),i=await e.api.post(t.callback_urls.signature,{oid:n.order_number,price:n.amount,timestamp:o,buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??""}),{signature:s,verification:a,mKey:c}=i.data;if(We()&&Ve(t.sdk_url),window.INIStdPay||await st(t.sdk_url),window.INIStdPay||await new Promise(p=>setTimeout(p,100)),!window.INIStdPay)throw new Error("INIStdPay SDK not available");const u=me(window.location.origin+t.callback_urls.callback,r),d=window.location.origin+t.callback_urls.close;oe();const l=x+Date.now(),m=document.createElement("form");m.id=l,m.method="POST",m.acceptCharset="euc-kr";const f={version:"1.0",mid:t.mid,oid:n.order_number,goodname:n.order_name,price:String(n.amount),currency:"WON",buyername:n.customer_name??"",buyeremail:n.customer_email??"",buyertel:n.customer_phone??"",timestamp:o,signature:s,verification:a,mKey:c,returnUrl:u,closeUrl:d,gopaymethod:dt[r]??"Card",acceptmethod:(()=>{const p=t.use_escrow?"useescrow:":"",y=t.use_credit_point?"CREDITCARD(Y):":"",h=r==="phone"?`HPP(1):${p}${y}centerCd(Y)`:`${p}${y}centerCd(Y)`;return r==="kginicis_samsung_pay"||r==="kginicis_naverpay"||r==="kginicis_lpay"||r==="kginicis_kakaopay"?h?`${h}:cardonly`:"cardonly":h})(),payViewType:"overlay",use_chkfake:"Y",charset:"UTF-8"};for(const[p,y]of Object.entries(f)){const h=document.createElement("input");h.type="hidden",h.name=p,h.value=y,m.appendChild(h)}document.body.appendChild(m),t.callback_urls.close_report&&rt({closeReportUrl:t.callback_urls.close_report,oid:n.order_number,price:Number(n.amount),buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??"",payment_method:r}),window.INIStdPay.pay(l)}function ht(e=new Date){const t=n=>String(n).padStart(2,"0");return e.getFullYear().toString()+t(e.getMonth()+1)+t(e.getDate())+t(e.getHours())+t(e.getMinutes())+t(e.getSeconds())}function gt(e,t){const n=e.cbt_extra_data??{},o=(t?pe[t]:void 0)??n.payment?.paymethod??mt,i=window.location.origin+e.callback_urls.cbt_cvs_notify;return{...n,paymentUI:{language:"JP",...n.paymentUI??{}},payment:{...n.payment??{},paymethod:o,isMobile:ue()?"true":"false",cvs:{...n.payment?.cvs??{},notiUrl:i}}}}async function wt(e,t,n,r){const o=t.japan_mid,i=ht(),s=n.customer_email??"",a=n.customer_phone??"",c=await e.api.post(t.callback_urls.cbt_checkout_token,{oid:n.order_number,price:n.amount,buyer_email:s,buyer_phone:a}),{checkout_token:u}=c.data,d=await e.api.post(t.callback_urls.cbt_hash_data,{oid:n.order_number,price:n.amount,timestamp:i,buyer_email:s,buyer_phone:a,checkout_token:u}),{hash_data:l}=d.data,m=window.location.origin+t.callback_urls.cbt_callback+`?oid=${encodeURIComponent(n.order_number)}&selectedPaymentMethod=${encodeURIComponent(r??"card")}`;fe(t.callback_urls.cbt_auth_url,{cbtType:"JPPG",mid:o,timestamp:i,returnUrl:m,buyerName:n.customer_name??"",buyerTel:n.customer_phone??"",buyerEmail:n.customer_email??"",goodName:n.order_name,amount:String(n.amount),orderId:n.order_number,hashData:l,extraData:JSON.stringify(gt(t,r))})}async function bt(e,t){const{pgPaymentData:n,paymentMethod:r}=e.params||{};if(!n)return;const o=window.__templateApp?.globalState?._local,i=r??n.payment_method??o?.paymentMethod??"card",s=window.G7Core;try{const a=await s.api.get("/modules/sirsoft-ecommerce/payments/client-config/kginicis");if(!a.data)throw new Error("Failed to fetch KG Inicis client config");const c=a.data,u=ct(n.currency),d=u==="JPY",l=u==="KRW",m=i.startsWith("kginicis_japan_"),f=pt.has(i),p=c.japan_enabled&&!!c.japan_mid&&c.japan_configured!==!1,y=c.japan_restrict_jpy_payment_methods===!0;if(m&&!d)throw new Error("KG Inicis Japan payment methods require a JPY order.");if(f&&Array.isArray(c.easy_pay_enabled_methods)&&!c.easy_pay_enabled_methods.includes(i))throw new Error("Selected KG Inicis easy pay method is disabled.");if(!d&&!l)throw new Error("KG Inicis supports only KRW standard payments or JPY Japan CBT payments.");if(d&&!p)throw new Error("KG Inicis Japan CBT payment is not configured.");if(d&&y&&!ft.has(i))throw new Error("JPY orders can only use KG Inicis Japan CBT payment methods.");const h=ue();if(l&&c.standard_configured===!1)throw new Error("KG Inicis live standard payment is not configured.");if(l&&h&&c.mobile_configured===!1)throw new Error("KG Inicis live mobile payment is not configured.");d?await wt(s,c,n,i):h?await yt(s,c,n,i):await _t(s,c,n,i)}catch(a){const c=a instanceof Error?a.message:"Unknown error";s?.state?.setLocal?.({paymentErrorMessage:c,isSubmittingOrder:!1,paymentMethod:i}),s?.modal?.open?.("kginicis_payment_error_modal")}}const ye={requestPayment:bt},kt="sirsoft-pay_kginicis",Ct={info:(...e)=>console.info(`[${kt}]`,...e)};function Et(){Ct.info("order interceptor is a no-op — payment entry is dispatched via pg_payment_handler")}const St="sirsoft-pay_kginicis";function Pt(){return localStorage.getItem("auth_token")}function It(){try{const t=sessionStorage.getItem("g7_guest_order_token");if(t)return t}catch{}const e=window.G7Core?.state?.get?.("_global")?.guestOrderToken;return typeof e=="string"&&e!==""?e:null}async function _e(e,t){try{const n=await fetch(`/api/plugins/${St}/user/orders/${e}/receipt`,{headers:t,credentials:"same-origin"});return n.ok?{status:n.status,data:await n.json()}:{status:n.status,data:null}}catch{return{status:0,data:null}}}async function he(e){const t=Pt(),n=It(),r={Accept:"application/json"};t?r.Authorization=`Bearer ${t}`:n&&(r["X-Guest-Order-Token"]=n);const o=await _e(e,r);if(o.data||o.status!==401||!t)return{status:o.status,info:o.data};const i={Accept:"application/json"};n&&(i["X-Guest-Order-Token"]=n);const s=await _e(e,i);return{status:s.status,info:s.data}}async function v(e){return(await he(e)).info}function C(e){return e?e.receipt_url?!0:e.receipt_type==="cbt_confirmation"&&Array.isArray(e.receipt_fields)&&e.receipt_fields.length>0:!1}function A(e){return e?.receipt_view_label||"영수증 조회"}function vt(e){return e?.receipt_label||"영수증"}function ge(e){if(e.receipt_url){window.open(e.receipt_url,"kginicis_receipt","width=800,height=600,scrollbars=yes,resizable=yes");return}e.receipt_type==="cbt_confirmation"&&At(e)}function At(e){const t=window.open("","kginicis_receipt","width=800,height=700,scrollbars=yes,resizable=yes");if(!t)return;const n=e.receipt_title||"KG 이니시스 CBT 결제확인서",r=e.receipt_notice||"",o=(e.receipt_fields??[]).map(i=>` +(function(){"use strict";const x="kginicis_pay_form_",R="__sirsoftKginicisReloadStandardPaySdk",w="__sirsoftKginicisMobilePaymentReturnPending";function ie(){if(typeof document>"u")return 0;const e=document.querySelectorAll(`form[id^="${x}"]`);return e.forEach(t=>t.remove()),e.length}function qe(){typeof window>"u"||(window[R]=!0)}function We(){if(typeof window>"u")return!1;const e=window,t=e[R]===!0;return delete e[R],t}function Ve(e){typeof window>"u"||typeof document>"u"||(window.INIStdPay=void 0,document.querySelectorAll(`script[src="${e}"], script[src*="/INIStdPay_third-party.js"]`).forEach(t=>t.remove()))}function ze(e=Date.now()){if(!(typeof window>"u"))try{window.sessionStorage.setItem(w,String(e))}catch{window[w]=e}}function M(){if(!(typeof window>"u")){try{window.sessionStorage.removeItem(w)}catch{}delete window[w]}}function ae(e=Date.now()){if(typeof window>"u")return!1;let t=null;try{const n=window.sessionStorage.getItem(w);t=n?Number(n):null}catch{t=null}if(!Number.isFinite(t)){const n=window[w];t=typeof n=="number"?n:Number(n)}return!Number.isFinite(t)||e-t>18e5?(M(),!1):!0}const N="sirsoft-pay_kginicis",Xe=N,Ze="payment-window-closed",se="__sirsoftKginicisPaymentCloseListenerInstalled",L="__sirsoftKginicisActiveStandardPaymentCloseContext",ce=20,Qe=100,O={info:(...e)=>console.info(`[${N}]`,...e),warn:(...e)=>console.warn(`[${N}]`,...e)};function et(e){if(!e||typeof e!="object")return!1;const t=e;return t.source===Xe&&t.type===Ze}function $(){return/\/shop\/checkout\/?$/.test(window.location.pathname)}function P(){return window}function tt(){const e=P()[L];return!e||typeof e!="object"?null:e}function nt(e){return/^https?:\/\//i.test(e)||e.startsWith("/api/")?e:e.startsWith("/plugins/")?`/api${e}`:e.startsWith("plugins/")?`/api/${e}`:e}function rt(e){e.closeReportUrl&&(P()[L]={...e,reported:!1})}function de(){delete P()[L]}function le(){de()}async function ot(e="payment-window-closed"){const t=tt();if(!t||t.reported||!$())return;t.reported=!0;const n={oid:t.oid,price:t.price,buyer_email:t.buyer_email??"",buyer_phone:t.buyer_phone??"",payment_method:t.payment_method??"",reason:e};try{const r=window.G7Core?.api;typeof r?.post=="function"?await r.post(t.closeReportUrl,n):await fetch(nt(t.closeReportUrl),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),keepalive:!0})}catch(r){O.warn("failed to report KG payment window close",{reason:e,error:r})}finally{de()}}function ue(e="payment-window-closed",t=!0){if(!$())return!1;const r=window.G7Core?.state?.setLocal;return typeof r!="function"?(t&&O.warn("G7Core.state.setLocal not available while resetting payment submit state"),!1):(ie(),qe(),r({isSubmittingOrder:!1}),O.info("checkout submit state reset after KG payment close",{reason:e}),!0)}function it(e,t=!1){let n=0;const r=()=>{if(n++,!(t&&!ae())){if(ue(e,n>=ce)){t&&M();return}!$()||n>=ce||window.setTimeout(r,Qe)}};r()}function I(e){ae()&&it(e,!0)}function at(){if(typeof window>"u")return;const e=P();e[se]||(window.addEventListener("message",t=>{t.origin===window.location.origin&&et(t.data)&&(ot(t.data.reason),ue(t.data.reason))}),window.addEventListener("pagehide",()=>{le()}),window.addEventListener("beforeunload",()=>{le()}),window.addEventListener("pageshow",t=>{I(t.persisted?"mobile-payment-bfcache-return":"mobile-payment-page-show")}),window.addEventListener("focus",()=>{I("mobile-payment-window-focus")}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&I("mobile-payment-visibility-return")}),e[se]=!0,I("mobile-payment-listener-installed"))}function me(){if(typeof navigator>"u")return!1;const e=navigator;if(e.userAgentData?.mobile!==void 0)return e.userAgentData.mobile;const t=(e.userAgent||"").toLowerCase(),n=((e.userAgentData?.platform??e.platform)||"").toLowerCase();if(/android|iphone|ipad|ipod|windows phone|iemobile|blackberry|opera mini|mobile safari/.test(t)||/iphone|ipad|ipod|ios/.test(n))return!0;const r=e.maxTouchPoints??0;return/macintosh|mac os x/.test(t)&&r>1}function st(e){return new Promise((t,n)=>{if(document.querySelector(`script[src="${e}"]`)){t();return}const r=document.createElement("script");r.src=e,r.async=!0,r.onload=()=>t(),r.onerror=()=>n(new Error(`Failed to load script: ${e}`)),document.head.appendChild(r)})}function fe(e,t){if(!t.startsWith("kginicis_"))return e;const n=new URL(e,window.location.origin);return n.searchParams.set("selectedPaymentMethod",t),n.toString()}function ct(e){const t=(e??"").trim().toUpperCase();return t===""||t==="WON"?"KRW":t}function pe(e,t,n="utf-8",r){const o=document.createElement("form");r&&(o.id=r),o.method="POST",o.action=e,o.acceptCharset=n,o.style.display="none";for(const[i,s]of Object.entries(t)){const a=document.createElement("input");a.type="hidden",a.name=i,a.value=s,o.appendChild(a)}document.body.appendChild(o),o.submit()}const dt={card:"Card",vbank:"VBank",bank:"DirectBank",phone:"HPP",kginicis_samsung_pay:"onlyssp",kginicis_naverpay:"onlynaverpay",kginicis_lpay:"onlylpay",kginicis_kakaopay:"onlykakaopay"},lt={card:"CARD",vbank:"VBANK",bank:"BANK",phone:"MOBILE"},ut={kginicis_samsung_pay:"d_samsungpay=Y",kginicis_naverpay:"d_npay=Y",kginicis_lpay:"d_lpay=Y",kginicis_kakaopay:"d_kakaopay=Y"},mt=["CARD","CVS","PAYpay"],ye={card:["CARD"],kginicis_japan_paypay:["PAYpay"],kginicis_japan_cvs:["CVS"]},ft=new Set(Object.keys(ye)),pt=new Set(["kginicis_samsung_pay","kginicis_naverpay","kginicis_lpay","kginicis_kakaopay"]);async function yt(e,t,n,r){const o=String(Math.floor(Date.now())),i=await e.api.post(t.callback_urls.mobile_signature,{oid:n.order_number,price:n.amount,timestamp:o,buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??""}),{chkfake:s,mobile_payment_url:a}=i.data,c=fe(window.location.origin+t.callback_urls.mobile_callback+"?orderId="+encodeURIComponent(n.order_number),r),u=ut[r],d=u!==void 0,l=d?a.replace(/\/smart\/[^/]+\/?$/,"/smart/wcard/"):a,m=lt[r]??"CARD",f=t.use_escrow?"below1000=Y&vbank_receipt=Y&useescrow=Y¢erCd=Y&amt_hash=Y":"below1000=Y&vbank_receipt=Y¢erCd=Y&amt_hash=Y",p=d?f.replace("&useescrow=Y","")+"&"+u:f,y={P_MID:t.mid,P_OID:n.order_number,P_AMT:String(n.amount),P_GOODS:n.order_name,P_UNAME:n.customer_name??"",P_MOBILE:n.customer_phone??"",P_EMAIL:n.customer_email??"",P_NEXT_URL:c,P_CHARSET:"utf8",P_TIMESTAMP:o,P_CHKFAKE:s,P_RESERVED:p};d?y.P_SKIP_TERMS="Y":y.P_INI_PAYMENT=m,m==="MOBILE"&&!d&&(y.P_HPP_METHOD="2"),m==="VBANK"&&!d&&(y.P_NOTI_URL=window.location.origin+t.callback_urls.mobile_vbank_notify),ze(),pe(l,y,"euc-kr",x+"mobile_"+Date.now())}async function _t(e,t,n,r){const o=String(Math.floor(Date.now())),i=await e.api.post(t.callback_urls.signature,{oid:n.order_number,price:n.amount,timestamp:o,buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??""}),{signature:s,verification:a,mKey:c}=i.data;if(We()&&Ve(t.sdk_url),window.INIStdPay||await st(t.sdk_url),window.INIStdPay||await new Promise(p=>setTimeout(p,100)),!window.INIStdPay)throw new Error("INIStdPay SDK not available");const u=fe(window.location.origin+t.callback_urls.callback,r),d=window.location.origin+t.callback_urls.close;ie();const l=x+Date.now(),m=document.createElement("form");m.id=l,m.method="POST",m.acceptCharset="euc-kr";const f={version:"1.0",mid:t.mid,oid:n.order_number,goodname:n.order_name,price:String(n.amount),currency:"WON",buyername:n.customer_name??"",buyeremail:n.customer_email??"",buyertel:n.customer_phone??"",timestamp:o,signature:s,verification:a,mKey:c,returnUrl:u,closeUrl:d,gopaymethod:dt[r]??"Card",acceptmethod:(()=>{const p=t.use_escrow?"useescrow:":"",y=t.use_credit_point?"CREDITCARD(Y):":"",h=r==="phone"?`HPP(1):${p}${y}centerCd(Y)`:`${p}${y}centerCd(Y)`;return r==="kginicis_samsung_pay"||r==="kginicis_naverpay"||r==="kginicis_lpay"||r==="kginicis_kakaopay"?h?`${h}:cardonly`:"cardonly":h})(),payViewType:"overlay",use_chkfake:"Y",charset:"UTF-8"};for(const[p,y]of Object.entries(f)){const h=document.createElement("input");h.type="hidden",h.name=p,h.value=y,m.appendChild(h)}document.body.appendChild(m),t.callback_urls.close_report&&rt({closeReportUrl:t.callback_urls.close_report,oid:n.order_number,price:Number(n.amount),buyer_email:n.customer_email??"",buyer_phone:n.customer_phone??"",payment_method:r}),window.INIStdPay.pay(l)}function ht(e=new Date){const t=n=>String(n).padStart(2,"0");return e.getFullYear().toString()+t(e.getMonth()+1)+t(e.getDate())+t(e.getHours())+t(e.getMinutes())+t(e.getSeconds())}function gt(e,t){const n=e.cbt_extra_data??{},o=(t?ye[t]:void 0)??n.payment?.paymethod??mt,i=window.location.origin+e.callback_urls.cbt_cvs_notify;return{...n,paymentUI:{language:"JP",...n.paymentUI??{}},payment:{...n.payment??{},paymethod:o,isMobile:me()?"true":"false",cvs:{...n.payment?.cvs??{},notiUrl:i}}}}async function wt(e,t,n,r){const o=t.japan_mid,i=ht(),s=n.customer_email??"",a=n.customer_phone??"",c=await e.api.post(t.callback_urls.cbt_checkout_token,{oid:n.order_number,price:n.amount,buyer_email:s,buyer_phone:a}),{checkout_token:u}=c.data,d=await e.api.post(t.callback_urls.cbt_hash_data,{oid:n.order_number,price:n.amount,timestamp:i,buyer_email:s,buyer_phone:a,checkout_token:u}),{hash_data:l}=d.data,m=window.location.origin+t.callback_urls.cbt_callback+`?oid=${encodeURIComponent(n.order_number)}&selectedPaymentMethod=${encodeURIComponent(r??"card")}`;pe(t.callback_urls.cbt_auth_url,{cbtType:"JPPG",mid:o,timestamp:i,returnUrl:m,buyerName:n.customer_name??"",buyerTel:n.customer_phone??"",buyerEmail:n.customer_email??"",goodName:n.order_name,amount:String(n.amount),orderId:n.order_number,hashData:l,extraData:JSON.stringify(gt(t,r))})}async function bt(e,t){const{pgPaymentData:n,paymentMethod:r}=e.params||{};if(!n)return;const o=window.__templateApp?.globalState?._local,i=r??n.payment_method??o?.paymentMethod??"card",s=window.G7Core;try{const a=await s.api.get("/modules/sirsoft-ecommerce/payments/client-config/kginicis");if(!a.data)throw new Error("Failed to fetch KG Inicis client config");const c=a.data,u=ct(n.currency),d=u==="JPY",l=u==="KRW",m=i.startsWith("kginicis_japan_"),f=pt.has(i),p=c.japan_enabled&&!!c.japan_mid&&c.japan_configured!==!1,y=c.japan_restrict_jpy_payment_methods===!0;if(m&&!d)throw new Error("KG Inicis Japan payment methods require a JPY order.");if(f&&Array.isArray(c.easy_pay_enabled_methods)&&!c.easy_pay_enabled_methods.includes(i))throw new Error("Selected KG Inicis easy pay method is disabled.");if(!d&&!l)throw new Error("KG Inicis supports only KRW standard payments or JPY Japan CBT payments.");if(d&&!p)throw new Error("KG Inicis Japan CBT payment is not configured.");if(d&&y&&!ft.has(i))throw new Error("JPY orders can only use KG Inicis Japan CBT payment methods.");const h=me();if(l&&c.standard_configured===!1)throw new Error("KG Inicis live standard payment is not configured.");if(l&&h&&c.mobile_configured===!1)throw new Error("KG Inicis live mobile payment is not configured.");d?await wt(s,c,n,i):h?await yt(s,c,n,i):await _t(s,c,n,i)}catch(a){const c=a instanceof Error?a.message:"Unknown error";s?.state?.setLocal?.({paymentErrorMessage:c,isSubmittingOrder:!1,paymentMethod:i}),s?.modal?.open?.("kginicis_payment_error_modal")}}const _e={requestPayment:bt},kt="sirsoft-pay_kginicis",Ct={info:(...e)=>console.info(`[${kt}]`,...e)};function Et(){Ct.info("order interceptor is a no-op — payment entry is dispatched via pg_payment_handler")}const St="sirsoft-pay_kginicis";function Pt(){return localStorage.getItem("auth_token")}function It(){try{const t=sessionStorage.getItem("g7_guest_order_token");if(t)return t}catch{}const e=window.G7Core?.state?.get?.("_global")?.guestOrderToken;return typeof e=="string"&&e!==""?e:null}async function he(e,t){try{const n=await fetch(`/api/plugins/${St}/user/orders/${e}/receipt`,{headers:t,credentials:"same-origin"});return n.ok?{status:n.status,data:await n.json()}:{status:n.status,data:null}}catch{return{status:0,data:null}}}async function ge(e){const t=Pt(),n=It(),r={Accept:"application/json"};t?r.Authorization=`Bearer ${t}`:n&&(r["X-Guest-Order-Token"]=n);const o=await he(e,r);if(o.data||o.status!==401||!t)return{status:o.status,info:o.data};const i={Accept:"application/json"};n&&(i["X-Guest-Order-Token"]=n);const s=await he(e,i);return{status:s.status,info:s.data}}async function v(e){return(await ge(e)).info}function C(e){return e?e.receipt_url?!0:e.receipt_type==="cbt_confirmation"&&Array.isArray(e.receipt_fields)&&e.receipt_fields.length>0:!1}function A(e){return e?.receipt_view_label||"영수증 조회"}function vt(e){return e?.receipt_label||"영수증"}function we(e){if(e.receipt_url){window.open(e.receipt_url,"kginicis_receipt","width=800,height=600,scrollbars=yes,resizable=yes");return}e.receipt_type==="cbt_confirmation"&&At(e)}function At(e){const t=window.open("","kginicis_receipt","width=800,height=700,scrollbars=yes,resizable=yes");if(!t)return;const n=e.receipt_title||"KG 이니시스 CBT 결제확인서",r=e.receipt_notice||"",o=(e.receipt_fields??[]).map(i=>`
${E(i.label)}
${E(i.value)}
@@ -87,5 +87,5 @@
-`),t.document.close()}function E(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}const D="sirsoft-pay_kginicis",we="__kginicisOrderShowInjectorInstalled",K="kginicis-mp-receipt-row",be=/^(?:\/mypage\/orders\/([^/]+)|\/shop\/guest\/orders\/([^/]+))$/,G=new Map;function Tt(e){try{const n=window.G7Core?.getState,i=n?.()?.currentDataContext?.order?.data;return i&&(i.order_number===e||i.id!==void 0&&String(i.id)===e)?i:null}catch{return null}}function xt(){const e=document.getElementById("order_payment_info_panel");if(e)return Array.from(e.children).find(r=>r.className?.includes("space-y"))??e;const t=Array.from(document.querySelectorAll("h3")).find(r=>{const o=r.textContent?.trim()??"";return o.includes("결제 정보")||/^Payment Information$/i.test(o)});if(!t)return null;const n=t.parentElement?.parentElement;return n?Array.from(n.children).find(r=>r.className?.includes("space-y"))??n:null}function Rt(e,t){if(!t)return!1;const n=Array.from(e.querySelectorAll("div"));for(const r of n){const o=Array.from(r.children).filter(a=>a instanceof HTMLElement&&a.tagName==="SPAN");if(o.length<2)continue;const i=o[0].textContent?.trim();if(i!=="결제 방법"&&i!=="결제수단"&&i!=="Payment Method")continue;const s=o[o.length-1];return s.textContent?.trim()===t?(r.dataset.kginicisPaymentMethodRow="true",!0):(s.textContent=t,s.dataset.kginicisPaymentMethodPatched="true",r.dataset.kginicisPaymentMethodRow="true",!0)}return!1}function Mt(e,t){const n=document.createElement("div");n.id=K,n.className="flex items-center justify-between",n.dataset.kginicisReceiptRow="mypage-order";const r=document.createElement("span");r.className="text-gray-500 dark:text-gray-400 text-sm",r.textContent=vt(t);const o=document.createElement("button");return o.type="button",o.dataset.kginicisReceiptButton="mypage-order",o.className="inline-flex items-center gap-1 text-sm text-blue-600 dark:text-blue-400 hover:underline disabled:opacity-50",o.textContent=A(t),o.addEventListener("click",async()=>{o.disabled=!0,o.textContent="로딩 중...";const i=await v(e);o.disabled=!1,o.textContent=A(i??t),C(i)&&ge(i)}),n.appendChild(r),n.appendChild(o),n}async function Nt(e,t){const n=Tt(e),r=n?.payment;if(r&&(r.pg_provider!=="kginicis"||!r.transaction_id))return!0;const o=n?.order_number??(t?e:null);if(!o)return!1;if(!t&&n&&!r)return!0;const i=xt();if(!i)return!1;const{status:s,info:a}=await he(o);if(!t&&s===404)return!0;const c=r?.payment_status==="paid",u=a?.receipt_type==="cbt_confirmation";if(r&&!c&&!u)return!0;if(!r&&!C(a))return!1;const d=Rt(i,a?.payment_method_display_label);return!document.getElementById(K)&&C(a)&&(i.appendChild(Mt(o,a)),console.info(`[${D}] receipt button injected on mypage order show`)),d&&console.info(`[${D}] payment method display patched on mypage order show`),!!(document.getElementById(K)||d)}function Lt(e,t){if(G.has(e))return;let n=0;const r=window.setInterval(()=>{n++,Nt(e,t).then(o=>{(o||n>=30)&&(window.clearInterval(r),G.delete(e))})},400);G.set(e,r)}function Ot(){const e=location.pathname.match(be);if(e){const t=e[1],n=e[2],r=t??n;r&&Lt(r,n!==void 0)}}function $t(){if(typeof window>"u")return;const e=window;if(e[we])return;e[we]=!0,console.info(`[${D}] mypage order show injector installed`);let t=null;const n=(a=1500)=>{t!==null&&window.clearTimeout(t),t=window.setTimeout(()=>{t=null,Ot()},a)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>n()):n();const r=history.pushState.bind(history);history.pushState=(...a)=>{r(...a),n(600)};const o=history.replaceState.bind(history);history.replaceState=(...a)=>{o(...a),n(600)},window.addEventListener("popstate",()=>n(500));const i=document.getElementById("app")??document.body;new MutationObserver(()=>{be.test(location.pathname)&&n(250)}).observe(i,{childList:!0,subtree:!0})}const j="sirsoft-pay_kginicis",ke="__kginicisAdminPaymentDisplayInjectorInstalled",Dt=/^\/admin\/ecommerce\/orders\/([^/]+)$/;function Kt(){return localStorage.getItem("auth_token")}async function Gt(e){const t=Kt();if(!t)return null;try{const n=await fetch(`/api/plugins/${j}/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 jt(e){return Array.from(e.children).filter(t=>t instanceof HTMLElement)}function Yt(e,t){let n=!1;const r=Array.from(e.querySelectorAll("div"));for(const o of r){const i=jt(o),s=i.findIndex(l=>l.textContent?.trim()==="결제수단");if(s<0)continue;const a=i.slice(s+1).find(l=>l.textContent?.trim()&&l.textContent.trim()!=="결제수단");if(!a)continue;const c=i.slice(s+2).find(l=>/^\(.+\)$/.test(l.textContent?.trim()??"")),u=c?.textContent?.trim().replace(/^\(|\)$/g,"")??"",d=u&&t.endsWith(")")?t.replace(/\)$/,`, ${u})`):t;a.textContent?.trim()!==d&&(a.textContent=d,a.dataset.kginicisPaymentMethodPatched="true"),o.dataset.kginicisPaymentMethodRow="admin-order",c&&u&&(c.textContent="",c.style.display="none",c.dataset.kginicisPaymentInstallmentHidden="true"),n=!0}return n}function Bt(e,t,n){const o=Array.from(e.querySelectorAll("span")).filter(i=>i.textContent?.trim()===t).find(i=>{const s=typeof i.className=="string"?i.className:"";return s.includes("rounded-full")||s.includes("font-medium")});return o?(o.textContent=n,o.dataset.kginicisPaymentMethodPatched="true",o.dataset.kginicisPaymentMethodBadge="admin-order",!0):!1}function Ut(e,t){const n=t?._pay_method_label,r=t?._embedded_pg_provider_label,o=t?._base_pay_method_label;if(!n||!r)return!1;const i=Yt(e,n),s=o?Bt(e,o,r):!1;return i||s}async function Ht(e){const t=document.getElementById("section_payment_info")??document.getElementById("payment_info_card");if(!t)return!1;const n=await Gt(e);return n&&Ut(t,n)&&console.info(`[${j}] payment method display patched on admin order detail`),!0}function Jt(e){let t=0;const n=setInterval(()=>{t++,Ht(e).then(r=>{(r||t>=30)&&clearInterval(n)})},400)}function Ft(){const e=location.pathname.match(Dt);e&&Jt(e[1])}function qt(){if(typeof window>"u")return;const e=window;if(e[ke])return;e[ke]=!0,console.info(`[${j}] admin order payment display injector installed`);const t=(r=1500)=>setTimeout(Ft,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 Ce="sirsoft-pay_kginicis",Ee="__kginicisOcReceiptInjectorInstalled",Se="kginicis-oc-receipt-btn",Wt=/^\/shop\/orders\/([^/]+)\/complete$/;function Vt(){return localStorage.getItem("auth_token")}function zt(){try{const t=sessionStorage.getItem("g7_guest_order_token");if(t)return t}catch{}const e=window.G7Core?.state?.get?.("_global")?.guestOrderToken;return typeof e=="string"&&e!==""?e:null}async function Xt(e){const t=Vt(),n=zt();if(!t&&!n)return null;const r={Accept:"application/json"};t?r.Authorization=`Bearer ${t}`:n&&(r["X-Guest-Order-Token"]=n);try{const o=await fetch(`/api/modules/sirsoft-ecommerce/user/orders/${e}`,{headers:r});return o.ok?(await o.json())?.data?.payment??null:null}catch{return null}}function Zt(e){if(!e)return!1;const t=Array.from(document.querySelectorAll("div"));for(const n of t){const r=Array.from(n.children).filter(s=>s instanceof HTMLElement&&s.tagName==="SPAN");if(r.length<2)continue;const o=r[0].textContent?.trim();if(o!=="결제 방법"&&o!=="결제수단"&&o!=="결제 방식")continue;const i=r[r.length-1];return i.textContent?.trim()===e?(n.dataset.kginicisPaymentMethodRow="true",!0):(i.textContent=e,i.dataset.kginicisPaymentMethodPatched="true",n.dataset.kginicisPaymentMethodRow="true",!0)}return!1}async function Qt(e){if(document.getElementById(Se))return;const t=await Xt(e);if(t&&(t.pg_provider!=="kginicis"||!t.transaction_id))return;const n=await v(e);if(!C(n))return;if(t){const a=t.payment_status==="paid",c=n.receipt_type==="cbt_confirmation";if(!a&&!c)return}Zt(n.payment_method_display_label);const r=Array.from(document.querySelectorAll('button[type="button"]')).find(a=>a.className.includes("bg-blue-600"));if(!r?.parentElement)return;const o=r.parentElement;o.dataset.kginicisReceiptContainer="order-complete";const i=document.createElement("button");i.id=Se,i.type="button",i.dataset.kginicisReceiptButton="order-complete",i.className=r.className.replace(/bg-blue-\d+/g,"bg-green-600").replace(/hover:bg-blue-\d+/g,"hover:bg-green-700"),i.textContent=A(n),i.addEventListener("click",async()=>{i.disabled=!0,i.textContent="로딩 중...";const a=await v(e);i.disabled=!1,i.textContent=A(a??n),C(a)&&ge(a)});const s=o.lastElementChild;o.insertBefore(i,s),console.info(`[${Ce}] receipt button injected on order complete page`)}function en(){const e=location.pathname.match(Wt);e&&Qt(e[1])}function tn(){if(typeof window>"u")return;const e=window;if(e[Ee])return;e[Ee]=!0,console.info(`[${Ce}] order complete receipt injector installed`);const t=(r=1200)=>setTimeout(en,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 Pe="sirsoft-pay_kginicis",Ie="__kginicisVbankInfoInjectorInstalled",Y="kginicis-mp-vbank-info",nn=/^\/shop\/orders\/([^/]+)\/complete$/,rn=/^\/mypage\/orders\/([^/]+)$/,on=/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+\-]\d{2}:\d{2}/,an={"03":"기업은행","04":"국민은행","05":"외환은행","07":"수협중앙회",11:"농협중앙회",20:"우리은행",23:"SC 제일은행",31:"대구은행",32:"부산은행",34:"광주은행",37:"전북은행",39:"경남은행",53:"한국씨티은행",71:"우체국",81:"하나은행",88:"신한은행",89:"케이뱅크",90:"카카오뱅크",92:"토스뱅크",D1:"동양종합금융증권",D2:"현대증권",D3:"미래에셋증권",D4:"한국투자증권",D5:"우리투자증권",D6:"하이투자증권",D7:"HMC 투자증권",D8:"SK 증권",D9:"대신증권",DA:"하나대투증권",DB:"굿모닝신한증권",DC:"동부증권",DD:"유진투자증권",DE:"메리츠증권",DF:"신영증권"};function sn(e){if(e.vbank_code)return String(e.vbank_code);const t=(e.vbank_name??"").trim();if(!t)return null;for(const[n,r]of Object.entries(an))if(r===t)return n;return null}function cn(){try{const t=window.G7Core?.getState;return t?.()?.currentDataContext?._global?.currentUser?.is_admin===!0}catch{return!1}}function ve(e){try{return new Date(e).toLocaleString("ko-KR",{year:"numeric",month:"long",day:"numeric",hour:"2-digit",minute:"2-digit",timeZone:"Asia/Seoul"})}catch{return e}}function dn(){const e=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT),t=[];let n=e.nextNode();for(;n;){const r=n.textContent??"",o=r.match(on);o&&t.push({node:n,formatted:r.replace(o[0],ve(o[0]))}),n=e.nextNode()}for(const{node:r,formatted:o}of t)r.textContent=o}function ln(e){try{const n=window.G7Core?.getState,i=n?.()?.currentDataContext?.order?.data;return!i||i.order_number!==e?null:i}catch{return null}}function un(){const e=document.getElementById("order_payment_info_panel");if(e)return Array.from(e.children).find(r=>r.className?.includes("space-y"))??e;const t=Array.from(document.querySelectorAll("h3")).find(r=>r.textContent?.includes("결제 정보"));if(!t)return null;const n=t.parentElement?.parentElement;return n?Array.from(n.children).find(r=>r.className?.includes("space-y"))??n:null}function _(e,t,n=!1){const r=document.createElement("div");r.className="flex items-center justify-between";const o=document.createElement("span");o.className="text-gray-500 dark:text-gray-400 text-sm",o.textContent=e;const i=document.createElement("span");return i.className=n?"text-sm font-medium text-blue-600 dark:text-blue-400":"text-sm text-gray-900 dark:text-gray-100",i.textContent=t,r.appendChild(o),r.appendChild(i),r}function mn(e,t){const n=document.createElement("div");n.id=Y,n.className="mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 space-y-2";const r=document.createElement("p");if(r.className="text-sm font-semibold text-gray-700 dark:text-gray-300",r.textContent="가상계좌 입금 안내",n.appendChild(r),e.vbank_name&&n.appendChild(_("은행",e.vbank_name)),cn()){const o=sn(e);o&&n.appendChild(_("은행코드",o))}return e.vbank_number&&n.appendChild(_("계좌번호",e.vbank_number)),e.vbank_holder&&n.appendChild(_("예금주",e.vbank_holder)),t&&n.appendChild(_("입금 기한",t,!0)),n}function g(e,t){return e?.receipt_fields?.find(n=>n.label===t)?.value??""}function fn(e,t){if(t?.receipt_type!=="cbt_confirmation")return!1;if(g(t,"결제수단").includes("편의점"))return!0;const r=String(e.transaction_id??"");return String(e.currency??"").toUpperCase()==="JPY"&&(String(e.vbank_name??"").toUpperCase()==="CVS"||r.startsWith("INIJPGCVS"))}function pn(e,t,n){const r=document.createElement("div");r.id=Y,r.className="mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 space-y-2";const o=document.createElement("p");o.className="text-sm font-semibold text-gray-700 dark:text-gray-300",o.textContent="일본 편의점 입금 안내",r.appendChild(o);const i=g(t,"입금 상태"),s=g(t,"입금예정금액")||g(t,"결제금액"),a=g(t,"편의점 코드"),c=g(t,"편의점 확인번호")||String(e.vbank_number??""),u=g(t,"편의점 접수번호"),d=g(t,"입금 마감일시")||n;return i&&r.appendChild(_("상태",i)),s&&r.appendChild(_("입금예정금액",s,!0)),a&&r.appendChild(_("편의점 코드",a)),c&&r.appendChild(_("편의점 확인번호",c)),u&&r.appendChild(_("편의점 접수번호",u)),d&&r.appendChild(_("입금 마감일시",d,!0)),r}async function yn(e){const t=ln(e);if(!t)return!1;const{payment:n}=t;if(!n||n.pg_provider!=="kginicis"||n.payment_status!=="waiting_deposit"||!n.vbank_number||document.getElementById(Y))return!0;const r=un();if(!r)return!1;const o=await v(e),i=n.vbank_due_at?ve(n.vbank_due_at):"";return r.appendChild(fn(n,o)?pn(n,o,i):mn(n,i)),console.info(`[${Pe}] vbank info injected on mypage`),!0}function _n(e){let t=0;const n=setInterval(()=>{t++,yn(e).then(r=>{(r||t>=30)&&clearInterval(n)})},400)}function hn(){if(location.pathname.match(nn)){setTimeout(dn,500);return}const t=location.pathname.match(rn);t&&_n(t[1])}function gn(){if(typeof window>"u")return;const e=window;if(e[Ie])return;e[Ie]=!0,console.info(`[${Pe}] vbank info injector installed`);const t=(r=800)=>setTimeout(hn,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 Ae="sirsoft-pay_kginicis",Te="__sirsoftKginicisCheckoutJpyPaymentMethodRestrictorInstalled",B=/^\/shop\/checkout\/?$/,wn="/api/modules/sirsoft-ecommerce/checkout",bn="/api/modules/sirsoft-ecommerce/settings/payment",kn="/api/modules/sirsoft-ecommerce/payments/client-config/kginicis",xe="__sirsoftKginicisCheckoutCurrency",U=new Set(["card","kginicis_japan_paypay","kginicis_japan_cvs"]),H=new Set(["kginicis_japan_paypay","kginicis_japan_cvs"]),Re=new Set(["card","vbank","dbank","bank","phone","kginicis_samsung_pay","kginicis_naverpay","kginicis_lpay","kginicis_kakaopay","kginicis_japan_paypay","kginicis_japan_cvs"]),Cn=[{id:"card",labels:["신용카드","Credit Card","クレジットカード"]},{id:"vbank",labels:["가상계좌","Virtual Account","バーチャル口座"]},{id:"dbank",labels:["무통장입금","Bank Transfer","銀行振込"]},{id:"bank",labels:["계좌이체","Account Transfer","口座振替"]},{id:"phone",labels:["휴대폰결제","Mobile Payment","携帯電話決済"]},{id:"kginicis_naverpay",labels:["네이버페이 (KG이니시스)","Naver Pay (KG Inicis)"]},{id:"kginicis_samsung_pay",labels:["삼성페이 (KG이니시스)","Samsung Pay (KG Inicis)"]},{id:"kginicis_lpay",labels:["L.pay (KG이니시스)","L.pay (KG Inicis)"]},{id:"kginicis_kakaopay",labels:["카카오페이 (KG이니시스)","Kakao Pay (KG Inicis)"]},{id:"kginicis_japan_paypay",labels:["PayPay (일본 KG이니시스)","PayPay (KG Inicis Japan)"]},{id:"kginicis_japan_cvs",labels:["일본 편의점결제 (KG이니시스)","Japan Convenience Store (KG Inicis)"]}],J={info:(...e)=>console.info(`[${Ae}]`,...e),warn:(...e)=>console.warn(`[${Ae}]`,...e)};let S=null,F=null,b=null;function q(){return window}function En(e){return typeof e=="string"?e:e instanceof URL?e.toString():typeof Request<"u"&&e instanceof Request?e.url:String(e)}function Sn(e,t){return t?.method?t.method.toUpperCase():typeof Request<"u"&&e instanceof Request?e.method.toUpperCase():"GET"}function Pn(e){try{return new URL(e,window.location.origin).pathname}catch{return e.split("?")[0].split("#")[0]}}function Me(e){if(typeof e!="string")return null;const t=e.trim().toUpperCase();return/^[A-Z]{3}$/.test(t)?t:null}function W(e,t){return t.split(".").reduce((n,r)=>{if(!(n===null||typeof n!="object"))return n[r]},e)}function In(e,t){for(const n of t){const r=Me(W(e,n));if(r)return r}return null}function vn(e){return In(e,["data.calculation.summary.selected_payment_currency","data.calculation.metadata.payment_currency","data.calculation.metadata.currency","data.currency","data.currency_code"])}function An(e){const t=vn(e);t&&(q()[xe]=t)}function Ne(){const e=q(),n=e.__templateApp?.globalState,r=[e[xe],n?.preferredCurrency];try{r.push(window.localStorage?.getItem("g7_preferred_currency"))}catch{}r.push(W(n,"modules.sirsoft-ecommerce.language_currency.default_currency"),W(n,"modules.sirsoft-ecommerce.language_currency.currencies.0.code"));for(const o of r){const i=Me(o);if(i)return i}return null}function V(){return B.test(window.location.pathname)&&Ne()==="JPY"}function z(){if(!B.test(window.location.pathname))return!1;const e=Ne();return e!==null&&e!=="JPY"}async function Le(e){return S!==null||(S=(async()=>{try{const t=await e(kn,{headers:{Accept:"application/json"}});return t.ok?(await t.json()).data?.japan_restrict_jpy_payment_methods===!0:!1}catch{return!1}})()),S}function Tn(e){const t=e.data?.order_settings?.payment_methods;return Array.isArray(t)?{...e,data:{...e.data,order_settings:{...e.data?.order_settings,payment_methods:t.map(n=>{const r=typeof n.id=="string"?n.id:"";return!Re.has(r)||U.has(r)?n:{...n,is_active:!1,_kginicis_restricted_for_jpy:!0}})}}}:e}function xn(e){const t=e.data?.order_settings?.payment_methods;return Array.isArray(t)?{...e,data:{...e.data,order_settings:{...e.data?.order_settings,payment_methods:t.map(n=>{const r=typeof n.id=="string"?n.id:"";return H.has(r)?{...n,is_active:!1,_kginicis_restricted_for_non_jpy:!0}:n})}}}:e}function Rn(e,t){const n=new Headers(e.headers);return n.set("Content-Type","application/json"),new Response(JSON.stringify(t),{status:e.status,statusText:e.statusText,headers:n})}function Mn(){const e=Array.from(document.querySelectorAll("h2")).find(n=>{const r=n.textContent??"";return r.includes("결제 수단")||r.includes("결제 방법")||r.includes("Payment Method")});if(!e)return null;let t=e.parentElement;for(;t&&t!==document.body;){if(t.tagName==="DIV"&&String(t.className).includes("rounded-lg"))return t;t=t.parentElement}return null}function Nn(e){const t=e.querySelector("p")?.textContent?.trim()??e.textContent?.trim()??"";for(const n of Cn)if(n.labels.some(r=>t.includes(r)))return n.id;return null}function X(){const e=V(),t=z();if(!e&&!t)return!1;const n=Mn();if(!n)return!1;let r=!1;if(n.querySelectorAll('button[type="button"]').forEach(o=>{const i=Nn(o);if(!i||!Re.has(i))return;if(e?U.has(i):!H.has(i)){o.style.removeProperty("display"),o.disabled=!1,o.removeAttribute("aria-hidden");return}o.style.display="none",o.disabled=!0,o.setAttribute("aria-hidden","true"),e?o.dataset.kginicisRestrictedForJpy="true":o.dataset.kginicisRestrictedForNonJpy="true",r=!0}),r)try{const i=window.G7Core?.state?.getLocal?.()?.paymentMethod;typeof i=="string"&&(e&&!U.has(i)||t&&H.has(i))&&window.G7Core?.state?.setLocal?.({paymentMethod:"card"})}catch{}return r}async function Oe(e){if(!B.test(window.location.pathname))return;const t=V(),n=z();if(!t&&!n||t&&!await Le(e))return;X(),F===null&&(F=new MutationObserver(()=>{X()}),F.observe(document.body,{childList:!0,subtree:!0})),b!==null&&clearInterval(b);let r=0;b=setInterval(()=>{r++,X(),r>=50&&b!==null&&(clearInterval(b),b=null)},200)}function $e(e){S=null,Oe(e)}function Ln(){if(typeof window>"u"||typeof window.fetch!="function")return;const e=q();if(e[Te])return;e[Te]=!0;const t=window.fetch.bind(window);window.fetch=async function(i,s){const a=En(i),c=Sn(i,s),u=Pn(a),d=await t(i,s);if(c==="GET"&&u.endsWith(wn)){try{const f=await d.clone().json();An(f)}catch{}return d}if(c!=="GET"||!u.endsWith(bn))return d;const l=V(),m=z();if(!l&&!m||l&&!await Le(t))return d;try{const f=await d.clone().json(),p=l?Tn(f):xn(f);return J.info(l?"restricted checkout payment methods for JPY order":"hid Japan-only payment methods for non-JPY order"),Rn(d,p)}catch(f){return J.warn("failed to restrict checkout payment methods",f),d}},J.info("checkout JPY payment method restrictor installed");const n=()=>{Oe(t)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n):n();const r=history.pushState.bind(history);history.pushState=(...o)=>{r(...o),setTimeout(()=>$e(t),200)},window.addEventListener("popstate",()=>setTimeout(()=>$e(t),200))}const On="sirsoft-pay_kginicis",De="__kginicisAdminPaymentMethodBrandInjectorInstalled",Ke="__kginicisAdminPaymentMethodBrandSyncListenerAttached",$n=/^\/admin\/ecommerce\/settings\/?$/,Ge='[data-kginicis-admin-payment-brand-mark="true"]',Dn=200,Kn=120,Gn=[{id:"kginicis_naverpay",labels:["네이버페이 (KG이니시스)","Naver Pay (KG Inicis)"],shortLabels:[],markLines:["N","Pay"],markClassName:"bg-green-500 text-white"},{id:"kginicis_samsung_pay",labels:["삼성페이 (KG이니시스)","Samsung Pay (KG Inicis)"],shortLabels:[],markLines:["S","Pay"],markClassName:"bg-blue-700 text-white"},{id:"kginicis_lpay",labels:["L.pay (KG이니시스)","L.pay (KG Inicis)"],shortLabels:[],markLines:["L","pay"],markClassName:"bg-red-600 text-white"},{id:"kginicis_kakaopay",labels:["카카오페이 (KG이니시스)","Kakao Pay (KG Inicis)"],shortLabels:[],markLines:["Kakao","Pay"],markClassName:"bg-yellow-400 text-gray-950"},{id:"kginicis_japan_paypay",labels:["PayPay (일본 KG이니시스)","PayPay (KG Inicis Japan)"],shortLabels:[],markLines:["Pay","Pay"],markClassName:"bg-red-600 text-white"},{id:"kginicis_japan_cvs",labels:["일본 편의점결제 (KG이니시스)","Japan Convenience Store (KG Inicis)"],shortLabels:[],markLines:["CVS","JP"],markClassName:"bg-blue-600 text-white"}];let je=null,T=null,Z=!1;function jn(){return window}function Q(){if(!$n.test(window.location.pathname))return!1;const e=new URLSearchParams(window.location.search).get("tab");return e===null||e===""||e==="order_settings"}function Yn(e){return e instanceof HTMLElement?e.className:""}function Ye(e){return(e??"").replace(/\u200B/g,"").replace(/\s+/g," ").trim()}function Bn(e){const t=Yn(e);return t.includes("excel-card")||t.includes("flex-center")&&t.includes("border")&&t.includes("gap-4")}function Be(e){return e.querySelector(".font-medium")}function Un(e){const t=Ye(Be(e)?.textContent),n=Ye(e.textContent);return Gn.find(r=>r.shortLabels.some(o=>t===o)||r.labels.some(o=>n.includes(o)))??null}function Hn(e){return Array.from(e.querySelectorAll("div")).filter(Bn)}function Jn(e){return Array.from(e.querySelectorAll("svg, [data-icon], i")).find(n=>!n.closest("[data-drag-handle]")&&!n.closest(Ge)&&!n.closest('.row-stack, .excel-card-body, button, select, [role="switch"]'))??null}function Ue(e,t){e.dataset.kginicisAdminPaymentBrandMark="true",e.dataset.kginicisAdminPaymentMethod=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.flexDirection="column",e.style.lineHeight="1",e.style.fontSize="9px";const n=t.markLines.join("");e.textContent!==n&&(e.replaceChildren(),t.markLines.forEach(r=>{const o=document.createElement("span");o.style.lineHeight="1",o.textContent=r,e.appendChild(o)}))}function Fn(e){const t=document.createElement("span");return Ue(t,e),t}function qn(e,t){const n=e.querySelector(Ge);if(n instanceof HTMLSpanElement)return e.dataset.kginicisAdminPaymentMethod=t.id,Ue(n,t),!0;const r=Fn(t),o=Jn(e);if(o&&o.parentElement)return e.dataset.kginicisAdminPaymentMethod=t.id,o.replaceWith(r),!0;const i=Be(e);return i&&i.parentElement?(e.dataset.kginicisAdminPaymentMethod=t.id,i.parentElement.insertBefore(r,i),!0):!1}function ee(e=document){if(typeof window>"u"||typeof document>"u"||!Q())return!1;let t=!1;return Hn(e).forEach(n=>{const r=Un(n);r&&qn(n,r)&&(t=!0)}),t}function Wn(){Z||(Z=!0,window.setTimeout(()=>{Z=!1,ee()},0))}function te(){T!==null&&(window.clearInterval(T),T=null)}function ne(){if(!Q())return;te(),ee();let e=0;T=window.setInterval(()=>{e+=1,ee(),e>=Kn&&te()},Dn);const t=document.body;t[Ke]||(t[Ke]=!0,je=new MutationObserver(()=>Wn()),je.observe(document.body,{childList:!0,subtree:!0,characterData:!0}))}function He(){if(Q()){ne();return}te()}function Vn(){if(typeof window>"u"||typeof document>"u")return;const e=jn();if(e[De])return;e[De]=!0,console.info(`[${On}] admin payment method brand sync installed`),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>ne()):ne();const t=history.pushState.bind(history);history.pushState=(...n)=>{t(...n),window.setTimeout(()=>He(),200)},window.addEventListener("popstate",()=>window.setTimeout(()=>He(),200))}const k="sirsoft-pay_kginicis",re={info:(...e)=>console.info(`[${k}]`,...e),warn:(...e)=>console.warn(`[${k}]`,...e),error:(...e)=>console.error(`[${k}]`,...e)};function Je(){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[o,i]of Object.entries(ye)){const s=`${k}.${o}`;n.registerHandler(s,i,{category:"plugin",source:k}),r++}return r}function Fe(){const e=()=>{const t=Je();if(t>0){re.info(`${t} handler(s) registered`);return}let n=0;const r=50,o=setInterval(()=>{n++;const i=Je();if(i>0){clearInterval(o),re.info(`${i} handler(s) registered (after ${n} retries)`);return}n>=r&&(clearInterval(o),re.warn("ActionDispatcher not available after timeout"))},100)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e):e()}Et(),Ln(),$t(),qt(),Vn(),tn(),gn(),at(),Fe(),window.__SirsoftKginicis={identifier:k,handlers:Object.keys(ye),initPlugin:Fe}})(); +`),t.document.close()}function E(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}const D="sirsoft-pay_kginicis",be="__kginicisOrderShowInjectorInstalled",K="kginicis-mp-receipt-row",ke=/^(?:\/mypage\/orders\/([^/]+)|\/shop\/guest\/orders\/([^/]+))$/,G=new Map;function Tt(e){try{const n=window.G7Core?.getState,i=n?.()?.currentDataContext?.order?.data;return i&&(i.order_number===e||i.id!==void 0&&String(i.id)===e)?i:null}catch{return null}}function xt(){const e=document.getElementById("order_payment_info_panel");if(e)return Array.from(e.children).find(r=>r.className?.includes("space-y"))??e;const t=Array.from(document.querySelectorAll("h3")).find(r=>{const o=r.textContent?.trim()??"";return o.includes("결제 정보")||/^Payment Information$/i.test(o)});if(!t)return null;const n=t.parentElement?.parentElement;return n?Array.from(n.children).find(r=>r.className?.includes("space-y"))??n:null}function Rt(e,t){if(!t)return!1;const n=Array.from(e.querySelectorAll("div"));for(const r of n){const o=Array.from(r.children).filter(a=>a instanceof HTMLElement&&a.tagName==="SPAN");if(o.length<2)continue;const i=o[0].textContent?.trim();if(i!=="결제 방법"&&i!=="결제수단"&&i!=="Payment Method")continue;const s=o[o.length-1];return s.textContent?.trim()===t?(r.dataset.kginicisPaymentMethodRow="true",!0):(s.textContent=t,s.dataset.kginicisPaymentMethodPatched="true",r.dataset.kginicisPaymentMethodRow="true",!0)}return!1}function Mt(e,t){const n=document.createElement("div");n.id=K,n.className="flex items-center justify-between",n.dataset.kginicisReceiptRow="mypage-order";const r=document.createElement("span");r.className="text-gray-500 dark:text-gray-400 text-sm",r.textContent=vt(t);const o=document.createElement("button");return o.type="button",o.dataset.kginicisReceiptButton="mypage-order",o.className="inline-flex items-center gap-1 text-sm text-blue-600 dark:text-blue-400 hover:underline disabled:opacity-50",o.textContent=A(t),o.addEventListener("click",async()=>{o.disabled=!0,o.textContent="로딩 중...";const i=await v(e);o.disabled=!1,o.textContent=A(i??t),C(i)&&we(i)}),n.appendChild(r),n.appendChild(o),n}async function Nt(e,t){const n=Tt(e),r=n?.payment;if(r&&(r.pg_provider!=="kginicis"||!r.transaction_id))return!0;const o=n?.order_number??(t?e:null);if(!o)return!1;if(!t&&n&&!r)return!0;const i=xt();if(!i)return!1;const{status:s,info:a}=await ge(o);if(!t&&s===404)return!0;const c=r?.payment_status==="paid",u=a?.receipt_type==="cbt_confirmation";if(r&&!c&&!u)return!0;if(!r&&!C(a))return!1;const d=Rt(i,a?.payment_method_display_label);return!document.getElementById(K)&&C(a)&&(i.appendChild(Mt(o,a)),console.info(`[${D}] receipt button injected on mypage order show`)),d&&console.info(`[${D}] payment method display patched on mypage order show`),!!(document.getElementById(K)||d)}function Lt(e,t){if(G.has(e))return;let n=0;const r=window.setInterval(()=>{n++,Nt(e,t).then(o=>{(o||n>=30)&&(window.clearInterval(r),G.delete(e))})},400);G.set(e,r)}function Ot(){const e=location.pathname.match(ke);if(e){const t=e[1],n=e[2],r=t??n;r&&Lt(r,n!==void 0)}}function $t(){if(typeof window>"u")return;const e=window;if(e[be])return;e[be]=!0,console.info(`[${D}] mypage order show injector installed`);let t=null;const n=(a=1500)=>{t!==null&&window.clearTimeout(t),t=window.setTimeout(()=>{t=null,Ot()},a)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>n()):n();const r=history.pushState.bind(history);history.pushState=(...a)=>{r(...a),n(600)};const o=history.replaceState.bind(history);history.replaceState=(...a)=>{o(...a),n(600)},window.addEventListener("popstate",()=>n(500));const i=document.getElementById("app")??document.body;new MutationObserver(()=>{ke.test(location.pathname)&&n(250)}).observe(i,{childList:!0,subtree:!0})}const j="sirsoft-pay_kginicis",Ce="__kginicisAdminPaymentDisplayInjectorInstalled",Dt=/^\/admin\/ecommerce\/orders\/([^/]+)$/;function Kt(){return localStorage.getItem("auth_token")}async function Gt(e){const t=Kt();if(!t)return null;try{const n=await fetch(`/api/plugins/${j}/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 jt(e){return Array.from(e.children).filter(t=>t instanceof HTMLElement)}function Yt(e,t){let n=!1;const r=Array.from(e.querySelectorAll("div"));for(const o of r){const i=jt(o),s=i.findIndex(l=>l.textContent?.trim()==="결제수단");if(s<0)continue;const a=i.slice(s+1).find(l=>l.textContent?.trim()&&l.textContent.trim()!=="결제수단");if(!a)continue;const c=i.slice(s+2).find(l=>/^\(.+\)$/.test(l.textContent?.trim()??"")),u=c?.textContent?.trim().replace(/^\(|\)$/g,"")??"",d=u&&t.endsWith(")")?t.replace(/\)$/,`, ${u})`):t;a.textContent?.trim()!==d&&(a.textContent=d,a.dataset.kginicisPaymentMethodPatched="true"),o.dataset.kginicisPaymentMethodRow="admin-order",c&&u&&(c.textContent="",c.style.display="none",c.dataset.kginicisPaymentInstallmentHidden="true"),n=!0}return n}function Bt(e,t,n){const o=Array.from(e.querySelectorAll("span")).filter(i=>i.textContent?.trim()===t).find(i=>{const s=typeof i.className=="string"?i.className:"";return s.includes("rounded-full")||s.includes("font-medium")});return o?(o.textContent=n,o.dataset.kginicisPaymentMethodPatched="true",o.dataset.kginicisPaymentMethodBadge="admin-order",!0):!1}function Ut(e,t){const n=t?._pay_method_label,r=t?._embedded_pg_provider_label,o=t?._base_pay_method_label;if(!n||!r)return!1;const i=Yt(e,n),s=o?Bt(e,o,r):!1;return i||s}async function Ht(e){const t=document.getElementById("section_payment_info")??document.getElementById("payment_info_card");if(!t)return!1;const n=await Gt(e);return n&&Ut(t,n)&&console.info(`[${j}] payment method display patched on admin order detail`),!0}function Jt(e){let t=0;const n=setInterval(()=>{t++,Ht(e).then(r=>{(r||t>=30)&&clearInterval(n)})},400)}function Ft(){const e=location.pathname.match(Dt);e&&Jt(e[1])}function qt(){if(typeof window>"u")return;const e=window;if(e[Ce])return;e[Ce]=!0,console.info(`[${j}] admin order payment display injector installed`);const t=(r=1500)=>setTimeout(Ft,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 Ee="sirsoft-pay_kginicis",Se="__kginicisOcReceiptInjectorInstalled",Pe="kginicis-oc-receipt-btn",Wt=/^\/shop\/orders\/([^/]+)\/complete$/;function Vt(){return localStorage.getItem("auth_token")}function zt(){try{const t=sessionStorage.getItem("g7_guest_order_token");if(t)return t}catch{}const e=window.G7Core?.state?.get?.("_global")?.guestOrderToken;return typeof e=="string"&&e!==""?e:null}async function Xt(e){const t=Vt(),n=zt();if(!t&&!n)return null;const r={Accept:"application/json"};t?r.Authorization=`Bearer ${t}`:n&&(r["X-Guest-Order-Token"]=n);try{const o=await fetch(`/api/modules/sirsoft-ecommerce/user/orders/${e}`,{headers:r});return o.ok?(await o.json())?.data?.payment??null:null}catch{return null}}function Zt(e){if(!e)return!1;const t=Array.from(document.querySelectorAll("div"));for(const n of t){const r=Array.from(n.children).filter(s=>s instanceof HTMLElement&&s.tagName==="SPAN");if(r.length<2)continue;const o=r[0].textContent?.trim();if(o!=="결제 방법"&&o!=="결제수단"&&o!=="결제 방식")continue;const i=r[r.length-1];return i.textContent?.trim()===e?(n.dataset.kginicisPaymentMethodRow="true",!0):(i.textContent=e,i.dataset.kginicisPaymentMethodPatched="true",n.dataset.kginicisPaymentMethodRow="true",!0)}return!1}async function Qt(e){if(document.getElementById(Pe))return;const t=await Xt(e);if(t&&(t.pg_provider!=="kginicis"||!t.transaction_id))return;const n=await v(e);if(!C(n))return;if(t){const a=t.payment_status==="paid",c=n.receipt_type==="cbt_confirmation";if(!a&&!c)return}Zt(n.payment_method_display_label);const r=Array.from(document.querySelectorAll('button[type="button"]')).find(a=>a.className.includes("bg-blue-600"));if(!r?.parentElement)return;const o=r.parentElement;o.dataset.kginicisReceiptContainer="order-complete";const i=document.createElement("button");i.id=Pe,i.type="button",i.dataset.kginicisReceiptButton="order-complete",i.className=r.className.replace(/bg-blue-\d+/g,"bg-green-600").replace(/hover:bg-blue-\d+/g,"hover:bg-green-700"),i.textContent=A(n),i.addEventListener("click",async()=>{i.disabled=!0,i.textContent="로딩 중...";const a=await v(e);i.disabled=!1,i.textContent=A(a??n),C(a)&&we(a)});const s=o.lastElementChild;o.insertBefore(i,s),console.info(`[${Ee}] receipt button injected on order complete page`)}function en(){const e=location.pathname.match(Wt);e&&Qt(e[1])}function tn(){if(typeof window>"u")return;const e=window;if(e[Se])return;e[Se]=!0,console.info(`[${Ee}] order complete receipt injector installed`);const t=(r=1200)=>setTimeout(en,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 Ie="sirsoft-pay_kginicis",ve="__kginicisVbankInfoInjectorInstalled",Y="kginicis-mp-vbank-info",nn=/^\/shop\/orders\/([^/]+)\/complete$/,rn=/^\/mypage\/orders\/([^/]+)$/,on=/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+\-]\d{2}:\d{2}/,an={"03":"기업은행","04":"국민은행","05":"외환은행","07":"수협중앙회",11:"농협중앙회",20:"우리은행",23:"SC 제일은행",31:"대구은행",32:"부산은행",34:"광주은행",37:"전북은행",39:"경남은행",53:"한국씨티은행",71:"우체국",81:"하나은행",88:"신한은행",89:"케이뱅크",90:"카카오뱅크",92:"토스뱅크",D1:"동양종합금융증권",D2:"현대증권",D3:"미래에셋증권",D4:"한국투자증권",D5:"우리투자증권",D6:"하이투자증권",D7:"HMC 투자증권",D8:"SK 증권",D9:"대신증권",DA:"하나대투증권",DB:"굿모닝신한증권",DC:"동부증권",DD:"유진투자증권",DE:"메리츠증권",DF:"신영증권"};function sn(e){if(e.vbank_code)return String(e.vbank_code);const t=(e.vbank_name??"").trim();if(!t)return null;for(const[n,r]of Object.entries(an))if(r===t)return n;return null}function cn(){try{const t=window.G7Core?.getState;return t?.()?.currentDataContext?._global?.currentUser?.is_admin===!0}catch{return!1}}function Ae(e){try{return new Date(e).toLocaleString("ko-KR",{year:"numeric",month:"long",day:"numeric",hour:"2-digit",minute:"2-digit",timeZone:"Asia/Seoul"})}catch{return e}}function dn(){const e=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT),t=[];let n=e.nextNode();for(;n;){const r=n.textContent??"",o=r.match(on);o&&t.push({node:n,formatted:r.replace(o[0],Ae(o[0]))}),n=e.nextNode()}for(const{node:r,formatted:o}of t)r.textContent=o}function ln(e){try{const n=window.G7Core?.getState,i=n?.()?.currentDataContext?.order?.data;return!i||i.order_number!==e?null:i}catch{return null}}function un(){const e=document.getElementById("order_payment_info_panel");if(e)return Array.from(e.children).find(r=>r.className?.includes("space-y"))??e;const t=Array.from(document.querySelectorAll("h3")).find(r=>r.textContent?.includes("결제 정보"));if(!t)return null;const n=t.parentElement?.parentElement;return n?Array.from(n.children).find(r=>r.className?.includes("space-y"))??n:null}function _(e,t,n=!1){const r=document.createElement("div");r.className="flex items-center justify-between";const o=document.createElement("span");o.className="text-gray-500 dark:text-gray-400 text-sm",o.textContent=e;const i=document.createElement("span");return i.className=n?"text-sm font-medium text-blue-600 dark:text-blue-400":"text-sm text-gray-900 dark:text-gray-100",i.textContent=t,r.appendChild(o),r.appendChild(i),r}function mn(e,t){const n=document.createElement("div");n.id=Y,n.className="mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 space-y-2";const r=document.createElement("p");if(r.className="text-sm font-semibold text-gray-700 dark:text-gray-300",r.textContent="가상계좌 입금 안내",n.appendChild(r),e.vbank_name&&n.appendChild(_("은행",e.vbank_name)),cn()){const o=sn(e);o&&n.appendChild(_("은행코드",o))}return e.vbank_number&&n.appendChild(_("계좌번호",e.vbank_number)),e.vbank_holder&&n.appendChild(_("예금주",e.vbank_holder)),t&&n.appendChild(_("입금 기한",t,!0)),n}function g(e,t){return e?.receipt_fields?.find(n=>n.label===t)?.value??""}function fn(e,t){if(t?.receipt_type!=="cbt_confirmation")return!1;if(g(t,"결제수단").includes("편의점"))return!0;const r=String(e.transaction_id??"");return String(e.currency??"").toUpperCase()==="JPY"&&(String(e.vbank_name??"").toUpperCase()==="CVS"||r.startsWith("INIJPGCVS"))}function pn(e,t,n){const r=document.createElement("div");r.id=Y,r.className="mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 space-y-2";const o=document.createElement("p");o.className="text-sm font-semibold text-gray-700 dark:text-gray-300",o.textContent="일본 편의점 입금 안내",r.appendChild(o);const i=g(t,"입금 상태"),s=g(t,"입금예정금액")||g(t,"결제금액"),a=g(t,"편의점 코드"),c=g(t,"편의점 확인번호")||String(e.vbank_number??""),u=g(t,"편의점 접수번호"),d=g(t,"입금 마감일시")||n;return i&&r.appendChild(_("상태",i)),s&&r.appendChild(_("입금예정금액",s,!0)),a&&r.appendChild(_("편의점 코드",a)),c&&r.appendChild(_("편의점 확인번호",c)),u&&r.appendChild(_("편의점 접수번호",u)),d&&r.appendChild(_("입금 마감일시",d,!0)),r}async function yn(e){const t=ln(e);if(!t)return!1;const{payment:n}=t;if(!n||n.pg_provider!=="kginicis"||n.payment_status!=="waiting_deposit"||!n.vbank_number||document.getElementById(Y))return!0;const r=un();if(!r)return!1;const o=await v(e),i=n.vbank_due_at?Ae(n.vbank_due_at):"";return r.appendChild(fn(n,o)?pn(n,o,i):mn(n,i)),console.info(`[${Ie}] vbank info injected on mypage`),!0}function _n(e){let t=0;const n=setInterval(()=>{t++,yn(e).then(r=>{(r||t>=30)&&clearInterval(n)})},400)}function hn(){if(location.pathname.match(nn)){setTimeout(dn,500);return}const t=location.pathname.match(rn);t&&_n(t[1])}function gn(){if(typeof window>"u")return;const e=window;if(e[ve])return;e[ve]=!0,console.info(`[${Ie}] vbank info injector installed`);const t=(r=800)=>setTimeout(hn,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 Te="sirsoft-pay_kginicis",xe="__sirsoftKginicisCheckoutJpyPaymentMethodRestrictorInstalled",B=/^\/shop\/checkout\/?$/,wn="/api/modules/sirsoft-ecommerce/checkout",bn="/api/modules/sirsoft-ecommerce/settings/payment",kn="/api/modules/sirsoft-ecommerce/payments/client-config/kginicis",Re="__sirsoftKginicisCheckoutCurrency",U=new Set(["card","kginicis_japan_paypay","kginicis_japan_cvs"]),H=new Set(["kginicis_japan_paypay","kginicis_japan_cvs"]),Me=new Set(["card","vbank","dbank","bank","phone","kginicis_samsung_pay","kginicis_naverpay","kginicis_lpay","kginicis_kakaopay","kginicis_japan_paypay","kginicis_japan_cvs"]),Cn=[{id:"card",labels:["신용카드","Credit Card","クレジットカード"]},{id:"vbank",labels:["가상계좌","Virtual Account","バーチャル口座"]},{id:"dbank",labels:["무통장입금","Bank Transfer","銀行振込"]},{id:"bank",labels:["계좌이체","Account Transfer","口座振替"]},{id:"phone",labels:["휴대폰결제","Mobile Payment","携帯電話決済"]},{id:"kginicis_naverpay",labels:["네이버페이 (KG이니시스)","Naver Pay (KG Inicis)"]},{id:"kginicis_samsung_pay",labels:["삼성페이 (KG이니시스)","Samsung Pay (KG Inicis)"]},{id:"kginicis_lpay",labels:["L.pay (KG이니시스)","L.pay (KG Inicis)"]},{id:"kginicis_kakaopay",labels:["카카오페이 (KG이니시스)","Kakao Pay (KG Inicis)"]},{id:"kginicis_japan_paypay",labels:["PayPay (일본 KG이니시스)","PayPay (KG Inicis Japan)"]},{id:"kginicis_japan_cvs",labels:["일본 편의점결제 (KG이니시스)","Japan Convenience Store (KG Inicis)"]}],J={info:(...e)=>console.info(`[${Te}]`,...e),warn:(...e)=>console.warn(`[${Te}]`,...e)};let S=null,F=null,b=null;function q(){return window}function En(e){return typeof e=="string"?e:e instanceof URL?e.toString():typeof Request<"u"&&e instanceof Request?e.url:String(e)}function Sn(e,t){return t?.method?t.method.toUpperCase():typeof Request<"u"&&e instanceof Request?e.method.toUpperCase():"GET"}function Pn(e){try{return new URL(e,window.location.origin).pathname}catch{return e.split("?")[0].split("#")[0]}}function Ne(e){if(typeof e!="string")return null;const t=e.trim().toUpperCase();return/^[A-Z]{3}$/.test(t)?t:null}function W(e,t){return t.split(".").reduce((n,r)=>{if(!(n===null||typeof n!="object"))return n[r]},e)}function In(e,t){for(const n of t){const r=Ne(W(e,n));if(r)return r}return null}function vn(e){return In(e,["data.calculation.summary.selected_payment_currency","data.calculation.metadata.payment_currency","data.calculation.metadata.currency","data.currency","data.currency_code"])}function An(e){const t=vn(e);t&&(q()[Re]=t)}function Le(){const e=q(),n=e.__templateApp?.globalState,r=[e[Re],n?.preferredCurrency];try{r.push(window.localStorage?.getItem("g7_preferred_currency"))}catch{}r.push(W(n,"modules.sirsoft-ecommerce.language_currency.default_currency"),W(n,"modules.sirsoft-ecommerce.language_currency.currencies.0.code"));for(const o of r){const i=Ne(o);if(i)return i}return null}function V(){return B.test(window.location.pathname)&&Le()==="JPY"}function z(){if(!B.test(window.location.pathname))return!1;const e=Le();return e!==null&&e!=="JPY"}async function Oe(e){return S!==null||(S=(async()=>{try{const t=await e(kn,{headers:{Accept:"application/json"}});return t.ok?(await t.json()).data?.japan_restrict_jpy_payment_methods===!0:!1}catch{return!1}})()),S}function Tn(e){const t=e.data?.order_settings?.payment_methods;return Array.isArray(t)?{...e,data:{...e.data,order_settings:{...e.data?.order_settings,payment_methods:t.map(n=>{const r=typeof n.id=="string"?n.id:"";return!Me.has(r)||U.has(r)?n:{...n,is_active:!1,_kginicis_restricted_for_jpy:!0}})}}}:e}function xn(e){const t=e.data?.order_settings?.payment_methods;return Array.isArray(t)?{...e,data:{...e.data,order_settings:{...e.data?.order_settings,payment_methods:t.map(n=>{const r=typeof n.id=="string"?n.id:"";return H.has(r)?{...n,is_active:!1,_kginicis_restricted_for_non_jpy:!0}:n})}}}:e}function Rn(e,t){const n=new Headers(e.headers);return n.set("Content-Type","application/json"),new Response(JSON.stringify(t),{status:e.status,statusText:e.statusText,headers:n})}function Mn(){const e=Array.from(document.querySelectorAll("h2")).find(n=>{const r=n.textContent??"";return r.includes("결제 수단")||r.includes("결제 방법")||r.includes("Payment Method")});if(!e)return null;let t=e.parentElement;for(;t&&t!==document.body;){if(t.tagName==="DIV"&&String(t.className).includes("rounded-lg"))return t;t=t.parentElement}return null}function Nn(e){const t=e.querySelector("p")?.textContent?.trim()??e.textContent?.trim()??"";for(const n of Cn)if(n.labels.some(r=>t.includes(r)))return n.id;return null}function X(){const e=V(),t=z();if(!e&&!t)return!1;const n=Mn();if(!n)return!1;let r=!1;if(n.querySelectorAll('button[type="button"]').forEach(o=>{const i=Nn(o);if(!i||!Me.has(i))return;if(e?U.has(i):!H.has(i)){o.style.removeProperty("display"),o.disabled=!1,o.removeAttribute("aria-hidden");return}o.style.display="none",o.disabled=!0,o.setAttribute("aria-hidden","true"),e?o.dataset.kginicisRestrictedForJpy="true":o.dataset.kginicisRestrictedForNonJpy="true",r=!0}),r)try{const i=window.G7Core?.state?.getLocal?.()?.paymentMethod;typeof i=="string"&&(e&&!U.has(i)||t&&H.has(i))&&window.G7Core?.state?.setLocal?.({paymentMethod:"card"})}catch{}return r}async function $e(e){if(!B.test(window.location.pathname))return;const t=V(),n=z();if(!t&&!n||t&&!await Oe(e))return;X(),F===null&&(F=new MutationObserver(()=>{X()}),F.observe(document.body,{childList:!0,subtree:!0})),b!==null&&clearInterval(b);let r=0;b=setInterval(()=>{r++,X(),r>=50&&b!==null&&(clearInterval(b),b=null)},200)}function De(e){S=null,$e(e)}function Ln(){if(typeof window>"u"||typeof window.fetch!="function")return;const e=q();if(e[xe])return;e[xe]=!0;const t=window.fetch.bind(window);window.fetch=async function(i,s){const a=En(i),c=Sn(i,s),u=Pn(a),d=await t(i,s);if(c==="GET"&&u.endsWith(wn)){try{const f=await d.clone().json();An(f)}catch{}return d}if(c!=="GET"||!u.endsWith(bn))return d;const l=V(),m=z();if(!l&&!m||l&&!await Oe(t))return d;try{const f=await d.clone().json(),p=l?Tn(f):xn(f);return J.info(l?"restricted checkout payment methods for JPY order":"hid Japan-only payment methods for non-JPY order"),Rn(d,p)}catch(f){return J.warn("failed to restrict checkout payment methods",f),d}},J.info("checkout JPY payment method restrictor installed");const n=()=>{$e(t)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n):n();const r=history.pushState.bind(history);history.pushState=(...o)=>{r(...o),setTimeout(()=>De(t),200)},window.addEventListener("popstate",()=>setTimeout(()=>De(t),200))}const On="sirsoft-pay_kginicis",Ke="__kginicisAdminPaymentMethodBrandInjectorInstalled",Ge="__kginicisAdminPaymentMethodBrandSyncListenerAttached",$n=/^\/admin\/ecommerce\/settings\/?$/,je='[data-kginicis-admin-payment-brand-mark="true"]',Dn=200,Kn=120,Gn=[{id:"kginicis_naverpay",labels:["네이버페이 (KG이니시스)","Naver Pay (KG Inicis)"],shortLabels:[],markLines:["N","Pay"],markClassName:"bg-green-500 text-white"},{id:"kginicis_samsung_pay",labels:["삼성페이 (KG이니시스)","Samsung Pay (KG Inicis)"],shortLabels:[],markLines:["S","Pay"],markClassName:"bg-blue-700 text-white"},{id:"kginicis_lpay",labels:["L.pay (KG이니시스)","L.pay (KG Inicis)"],shortLabels:[],markLines:["L","pay"],markClassName:"bg-red-600 text-white"},{id:"kginicis_kakaopay",labels:["카카오페이 (KG이니시스)","Kakao Pay (KG Inicis)"],shortLabels:[],markLines:["Kakao","Pay"],markClassName:"bg-yellow-400 text-gray-950"},{id:"kginicis_japan_paypay",labels:["PayPay (일본 KG이니시스)","PayPay (KG Inicis Japan)"],shortLabels:[],markLines:["Pay","Pay"],markClassName:"bg-red-600 text-white"},{id:"kginicis_japan_cvs",labels:["일본 편의점결제 (KG이니시스)","Japan Convenience Store (KG Inicis)"],shortLabels:[],markLines:["CVS","JP"],markClassName:"bg-blue-600 text-white"}];let Ye=null,T=null,Z=!1;function jn(){return window}function Q(){if(!$n.test(window.location.pathname))return!1;const e=new URLSearchParams(window.location.search).get("tab");return e===null||e===""||e==="order_settings"}function Yn(e){return e instanceof HTMLElement?e.className:""}function Be(e){return(e??"").replace(/\u200B/g,"").replace(/\s+/g," ").trim()}function Bn(e){const t=Yn(e);return t.includes("excel-card")||t.includes("flex-center")&&t.includes("border")&&t.includes("gap-4")}function Ue(e){return e.querySelector(".font-medium")}function Un(e){const t=Be(Ue(e)?.textContent),n=Be(e.textContent);return Gn.find(r=>r.shortLabels.some(o=>t===o)||r.labels.some(o=>n.includes(o)))??null}function Hn(e){return Array.from(e.querySelectorAll("div")).filter(Bn)}function Jn(e){return Array.from(e.querySelectorAll("svg, [data-icon], i")).find(n=>!n.closest("[data-drag-handle]")&&!n.closest(je)&&!n.closest('.row-stack, .excel-card-body, button, select, [role="switch"]'))??null}function He(e,t){e.dataset.kginicisAdminPaymentBrandMark="true",e.dataset.kginicisAdminPaymentMethod=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.flexDirection="column",e.style.lineHeight="1",e.style.fontSize="9px";const n=t.markLines.join("");e.textContent!==n&&(e.replaceChildren(),t.markLines.forEach(r=>{const o=document.createElement("span");o.style.lineHeight="1",o.textContent=r,e.appendChild(o)}))}function Fn(e){const t=document.createElement("span");return He(t,e),t}function qn(e,t){const n=e.querySelector(je);if(n instanceof HTMLSpanElement)return e.dataset.kginicisAdminPaymentMethod=t.id,He(n,t),!0;const r=Fn(t),o=Jn(e);if(o&&o.parentElement)return e.dataset.kginicisAdminPaymentMethod=t.id,o.replaceWith(r),!0;const i=Ue(e);return i&&i.parentElement?(e.dataset.kginicisAdminPaymentMethod=t.id,i.parentElement.insertBefore(r,i),!0):!1}function ee(e=document){if(typeof window>"u"||typeof document>"u"||!Q())return!1;let t=!1;return Hn(e).forEach(n=>{const r=Un(n);r&&qn(n,r)&&(t=!0)}),t}function Wn(){Z||(Z=!0,window.setTimeout(()=>{Z=!1,ee()},0))}function te(){T!==null&&(window.clearInterval(T),T=null)}function ne(){if(!Q())return;te(),ee();let e=0;T=window.setInterval(()=>{e+=1,ee(),e>=Kn&&te()},Dn);const t=document.body;t[Ge]||(t[Ge]=!0,Ye=new MutationObserver(()=>Wn()),Ye.observe(document.body,{childList:!0,subtree:!0,characterData:!0}))}function re(){if(Q()){ne();return}te()}function Vn(){if(typeof window>"u"||typeof document>"u")return;const e=jn();if(e[Ke])return;e[Ke]=!0,console.info(`[${On}] admin payment method brand sync installed`),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>ne()):ne();const t=history.pushState.bind(history);history.pushState=(...r)=>{t(...r),window.setTimeout(()=>re(),200)};const n=history.replaceState.bind(history);history.replaceState=(...r)=>{n(...r),window.setTimeout(()=>re(),200)},window.addEventListener("popstate",()=>window.setTimeout(()=>re(),200))}const k="sirsoft-pay_kginicis",oe={info:(...e)=>console.info(`[${k}]`,...e),warn:(...e)=>console.warn(`[${k}]`,...e),error:(...e)=>console.error(`[${k}]`,...e)};function Je(){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[o,i]of Object.entries(_e)){const s=`${k}.${o}`;n.registerHandler(s,i,{category:"plugin",source:k}),r++}return r}function Fe(){const e=()=>{const t=Je();if(t>0){oe.info(`${t} handler(s) registered`);return}let n=0;const r=50,o=setInterval(()=>{n++;const i=Je();if(i>0){clearInterval(o),oe.info(`${i} handler(s) registered (after ${n} retries)`);return}n>=r&&(clearInterval(o),oe.warn("ActionDispatcher not available after timeout"))},100)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e):e()}Et(),Ln(),$t(),qt(),Vn(),tn(),gn(),at(),Fe(),window.__SirsoftKginicis={identifier:k,handlers:Object.keys(_e),initPlugin:Fe}})(); //# sourceMappingURL=plugin.iife.js.map diff --git a/plugins/_bundled/sirsoft-pay_kginicis/resources/js/adminPaymentMethodBrandInjector.ts b/plugins/_bundled/sirsoft-pay_kginicis/resources/js/adminPaymentMethodBrandInjector.ts index 500e8f55..1cad239c 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/resources/js/adminPaymentMethodBrandInjector.ts +++ b/plugins/_bundled/sirsoft-pay_kginicis/resources/js/adminPaymentMethodBrandInjector.ts @@ -265,6 +265,17 @@ export function installAdminPaymentMethodBrandInjector(): void { origPush(...args); window.setTimeout(() => onRouteChange(), 200); }; + + // replaceState 도 후킹한다 — 환경설정 화면의 탭 전환은 pushState 가 아니라 + // replaceState 로 URL 만 바꾼다(실측: 탭 왕복 1회에 push 0 / replace 2). pushState 만 + // 후킹하면 다른 탭에 갔다 돌아왔을 때 onRouteChange 가 발화하지 않아 배지가 사라진 채로 + // 남는다(행은 그대로 렌더되므로 화면상 아이콘만 회색으로 되돌아간다). + const origReplace = history.replaceState.bind(history); + history.replaceState = (...args: Parameters) => { + origReplace(...args); + window.setTimeout(() => onRouteChange(), 200); + }; + window.addEventListener('popstate', () => window.setTimeout(() => onRouteChange(), 200)); } diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md index 25eb32b4..ec573058 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md @@ -12,6 +12,7 @@ ### Fixed +- 이커머스 관리자 주문설정에서 다른 탭에 갔다 돌아오면 간편결제 항목의 브랜드 색상 배지가 사라지고 회색 기본 아이콘으로 남던 문제를 수정했습니다. 화면을 새로고침해야만 다시 표시됐습니다. - 관리자 주문 상세의 거래 조회에서 취소·환불 금액에 원화 단위가 고정 표기되던 문제를 수정했습니다. 이제 주문 시점 기준 통화로 표시됩니다. - 결제 취소 기록의 환불 금액 표기도 결제 통화를 따르도록 수정했습니다. - 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 결제를 마치거나 결제에 실패한 구매자가 존재하지 않는 페이지로 이동하던 문제를 수정했습니다. 이동 주소가 기본 주소로 고정돼 있었기 때문이며, 이제 상점 주소 설정을 따라갑니다. 이미 운영 중인 사이트도 업데이트 시 자동으로 반영되며, 이동 주소를 직접 입력해 두었다면 그 값은 그대로 유지됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/components.json b/plugins/_bundled/sirsoft-pay_nhnkcp/components.json index b713834c..ebca39c6 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/components.json +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/components.json @@ -1,7 +1,7 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "identifier": "sirsoft-pay_nhnkcp", - "version": "1.0.0", + "version": "1.0.1", "components": { "basic": [], "composite": [], diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/dist/js/plugin.iife.js b/plugins/_bundled/sirsoft-pay_nhnkcp/dist/js/plugin.iife.js index 4ccf9cfa..aeb84cc3 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/dist/js/plugin.iife.js +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/dist/js/plugin.iife.js @@ -1,4 +1,4 @@ -(function(){"use strict";function Le(e){return/^https?:\/\//i.test(e)||e.startsWith("/api/")?e:e.startsWith("/plugins/")?`/api${e}`:e.startsWith("plugins/")?`/api/${e}`:e}function Oe(e){return e.trim().slice(0,160)}function Ke(e){if(e)return e.replace(/\/payment\/close-report$/,"/payment/retry")}async function ee(e,t,n=!1){const o=window.G7Core?.api;if(typeof o?.post=="function"){await o.post(e,t);return}const r=await fetch(Le(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:n});if(!r.ok){let a=`NHN KCP payment request failed (${r.status})`;try{const s=await r.json(),i=Array.isArray(s?.errors?.message)?s.errors.message[0]:s?.error??s?.message;typeof i=="string"&&i.trim()!==""&&(a=i)}catch{}throw new Error(a)}}async function je(e){const t=Ke(e.closeReportUrl);t&&await ee(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 Be(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:Oe(t)||"kcp-window-closed"};try{await ee(e.closeReportUrl,n,!0)}catch(o){console.warn("[sirsoft-pay_nhnkcp] failed to report payment window close",o)}}const De="nhnkcp_applepay";function S(e){return e===De}function x(){if(typeof navigator>"u")return!1;const e=navigator,t=(e.userAgent||"").toLowerCase(),n=((e.userAgentData?.platform??e.platform)||"").toLowerCase(),o=e.maxTouchPoints??0;return/iphone|ipad|ipod/.test(t)||/iphone|ipad|ipod|ios/.test(n)?!0:/macintosh|mac os x/.test(t)&&o>1}function M(){return((typeof document<"u"?document.documentElement.lang:"")||"").toLowerCase().startsWith("ko")?"애플페이는 IOS 기기에 모바일결제만 가능합니다.":"Apple Pay is available only for mobile payments on iOS devices."}function T(e){return(e??"KRW").trim().toUpperCase()||"KRW"}function He(e){return T(e)==="KRW"}function Fe(e){const t=T(e);return((typeof document<"u"?document.documentElement.lang:"")||"").toLowerCase().startsWith("ko")?`NHN KCP는 KRW 결제만 지원합니다. (${t})`:`NHN KCP supports KRW payments only. (${t})`}function qe(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 o=Math.max(0,Math.round(Number(e.tax_amount??0))),r=Math.max(0,Math.round(Number(e.vat_amount??0))),a=Math.max(0,t-n),s=a>0&&o>0&&r>0?Math.min(a,Math.round(a*(r/o))):0,i=a-s;return{tax_flag:"TG03",comm_tax_mny:String(i),comm_vat_mny:String(s),comm_free_mny:String(n)}}class R extends Error{constructor(t){super(t??"결제가 취소되었습니다."),this.name="KcpCancelledError"}}const Ue={card:"100000000000",bank_transfer:"010000000000",virtual_account:"001000000000",mobile:"000010000000",bank:"010000000000",vbank:"001000000000",phone:"000010000000"},te={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 Ye(e,t){const n=e.toLowerCase();return!t||!Object.prototype.hasOwnProperty.call(te,n)?{}:{param_opt_1:n,nhnkcp_easy_pay_method:n}}function Ge(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 We(e,t){let n=!1,o,r;const a=()=>{n=!0,r&&(r.disconnect(),r=void 0),o!==void 0&&(window.clearInterval(o),o=void 0)},s=()=>{n||!Ge(e)||(a(),t())},i=document.body??document.documentElement;return i&&typeof MutationObserver<"u"&&(r=new MutationObserver(s),r.observe(i,{attributes:!0,attributeFilter:["class","hidden","style"],childList:!0,subtree:!0})),o=window.setInterval(s,300),a}function ze(){if(typeof navigator>"u")return!1;if(x())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 Je(e,t){const{pgPaymentData:n,paymentMethod:o}=e.params||{};if(!n){console.error("[sirsoft-pay_nhnkcp] pgPaymentData is required");return}const r=o??n.payment_method??n.pay_method??"card",a=typeof r=="string"&&r.startsWith("nhnkcp_"),s=window.G7Core;let i=null;try{if(!He(n.currency)){const u=Fe(n.currency);s?.state?.setLocal?.({paymentErrorMessage:u,isSubmittingOrder:!1,paymentMethod:r}),s?.modal?.open?.("nhnkcp_payment_error_modal");return}if(S(r)&&!x()){const u=M();s?.state?.setLocal?.({paymentErrorMessage:u,isSubmittingOrder:!1,paymentMethod:r}),s?.modal?.open?.("nhnkcp_payment_error_modal");return}const c=await s.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;i={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:r};const l=window.location.origin+d.callback_urls.callback;await je(i),ze()?await Ve(s,n,r,a,l):await Qe(d,n,r,a,l)}catch(c){if(c instanceof R){i&&await Be(i,c.message||"kcp-window-closed"),s?.state?.setLocal?.({isSubmittingOrder:!1,paymentMethod:r});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,p=l?.error??l?.message??u??(c instanceof Error?c.message:"Unknown error");s?.state?.setLocal?.({paymentErrorMessage:p,isSubmittingOrder:!1,paymentMethod:r}),s?.modal?.open?.("nhnkcp_payment_error_modal")}}async function Ve(e,t,n,o,r){const a=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:r,currency:T(t.currency)});if(!a.success||!a.data){const d=a.errors,l=d?Object.values(d)[0]?.[0]:void 0;throw new Error(a.error??a.message??l??"KCP 모바일 승인키 획득 실패")}const{pay_url:s,fields:i}=a.data,c=document.createElement("form");c.method="POST",c.action=s,c.acceptCharset="euc-kr",c.style.display="none";for(const[d,l]of Object.entries(i)){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 Qe(e,t,n,o,r){const a=o?"100000000000":Ue[t.pay_method??"card"]??"100000000000",i={site_cd:n==="nhnkcp_payco"?e.easy_pay_client_id??e.client_id:e.use_escrow&&!o?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:a,Ret_URL:r};if(Object.assign(i,qe(t)),Object.assign(i,Ye(n,o)),a==="001000000000"&&(i.vcnt_expire_term=String(e.vbank_expire_days??3),i.disp_tax_yn="N"),e.use_escrow&&!o&&(i.escw_used="Y",i.pay_mod="O"),o){i.payco_direct="",i.naverpay_direct="A",i.kakaopay_direct="A",i.applepay_direct="A";const d=te[n];d&&Object.assign(i,d)}const c=Object.entries(i).map(([d,l])=>``).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 p=document.createElement("iframe");p.id="kcp-sdk-iframe",p.setAttribute("allowtransparency","true"),p.style.cssText="position:fixed;top:0;left:0;width:100%;height:100%;border:0;z-index:99999;background:transparent;",document.body.appendChild(p);const f=p.contentWindow;let V=!1,y,k;const cn=()=>{k?.(),k=void 0,y!==void 0&&(clearTimeout(y),y=void 0),p.remove(),u.remove()},N=m=>{V||(V=!0,cn(),l(m))},dn=()=>{V=!0,k?.(),k=void 0,y!==void 0&&(clearTimeout(y),y=void 0)};k=We(p,()=>{N(new R("kcp-payment-frame-closed"))}),f.m_Completepayment=function(m){const A=m.elements.res_cd?.value??"",X=m.elements.res_msg?.value??"";if(A==="0000"){dn();const h=f.document.forms.namedItem("order_info"),C=h&&h!==m?h:m;if(h&&h!==m)for(let Z=0;Z{N(m)};const Q=p.contentDocument||f.document;Q.open(),Q.write(` +(function(){"use strict";function Le(e){return/^https?:\/\//i.test(e)||e.startsWith("/api/")?e:e.startsWith("/plugins/")?`/api${e}`:e.startsWith("plugins/")?`/api/${e}`:e}function Oe(e){return e.trim().slice(0,160)}function Ke(e){if(e)return e.replace(/\/payment\/close-report$/,"/payment/retry")}async function te(e,t,n=!1){const o=window.G7Core?.api;if(typeof o?.post=="function"){await o.post(e,t);return}const r=await fetch(Le(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:n});if(!r.ok){let a=`NHN KCP payment request failed (${r.status})`;try{const s=await r.json(),i=Array.isArray(s?.errors?.message)?s.errors.message[0]:s?.error??s?.message;typeof i=="string"&&i.trim()!==""&&(a=i)}catch{}throw new Error(a)}}async function je(e){const t=Ke(e.closeReportUrl);t&&await te(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 Be(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:Oe(t)||"kcp-window-closed"};try{await te(e.closeReportUrl,n,!0)}catch(o){console.warn("[sirsoft-pay_nhnkcp] failed to report payment window close",o)}}const De="nhnkcp_applepay";function S(e){return e===De}function x(){if(typeof navigator>"u")return!1;const e=navigator,t=(e.userAgent||"").toLowerCase(),n=((e.userAgentData?.platform??e.platform)||"").toLowerCase(),o=e.maxTouchPoints??0;return/iphone|ipad|ipod/.test(t)||/iphone|ipad|ipod|ios/.test(n)?!0:/macintosh|mac os x/.test(t)&&o>1}function M(){return((typeof document<"u"?document.documentElement.lang:"")||"").toLowerCase().startsWith("ko")?"애플페이는 IOS 기기에 모바일결제만 가능합니다.":"Apple Pay is available only for mobile payments on iOS devices."}function T(e){return(e??"KRW").trim().toUpperCase()||"KRW"}function He(e){return T(e)==="KRW"}function Fe(e){const t=T(e);return((typeof document<"u"?document.documentElement.lang:"")||"").toLowerCase().startsWith("ko")?`NHN KCP는 KRW 결제만 지원합니다. (${t})`:`NHN KCP supports KRW payments only. (${t})`}function qe(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 o=Math.max(0,Math.round(Number(e.tax_amount??0))),r=Math.max(0,Math.round(Number(e.vat_amount??0))),a=Math.max(0,t-n),s=a>0&&o>0&&r>0?Math.min(a,Math.round(a*(r/o))):0,i=a-s;return{tax_flag:"TG03",comm_tax_mny:String(i),comm_vat_mny:String(s),comm_free_mny:String(n)}}class R extends Error{constructor(t){super(t??"결제가 취소되었습니다."),this.name="KcpCancelledError"}}const Ue={card:"100000000000",bank_transfer:"010000000000",virtual_account:"001000000000",mobile:"000010000000",bank:"010000000000",vbank:"001000000000",phone:"000010000000"},ne={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 Ye(e,t){const n=e.toLowerCase();return!t||!Object.prototype.hasOwnProperty.call(ne,n)?{}:{param_opt_1:n,nhnkcp_easy_pay_method:n}}function Ge(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 We(e,t){let n=!1,o,r;const a=()=>{n=!0,r&&(r.disconnect(),r=void 0),o!==void 0&&(window.clearInterval(o),o=void 0)},s=()=>{n||!Ge(e)||(a(),t())},i=document.body??document.documentElement;return i&&typeof MutationObserver<"u"&&(r=new MutationObserver(s),r.observe(i,{attributes:!0,attributeFilter:["class","hidden","style"],childList:!0,subtree:!0})),o=window.setInterval(s,300),a}function ze(){if(typeof navigator>"u")return!1;if(x())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 Je(e,t){const{pgPaymentData:n,paymentMethod:o}=e.params||{};if(!n){console.error("[sirsoft-pay_nhnkcp] pgPaymentData is required");return}const r=o??n.payment_method??n.pay_method??"card",a=typeof r=="string"&&r.startsWith("nhnkcp_"),s=window.G7Core;let i=null;try{if(!He(n.currency)){const u=Fe(n.currency);s?.state?.setLocal?.({paymentErrorMessage:u,isSubmittingOrder:!1,paymentMethod:r}),s?.modal?.open?.("nhnkcp_payment_error_modal");return}if(S(r)&&!x()){const u=M();s?.state?.setLocal?.({paymentErrorMessage:u,isSubmittingOrder:!1,paymentMethod:r}),s?.modal?.open?.("nhnkcp_payment_error_modal");return}const c=await s.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;i={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:r};const l=window.location.origin+d.callback_urls.callback;await je(i),ze()?await Ve(s,n,r,a,l):await Qe(d,n,r,a,l)}catch(c){if(c instanceof R){i&&await Be(i,c.message||"kcp-window-closed"),s?.state?.setLocal?.({isSubmittingOrder:!1,paymentMethod:r});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,p=l?.error??l?.message??u??(c instanceof Error?c.message:"Unknown error");s?.state?.setLocal?.({paymentErrorMessage:p,isSubmittingOrder:!1,paymentMethod:r}),s?.modal?.open?.("nhnkcp_payment_error_modal")}}async function Ve(e,t,n,o,r){const a=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:r,currency:T(t.currency)});if(!a.success||!a.data){const d=a.errors,l=d?Object.values(d)[0]?.[0]:void 0;throw new Error(a.error??a.message??l??"KCP 모바일 승인키 획득 실패")}const{pay_url:s,fields:i}=a.data,c=document.createElement("form");c.method="POST",c.action=s,c.acceptCharset="euc-kr",c.style.display="none";for(const[d,l]of Object.entries(i)){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 Qe(e,t,n,o,r){const a=o?"100000000000":Ue[t.pay_method??"card"]??"100000000000",i={site_cd:n==="nhnkcp_payco"?e.easy_pay_client_id??e.client_id:e.use_escrow&&!o?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:a,Ret_URL:r};if(Object.assign(i,qe(t)),Object.assign(i,Ye(n,o)),a==="001000000000"&&(i.vcnt_expire_term=String(e.vbank_expire_days??3),i.disp_tax_yn="N"),e.use_escrow&&!o&&(i.escw_used="Y",i.pay_mod="O"),o){i.payco_direct="",i.naverpay_direct="A",i.kakaopay_direct="A",i.applepay_direct="A";const d=ne[n];d&&Object.assign(i,d)}const c=Object.entries(i).map(([d,l])=>``).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 p=document.createElement("iframe");p.id="kcp-sdk-iframe",p.setAttribute("allowtransparency","true"),p.style.cssText="position:fixed;top:0;left:0;width:100%;height:100%;border:0;z-index:99999;background:transparent;",document.body.appendChild(p);const f=p.contentWindow;let Q=!1,y,k;const cn=()=>{k?.(),k=void 0,y!==void 0&&(clearTimeout(y),y=void 0),p.remove(),u.remove()},N=m=>{Q||(Q=!0,cn(),l(m))},dn=()=>{Q=!0,k?.(),k=void 0,y!==void 0&&(clearTimeout(y),y=void 0)};k=We(p,()=>{N(new R("kcp-payment-frame-closed"))}),f.m_Completepayment=function(m){const A=m.elements.res_cd?.value??"",Z=m.elements.res_msg?.value??"";if(A==="0000"){dn();const h=f.document.forms.namedItem("order_info"),C=h&&h!==m?h:m;if(h&&h!==m)for(let ee=0;ee{N(m)};const X=p.contentDocument||f.document;X.open(),X.write(`