PageSourceSearch

https://numberplate.kr/admin/js/payment.js?1787117512

js numberplate.kr collected 2026-10-02 02:00:16 UTC 80,077 bytes, 1,928 lines download raw bytes

1var PAYMENT = {
2    onClickStep2 : function() {
3        var data = $('#form-step1').serializeObject();
4
5        $.ajax({
6            type: 'POST',
7            data: data,
8            url: ('/admin/ajax/upgrade_plan_step1.cm'),
9            dataType: 'json',
10            async: false,
11            cache: false,
12            success:function(result)
13            {
14                if(result.msg == 'SUCCESS') {
15
16                    var url = '/admin/upgrade/list/?mode=' + result.mode + '&plan=' + result.plan + '&type=' + result.type + '&step=' + result.step
17                        + '&period_type=' + result.period_type;
18
19                    if(result.monthly_type != '')
20                        url += '&monthly_type=' + result.monthly_type;
21
22                    window.parent.location.href = url;
23                }
24                else {
25                    alert(result.msg);
26                }
27            }
28        });
29    },
30
31    onSelectMonthlyPayment : function(basic_price, period, version) {
32        $.ajax({
33            type: 'POST',
34            data: {'basic_price': basic_price, 'period': period, 'version': version },
35            url: ('/admin/ajax/select_monthly_price.cm'),
36            dataType : 'json',
37            async: false,
38            cache: false,
39            success:function(result)
40            {
41                if(result.msg == 'SUCCESS') {
42                    //alert(result.html);
43                    $('#month_select_price').empty().html(result.html);
44                }
45            }
46        });
47    },
48
49    onClickPaymentSubmitForm : function() {
50        $('#payment_submit_form').submit();
51    },
52
53    //가상계좌 입금계좌 확인 모달출력 함수
54    checkDepositAccount : function(order_number){
55        $.ajax({
56            type : "POST",
57            data : {"order_number" : order_number},
58            url : ("/admin/ajax/check_deposit_account.cm"),
59            dataType : "json",
60            async : false,
61            cache : false,
62            success : function(result){
63                if(result.msg === "SUCCESS"){
64                    $.cocoaDialog.open({type : "admin_check_deposit_account", custom_popup : result.html});
65                }else{
66                    alert(result.msg);
67                }
68            }
69        });
70    }
71};
72
73var PRICE = {
74    country: "",
75    cache: {},
76    priceData: {},
77    /**
78     * @params {couponData.couponCode} string 쿠폰 코드
79     * @params {couponData.couponType} period | fixedAmount | percentage 할인 타입
80     * @params {couponData.discountAmount} number 할인 가격(fixedAmount인 경우)
81     * @params {couponData.discountRate} number 할인률(percentage 인 경우)
82     * @params {couponData.period} number 기간 연장
83     * @params {couponData.periodType} day | month 기간 연장 타입
84     */
85    couponData: null,
86    init: function(data = {}) {
87    const periodData = (data.period === '0' ? null : data.period) ?? '12'; // 1년 기본값, period가 0인 경우에도 1년 기본값 처리
88    const isTrialSite = data.isTrialSite ?? false;
89		const currentVersion = data.currentVersion ?? '';
90		const defaultVersion = data.defaultVersion ?? '';
91		const defaultPeriod = data.defaultPeriod ?? '';
92		const forcePeriod = data.forcePeriod ?? '';
93		const removedPeriods = data.removedPeriods ?? [];
94
95    const params = PRICE.getParams();
96		// FS-2883: 제거된 기간이 URL 쿼리로 들어오면 무시
97		const paramPeriod = removedPeriods.indexOf(params.period) !== -1 ? '' : params.period;
98		const period = forcePeriod || paramPeriod || defaultPeriod || PRICE.getTermKindValue(periodData);
99
100        PRICE.priceData = {
101            period: isTrialSite && period === 'non_extension' ? 'one_year' : period,
102            isTrialSite,
103			currentVersion,
104			defaultVersion,
105			forcePeriod,
106        };
107    },
108    start : function(country){
109        this.country = country;
110        var $payment_type = $("#div_payment_type");
111        var type = $('#type').val();
112        //기간연장/업그레이드
113        if(type === "upgrade") {
114            ADMIN_ADD_CARD.reloadedValueCheck();
115            PRICE.initParams();
116            PRICE.setVersion();
117            PRICE.setPeriod();
118			$("#coupon_value").on("focus",function(){
119				if (PRICE.isPaidUpgradeOrder()) {
120					return;
121				}
122				if (PRICE.priceData.forcePeriod) {
123					return;
124				}
125                var $radio_term_item = $("._day_ck").find("[name='rdo_term_kind']");
126                if($("._day_ck").find("[name='rdo_term_kind']:radio:checked").val() !== "coupon"){
127                    $radio_term_item.each(function(){
128                        if($(this).val() === "coupon"){
129                            $(this).prop("checked", true);
130                        }
131                    });
132                }
133                PRICE.setPeriod();
134            });
135
136            if (PRICE.priceData.isTrialSite) {
137                $('#is_terminate_trial').change(function() {
138                    PRICE.setPeriod();
139
140                    const isChecked = $(this).prop('checked');
141
142                    $('#select_card_submit_btn').text(isChecked ? '즉시 결제' : '저장');
143                });
144            }
145        }
146        //부가 서비스
147        else {
148            var proc_file = "./payment/proc_ajax.cm";
149            var param = {};
150            param.mode = "get_site_infomation";
151            param.country = this.country;
152            param.site_code = $("#sel_site").val();
153            param.version = $("#value_version").val();
154            param.site_changed = "N";
155
156            $.ajax({
157                type: 'POST',
158                url: proc_file,
159                data: param,
160                async: false,
161                success: function(data) {
162                    service_info = $.parseJSON(data);
163                }
164            });
165            PRICE.setExtraService(type);
166        }
167
168        // 결제방식 제어
169        $payment_type.find('.item-wrap').find('a.item').on('click', function(){
170            if ( $(this).hasClass('text-gray-bright') ) {
171                var disabled_msg = $(this).data('disabled_msg');
172                if ( disabled_msg.trim() != '' )    alert(disabled_msg);
173            } else {
174                $('#div_payment_type').find('.item-wrap').find('a.item.active').removeClass('active');
175                $(this).addClass('active');
176                $('input[name=sel_payment_type]').val($(this).data('paymethod'));
177            }
178        });
179
180
181        $("#prev_version_price").val(service_info.version_price);
182        $("#request_site_version").val(service_info["site_version"]);
183        $("#request_price").val(service_info["price"]);
184        $('#btn_payment').on('click', function(e){
185            e.stopPropagation();
186            PRICE.submit();
187            return false;
188        });
189        this.paymentInit();
190
191        switch(this.country){
192            case KOREA_COUNTRY_CODE:
193                this.initKR();
194                break;
195            case TAIWAN_COUNTRY_CODE:
196                this.initTW();
197                break;
198        }
199    },
200
201    initKR: function(){
202        // 정기결제 관련 제어
203        var $payment_type = $('#div_payment_type');
204        $('input[name="rdo_term_kind"]:radio').on('change', function(){
205            $payment_type.find('.item-wrap').find('a.item').each(function(){
206                $(this).toggleClass('text-gray-bright', !$(this).data('default'));
207            });
208
209            if ($(this).val() === 'one_month') {
210                $payment_type.find('.item-wrap').find('a.item').each(function(){
211                    var _pay_method = $(this).data('paymethod');
212                    if (_pay_method === "card") {
213                        $(this).toggleClass('disabled', false);
214                        if ( !$(this).hasClass('active') ) {
215                            $payment_type.find('.item-wrap').find('a.item').removeClass('active');
216                            $(this).addClass('active');
217                            $('input[name=sel_payment_type]').val(_pay_method);
218                        }
219                    } else {
220                        $(this).toggleClass('text-gray-bright', true);
221                    }
222                });
223            }
224        });
225
226        $.each($('input[name=rdo_term_kind]'), (idx, el) => {
227            const $el = $(el)
228            const value = $el.val()
229
230            if (value === 'non_extension' || value === 'coupon') {
231                $el.on('change', () => PRICE.handleChangeNonPeriod())
232            } else {
233                $el.on('change', () => PRICE.handleChangePeriod($el))
234            }
235        })
236
237        $('._extend_period_list').find('input[name=value_version]').on('change', PRICE.handleChangeVersion)
238    },
239
240    initTW: function(){
241        var $invoice_wrapper = $('._invoice_wrapper');
242        $invoice_wrapper.find('select').on('change', function(){
243            $invoice_wrapper.find('._invoice_data_wrapper').toggle( ($(this).val().trim()!= '') );
244            var invoice_type = $(this).val();
245            $invoice_wrapper.find('._invoice_data').each(function(){
246                var target = $(this).data('target');
247                $(this).toggle(target.indexOf(invoice_type) != -1);
248            });
249        });
250
251        $invoice_wrapper.find('._invoice_love_code').on('keyup', function(){
252            $(this).data('checked', false);
253            $invoice_wrapper.find('._love_code_chk_btn').addClass('btn-primary');
254        });
255
256        $('input[name=rdo_term_kind]').on('change', PRICE.setPeriod)
257
258        $('._extend_period_list').find('input[name=value_version]').on('change', PRICE.setVersion)
259    },
260
261    checkLoveCode: function(){
262        var love_code = $('._invoice_love_code').val();
263        if ( love_code.length > 0 ) {
264            $.ajax({
265                "type": "POST",
266                "url": "/admin/ajax/check_invoice_donation_code.cm",
267                "data": {"love_code": love_code},
268                "dataType": "JSON",
269                "success": function(res){
270                    if ( res.msg == 'SUCCESS' ) {
271                        $('._invoice_love_code').data('checked', true);
272                        $('._love_code_chk_btn').removeClass('btn-primary');
273                    } else {
274                        alert(res.msg);
275                    }
276                }
277            });
278        }
279        return false;
280    },
281
282    initParams: function() {
283      const version = this.getParams().version || PRICE.priceData.defaultVersion || 'free';
284      const period = PRICE.priceData.period;
285
286      [version, period].forEach(value => {
287        const $radio = document.querySelector(`input[type="radio"][value="${value}"]`);
288        if (!$radio) return;
289
290        $radio.checked = true;
291      });
292
293      /**
294       * PG 프로모션 조건
295       * pro 버전 - 1, 3, 6개월 선택 시 띄우기
296       * global 버전 - 1, 3개월 선택 시 띄우기
297       */
298      const modal_period = {
299        pro: ['one_month', 'three_month', 'six_month'],
300        global: ['one_month', 'three_month'],
301      }[version] ?? []
302
303      if (modal_period.includes(period)) {
304        PRICE.openPromotionPGModal(version);
305        PRICE.togglePromotionPGInfo(false);
306      } else {
307        PRICE.togglePromotionPGInfo(true);
308      }
309    },
310
311    getTermKindValue: function(period) {
312        const value = {
313            '0': 'non_extension',
314            '1': 'one_month',
315            '3': 'three_month',
316            '6': 'six_month',
317            '12': 'one_year',
318            '24': 'two_year',
319            'coupon': 'coupon',
320        }[period];
321
322        return value ?? 'one_year';
323    },
324
325    getTermKindNumber: function(term_kind) {
326        return {
327            'non_extension': 0,
328            'one_month': 1,
329            'three_month': 3,
330            'six_month': 6,
331            'one_year': 12,
332            'two_year': 24,
333        }[term_kind];
334    },
335
336    getParams: function() {
337      return Object.fromEntries(new URLSearchParams(window.location.search));
338    },
339
340	isUpgradeOrder: function() {
341		if ($('#type').val() !== 'upgrade') {
342			return false;
343		}
344		const selected_version = $('input[name="value_version"]:checked').val();
345		const current_version = (typeof php_site_version !== 'undefined' && php_site_version) ? php_site_version : (PRICE.priceData.currentVersion || '');
346		if (!selected_version || !current_version) {
347			return false;
348		}
349		return selected_version !== current_version;
350	},
351
352	isPaidUpgradeOrder: function() {
353		if (!PRICE.isUpgradeOrder()) {
354			return false;
355		}
356		const selected_version = $('input[name="value_version"]:checked').val();
357		const upgradePriceKeyMap = {
358			starter: 'starter_price_upgrade',
359			pro: 'pro_price_upgrade',
360			global: 'global_price_upgrade',
361		};
362		const key = upgradePriceKeyMap[selected_version] || 'price_upgrade';
363		const price = parseInt(service_info[key], 10);
364		return !isNaN(price) && price > 0;
365	},
366
367    setParams: function(params) {
368      const searchParams = new URLSearchParams(window.location.search);
369      Object.keys(params).forEach(key => searchParams.set(key, params[key]));
370      window.history.replaceState({}, '', `${window.location.pathname}?${searchParams}`);
371    },
372
373    //요금 티어 선택
374    setVersion : function(){
375        var select_version;
376        select_version = $("input[name='value_version']:checked").val();
377        if(select_version == 'free' || select_version == 'sample') {
378            $("._extend_list").hide();
379        } else {
380            $("._extend_list").show();
381        }
382
383        PRICE.setParams({ version: select_version });
384        PRICE.togglePaymentInfoVersionFree();
385        var proc_file = "./payment/proc_ajax.cm";
386        var param = {};
387
388        param.country = this.country;
389        param.mode = "get_site_infomation";
390        param.site_code = $("#sel_site").val();
391        param.version = select_version;
392        param.site_changed = "N";
393        param.term_kind = $("._day_ck").find("[name='rdo_term_kind']:checked").val();
394        param.is_trial_site = $("#is_trial_site").val() || 'N';
395        param.is_terminate_trial = $("#is_terminate_trial").prop("checked") ? 'Y' :'N';
396
397        $.ajax({
398            type: 'POST',
399            url: proc_file,
400            data: param,
401            async: false,
402            success: function(data) {
403                service_info = $.parseJSON(data);
404            }
405        });
406
407        if(service_info.site_version !== "free" && service_info.site_version !== 'sample') {
408            var current_version_span_id = "#div_upgrade_"+service_info.site_version+"_price_sub";
409
410            $("#div_upgrade_starter_price_sub").html(this.makePriceStr(service_info.starter_price_upgrade));
411            $("#div_upgrade_pro_price_sub").html(this.makePriceStr(service_info.pro_price_upgrade));
412            $("#div_upgrade_global_price_sub").html(this.makePriceStr(service_info.global_price_upgrade));
413            $(current_version_span_id).html("");
414
415            $("#div_upgrade_pay").show();
416
417        } else {
418            $(".not_extend").empty().toggleClass('border-bottom', false);
419            $("#div_upgrade_pay").hide();
420            $("#div_upgrade_price").html("");
421        }
422        if(service_info.upgrade_version && service_info.upgrade_version !== "free") {
423            var event_discount = 1;
424            var discount = 1;
425            var site_version_price = service_info['default_price'] * discount * event_discount;
426            var is_event = false;
427
428            if ( typeof service_info['event_discount'] != 'undefined') {
429                service_info['event_discount'] = parseFloat(service_info['event_discount']);
430                if ( !isNaN(service_info['event_discount']) && service_info['event_discount'] !== 0 ) {
431                    event_discount = 1 - (service_info['event_discount'] / 100);
432                }
433            }
434
435            var price_str_per_month = "/" + getLocalizeString('타이틀_월', '', '월');
436            var price_wrapper = {1: "price_one_month", 3: "price_three_month", 6: "price_six_month", 12: "price_one_year", 24: "price_two_year"};
437            for ( var _period in price_wrapper ) {
438                _period = parseInt(_period);
439                if ( typeof service_info['discount'][_period] != "undefined" )  discount = 1 - (service_info['discount'][_period] / 100);
440                site_version_price = service_info['default_price'] * discount * event_discount;
441
442                $("#"+price_wrapper[_period]).html(this.makePriceStr(service_info["default_price"]) + price_str_per_month);
443                $("#"+price_wrapper[_period]).toggle(service_info['default_price'] > site_version_price);
444                $("#discount_" + price_wrapper[_period]).html(this.makePriceStr(site_version_price) + price_str_per_month);
445                $("#discount_" + price_wrapper[_period]).toggleClass('text-primary', (service_info['price'] > site_version_price));
446
447                if(service_info['discount_str'][service_info.upgrade_version][_period] !== ''){
448                    $(".discount_" + price_wrapper[_period] + "_str").text( " (" + getLocalizeString('설명_n프로할인', service_info['discount_str'][service_info.upgrade_version][_period], service_info['discount_str'][service_info.upgrade_version][_period] + '%') + ")");
449                }
450            }
451        }
452        $("#prev_version_price").val(service_info.version_price);
453        $("#request_extend_price").val(service_info.price_extend);
454        $("#request_upgrade_price").val(service_info.price_upgrade);
455
456        service_info.total_price = parseInt(service_info.price_extend, 10);
457        this.setdiscountRate();
458        this.drawPriceSection();
459    },
460    togglePaymentInfoVersionFree : function (){
461      //if Version === Free, this function will be operated Once.
462      if($("input[name='value_version']:checked").val() === 'free'){
463        $("#notify_regularly_payment").addClass("tw-hidden");
464      } else {
465        $("#notify_regularly_payment").removeClass("tw-hidden");
466      }
467    },
468
469    setdiscountRate : function(){
470      var discount_wrapper = {
471        1: "discount_rate_by_version_one_month",
472        3: "discount_rate_by_version_three_month",
473        6: "discount_rate_by_version_six_month",
474        12: "discount_rate_by_version_one_year",
475        24: "discount_rate_by_version_two_year",
476      };
477      switch ( this.country ) {
478        case 'kr':
479          for(var _discount in discount_wrapper){
480            if(_discount === '1'){
481              $(`#${discount_wrapper[_discount]}`).html( getLocalizeString("설명_n개월",_discount,"%1개월") );
482            } else {
483              $(`#${discount_wrapper[_discount]}`).html(
484                getLocalizeString("설명_n개월",_discount,"%1개월")
485                +` (`
486                + service_info.discount[_discount]
487                +'% '
488                + getLocalizeString("설명_할인",'',"off")
489                +`)`
490              )
491            }
492          }
493          break;
494        case 'tw':
495          for(var _discount in discount_wrapper){
496              $(`#${discount_wrapper[_discount]}`).html(
497                getLocalizeString("설명_n개월",_discount,"%1개월")
498                +` (`
499                + service_info.discount_str[service_info['upgrade_version']][_discount]
500                +'% '
501                + getLocalizeString("설명_할인",'',"off")
502                +`)`
503              )
504          }
505          break;
506      }
507    },
508    //기간 선택
509    setPeriod : function(){
510        var proc_file = "./payment/proc_ajax.cm";
511        var param = {};
512
513        param.country = this.country;
514        param.mode = "get_site_infomation";
515        param.site_code = $("#sel_site").val();
516        param.version = service_info.upgrade_version;
517        param.site_changed = "N";
518        param.term_kind = $("._day_ck").find("[name='rdo_term_kind']:checked").val();
519	    console.log('param.term_kind', param.term_kind);
520	    param.is_trial_site = $("#is_trial_site").val() || 'N';
521        param.is_terminate_trial = $("#is_terminate_trial").prop("checked") ? 'Y' :'N';
522
523        /** 쿠폰은 URL에 저장하지 않는다 */
524        if (param.term_kind !== 'coupon') {
525            PRICE.setParams({ period: param.term_kind });
526        }
527
528        $.ajax({
529            type: "POST",
530            url: proc_file,
531            data: param,
532            async: false,
533            success: function(data) {
534                service_info = $.parseJSON(data);
535            }
536        });
537        $("#prev_version_price").val(service_info.version_price);
538        $("#request_extend_price").val(service_info.price_extend);
539        $("#request_upgrade_price").val(service_info.price_upgrade);
540        $("#next_pay_date").html(service_info.next_pay_date + " ");
541
542        service_info.total_price = parseInt(service_info.price_extend, 10);
543        this.paymentInit();
544        this.drawPriceSection();
545        if(this.country === "kr"){
546          this.drawPeriodSection();
547        }
548    },
549
550    setExtraService : function(type) {
551        service_info.price_extend = 0;
552        service_info.price_upgrade = 0;
553
554        if(type === 'ios') {
555            $('#ios_price_list').toggle(service_info["is_ios_infinite"] !== 'Y');
556            if((service_info["is_ios_infinite"] !== 'Y') && $('#ios_price_list').find(':radio:checked').length > 0){
557                var ios_price_selected = $('#ios_price_list').find(':radio:checked').val();
558                if(service_info["ios_price"] && service_info["ios_price"][ios_price_selected] !== undefined && service_info.is_ios_infinite !== 'Y'){
559                    $("#request_ios").val(service_info['ios_price'][ios_price_selected]);
560                    service_info.total_price = parseInt(service_info['ios_price'][ios_price_selected]);
561                }
562            }
563        } else if(type === 'android') {
564            if($("#chk_android").is(":checked") && service_info.app_android === 'N'){
565                $("#request_android").val(parseInt(service_info.android_price));
566                service_info.total_price = parseInt(service_info.android_price);
567            }
568            $("#div_android_price_wrapper").find(".text-line-through").html(this.makePriceStr(100000));
569            $("#div_android_price_wrapper").find(".text-primary").html(this.makePriceStr(service_info.android_price));
570        } else if(type === 'adult') {
571            $("#auth_service_price_dream_security").html(this.makePriceStr(service_info.auth_service_price_dream_security));
572            $("#auth_service_price_mobilians").html(this.makePriceStr(service_info.auth_service_price_mobilians));
573            $("#auth_service_price_inicis").html(this.makePriceStr(service_info.auth_service_price_inicis));
574
575            var auth_comobination_price_html = this.makePriceStr(service_info.auth_service_price_combination);
576            if(service_info.auth_service_price_combination === 0) auth_comobination_price_html = "<del class='text-gray-bright'>30,000원</del>"+"<span class='text-danger'> "+auth_comobination_price_html+"</span>";
577
578            $("#auth_service_price_combination").html(auth_comobination_price_html);
579
580            service_info.total_price = 0;
581
582            $("#chk_auth_service_dream_security").change(function(){
583                if($("#chk_auth_service_dream_security").prop("checked")){
584                    service_info.total_price += parseInt(service_info.auth_service_price_dream_security);
585                    $("#request_auth_service_dream_security").val(service_info.auth_service_price_dream_security);
586                }else{
587                    service_info.total_price -= parseInt(service_info.auth_service_price_dream_security);
588                    $("#request_auth_service_dream_security").val(0);
589                }
590                PRICE.drawPriceSection();
591            });
592            $("#chk_auth_service_mobilians").change(function(){
593                if($("#chk_auth_service_mobilians").prop("checked")){
594                    $("._auth_mobilians_description").show();
595
596                    service_info.total_price += parseInt(service_info.auth_service_price_mobilians);
597                    $("#request_auth_service_mobilians").val(service_info.auth_service_price_mobilians);
598                }else{
599                    $("._auth_mobilians_description").hide();
600
601                    service_info.total_price -= parseInt(service_info.auth_service_price_mobilians);
602                    $("#request_auth_service_mobilians").val(0);
603                }
604                PRICE.drawPriceSection();
605            });
606            $("#chk_auth_service_inicis").change(function(){
607                if($("#chk_auth_service_inicis").prop("checked")){
608                    service_info.total_price += parseInt(service_info.auth_service_price_inicis);
609                    $("#request_auth_service_inicis").val(service_info.auth_service_price_inicis);
610                }else{
611                    service_info.total_price -= parseInt(service_info.auth_service_price_inicis);
612                    $("#request_auth_service_inicis").val(0);
613                }
614                PRICE.drawPriceSection();
615            });
616            $("#chk_auth_service_combination").change(function(){
617                if($("#chk_auth_service_combination").prop("checked")){
618                    service_info.total_price += parseInt(service_info.auth_service_price_combination);
619                    $("#request_auth_service_combination").val(service_info.auth_service_price_combination);
620                }else{
621                    service_info.total_price -= parseInt(service_info.auth_service_price_combination);
622                    $("#request_auth_service_combination").val(0);
623                }
624                PRICE.drawPriceSection();
625            });
626        }
627        PRICE.drawPriceSection();
628
629    },
630
631    getTotalDiscountAmount: function() {
632        var term_kind = $("._day_ck").find("[name='rdo_term_kind']:checked").val();
633        var term_kind_number = PRICE.getTermKindNumber(term_kind);
634        var discount_percent = service_info.discount[term_kind_number];
635
636        if (!discount_percent) {
637            return {
638                rate: 0,
639                amount: 0,
640            };
641        }
642
643        var price_rate = discount_percent / 100;
644        var discount_amount = (service_info['default_price'] * price_rate) * term_kind_number;
645
646        return {
647            rate: price_rate * 100,
648            amount: discount_amount,
649        };
650    },
651
652    shouldCalculateCouponDiscountPrice: function() {
653        if (PRICE.couponData === null) {
654            return false;
655        }
656
657		if (PRICE.isPaidUpgradeOrder()) {
658			return false;
659		}
660
661        if (PRICE.couponData.couponType === 'period') {
662			return false;
663        }
664
665        return true;
666    },
667
668    calculateCouponDiscountPrice: function(total_price) {
669        if (!PRICE.shouldCalculateCouponDiscountPrice()) {
670            return 0;
671        }
672
673        const couponData = PRICE.couponData;
674
675        if (couponData.couponType === 'fixedAmount') {
676            return couponData.discountAmount;
677        }
678
679        return total_price ? total_price * (couponData.discountRate / 100) : 0;
680    },
681
682    drawPriceSection : function() {
683        var default_price_extend = parseInt(service_info.default_price_extend, 10);
684        var total_discount_amount = PRICE.getTotalDiscountAmount();
685
686        var total_price = parseInt(service_info.total_price);
687        var upgrage_price = parseInt(service_info.price_upgrade);
688        var coupon_discount_price = PRICE.calculateCouponDiscountPrice(total_price);
689        var price_tax = 0;
690        var sum_data = Math.max(total_price + upgrage_price - coupon_discount_price, 0);
691        var next_pay_price = 0;
692
693		switch ( this.country ) {
694			default:
695			case KOREA_COUNTRY_CODE:
696				price_tax = parseInt(sum_data * service_info.vat, 10);
697				sum_data += price_tax;
698				next_pay_price = total_price + parseInt(total_price * service_info.vat, 10);
699				break;
700			case TAIWAN_COUNTRY_CODE:
701				total_price = Math.round(total_price / (1 + service_info.vat));
702				upgrage_price = Math.round((upgrage_price / (1 + service_info.vat)));
703				price_tax = sum_data - (total_price + upgrage_price);
704				break;
705		}
706
707        // upgrade케이스가 아닌 경우 1의자리 절삭한다
708        if (upgrage_price == 0) {
709          sum_data = parseInt(sum_data / 10, 10) * 10;
710        }
711
712		$("#div_total_price").html(this.makePriceStr(default_price_extend));
713		$("#div_upgrade_price").html(this.makePriceStr(upgrage_price));
714		$("#div_total_tax").html(this.makePriceStr(price_tax));
715		$("#div_total").html(this.makePriceStr(sum_data));
716
717        var term_kind = $("._day_ck").find("[name='rdo_term_kind']:checked").val();
718        if (this.country === KOREA_COUNTRY_CODE && term_kind === 'non_extension' && $('#type').val() === 'upgrade') {
719            var next_regular_payment_price = parseInt(service_info.regular_payment_price, 10);
720            if (!isNaN(next_regular_payment_price) && next_regular_payment_price > 0) {
721                next_pay_price = next_regular_payment_price;
722            }
723        }
724
725		$("#regular_payment_price").html(this.makePriceStr(next_pay_price));
726
727        if (total_discount_amount.rate === 0) {
728            $("#div_discount_amount").hide();
729            $("#div_discount_amount").find('._discount_rate').text('');
730            $("#div_discount_amount").find('._discount_amount').text('');
731        } else {
732            $("#div_discount_amount").show();
733            $("#div_discount_amount").find('._discount_rate').text(`${total_discount_amount.rate}% 할인`);
734            $("#div_discount_amount").find('._discount_amount').text(`-${total_discount_amount.amount.toLocaleStr
734ing()}원`);
735        }
736
737        if (PRICE.getCouponData() === null) {
738            $("#div_coupon_discount_amount").hide();
739            $("#div_discount_amount").find('._coupon_discount_amount').text('');
740
741            $("._coupon_description").hide();
742        } else {
743            $("#div_coupon_discount_amount").show();
744            $("#div_coupon_discount_amount").find('._coupon_discount_amount').text(coupon_discount_price ? `-${coupon_discount_price.toLocaleString()}원` : '0원');
745
746            $("._coupon_description").show();
747        }
748
749        if ( this.country == 'tw' ) {
750            this.checkLimit(sum_data);
751        }
752    },
753    drawPeriodSection : function(){
754      let period = "12개월";
755	  switch ($("._day_ck").find("[name='rdo_term_kind']:checked").val()){
756	    case "non_extension":
757	      var next_period = parseInt(service_info.regular_payment_period, 10);
758	      if (!isNaN(next_period) && next_period > 0) {
759	        $("#regular_payment_period").html(getLocalizeString("설명_n개월", next_period, next_period + "개월"));
760	      } else {
761	        $("#regular_payment_period").html('12개월');
762	      }
763	      $("#select_promotion_code").removeClass('tw-hidden');
764	      $("#view_select_promotion_code").addClass('tw-hidden');
765	    break;
766        case "one_month":
767          $("#regular_payment_period").html('1개월');
768	      $("#select_promotion_code").removeClass('tw-hidden');
769	      $("#view_select_promotion_code").addClass('tw-hidden');
770          break;
771        case "three_month":
772          $("#regular_payment_period").html('3개월');
773	      $("#select_promotion_code").removeClass('tw-hidden');
774	      $("#view_select_promotion_code").addClass('tw-hidden');
775          break;
776        case "six_month":
777          $("#regular_payment_period").html('6개월');
778	      $("#select_promotion_code").removeClass('tw-hidden');
779	      $("#view_select_promotion_code").addClass('tw-hidden');
780          break;
781        case "one_year":
782          $("#regular_payment_period").html('12개월');
783	      $("#select_promotion_code").removeClass('tw-hidden');
784	      $("#view_select_promotion_code").addClass('tw-hidden');
785          break;
786        case "two_year":
787          $("#regular_payment_period").html('24개월');
788	      $("#select_promotion_code").removeClass('tw-hidden');
789	      $("#view_select_promotion_code").addClass('tw-hidden');
790          break;
791        case "coupon" :
792          $("#select_promotion_code").addClass('tw-hidden');
793          $("#view_select_promotion_code").removeClass('tw-hidden');
794          $("#view_select_promotion_code").html(`
795            <li class="tw-flex tw-justify-between tw-items-center tw-mb-[8px]">
796              <label class="tw-m-0">총 결제 금액</label>
797              <p class="tw-p-0 tw-m-0 tw-font-bold tw-text-[12px] tw-text-[#757575] text-primary tw-text-[18px]">무료</p>
798            </li>
799          `);
800        default : $("#regular_payment_period").html('12개월');
801      }
802
803    },
804
805    checkLimit: function(total_price){
806        // 일단은 임시 처리 개념.. (결제 수단 별로 결제 한도가 다름)
807        var _PAYMENT_LIMIT = {
808            "card": 	{"min": 1, "max": 200000},
809            "webatm": 	{"min": 11, "max": 30000},
810            "atm": 		{"min": 11, "max": 30000},
811            "cvs": 		{"min": 31, "max": 20000},
812            "barcode": 	{"min": 16, "max": 30000},
813        };
814
815        var disabled_list = [];
816        disabled_list.push("android");
817        for ( var key in _PAYMENT_LIMIT ) {
818            //if ( _PAYMENT_LIMIT[key]['min'] > total_price ) disabled_list.push(key);
819            if ( _PAYMENT_LIMIT[key]['max'] < total_price ) disabled_list.push(key);
820        }
821
822        if ( disabled_list.length > 0 ) {
823            var $payment_type = $('#div_payment_type');
824            $payment_type.find('.item-wrap').find('a.item').each(function(){
825                if ( disabled_list.indexOf($(this).data('paymethod')) !== -1 )	{
826                    $(this).addClass('disabled');
827                } else {
828                    $(this).removeClass('disabled');
829                }
830            });
831
832            if ( $payment_type.find('.item-wrap').find('a.item.active').hasClass('disabled') ) {
833                $payment_type.find('.item-wrap').find('a.item.active').removeClass('active');
834                if ( $payment_type.find('.item-wrap').find('a.item:not(.disabled)').length > 0 ) {
835                    var $new_paymethod = $payment_type.find('.item-wrap').find('a.item:not(.disabled)').first();
836                    $new_paymethod.addClass('active');
837                    $('input[name=sel_payment_type]').val($new_paymethod.data('paymethod'));
838                }
839            }
840        }
841    },
842
843    submit : function(session_uid = ""){
844        // 아직 로딩이 완료되지 않은 상태
845        if ( typeof service_info == 'undefined' ) return false;
846
847        var is_error = false;
848        var $form = $('#payment_submit_form');
849        var form_data = $form.serializeObject();
850        let payment_type ='';
851        switch (form_data.type){
852          case'ios': payment_type ='ios';
853            break;
854          case 'android' : payment_type ='android';
855            break;
856          case 'adult' : payment_type ='adult';
857            break;
858        }
859        if (payment_type !== 'adult' && payment_type !== 'android' && payment_type !== 'ios' && this.country === KOREA_COUNTRY_CODE) {
860          const term_kind = $("._day_ck").find("[name='rdo_term_kind']:radio:checked").val();
861          const upgrade_price = parseInt(form_data.request_upgrade_price || 0, 10);
862          const is_upgrade_non_extension = form_data.type === 'upgrade' && term_kind === 'non_extension' && upgrade_price > 0;
863          const is_regular_period = term_kind !== 'coupon' && term_kind !== 'non_extension';
864
865          if ((is_regular_period || is_upgrade_non_extension) && form_data.billing_code === undefined) {
866            alert('결제할 카드를 선택해 주세요.');
867            return false;
868          }
869        }
870      if ( this.country == KOREA_COUNTRY_CODE ) {
871            if($("#chk_ios").is(":checked")&& !$('#ios_price_list').find(':radio:checked').length){
872                if (service_info.is_ios_infinite !== 'Y') {
873                    is_error = true;
874                    alert(getLocalizeString("설명_Ios사용기간선택", '', "IOS APP의 사용 기간을 선택해주세요."));
875                    return false;
876                }
877            }
878        }
879
880        if ( this.country == TAIWAN_COUNTRY_CODE ) {
881            var invoice_type = form_data['invoice[type]'];
882            if ( invoice_type.trim() == '' ) {
883                is_error = true;
884                alert(getLocalizeString('설명_통일영수증정보를입력해주세요', '', '통일영수증 정보를 입력해주세요.'));
885                return false;
886            }
887            $form.find('._invoice_data_wrapper').find('._invoice_data').each(function(){
888                var target = $(this).data('target');
889                if ( ['all', invoice_type].indexOf(target) != -1 ) {
890                    if ( $(this).find('input').val().trim() == '' ) is_error = true;
891                }
892            });
893
894            if ( is_error ) {
895                alert(getLocalizeString('설명_통일영수증정보를모두입력해주세요', '', '통일 영수증 정보를 모두 입력해 주세요.'));
896                return false;
897            }
898
899            if ( invoice_type == 'donation' ) {
900                if ( !$('._invoice_love_code').data('checked') ) {
901                    is_error = true;
902                    alert(getLocalizeString('설명_기부코드를체크해주세요', '', '기부코드를 체크 해 주세요.'));
903                    return false;
904                }
905            }
906        }
907
908
909        if( form_data['type'] === 'upgrade' && form_data['rdo_term_kind'] === 'coupon' ){ // 쿠폰일때는 결제 금액이 없어서 결제금액 확인 패스
910        }else{
911            if ( ! (this.checkTotalPrice(form_data) > 0) && service_info.auth_service_combination === 0 && parseInt(form_data.request_auth_service_combination) === 0) {
912                is_error = true;
913                alert(getLocalizeString('설명_결제금액을확인해주세요', '', '결제 금액을 확인해주세요.'));
914                return false;
915            }
916        }
917
918        if (this.country == "kr" && !is_error) {
919        switch ($("._day_ck").find("[name='rdo_term_kind']:radio:checked").val()){
920          case 'one_month':
921          case 'three_month':
922          case 'six_month':
923          case 'one_year':
924          default: {
925            $form.submit();
926          }
927            break;
928        }
929      } else {
930        if (!is_error) {
931          $form.submit();
932        }
933      }
934        return false;
935    },
936
937    checkTotalPrice: function(form_data){
938        var total_price = 0;
939        var check_list = ['1','request_upgrade_price', 'request_extend_price', 'request_android', 'request_ios', 'request_auth_service_dream_security', 'request_auth_service_mobilians', 'request_auth_service_inicis', 'request_auth_service_combination'];
940        for (var _key in check_list ) {
941            if ( typeof form_data[check_list[_key]] != "undefined" ) {
942                total_price += isNaN( parseInt(form_data[check_list[_key]]) ) ? 0 : parseInt(form_data[check_list[_key]]);
943            }
944        }
945        return total_price;
946    },
947
948    paymentInit : function(){
949        if($("._day_ck").find("[name='rdo_term_kind']:checked").val() === 'coupon'){
950            $("._total_price_wrap").hide();
951            $("#div_payment_type").hide();
952            $("#btn_payment").hide();
953            $("#btn_coupon").show();
954            $('#payment_mode').val('price_page_coupon');
955            $("#select_card_container").hide();
956            $("#select_card_submit_btn").attr("disabled", false);
957	          $("._promotion_text_info").css('display', 'flex');
958        }else{
959            $("._total_price_wrap").show();
960            $("._payment_type_wrap").show();
961            $("#btn_payment").show();
962            $("#btn_coupon").hide();
963            $('#payment_mode').val('price_page');
964            $("#select_card_container").show();
965	          $("._promotion_text_info").hide();
966            // 만약
967          if($("#select_card_container")){
968            $("input[name='billing_code']").val() ?
969              $("#select_card_submit_btn").attr("disabled", false)
970              :
971              $("#select_card_submit_btn").attr("disabled", true);
972          }
973        }
974    },
975
976    // admin/payment/service.sub 에서 사용
977    updateRegularPayment : function(id){
978        var url = "/payment/index.cm";
979
980        var form = document.createElement("form");
981        form.setAttribute("method", "post");
982        form.setAttribute("action", url);
983
984        var hiddenField = document.createElement("input");
985        hiddenField.setAttribute("type", "hidden");
986        hiddenField.setAttribute("name", "site_idx");
987        hiddenField.setAttribute("value", id);
988        form.appendChild(hiddenField);
989        document.body.appendChild(form);
990
991        var hiddenField2 = document.createElement("input");
992        hiddenField2.setAttribute("type", "hidden");
993        hiddenField2.setAttribute("name", "payment_mode");
994        hiddenField2.setAttribute("value", "regular_payment_update");
995        form.appendChild(hiddenField2);
996        document.body.appendChild(form);
997
998        var hiddenField3 = document.createElement("input");
999        hiddenField3.setAttribute("type", "hidden");
1000        hiddenField3.setAttribute("name", "pg_back_url");
1001        hiddenField3.setAttribute("value", "/admin/payment");
1002        form.appendChild(hiddenField3);
1003        document.body.appendChild(form);
1004
1005        var hiddenField4 = document.createElement("input");
1006        hiddenField4.setAttribute("type", "hidden");
1007        hiddenField4.setAttribute("name", "is_admin");
1008        hiddenField4.setAttribute("value", "Y");
1009        form.appendChild(hiddenField4);
1010        document.body.appendChild(form);
1011
1012        var hiddenField5 = document.createElement("input");
1013        hiddenField5.setAttribute("type", "hidden");
1014        hiddenField5.setAttribute("name", "is_regular_change");
1015        hiddenField5.setAttribute("value", "Y");
1016        form.appendChild(hiddenField5);
1017        document.body.appendChild(form);
1018
1019        form.submit();
1020    },
1021
1022  reasonsForLeave : function (id, next_pay_date) {
1023      $.ajax({
1024        type: 'POST',
1025        data: { idx : id, next_pay_date: next_pay_date },
1026        url: ('/admin/ajax/collection_of_reasons_for_leave.cm'),
1027        dataType: 'json',
1028        async: true,
1029        cache: false,
1030        success: function (res) {
1031          if (res.msg === 'SUCCESS') {
1032            $.cocoaDialog.open({ type: 'collection_of_reasons_for_leave', custom_popup: res.html });
1033          } else {
1034            console.log(res.msg);
1035          }
1036        }
1037      });
1038  },
1039
1040  confirmCancelRegularPayment : function () {
1041    if (
1042      confirm(getLocalizeString('설명_정기결제해지를취소하시겠습니까','','정기결제 해지를 취소하시겠습니까?'))
1043    ) {
1044      $.cocoaDialog.close();
1045    }
1046  },
1047
1048  unsetRegularPaymentSubmitReason : function( idx ) {
1049      const reasonForm = $('form#reasons_for_leave');
1050      const reasonData = reasonForm.serializeObject();
1051      const checkboxDissatisfaction = reasonForm.find('#dissatisfaction_other_reason_checkbox_0');
1052      const dissatisfactionOtherReasonTextareaWarp = reasonForm.find('#dissatisfaction_other_reason_0');
1053      const checkboxUseOtherService = reasonForm.find('#dissatisfaction_other_reason_checkbox_1');
1054      const otherServiceeasonTextareaWarp = reasonForm.find('#dissatisfaction_other_reason_1');
1055      const radioOtherReason = reasonForm.find('#radio_other_reason');
1056      const otherReasonTextareaWrap = reasonForm.find('#other_reason');
1057
1058    if (checkboxDissatisfaction.prop('checked') === true ) {
1059      const reason = dissatisfactionOtherReasonTextareaWarp.find('textarea');
1060      const showReason = dissatisfactionOtherReasonTextareaWarp.siblings('.show_alert');
1061      if ( reason.val().trim().length <= 0 ) {
1062        showReason.removeClass('tw-hidden');
1063        dissatisfactionOtherReasonTextareaWarp.removeClass('active:tw-border-[#1A6DFF] focus-within:tw-border-[#1A6DFF]');
1064        dissatisfactionOtherReasonTextareaWarp.addClass('active:tw-border-[#DD3344] focus-within:tw-border-[#DD3344] tw-border-[#DD3344]');
1065        return false;
1066      } else {
1067        showReason.addClass('tw-hidden');
1068      }
1069    }
1070    if (checkboxUseOtherService.prop('checked') === true ) {
1071      const reason = otherServiceeasonTextareaWarp.find('textarea');
1072      const showReason = otherServiceeasonTextareaWarp.siblings('.show_alert');
1073      if ( reason.val().trim().length <= 0 ) {
1074        showReason.removeClass('tw-hidden');
1075        otherServiceeasonTextareaWarp.removeClass('active:tw-border-[#1A6DFF] focus-within:tw-border-[#1A6DFF]');
1076        otherServiceeasonTextareaWarp.addClass('active:tw-border-[#DD3344] focus-within:tw-border-[#DD3344] tw-border-[#DD3344]');
1077        return false;
1078      } else {
1079        showReason.addClass('tw-hidden');
1080      }
1081    }
1082    if ( radioOtherReason.prop('checked') === true ) {
1083      const reason = otherReasonTextareaWrap.find('textarea');
1084      const showReason = otherReasonTextareaWrap.siblings('.show_alert');
1085      if (reason.val().trim().length <= 0) {
1086        console.log(reason.val().trim().length);
1087        showReason.removeClass('tw-hidden');
1088        otherReasonTextareaWrap.removeClass('active:tw-border-[#1A6DFF] focus-within:tw-border-[#1A6DFF]');
1089        otherReasonTextareaWrap.addClass('active:tw-border-[#DD3344] focus-within:tw-border-[#DD3344] tw-border-[#DD3344]');
1090        return false;
1091      } else {
1092        showReason.addClass('tw-hidden');
1093      }
1094    }
1095    $.cocoaDialog.close();
1096    $.ajax({
1097      url: "/admin/payment/update_regular_payment.cm",
1098      data: { "mode": "off", "idx": idx , reasonData : reasonData },
1099      type: "POST",
1100      dataType: "json",
1101      success: function(res){
1102        if(res['msg'] === 'SUCCESS') {
1103          $.cocoaDialog.open({ type: 'complete_submit_modal', custom_popup: res.html , width: 380 });
1104        } else {
1105          alert(res['msg']);
1106        }
1107      },
1108    });
1109  },
1110
1111  unsetRegularPayment : function(id, next_pay_date){
1112        if ( confirm(getLocalizeString("설명_정기결제해지알림", next_pay_date, "정기결제 해지시 다음 결제일부터 자동 결제 처리되지 않습니다.\n지금 해지해도 %1까지는 사용이 가능합니다.\n정기결제를 해지하시겠습니까?")) ) {
1113            $.ajax({
1114                "url": "/admin/payment/update_regular_payment.cm",
1115                "data": { "mode": "off", "idx": id },
1116                "type": "POST",
1117                "dataType": "json",
1118                "success": function(res){
1119                    if ( res['msg'] === 'SUCCESS' ) {
1120                        alert(getLocalizeString("설명_정기결제해지완료",'', "정기결제 해지가 완료 되었습니다."));
1121                        location.reload();
1122                    } else {
1123                        alert(res['msg']);
1124                    }
1125                }
1126            });
1127        }
1128    },
1129
1130    makePriceStr: function(price){
1131        var price_str = price;
1132        switch ( this.country ) {
1133            case KOREA_COUNTRY_CODE:
1134                price_str = getLocalizeString("설명_n원", money_format(price), "%1원");
1135                break;
1136            case TAIWAN_COUNTRY_CODE:
1137                price_str = "$" + money_format(price);
1138                break;
1139        }
1140        return price_str;
1141    },
1142    openPromotionPGModal: function(promotion_pg_type) {
1143        const cache_key = `promotion_pg_modal_${promotion_pg_type}`
1144
1145        const get_promotion_pg_modal = () => {
1146            return new Promise((resolve, reject) => {
1147                if (this.cache[cache_key]) {
1148                    return resolve(this.cache[cache_key])
1149                }
1150
1151                $.ajax({
1152                    type: 'POST',
1153                    dataType: 'html',
1154                    url: '/admin/ajax/promotion_pg_modal.cm',
1155                    data: { promotion_pg_type },
1156                    cache: false,
1157                    success: (html) => {
1158                        this.cache[cache_key] = html
1159
1160                        resolve(this.cache[cache_key])
1161                    },
1162                    error: reject
1163                })
1164            })
1165        }
1166
1167        get_promotion_pg_modal().then(html => {
1168            const $html = $(html);
1169
1170            $.cocoaDialog.open({
1171                type: 'promotion_pg_modal',
1172                custom_popup: $html,
1173                backdrop: false,
1174            }, function() {
1175                $html.find('._btn_submit').off('click').on('click', function() {
1176                    const period_value = $html.find('#period_value').val()
1177                    const period_element = $('._day_ck').find(`input[value=${period_value}]`)
1178
1179                    period_element.prop('checked', true)
1180
1181                    PRICE.setPeriod()
1182                    PRICE.togglePromotionPGInfo(true);
1183
1184                    $.cocoaDialog.close()
1185                })
1186            })
1187        }).catch((() => window.alert('프로모션 팝업을 불러오는도중 오류가 발생하였습니다')))
1188    },
1189    togglePromotionPGInfo: function(is_open) {
1190        $('._promotion_pg_info').toggle(is_open)
1191    },
1192    handleChangeNonPeriod: function() {
1193        PRICE.setPeriod()
1194        PRICE.togglePromotionPGInfo(false);
1195    },
1196    handleChangePeriod: function(el) {
1197        const allow_versions = ['pro', 'global']
1198        const version = $('._extend_period_list').find('input[name=value_version]:checked').val().toLowerCase()
1199        const value = $(el).val();
1200
1201        PRICE.setPeriod();
1202
1203        if (!allow_versions.includes(version)) {
1204            PRICE.togglePromotionPGInfo(false);
1205
1206            return false
1207        }
1208
1209        /**
1210         * PG 프로모션 조건
1211         * pro 버전 - 1, 3, 6개월 선택 시 띄우기
1212         * global 버전 - 1, 3개월 선택 시 띄우기
1213         */
1214        const modal_period = {
1215            pro: ['one_month', 'three_month', 'six_month'],
1216            global: ['one_month', 'three_month'],
1217        }[version] ?? []
1218
1219        if (modal_period.includes(value)) {
1220            PRICE.openPromotionPGModal(version);
1221            PRICE.togglePromotionPGInfo(false);
1222        } else {
1223            PRICE.togglePromotionPGInfo(true);
1224        }
1225    },
1226    handleChangeVersion: function() {
1227        const $el = $('input[name=rdo_term_kind]:checked')
1228
1229        PRICE.setVersion()
1230        PRICE.handleChangePeriod($el)
1231    },
1232    getServerInfo: function() {
1233        return service_info;
1234    },
1235    getCouponData: function() {
1236      return PRICE.couponData;
1237    },
1238	setCouponData: function(couponData) {
1239		if (PRICE.isPaidUpgradeOrder()) {
1240			return;
1241		}
1242		PRICE.couponData = couponData;
1243	},
1244    clearCouponData: function() {
1245        PRICE.couponData = null;
1246    },
1247};
1248
1249const ADMIN_ADD_CARD = (function(){
1250  const istrue = (e) => e === true;
1251  const reg_num = /\D/g;
1252  const reg_exception =/[a-z|A-Z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣|\{\}\[\]\/?.,;:|\)~`!^\-_+<>@\#$%&\\\=\(\'\"]/g;
1253  const reg_month = /^(0[1-9]|1[0-2])/g
1254
1255  const getImwebMainDomain = function() {
1256    return TEST_SERVER ? 'https://imtest.me' : 'https://imweb.me';
1257  };
1258
1259  const applyImwebMainDomainToRegularPaymentTermsLinks = function() {
1260    const imwebMainDomain = getImwebMainDomain();
1261    document.querySelectorAll('a[href^="/payment/regular_payment/terms/"]').forEach(function(anchor) {
1262      const href = anchor.getAttribute('href');
1263      if (typeof href !== 'string') {
1264        return;
1265      }
1266      anchor.setAttribute('href', imwebMainDomain + href);
1267    });
1268  };
1269  // 카드 번호 유효성 검사
1270  let array_card_number_check = [];
1271  let array_period = [];
1272  let is_personal_registration_number_check = false;
1273  let is_checkbox_check = false;
1274  // 변수 초기화 함수
1275  const resetValidationState = function() {
1276    array_card_number_check = [];
1277    array_period = [];
1278    is_personal_registration_number_check = false;
1279    is_checkbox_check = false;
1280  };
1281  const cardNumberCheck = function () {
1282    const add_card_numb_container = document.getElementById('add_card_numb_container');
1283    if(add_card_numb_container){
1284      const add_card_numb_input = document.querySelectorAll('.add_card_numb_input');
1285      const card_number_input_container = document.querySelector('#card_number_input_container');
1286      const _alert_msg_card = document.querySelector('._alert_msg_card');
1287      const isPassVaildation = (element,index) =>{
1288        const length = element.value.length;
1289        if(index === 3){
1290          if(length <= 2) {
1291            return false;
1292          } else {
1293            return true;
1294          }
1295        } else {
1296          if(length <= 3){
1297            return false;
1298          } else {
1299            return true;
1300          }
1301        }
1302      }
1303      const alertChangeCssByFlag = (flag=false) =>{
1304        if(flag) {
1305          card_number_input_container.classList.add('tw-border-[#EEEEEE]');
1306          card_number_input_container.classList.remove('tw-border-danger-500');
1307          card_number_input_container.classList.remove('tw-mb-[8px]');
1308        } else {
1309          card_number_input_container.classList.remove('tw-border-[#EEEEEE]');
1310          card_number_input_container.classList.add('tw-border-danger-500');
1311          card_number_input_container.classList.add('tw-mb-[8px]');
1312        }
1313      }
1314
1315      add_card_numb_input.forEach((element,index) => {
1316        element.addEventListener('keydown',(event)=>{
1317          if (event.key === '*') {
1318            event.preventDefault();
1319          }
1320        })
1321        element.addEventListener('focusout' , (event)=>{
1322          let is_card_number_pass = false;
1323          element.value = element.value.replace(reg_exception,'');
1324          is_card_number_pass = isPassVaildation(element,index);
1325          array_card_number_check[index] = is_card_number_pass;
1326          alertChangeCssByFlag(is_card_number_pass);
1327          if(array_card_number_check.every(istrue)){
1328            _alert_msg_card.innerHTML = '';
1329            activateButton();
1330          } else{
1331            if(element.value.length === 0){
1332              _alert_msg_card.innerHTML = '카드번호를 입력해 주세요.';
1333            } else if(element.value.length <4){
1334              _alert_msg_card.innerHTML = '유효하지 않은 카드번호입니다.';
1335            }
1336            alertChangeCssByFlag();
1337            activateButton();
1338          }
1339        })
1340      })
1341    }
1342  }
1343  // 유효기간 유효성 검사
1344  const periodCheck = function () {
1345    const expiration_period_container = document.getElementById('expiration_period_container');
1346    const expiration_input = expiration_period_container.querySelectorAll('.expiration_input');
1347    const _alert_msg_expiration = expiration_period_container.querySelector('._alert_msg_expiration');
1348    const _expiration__input = expiration_period_container.querySelector('._expiration__input');
1349    expiration_input.forEach((el, i) =>{
1350      el.addEventListener('focusout',()=>{
1351        el.value = el.value.replace(reg_num,'');
1352
1353        if(el.value.length === 0) {
1354          array_period[i] = false;
1355          activateButton();
1356        } else if( expiration_input[0].value.replace(reg_month,'') ||  el.value.length < 2 ) {
1357          array_period[i] = false;
1358          activateButton();
1359        } else if(el.value.length === 2) {
1360          array_period[i] = true;
1361          activateButton();
1362        }
1363
1364        if(array_period.every(istrue)){
1365          _expiration__input.classList.add('tw-border-[#E0E0E0]');
1366          _expiration__input.classList.remove('tw-border-danger-500','tw-mb-[8px]');
1367          _alert_msg_expiration.innerHTML = '';
1368          activateButton();
1369        } else if(el.value.length === 0) {
1370          _expiration__input.classList.remove('tw-border-[#E0E0E0]');
1371          _expiration__input.classList.add('tw-border-danger-500','tw-mb-[8px]');
1372          _alert_msg_expiration.innerHTML = '유효기간을 입력해 주세요.';
1373          activateButton();
1374        } else if( expiration_input[0].value.replace(reg_month,'') ||  el.value.length < 2 ) {
1375          _expiration__input.classList.remove('tw-border-[#E0E0E0]');
1376          _expiration__input.classList.add('tw-border-danger-500','tw-mb-[8px]');
1377          _alert_msg_expiration.innerHTML = '유효기간을 입력해 주세요.';
1378          activateButton();
1379        }
1380      })
1381    })
1382  }
1383  // 주민등록번호 유효성 검사
1384  const personalRegistrationNumberCheck = function() {
1385    const card_type_container_input = document.querySelectorAll('input[name="card_type"]');
1386    const personal_registration_number_container = document.getElementById('personal_registration_number_container');
1387    const personal_registration_number_input = personal_registration_number_container.querySelector('.personal_registration_number_input');
1388    const _alert_msg_personal_registration_number = personal_registration_number_container.querySelector('._alert_msg_personal_registration_number');
1389    let check_personal_registration_number_input = '';
1390    personal_registration_number_input.addEventListener('focusout',(el)=>{
1391      card_type_container_input.forEach(el=>{
1392        if(el.checked){
1393          check_personal_registration_number_input = el.value;
1394        }
1395      })
1396      el.target.value = el.target.value.replace(reg_num ,'');
1397      if(el.target.value === ''){
1398        el.target.classList.remove('tw-border-b-[#E0E0E0]');
1399        el.target.classList.add('tw-border-b-danger-500','tw-mb-[8px]');
1400        is_personal_registration_number_check = false;
1401        activateButton();
1402        check_personal_registration_number_input === "personal" ? _alert_msg_personal_registration_number.innerHTML = '생년월일을 입력하세요.' : _alert_msg_personal_registration_number.innerHTML = '사업자등록번호를 입력하세요.';
1403      } else if(el.target.value.length !== 6 && check_personal_registration_number_input === "personal") {
1404        el.target.classList.remove('tw-border-b-[#E0E0E0]');
1405        el.target.classList.add('tw-border-b-danger-500','tw-mb-[8px]');
1406        _alert_msg_personal_registration_number.innerHTML = '생년월일 6자리를 입력하세요.';
1407        is_personal_registration_number_check = false;
1408        activateButton();
1409      }  else if(el.target.value.length !== 10 && check_personal_registration_number_input === "business") {
1410        el.target.classList.remove('tw-border-b-[#E0E0E0]');
1411        el.target.classList.add('tw-border-b-danger-500','tw-mb-[8px]');
1412        _alert_msg_personal_registration_number.innerHTML = '사업자등록번호를 입력하세요.';
1413        is_personal_registration_number_check = false;
1414        activateButton();
1415      }
1416      else {
1417        el.target.classList.add('tw-border-b-[#E0E0E0]');
1418        el.target.classList.remove('tw-border-b-danger-500','tw-mb-[8px]');
1419        _alert_msg_personal_registration_number.innerHTML = '';
1420        is_personal_registration_number_check = true;
1421        activateButton();
1422      }
1423    })
1424
1425  }
1426  // 정책 동의 체크 검사
1427  const checkAgreePolicy = function () {
1428    const checkbox_policy_container = document.getElementById('checkbox_policy_container');
1429    const policy_agree_check_all = checkbox_policy_container.querySelector('#policy_agree_check_all');
1430    const _agree = checkbox_policy_container.querySelectorAll('._agree');
1431    const btn_new_card_enroll = document.querySelector('#btn_new_card_enroll');
1432    const _alert_msg_policy = document.querySelector('._alert_msg_policy');
1433
1434    // 결제 플랫폼 슬림 폼(data-pp-billing=1): 약관 1개 + 전체동의 체크박스 없음 → 개수 비의존 + null 가드
1435    const _pp_container = document.getElementById('add_credit_card_container');
1436    if (_pp_container && _pp_container.getAttribute('data-pp-billing') === '1') {
1437      const isAllAgreed = function () {
1438        return _agree.length > 0 && Array.prototype.every.call(_agree, function (el) { return el.checked; });
1439      };
1440      const syncAgreeState = function () {
1441        is_checkbox_check = isAllAgreed();
1442        if (policy_agree_check_all) { policy_agree_check_all.checked = is_checkbox_check; }
1443        activateButton();
1444      };
1445      _agree.forEach(function (el) { el.addEventListener('change', syncAgreeState); });
1446      if (policy_agree_check_all) {
1447        policy_agree_check_all.addEventListener('change', function () {
1448          _agree.forEach(function (el) { el.checked = policy_agree_check_all.checked; });
1449          syncAgreeState();
1450        });
1451      }
1452      btn_new_card_enroll.addEventListener('click', function () {
1453        _alert_msg_policy.innerHTML = isAllAgreed() ? '' : '모든 이용약관에 동의해 주세요.';
1454      });
1455      return;
1456    }
1457
1458    let alert_policy_check_array = [];
1459
1460    _agree.forEach((el,i) =>{
1461      el.addEventListener('change',()=>{
1462        _agree.forEach(e =>{ e.checked ? alert_policy_check_array.push(_agree[i].checked) : alert_policy_check_array.pop(); })
1463        if (alert_policy_check_array.length === 5 ) {  // 동의하기 체크박스가 다 체크 되었을 경우
1464          policy_agree_check_all.checked = true;
1465          alert_policy_check_array = [];
1466          is_checkbox_check = true;
1467          activateButton();
1468        }
1469        if(el.checked === false){ // 동의하기 체크박스가 하나라도 체크 안되었을 경우
1470          policy_agree_check_all.checked = false;
1471          is_checkbox_check = false;
1472          activateButton();
1473        }
1474        alert_policy_check_array = [];
1475      })
1476    })
1477
1478    policy_agree_check_all.addEventListener('change',()=>{ // 전체 선택 버튼 기능
1479      if(!policy_agree_check_all.checked ) {
1480        _agree.forEach(el => {
1481          el.checked = false;
1482          is_checkbox_check = false;
1483          activateButton();
1484        })
1485      } else {
1486        _agree.forEach(el => {
1487          el.checked = true;
1488          is_checkbox_check = true;
1489          activateButton();
1490        })
1491      }
1492    })
1493
1494    btn_new_card_enroll.addEventListener('click',()=>{  //등록하기 버튼 Event
1495      _agree.forEach(el=> {
1496        if(el.checked){alert_policy_check_array.push(el.getAttribute('checked'))}
1497      })
1498      alert_policy_check_array.length < 4 ? _alert_msg_policy.innerHTML = '모든 이용약관에 동의해 주세요.' : _alert_msg_policy.innerHTML = '';
1499      alert_policy_check_array = []; // array reset
1500    })
1501  }
1502  //focus 자동 이동
1503  const focusMove = function (){
1504    const add_credit_card_container = document.getElementById('add_credit_card_container');
1505    const _card_focus = add_credit_card_container.querySelectorAll('._card_focus');
1506    _card_focus.forEach((el, i) => {
1507      el.addEventListener('keyup',(e)=>{
1508        if(el.classList.contains('add_card_numb_input') && el.value.length === 4 ) {
1509          _card_focus[i+1].focus();
1510        } else if(el.classList.contains('expiration_input') && el.value.length === 2){
1511          _card_focus[i+1].focus();
1512        }
1513      })
1514    })
1515  }
1516  //버튼 활성화
1517  const activateButton = function () {
1518    const add_credit_card_container = document.getElementById('add_credit_card_container');
1519    const btn_new_card_enroll = add_credit_card_container.querySelector('#btn_new_card_enroll');
1520    const _alert_msg = {
1521      card: add_credit_card_container.querySelector('._alert_msg_card'),
1522      expiration: add_credit_card_container.querySelector('._alert_msg_expiration'),
1523      personal_registration_number: add_credit_card_container.querySelector('._alert_msg_personal_registration_number'),
1524    }
1525
1526    // 결제 플랫폼 슬림 폼(data-pp-billing=1): 카드 정보는 SDK 화면이 수집하므로 약관 동의만으로 버튼 활성
1527    if (add_credit_card_container.getAttribute('data-pp-billing') === '1') {
1528      if (is_checkbox_check) {
1529        btn_new_card_enroll.removeAttribute('disabled');
1530      } else {
1531        btn_new_card_enroll.setAttribute('disabled', true);
1532      }
1533      return;
1534    }
1535
1536    if(is_checkbox_check && is_personal_registration_number_check && array_period.every(istrue) && array_card_number_check.every(istrue)){
1537      btn_new_card_enroll.removeAttribute('disabled');
1538    } else {
1539      btn_new_card_enroll.setAttribute('disabled',true);
1540    }
1541  }
1542  // 카드 등록 실패/취소 시 에러 모달 (결제 플랫폼 프론트의 error phase 와 동일: 실패 안내 + 다시 시도)
1543  const showRegisterFailModal = function (addCreditCardCallback) {
1544    const failHtml =
1545      '<article style="position:relative;padding:24px;">'
1546      + '<div style="position:relative;display:flex;align-items:center;justify-content:center;padding-bottom:16px;margin-bottom:20px;border-bottom:1px solid #e5e5e5;">'
1547      + '<h3 style="margin:0;font-size:18px;font-weight:600;line-height:26px;color:#1f2937;text-align:center;">정기구독 결제 수단 등록</h3>'
1548      + '<button type="button" data-dismiss="modal" aria-label="Close" style="position:absolute;right:0;top:50%;transform:translateY(-50%);padding:0;border:none;background:transparent;font-size:16px;cursor:pointer;"><i aria-hidden="true" class="btl bt-times"></i></button>'
1549      + '</div>'
1550      + '<div style="text-align:center;padding:36px 0;">'
1551      + '<p style="margin:0 0 20px;font-size:15px;
1551color:#e74c3c;">카드 등록에 실패했습니다.</p>'
1552      + '<button type="button" id="pp_billing_retry_btn" style="height:44px;padding:0 28px;border:none;border-radius:4px;background:#293056;color:#fff;font-size:15px;font-weight:700;cursor:pointer;">다시 시도</button>'
1553      + '</div>'
1554      + '</article>';
1555    // SDK 모달 닫힘 애니메이션 이후에 띄워 모달 충돌을 피한다
1556    setTimeout(function () {
1557      $.cocoaDialog.open({ type : 'register_payment_method', custom_popup : failHtml, pc_width: 368 }, function () {
1558        const retryBtn = document.getElementById('pp_billing_retry_btn');
1559        if (retryBtn) {
1560          retryBtn.addEventListener('click', function () {
1561            registerRegularlyCard({ addCreditCardCallback : addCreditCardCallback });
1562          });
1563        }
1564      });
1565    }, 300);
1566  }
1567  // 결제 플랫폼 빌링 SDK 렌더 (카드 등록 화면을 iframe 으로 띄우고 콜백 결과를 수신)
1568  const openPaymentPlatformSdk = function (html, opts) {
1569    const { addCreditCardCallback } = (opts ?? {});
1570    // 성공/실패 결과를 받았는지 여부. 성공 신호 없이 SDK 가 닫히면(취소·이탈) 실패로 처리한다.
1571    let settled = false;
1572
1573    const onMessage = function (e) {
1574      if (e.origin !== window.location.origin) return;
1575      const d = e.data;
1576      if (!d || d.type !== 'PP_BILLING_REGISTER_RESULT') return;
1577      settled = true;
1578      window.removeEventListener('message', onMessage);
1579      try { $.cocoaDialog.close(); } catch (err) {}
1580      if (d.success) {
1581        if (typeof addCreditCardCallback === 'function') {
1582          addCreditCardCallback();
1583        } else {
1584          alert("카드가 등록되었습니다.");
1585          location.reload();
1586        }
1587      } else {
1588        // 콜백을 통해 전달된 실패 → 에러 모달
1589        showRegisterFailModal(addCreditCardCallback);
1590      }
1591    };
1592    window.addEventListener('message', onMessage);
1593
1594    // SDK iframe 위(밖)에 항상 보이는 헤더 + 닫기(X)를 둔다.
1595    // 취소 시 게이트웨이가 cross-origin 500 본문을 iframe 에 렌더해도 부모창이 이를 숨기거나 자동 닫을 수 없는데,
1596    // 헤더의 X 는 iframe 바깥이라 항상 노출되어 사용자가 명확히 닫을 수 있다(→ hide_event → 미완료로 보고 실패 모달).
1597    const sdkHtml =
1598      '<article style="position:relative;">'
1599      + '<div style="position:relative;display:flex;align-items:center;justify-content:center;padding:20px 24px;border-bottom:1px solid #e5e5e5;">'
1600      + '<h3 style="margin:0;font-size:18px;font-weight:600;line-height:26px;color:#1f2937;text-align:center;">정기구독 결제 수단 등록</h3>'
1601      + '<button type="button" data-dismiss="modal" aria-label="Close" style="position:absolute;right:24px;top:50%;transform:translateY(-50%);padding:0;border:none;background:transparent;font-size:16px;cursor:pointer;"><i aria-hidden="true" class="btl bt-times"></i></button>'
1602      + '</div>'
1603      + '<iframe id="pp_billing_sdk_frame" style="display:block;width:100%;height:720px;max-height:74vh;border:0;" sandbox="allow-forms allow-scripts allow-same-origin"></iframe>'
1604      + '</article>';
1605    $.cocoaDialog.close();
1606    $.cocoaDialog.open({
1607      type : 'pp_billing_sdk',
1608      custom_popup : sdkHtml,
1609      pc_width: 560,
1610      width: 560,
1611      // SDK 모달이 닫힐 때: 성공 신호(settled) 없이 닫혔다면 취소/이탈로 보고 실패 모달을 띄운다
1612      // (취소 시 결제 플랫폼이 cross-origin 500 을 반환해 postMessage 가 오지 않으므로 이 경로로 처리)
1613      hide_event : function () {
1614        // cocoaDialog 는 hide.bs.modal 을 매 open 마다 off 하지 않으므로, 다음 모달에 누적되지 않도록 자기 핸들러를 정리한다
1615        $(this).off('hide.bs.modal');
1616        window.removeEventListener('message', onMessage);
1617        if (!settled) {
1618          settled = true;
1619          showRegisterFailModal(addCreditCardCallback);
1620        }
1621      }
1622    }, function () {
1623      const frame = document.getElementById('pp_billing_sdk_frame');
1624      if (frame) frame.srcdoc = html;
1625    });
1626  }
1627  // 카드 버튼 등록하기
1628  const addCreditCard = function (options) {
1629    const { addCreditCardCallback } = (options ?? {});
1630
1631    const add_credit_card_container = document.getElementById('add_credit_card_container');
1632    const btn_new_card_enroll = add_credit_card_container.querySelector('#btn_new_card_enroll');
1633    let submit_flag = true;
1634    btn_new_card_enroll.addEventListener('click',(idx)=>{
1635      const data = $('#add_credit_card_container').find('form').serializeObject();
1636      // 결제 플랫폼 경로(기능키 ON)에서 콜백이 돌아올 BO 경로 (이니시스 경로에선 무시됨)
1637      data.pp_callback_path = '/payment/manage_credit_card/billing_register_callback.cm';
1638      if(submit_flag) {
1639        submit_flag = false;
1640        btn_new_card_enroll.setAttribute('disabled',true);
1641        $.ajax({
1642          type : 'POST',
1643          url : '/payment/index.cm',
1644          data: data,
1645          cache : false,
1646          success : function(result){
1647            let reason = '';
1648            const response =  JSON.parse(result);
1649            // 결제 플랫폼 렌더 응답: 자동 submit HTML 을 iframe 으로 실행 (이니시스 응답엔 mode 없음 → 통과)
1650            if (response.mode === 'pg_sdk') {
1651              openPaymentPlatformSdk(response.html, { addCreditCardCallback : addCreditCardCallback });
1652              return;
1653            }
1654            const auth_result = response.resultCode;
1655            if(auth_result == 'imweb01'){ // 아임웹 자체 에러메시지 처리
1656              reason = response.resultMsg;
1657            } else { // 이니시스 api 에러인 경우 에러메시지 문자열 처리
1658              const reason_arr = response.resultMsg.split('|'); // err_msg 문자열 분리
1659              reason = reason_arr[reason_arr.length-1].slice(0,-1);  // err_msg ']' 제거
1660            }
1661            let url_endpoint = ''
1662            switch (auth_result){
1663              case '00':
1664                if (typeof addCreditCardCallback === 'function') {
1665                  addCreditCardCallback();
1666                } else {
1667                  alert("카드가 등록되었습니다.");
1668                  $.cocoaDialog.close();
1669                  location.reload();
1670                }
1671                break;
1672              case '01':
1673                alert(reason+"입니다.");
1674                submit_flag = true;
1675                btn_new_card_enroll.removeAttribute('disabled');
1676                break;
1677              default:
1678                alert(reason+"입니다.");
1679                submit_flag = true;
1680                btn_new_card_enroll.removeAttribute('disabled');
1681                break;
1682            }
1683          },
1684          error : function(res){
1685          },
1686        });
1687      }
1688    })
1689  }
1690  const registerRegularlyCard = function(options){
1691    const { addCreditCardCallback } = (options ?? {});
1692
1693    $.ajax({
1694      type : 'POST',
1695      url : '/payment/manage_credit_card/bo_register_credit_card.cm',
1696      dataType : 'json',
1697      cache : false,
1698      success : function(result){
1699        if(result.msg == 'SUCCESS'){
1700          $.cocoaDialog.close();
1701          $.cocoaDialog.open({type : 'register_payment_method', custom_popup : result.html, pc_width: 368, }, function(){
1702            $(window).scroll(function() { return false; });
1703            // 모달을 다시 열 때(취소→다시 시도, 닫고 재오픈 등) 모듈 스코프의 검증 상태가 이전 동의 값(is_checkbox_check=true)으로 남아
1704            // 새로 렌더된 미체크 약관 체크박스와 어긋난 채 버튼이 활성화되는 문제를 막는다. 정기결제 재개 모달과 동일한 초기화 패턴.
1705            resetValidationState();
1706            applyImwebMainDomainToRegularPaymentTermsLinks();
1707            const _pp_card_container = document.getElementById('add_credit_card_container');
1708            if (_pp_card_container && _pp_card_container.getAttribute('data-pp-billing') === '1') {
1709              // 결제 플랫폼 슬림 폼: 카드 입력 필드가 없어 카드 검증 헬퍼는 호출하지 않는다.
1710              // 버튼 클릭 → SDK 렌더는 addCreditCard 가 response.mode==='pg_sdk' 분기로 처리한다.
1711              addCreditCard({ addCreditCardCallback });
1712              checkAgreePolicy();
1713              activateButton();
1714            } else {
1715              addCreditCard({ addCreditCardCallback });
1716              focusMove();
1717              personalRegistrationNumberCheck();
1718              periodCheck();
1719              cardNumberCheck();
1720              checkAgreePolicy();
1721              activateButton();
1722            }
1723          });
1724        }
1725      },
1726      error : function (res) {
1727
1728      }
1729    });
1730  }
1731  const updateRegularlyInfo = function(){
1732    const form = $("#credit_card_change_info_form");
1733    const data = form.serializeObject();
1734    $.ajax({
1735      data: data,
1736      type : 'POST',
1737      url : '/payment/index.cm',
1738      dataType : 'json',
1739      cache : false,
1740      success : function(res){
1741        if(res.result == 'SUCCESS'){
1742          location.reload();
1743        }
1744
1745        if (res.result === 'error') {
1746            window.alert(res.msg ?? '알 수 없는 에러가 발생하였습니다');
1747        }
1748      },
1749      error : function(res){
1750      }
1751    });
1752  }
1753  const updateRegularlyPeriod = function(){
1754    const form = $("#credit_card_change_info_form");
1755    const data = form.serializeObject();
1756    $.ajax({
1757      data: data,
1758      type : 'POST',
1759      url : '/payment/index.cm',
1760      dataType : 'json',
1761      cache : false,
1762      success : function(res){
1763        if(res.result == 'SUCCESS'){
1764          location.reload();
1765        }
1766      },
1767      error : function(res){
1768      }
1769    });
1770  }
1771
1772  const modalChangeInfoCreditCard = function(cannotChangePaymentMethod, data) {
1773    const from_admin_site = 'site_admin';
1774    if(cannotChangePaymentMethod){
1775      alert ('카드 변경 또는 신규 카드 추가 권한이 없습니다.\n소유자 계정으로 다시 시도해주시기 바랍니다.');
1776      return;
1777    }
1778    let dataJson = {
1779      idx : data,
1780      access_location : from_admin_site,
1781    }
1782    $.ajax({
1783      type : 'POST',
1784      url : ('/payment/manage_credit_card/modal_credit_card_change_info.cm'),
1785      data: dataJson,
1786      dataType: 'json',
1787      async : false,
1788      cache : false,
1789      success : function(result) {
1790        if(result.msg == 'SUCCESS'){
1791          $.cocoaDialog.close();
1792          $.cocoaDialog.open({ type: "credit_card_change_info", custom_popup: result.html, pc_width: 348, width:348 },function(){
1793          });
1794        } else {
1795          alert(result.msg);
1796        }
1797      },
1798      error: function(res) {
1799        console.log(res);
1800      }
1801    })
1802  }
1803  const modalChangePeriodCreditCard = function(idx) {
1804    const from_admin_site = 'site_admin';
1805    $.ajax({
1806      type : 'POST',
1807      url : ('/payment/manage_credit_card/modal_credit_card_change_period.cm'),
1808      data : {
1809        idx: idx,
1810        access_location : from_admin_site,
1811      },
1812      dataType: 'json',
1813      async : false,
1814      cache : false,
1815      success : function(result) {
1816        $.cocoaDialog.close();
1817        $.cocoaDialog.open({ type: "credit_card_change_info", custom_popup: result.html, pc_width: 565, width:348, },function(){
1818        });
1819      },
1820      error: function(res) {
1821        console.log(res);
1822      }
1823    })
1824  }
1825
1826  const setValueQueryString = function(){
1827    const term = $("input[name=rdo_term_kind]:checked").val();
1828    const upgrade = $("input[name=value_version]:checked").val();
1829    if(!(term === "coupon" || term === "non_extension")){
1830      let params = new URLSearchParams(location.search);
1831      const setOrAppendUrl = (name, value) =>{
1832        if(params.has(name)){
1833          params.set(name, value);
1834        } else {
1835          params.append(name, value);
1836        }
1837      }
1838      setOrAppendUrl('term',term);
1839      setOrAppendUrl('upgrade',upgrade);
1840      location.search = params.toString();
1841    }
1842  }
1843  const reloadedValueCheck = () =>{
1844    function searchParam(key) {
1845      return new URLSearchParams(location.search).get(key);
1846    };
1847    function hasUrlQuery(key) {
1848      return new URLSearchParams(location.search).has(key);
1849    };
1850    if(hasUrlQuery('term')){
1851      switch (searchParam('term')){
1852        case "one_month" : $("input:radio[name=rdo_term_kind]:input[value='one_month']").prop("checked", true);
1853          break;
1854        case "three_month" : $("input:radio[name=rdo_term_kind]:input[value='three_month']").prop("checked", true);
1855          break;
1856        case "six_month" : $("input:radio[name=rdo_term_kind]:input[value='six_month']").prop("checked", true);
1857          break;
1858        case "one_year" : $("input:radio[name=rdo_term_kind]:input[value='one_year']").prop("checked", true);
1859          break;
1860        default: $("input:radio[name=rdo_term_kind]:input[value='one_year']").prop("checked", true);
1861      }
1862      switch (searchParam('upgrade')){
1863        case  "free" : $("input:radio[name=value_version]:input[value='free']").prop("checked", true);
1864          break;
1865        case  "starter" : $("input:radio[name=value_version]:input[value='starter']").prop("checked", true);
1866          break;
1867        case  "pro" : $("input:radio[name=value_version]:input[value='pro']").prop("checked", true);
1868          break;
1869        case  "global" : $("input:radio[name=value_version]:input[value='global']").prop("checked", true);
1870          break;
1871      }
1872    }
1873  }
1874  const removeQueryValue = () =>{
1875    const end_point = location.pathname + '?payment&';
1876    history.replaceState({}, null, end_point);
1877  }
1878  return {
1879    registerRegularlyCard: function (options) {
1880      registerRegularlyCard(options);
1881    },
1882    modalChangeInfoCreditCard: function (cannotChangePaymentMethod, idx) {
1883      modalChangeInfoCreditCard(cannotChangePaymentMethod, idx);
1884    },
1885    modalChangePeriodCreditCard: function (idx) {
1886      modalChangePeriodCreditCard(idx);
1887    },
1888    updateRegularlyInfo: function () {
1889      updateRegularlyInfo();
1890    },
1891    updateRegularlyPeriod: function () {
1892      updateRegularlyPeriod();
1893    },
1894    setValueQueryString: function () {
1895      setValueQueryString();
1896    },
1897    reloadedValueCheck: function () {
1898      reloadedValueCheck();
1899    },
1900    removeQueryValue: function () {
1901      removeQueryValue();
1902    },
1903    addCreditCard: function (options) {
1904      addCreditCard(options);
1905    },
1906    focusMove: function () {
1907      focusMove();
1908    },
1909    personalRegistrationNumberCheck: function () {
1910      personalRegistrationNumberCheck();
1911    },
1912    periodCheck: function () {
1913      periodCheck();
1914    },
1915    cardNumberCheck: function () {
1916      cardNumberCheck();
1917    },
1918    checkAgreePolicy: function () {
1919      checkAgreePolicy();
1920    },
1921    activateButton: function () {
1922      activateButton();
1923    },
1924    resetValidationState: function () {
1925      resetValidationState();
1926    },
1927  }
1928})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.