PageSourceSearch

https://cherry.charity/assets/js/caas-payment-04a3fc72054d88e85741e9d179092115.js

js cherry.charity collected 2026-09-24 12:27:10 UTC 74,250 bytes, 1,821 lines download raw bytes

1/* **************************************************************************************
2 *	CaaS Payment 공통 JavaScript
3 *	@author yeongeun.seo
4 *	@since 2019.08.01
5 *	@history 2020.02.05 caas-appl에서 분리
6 */
7;'use strict';
8(function($) {
9	cmmPayment = {
10		// (2024.05.14) 본인인증 팝업을 공통으로 처리한다 (v2) (jina.lee)
11		certAlertPop : function(){
12			const message = `<span class="title">본인 인증이 필요한 기능이에요.</span><span class="mainTxt">설정 화면에서 본인 인증을 해주세요.</span>`;
13			cmmPop.confirmPopup(message, "본인인증 하기", "취소", ()=>location.href="/mypage/setting?from=payment");
14		},
15		doCertCheckNew : function(setleCd, keyData, okCallback) {
16			let param = { setleCd: setleCd, svcMenuNm: "cherry" };
17			const setleCdArray = ['C01', 'C03', 'C04', 'C05', 'C21'];
18			const mstr = setleCdArray.includes(setleCd) ? `${setleCd}|${keyData}` : `${setleCd}|`;
19			let url;
20			switch(setleCd) {
21				case 'C02' : url = '/public/cert/certCheckMnemonic';	break;
22				case 'C05' : url = '/public/member/cherryKidAgreCert';	break;
23				case 'C21' : url = '/public/cert/certCoprtn';			break;
24				default	:	 url = '/cert/certCheck';					break;
25			}
26
27			cmmCall.ajaxCall(url, param, function(data) {
28				function fillCertReqMapFields(certReqMap, mstr) {
29					certReqMap.MSTR = mstr;
30					for (const key in certReqMap) {
31						if (Object.prototype.hasOwnProperty.call(certReqMap, key)) {
32							$('#' + key).val(certReqMap[key]);
33						}
34					}
35				}
36
37				if(['C04', 'C07'].includes(setleCd)) {
38					fillCertReqMapFields(data.certReqMap, mstr);
39					if(setleCd === 'C04') {
40						cmmPop.fullPopOpen('#certIframePopup');
41					} else {
42						if(!cmmEnv.device.isMobileDevice()) { $('#CALL_TYPE').val('P'); }
43						else { cmmPop.fullPopOpen('#certIframePopup'); }
44					}
45					//MCASH_PAYMENT(document.payForm);
46					AUTH_PAYMENT(document.payForm);
47					
48				} else if(data.userCrtfcYn) {
49					if(okCallback) {
50						okCallback(data);
51					}
52				} else {
53					fillCertReqMapFields(data.certReqMap, mstr);
54
55					if(setleCd === 'C00') {
56						/**
57						 * (2024.05.14) 본인인증 팝업을 공통으로 처리한다 (v2) (jina.lee)
58						 * 		추가로, 설정 화면에서 호출하는 본인인증 은 C01 로 통일하였다.
59						 */
60						cmmPayment.certAlertPop();
61					} else {
62						if(['C01', 'C22'].includes(setleCd) && keyData === null && !cmmEnv.device.isMobileDevice()) {
63							$('#CALL_TYPE').val('P');
64						} else {
65							cmmPop.fullPopOpen('#certIframePopup');
66						}
67						//MCASH_PAYMENT(document.payForm);
68						AUTH_PAYMENT(document.payForm);
69					}
70				}
71			});
72		},
73		
74		/* 캠페인/단체후원함에서 기부하기 버튼 눌렀을때
75		 * grpDtl	단체상세->후원하기->단체상세
76		 * cmgpnDtl	단체상세->모금함상세->모금함상세->단체상세
77		 * myGrp	MY단체->썸네일후원하기->MY단체
78		 * home		검색결과
79		 *
80		 * doCertCheckCmpgn에서 중복클릭 방지를 위해 timer 적용. 이에 따라 기존 로직은 _doCertCheckCmpgn로 분리
81		 * 중복클릭 : 결제수단 미등록 사용자가 후원하기를 짧은시간내 클릭시 DB Commit 전에 2건이 등록되어 중복건 오류 발생
82		 * 2020.10.21 yeongeun.seo
83		 */
84		certCheckClick : true,
85		/*
86		* 2021.08.12 yeongeun.seo 체리-체리소울 통합버전 donateType (normal, fdrm) 추가 (*1)
87		* 2021.12.19 yeongeun.seo AppToApp 이슈로 donateType이 undefined인 경우 normal로 지정 (*2)
88		*/
89		doCertCheckCmpgn : function(cmpgnType, cmpgnSn, loc, donateType) { // (*1)
90			if(cmmPayment.certCheckClick) {
91				// (*2)
92				if(bfcStr.isNull(donateType)) {
93					donateType = 'normal';
94				}
95				cmmPayment._doCertCheckCmpgn(cmpgnType, cmpgnSn, loc, donateType);
96				cmmPayment.certCheckClick = !cmmPayment.certCheckClick;
97				setTimeout(() => { cmmPayment.certCheckClick = true; }, 1000);
98			}
99		},
100		
101		_doCertCheckCmpgn : function(cmpgnType, cmpgnSn, loc, donateType) {
102			cmmLogin.loginCheck(function() {
103				const $cmpgnSn = $('#cmpgnSn');
104				cmpgnSn = cmpgnSn ?? $cmpgnSn.val();
105				
106				// 001:체리런(캠페인), 002:참여형이벤트(캠페인), 003:정기후원이벤트(모금함)
107				cmmPayment.doCertCheckNew('C00', null, function(data) {
108					const commonPath = `cmpgnSn=${cmpgnSn}&setleCd=C00&loc=${loc}&donateType=${donateType}`;
109					if(cmpgnType === 'event') {
110						let cmpgnEventSeCode = $('#cmpgnEventSeCode').val();
111						//2022.09.26 캠페인이벤트유형코드 추가(006)
112						if(cmpgnEventSeCode === '001' || cmpgnEventSeCode === '006') {
113							let targetUrl = `/payment/cherryRun/rgstPage?${commonPath}`;
114							let recommenderCodeVal = $("#recommenderCode").val();
115							let recommenderCodeCookie = bfcCookie.getCookie("recommenderCode");
116							let finalRecommenderCode = recommenderCodeVal || recommenderCodeCookie;
117							if (!bfcStr.isNullOrBlank(finalRecommenderCode)) {
118								targetUrl += `&recommenderCode=${encodeURIComponent(finalRecommenderCode)}`;
119							}
120							cmmPayment.doWebAppUrlProc(targetUrl);
121						} else if(cmpgnEventSeCode === '002' || cmpgnEventSeCode === '005') {
122							cmmPayment.doWebAppUrlProc(`/payment/event/cmpgnEventPartcptReqstPage?${commonPath}`);
123						} else if(cmpgnEventSeCode === '003') {
124							let param = {
125									cmpgnSn: $cmpgnSn.val(),
126									startDe: '20210801'
127							};
128							// 정기후원 리워드 이벤트 기참여자 체크
129							cmmCall.ajaxCall('/payment/event/cmpgnEventPartcptReqstCheck', param, function(data) {
130								if(data.rs != null) {
131									let msg;
132									if(data.rs.donateTokenAmt < jsonOptn.mark.event_partcpt_min_amt) {
133										msg = data.userNcm + '님은 이 모금함에 이미 정기결제을 신청하셨습니다.<br>'
134										+ '정기결제 정보를 수정하시려면<br>' 
135										+ '마이체리 > 정기결제 탭에서 확인해주세요.<br>'
136										+ '(감사 선물을 받으시려면 기존 정기결제 해지 후 2만원 이상 기부해 주시기 바랍니다.)';
137									} else {
138										msg = data.userNcm + '님은 이 모금함에 이미 정기결제 및 감사 선물을 신청하셨습니다.<br>'
139										+ '정기결제 정보를 수정하시려면<br>' 
140										+ '마이체리 > 정기결제 탭에서 확인해주세요.<br>'
141										+ '그 외 문의사항은 마이체리 > 1:1문의로 연락해주세요.';
142									}
143									cmmPop.alertError(msg);
144									
145								} else {
146									cmmPayment.doWebAppUrlProc(`/payment/setleCnfirmPage?${commonPath}`);
147								}
148							});
149							
150						} else if (cmpgnEventSeCode === '008'){
151							// 23.07.03 Ticket case '008'
152							cmmPayment.doWebAppUrlProc(`/payment/event/cmpgnTicketEventPage?${commonPath}`);
153						}
154					} else if(loc === 'tgrdnt') { // 함께기부 2025.08.05
155						if(bfcStr.isNull(groupInfo.tgrdntGroupEventSn)) {
156							cmmPop.alertError('groupInfo.tgrdntGroupEventSn 없음');
157							return;
158						}
159						const _tgrdntGroupEventSn = donateType === 'fdrm' ? fdrmInfo.tgrdntGroupEventSn : groupInfo.tgrdntGroupEventSn;
160						const tgrdntPath = `${commonPath}&tgrdntGroupEventSn=${_tgrdntGroupEventSn}`;
161						cmmPayment.doWebAppUrlProc(`/payment/setleCnfirmPage?${tgrdntPath}`);
162					} else {
163						cmmPayment.doWebAppUrlProc(`/payment/setleCnfirmPage?${commonPath}`);
164					}
165				});
166			});
167		},
168		
169		donateProcType : null,
170		winPopup : null, /*웹결제시 사용할 팝업 변수*/
171		/* 기부하기 선처리 (바로기부, 나눔바구니 공통) */
172		doDonateProc : function() {
173			const type = cmmPayment.donateProcType;
174			const setleMeanId = cmmPayment.cmmSetleMeanSet().setleMeanId;
175			const setleMeanSeCode = setleMeanId.slice(-1);
176			const pointTypeMap = { 'P': 'chyPntSetle', 'l': 'lpointSetle' };
177			const setleAmtType = pointTypeMap[setleMeanSeCode] || 'gnrlSetle';		// 결제금액유형 (포인트(체리, L.POINT), 일반결제)
178			const setleCd = $('#setleCd').val();
179			const setleTotalAmt = bfcFmt.removeComma($('#setleTotalAmt').val());	// 최종결제금액
180			const setleTipAmt = !($('#setleTipAmt').val()) ? 0 : bfcFmt.removeComma($('#setleTipAmt').val());		// 체리Tip
181			const pageInfo = $('#pageInfo').val();
182			const isApp = $('#isApp').val();
183			const isCmpgnEvent = pageInfo === 'cherryRun' || pageInfo === 'cmpgnEventPartcpt';
184			const isTgrdnt = $("#isTgrdnt").val()
185			const $cmpgnSn = $('#cmpgnSn');
186			const $donateMessage = $('#donateMessage');
187			const $cmpgnEventPartcptSn = $('#cmpgnEventPartcptSn');
188			const $tgrdntGroupEventSn = $('#tgrdntGroupEventSn');
189
190			// PG 공통으로 들어가는 기본 파라미터 객체 생성
191			const baseParam = {
192				donateTokenAmt: bfcFmt.removeComma($('#donateTokenAmt').val()),
193				blceDonateTokenAmt: $('#cpoint').prop('checked') ? $('#blceDonateTokenAmt').val() : '0',
194				setleTotalAmt: setleTotalAmt,
195				setleMeanId: setleMeanId,
196				setleAmtType: setleAmtType,
197				userNcmOpenYn: $('input:radio[name=ftPrnt]:checked').attr('id') === 'ftPrnt01' ? 'Y' : 'N',
198				isApp: isApp,
199				svcMenuNm: 'cherry',
200				...(setleTipAmt.length > 0 && { setleTipAmt: setleTipAmt }),
201			};
202
203			let param = {}; // 최종적으로 사용될 파라미터
204			let donateBoxArray = {};
205			if (type === 'fdrmDonate') { // 정기후원 즉시 결제
206				param = {
207					...baseParam, // 공통 파라미터 복사
208					setleCd: isTgrdnt ? 'D11' : 'D2',
209					cmpgnSn: $cmpgnSn.val(),
210					blceDonateTokenAmt: 0, // 정기결제는 잔액 0으로 고정
211					donateTyCode: '02',
212					...(pageInfo === 'cmpgnEventPartcpt' && { cmpgnEventPartcptSn: $cmpgnEventPartcptSn.val() }),
213					...(isTgrdnt && { tgrdntGroupEventSn: $tgrdntGroupEventSn.val() })
214				};
215			} else if (isCmpgnEvent) { // 캠페인 이벤트
216				param = {
217					...baseParam,
218					setleCd: setleCd,
219					cmpgnSn: $cmpgnSn.val(),
220					donateMessage: $donateMessage.val(),
221					donateTyCode: '01',
222					cmpgnEventPartcptSn: $cmpgnEventPartcptSn.val(),
223				};
224			} else if (isTgrdnt) { // 함께기부
225				param = {
226					...baseParam,
227					setleCd: setleCd,
228					cmpgnSn: $cmpgnSn.val(),
229					donateMessage: $donateMessage.val(),
230					donateTyCode: '01',
231					tgrdntGroupEventSn: $tgrdntGroupEventSn.val(),
232				};
233			} else if (['D1', 'D2'].includes(setleCd)) { // 일반기부/단체후원
234				param = {
235					...baseParam,
236					setleCd: setleCd,
237					cmpgnSn: $cmpgnSn.val(),
238					donateMessage: $donateMessage.val(),
239					donateTyCode: '01',
240				};
241			} else { // 나눔바구니
242				// const donateBoxArray = $('input:hidden[name=userDonateBoxSn]').map(function() {
243				donateBoxArray = $('input:hidden[name=userDonateBoxSn]').map(function() {
244					const sn = $(this).val();
245					return {
246						userDonateBoxSn: sn,
247						cmpgnSn: $(`#cmpgnSn${sn}`).val(),
248						cmpgnDonateAmt: bfcFmt.removeComma($(`#cmpgnAmt${sn}`).val()),
249						donateMessage: $(`#cmpgnMsg${sn}`).val(),
250					};
251				}).get();
252
253				if (donateBoxArray.length > 0) {
254					param = {
255						...baseParam,
256						setleCd: setleCd,
257						cmpgnCnt: donateBoxArray.length,
258						donateBox: donateBoxArray,
259						donateTyCode: '01',
260					};
261				}
262			}
263
264			// 기부선처리
265			cmmCall.ajaxCallTimeout('/payment/donateSetlePreProcAjax', param, 0, function(data) {
266				if(setleAmtType === 'chyPntSetle' || setleAmtType === 'lpointSetle') {
267					if (!data.val) {
268						cmmPop.alertError('Error', '닫기');
269						return;
270					}
271
272					let val = data.val;
273					let param = {
274						val: val,
275						setleAmtType: setleAmtType,
276						...(setleAmtType === 'lpointSetle' && { authNo: $('#authNo').val() })
277					}
278
279					const handleSuccessRedirect = (val) => {
280						const maxLength = isCmpgnEvent ? 65 : 45;
281						const finalVal = val.length < maxLength ? encodeURIComponent(val) : val;
282						const redirectUrl = `/payment/setleCnfirmChkPage?val=${finalVal}&isExtSetle=N&flag=Y&rfsOnResm=1&isApp=${isApp}`;
283						location.replace(redirectUrl);
284					};
285
286					const pointPaymentConfigs = {
287						'chyPntSetle': {
288							url: '/payment/chyPntSetleReq', params: param,
289							parseResponse: (res) => res.result,
290							handleFailure: (result) => {
291								cmmPop.alertError(`[${result.code}]\n${result.message}`);
292							}
293						},
294						'lpointSetle': {
295							url: '/payment/lpoint/lpointSetleReq', params: param,
296							parseResponse: (res) => res.lpointMap,
297							handleFailure: (result) => {
298								cmmPop.alertError(`[${result.code}]\n${result.message}`, '확인', () => location.reload());
299							}
300						}
301					};
302					const config = pointPaymentConfigs[setleAmtType];
303					if (config) {
304						cmmCall.ajaxCallTimeout(config.url, config.params, 0, (responseData) => {
305							const result = config.parseResponse(responseData);
306							if (result.code !== '0000') {
307								config.handleFailure(result);
308							} else {
309								handleSuccessRedirect(val);
310							}
311						});
312					}
313				} else { // 일반기부
314					let baseParam = { setleCd: setleCd, setleAmt: setleTotalAmt, setleMeanId: setleMeanId, val: data.val, isApp: isApp, svcMenuNm: 'cherry' };
315					if(setleMeanId.endsWith('S') || setleMeanId.endsWith('V')) { // 스마트로
316						let midType = $("#cmpgnEventSeCode").val() === '008' ? 'gnrlTax' : 'donate';
317						const param = {
318							...baseParam,
319							midType: midType,
320							...(setleMeanId.endsWith('V') && {
321								// cmpgnSn: aJsonArray.length > 0 ? aJsonArray[0].cmpgnSn : $cmpgnSn.val()
322								cmpgnSn: donateBoxArray.length > 0 ? donateBoxArray[0].cmpgnSn : $cmpgnSn.val()
323							})
324						};
325						cmmPayment.pg.smartroPayInfo(param);
326					} else if(setleMeanId.endsWith('N')) { // 네이버페이
327						let param = {
328							...baseParam,
329							nextUrl: data.nextUrl,
330							donateType: type
331						};
332						cmmPayment.pg.nPayReady(param);
333					} else if(setleMeanId.endsWith('M')) { // MyPay
334						cmmPayment.pg.myPayInfo(baseParam);
335					} else if(setleMeanId.endsWith('L')) { // KSPAY
336						cmmPayment.pg.ksPayInfo(baseParam);
337					} else if(setleMeanId.endsWith('k')) { // 카카오페이
338						const donateType = $('#donateType').val();
339						const firstDonateBox = $('input:hidden[name=userDonateBoxSn]:first');
340						const productName = ['D1', 'D2', 'D11'].includes(setleCd) ? $('#cmpgnNm').val() : `${$('#cmpgnNm' + firstDonateBox.val()).val()}${$('#chkTotalCnt').val() > 1 ? ' 등' : ''}`;
341						const finalDonateType = ['normal', 'donateBox'].includes(donateType) ? ($("#cmpgnEventSeCode").val() === '008' ? 'ticket' : 'normal') : 'fdrm';
342						const param = {
343							...baseParam,
344							cmpgnSn: $cmpgnSn.val(),
345							cmpgnNm: productName,
346							donateType: finalDonateType,
347						};
348						cmmPayment.pg.kakaoPayReady(param);
349					} else { // 간편결제
350						let val = data.val;
351						let param = { val : data.val }
352						
353						if(type === 'fdrmDonate') {
354							param.pageType = type;
355							param.fdrmType = $('#fdrmType').val();
356							param.userSn = $('#userSn').val();
357							param.cmpgnSn = $cmpgnSn.val();
358							param.fdrmDonateAmt = bfcFmt.removeComma($('#setleAmt').val());
359							param.fdrmDonateNextDe = $('.fdrmDonateNextDe').attr('value');
360							param.setleMeanId = $('#setleMeanId').val();
361							param.cmpgnEventSeCode = $('#cmpgnEventSeCode').val();
362							param.cmpgnEventPartcptSn = $cmpgnEventPartcptSn.val();
363						}
364
365						cmmCall.ajaxCallTimeout('/payment/ksnet/setle', param, 0, function(data) {
366							if(data.result.code !== '0000') {
367								let errorMessage;
368								const redirectAction = () => cmmPayment.doGoAppByOS('/public/mainPage');
369								if (data.result.donateYn === 'Y') {
370									errorMessage = '이미 결제가 완료 된 캠페인입니다.<br>홈 화면으로 이동됩니다.';
371								} else if (data.result.code === 'S9999') {
372									errorMessage = `결제 오류가 발생되었습니다.<br>[${data.result.code}]${data.result.message}`;
373								} else {
374									errorMessage = `결제가 취소되었습니다.<br>[${data.result.respCode}][${data.result.extRespCode}]<br>${data.result.message}`;
375								}
376								cmmPop.alertError(errorMessage, '확인', redirectAction);
377							} else {
378								const maxLength = isCmpgnEvent ? 65 : 45;
379								if (val.length < maxLength) {
380									val = encodeURIComponent(val);
381								}
382
383								const queryParams = { val: val, isExtSetle: 'N', flag: 'Y', isApp: isApp };
384								if (type === 'fdrmDonate') {
385									queryParams.fdrmType = $('#fdrmType').val();
386									queryParams.userFdrmDonateReqstSn = data.userFdrmDonateReqstSn;
387									queryParams.loc = $('#loc').val();
388									queryParams.hstBckUrl = '1';
389								}
390								const searchString = new URLSearchParams(queryParams).toString();
391								const finalUrl = `/payment/setleCnfirmChkPage?${searchString}`;
392								location.replace(finalUrl);
393							}
394						});
395					}
396				}
397			});
398		},
399		
400		/* Payment Radio 버튼 처리 */
401		doRadioClick : function() {
402			$('input[type=radio]').bind('click', function() {
403				let obj = $(this);
404				const setleMeanAllowedChars = ['V', 'S', 'N', 'M', 'L', 'k'];
405				const $donateType = $('#donateType');
406				const $isIBoojaApp = $('#isIBoojaApp');
407				const $dntnMaxAmt = $('#dntnMaxAmt');
408				
409				if(obj.attr('name') === 'opt') {
410					let addAmt = parseInt($(this).val());
411					let setleAmt = $('#setleAmt').val()
412					let preAmt = 0;
413					if(setleAmt !== '') {
414						preAmt = parseInt(bfcFmt.removeComma(setleAmt));
415					}
416					
417					if($donateType.val() === 'normal') { // normal, donateBox, fdrm
418						const isIBoojaApp = !bfcStr.isNull($isIBoojaApp.val()) && $isIBoojaApp.val() === 'true';
419						const maxAmount = isIBoojaApp ? parseInt($dntnMaxAmt.val(), 10) : 2000000;
420						const message = window.i18n.payment.MAX_PAYMENT.replace('{0}',window.i18n.payment.MAX_PAYMENT.includes('KRW') ? maxAmount.toLocaleString() : (maxAmount / 10000).toLocaleString() + '만');
421						const finalAmount = parseInt(preAmt, 10) + addAmt;
422						if (finalAmount > maxAmount) {
423							cmmPop.alertError(message);
424							$('input[name=opt]').prop('checked', false);
425							return;
426						}
427					} else {
428						if(parseInt(preAmt) + addAmt > 2000000) {
429							cmmPop.alertError('정기결제 신청시 200만원까지 가능합니다.');
430							$('input[name=opt]').prop('checked', false);
431							return;
432						}
433					}
434					cmmPayment.doAmtProc(parseInt(preAmt) + addAmt, null);
435					
436				} else if(obj.attr('name') === 'optTip') {
437					let addAmt = parseInt($(this).val());
438					let setleAmt = $('#setleTipAmt').val()
439					let preAmt = 0;
440					if(setleAmt !== '') {
441						preAmt = parseInt(bfcFmt.removeComma(setleAmt));
442					}
443
444					if($donateType.val() === 'normal') { // normal, donateBox, fdrm
445						const isIBoojaApp = !bfcStr.isNull($isIBoojaApp.val()) && $isIBoojaApp.val() === 'true';
446						const maxAmount = isIBoojaApp ? parseInt($dntnMaxAmt.val(), 10) : 2000000;
447						const message = window.i18n.payment.MAX_PAYMENT.replace('{0}',window.i18n.payment.MAX_PAYMENT.includes('KRW') ? maxAmount.toLocaleString() : (maxAmount / 10000).toLocaleString() + '만');
448						const finalAmount = parseInt(preAmt, 10) + addAmt;
449						if (finalAmount > maxAmount) {
450							cmmPop.alertError(message);
451							$('input[name=opt]').prop('checked', false);
452							return;
453						}
454
455						const amt = parseInt(preAmt) + addAmt;
456						const amtValue = amt !== '0' ? bfcFmt.addComma(amt) : '';
457						const $setleTipAmt = $('#setleTipAmt');
458						const $btnDelete = $('#btnTipDelete');
459						$setleTipAmt.val(amtValue);
460						if($setleTipAmt.val().length > 0){
461							$btnDelete.css('visibility', 'visible');
462						} else {
463							$btnDelete.css('visibility', 'hidden');
464						}
465						cmmPayment.cmmTipAmtSetData();
466					}
467				} else if(obj.attr('id') === 'optKsnet') {
468					if($donateType.val() === 'fdrm') {
469						$('#fdrmSetleMeanNm').text( $('.swiper-container li.swiper-slide-active .bankInfo .bank').text() !== '' ? '간편결제(' + $('.swiper-container li.swiper-slide-active .bankInfo .bank').text()+ ')' : '' );
470						$('#setleMeanId').val($('.swiper-container li.swiper-slide-active').attr('id'));
471						$('#setleMeanSeCode').val('02');
472					}
473					
474				} else if(obj.attr('name') === 'setleMeanEtc' || obj.attr('id') === 'optetc') {
475					let setleMeanId = $('input:radio[name=setleMeanEtc]:checked').attr('id');
476					if($donateType.val() === 'fdrm') {
477						if(!bfcStr.isNullOrBlank(setleMeanId)) {
478							$('#fdrmSetleMeanNm').text(setleMeanId.endsWith('N') ? 'Npay' : '카카오페이');
479							$('#setleMeanId').val(setleMeanId);
480							$('#setleMeanSeCode').val(setleMeanId.endsWith('N') ? '21' : '23');
481						}
482					}
483
484				} else if(obj.attr('id') === 'acnut') {
485					const amountFieldId = ['D1', 'D2'].includes($('#setleCd').val()) ? '#setleAmt' : '#setleTotalAmt';
486					const amount = parseInt(bfcFmt.removeComma($(amountFieldId).val()), 10);
487					const maxAmount = parseInt($dntnMaxAmt.val(), 10);
488					if (amount > maxAmount) {
489						cmmPayment.alertVbankMsg();
490					}
491
492				} else if(setleMeanAllowedChars.includes(obj.attr('id').substring(19, 20))) {
493					if(location.pathname === '/payment/web/setleCnfirmPage') {
494						if($('#pageInfo').val().indexOf('fdrm') > -1) {
495							$('#fdrmSetleMeanNm').text($('#' + obj.attr('id')).val());
496						}
497					} else {
498						//console.log("doRadioClick");
499					}
500				}
501			});
502		},
503		
504		/* 가상계좌메세지알림 */
505		alertVbankMsg: function() {
506			cmmPop.alertError('기부금이 100만원 초과시 가상계좌로 가능합니다.', function() {
507				$('input:radio[name=setleMean]').prop('checked', false);
508				$('#acnutDiv').removeClass('on');
509				$('input:radio[name=setleMean]:radio[value=가상계좌]').prop('checked', true);
510			});
511		},
512		
513		/* 공통기부금액검증 pageInfo(현재 페이지 위치), type(나눔바구니여부)*/
514		doCheckAmt: function(pageInfo, type) {
515			//console.log(pageInfo);
516			//console.log(type);
517			const $isIBoojaApp = $('#isIBoojaApp');
518			const $dntnMaxAmt = $('#dntnMaxAmt');
519			const $dntnMinAmt = $('#dntnMinAmt');
520			const $setleAmt = $('#setleAmt');
521			const $setleTotalAmt = $('#setleTotalAmt');
522			const $channelSid = $("#channelSid");
523			const $cpoint = $('#cpoint');
524			const $lpoint = $('#lpoint');
525			const $isFrntnMberYn = $('#isFrntnMberYn');
526
527			// 바로결제
528			if(pageInfo === 'donate' || pageInfo.indexOf('fdrm') > -1 || pageInfo === 'cherryRun' || pageInfo === 'cmpgnEventPartcpt') {
529				// 바로결제시에 해당
530				if(bfcStr.isNullOrBlank($('#svcMenuNm').val())) { return false; }
531				
532				if(!$cpoint.prop('checked') && !$lpoint.prop('checked')) { // 체리 && 포인트결제가 아닐때 1,000원 제한
533					if(bfcFmt.removeComma($setleAmt.val()) < parseInt($dntnMinAmt.val())) {
534						if(type !== 'donateBox') {
535							if($('input:radio[name=setleMean]:checked').attr('id') !== 'optpnt') {
536								const message = $isFrntnMberYn.val() === 'true' ? window.i18n.payment.MIN_PAYMENT.replace('{0}', '1,000') : `결제는 ${bfcFmt.addComma(parseInt($dntnMinAmt.val()))}원 이상 가능합니다.`;
537								cmmPop.alertError(message);
538								return false;
539							}
540						} else {
541							if(bfcFmt.removeComma($setleAmt.val()) < 1) { cmmPop.alertError(window.i18n.payment.MIN_ADD_DONATE_BOX); return false; }
542						}
543					}
544				} else {
545					if(bfcFmt.removeComma($setleAmt.val()) < 1) { cmmPop.alertError(window.i18n.payment.MIN_PAYMENT_POINT); return false; }
546				}
547				
548				if(type == null) {
549					if(!bfcStr.isNull($channelSid.val()) && $channelSid.val() === "icmda2026") {
550						return true;
551					} else if(parseInt(bfcFmt.removeComma($setleTotalAmt.val())) > 2000000) {
552						let setleMeanId = cmmPayment.cmmSetleMeanSet().setleMeanId;
553						if(bfcStr.isNullOrBlank(setleMeanId)) { cmmPop.alertError(window.i18n.payment.SELECT_PAYMENT_METHOD); return; }
554						const isIBoojaApp = !bfcStr.isNull($isIBoojaApp.val()) && $isIBoojaApp.val() === 'true';
555						const maxAmount = isIBoojaApp ? parseInt($dntnMaxAmt.val(), 10) : 2000000;
556						const message = window.i18n.payment.MAX_PAYMENT.replace('{0}',window.i18n.payment.MAX_PAYMENT.includes('KRW') ? maxAmount.toLocaleString() : (maxAmount / 10000).toLocaleString() + '만');
557						if(isIBoojaApp) {
558							if(parseInt(preAmt) + addAmt > parseInt($dntnMaxAmt.val())) {
559								cmmPop.alertError(message);
560								$('input[name=opt]').prop('checked', false);
561								return;
562							}
563						} else {
564							cmmPop.alertError(message);
565							return false;
566						}
567					}
568				}
569				
570			} else {
571				// 나눔바구니
572				if($('#setleCd').val() === 'D3') {
573					let isTrue = false;
574					$('input[name=cmpgnList01], input[name=cmpgnList02]').each(function() {
575						let id = (this.id).replace('cmpgnAmt', '');
576						isTrue = $('#'+id).prop('checked') ? (bfcFmt.removeComma(this.value) < 1) : false;
577						if(isTrue) { return false; }
578					});
579					if(isTrue) {cmmPop.alertError('기부할 금액을 입력하세요.'); return false; }
580					if($setleTotalAmt.val() < 1000 && !$cpoint.prop('checked')) {
581						isTrue = true;
582						if(isTrue) { cmmPop.alertError('결제는 ' + bfcFmt.addComma(parseInt($dntnMinAmt.val())) + '원 이상 가능합니다.'); return false; }
583					}
584					if(parseInt(bfcFmt.removeComma($setleTotalAmt.val())) > 2000000) {
585						const maxAmount = 2000000;
586						const message = window.i18n.payment.MAX_PAYMENT.replace('{0}',window.i18n.payment.MAX_PAYMENT.includes('KRW') ? maxAmount.toLocaleString() : (maxAmount / 10000).toLocaleString() + '만');
587						cmmPop.alertError(message);
588						return false;
589					}
590				}
591			}
592			return true;
593		},
594
595		/* 공통기부금액처리 */
596		doAmtProc : function(amt, obj) {
597			const calculateFinalPoints = function(paymentAmt, userChyPnt, userLpoint) {
598				let finalUserPnt = 0;
599				if($('#cpoint').prop('checked')) {
600					finalUserPnt = userChyPnt - paymentAmt;
601				} else if($('#lpoint').prop('checked')) {
602					finalUserPnt = userLpoint - paymentAmt;
603				}
604				return finalUserPnt;
605			};
606
607			if(isNaN(amt)) { amt = '0'; }
608			else if(amt.length < 1) { amt = '0'; }
609
610			const donateType = $('#donateType').val();
611			const userChyPnt = $('#userChyPnt').val();
612			const userLpoint = $('#lpointYn').val() === 'Y' ? $('#userLpoint').val() : '0';
613			const amtValue = amt !== '0' ? bfcFmt.addComma(amt) : '';
614			const $setleAmt = $('#setleAmt');
615			const $btnDelete = $('#btnDelete');
616			if(donateType === 'normal') { // 일반기부
617				const finalUserPnt = calculateFinalPoints(amt, userChyPnt, userLpoint);
618				$setleAmt.val(amtValue);
619				cmmPayment.cmmSetleAmtSectionSetData(false, amt, finalUserPnt, false);
620				cmmPayment.cmmPntSetleChk('donate', userChyPnt, userLpoint, amt);
621				$btnDelete.css('visibility', 'visible');
622
623			} else if(donateType === 'donateBox') { // 나눔바구니
624				const $obj = $('#' + obj);
625				const commaAmt = bfcFmt.addComma(amt);
626				$obj.val(commaAmt);
627				$obj.attr('value', commaAmt);
628
629				let totalAmt = 0; // 캠페인/단체 체크 된 상태의 전체 금액 합산
630				$('input:checkbox[name=chkCmpgn]').each(function() {
631					if($(this).prop('checked')) {
632						let addAmt = $('#cmpgnAmt'+$(this).val()).val();
633						totalAmt = totalAmt + (addAmt === '' ? 0 : parseInt(bfcFmt.removeComma(addAmt)));
634					}
635				});
636				const finalUserPnt = calculateFinalPoints(amt, userChyPnt, userLpoint);
637				cmmPayment.cmmSetleAmtSectionSetData(false, totalAmt, finalUserPnt, false);
638				cmmPayment.cmmPntSetleChk('donateBox', userChyPnt, userLpoint, totalAmt);
639
640			} else { // 정기후원
641				if(amt > 2000000) {
642					cmmPop.alertError('정기결제 신청시 200만원까지 가능합니다.');
643					$setleAmt.val(2000000);
644					return;
645				}
646
647				const $setleTotalAmt = $('#setleTotalAmt');
648				const $donateTokenAmt = $('#donateTokenAmt');
649				const $fdrmAmt = $('.fdrmAmt');
650
651				$setleAmt.val(amtValue);
652				const setleAmt = $setleAmt.val();
653				$setleTotalAmt.val(setleAmt).text('₩'+bfcFmt.addComma(setleAmt));	// 최종결제금액
654				$donateTokenAmt.val(setleAmt).text('₩'+bfcFmt.addComma(setleAmt));	// 기부토큰수량
655				$fdrmAmt.text(amtValue || '0');
656				$btnDelete.css('visibility', 'visible');
657
658				// 정기후원 리워드 이벤트용
659				const jsonOptn = $('#jsonOptn').val();
660				if (jsonOptn) {
661					const minAmt = parseInt($('#eventPartcptMinAmt').val() || '0', 10);
662					if (minAmt > 0) {
663						const isOptnView = numericAmt >= minAmt;
664						$('#reward').toggle(isOptnView);
665						$('#btnFdrmDonateProc').text(isOptnView ? '동의 및 정기 결제 진행' : '정기결제');
666					}
667				}
668			}
669		},
670		doTipAmtProc : function(amt, obj) {
671			const calculateFinalPoints = function(paymentAmt, userChyPnt, userLpoint) {
672				let finalUserPnt = 0;
673				if($('#cpoint').prop('checked')) {
674					finalUserPnt = userChyPnt - paymentAmt;
675				} else if($('#lpoint').prop('checked')) {
676					finalUserPnt = userLpoint - paymentAmt;
677				}
678				return finalUserPnt;
679			};
680
681			if(isNaN(amt)) { amt = '0'; }
682			else if(amt.length < 1) { amt = '0'; }
683
684			const donateType = $('#donateType').val();
685			const amtValue = amt !== '0' ? bfcFmt.addComma(amt) : '';
686			const $setleTipAmt = $('#setleTipAmt');
687			const $btnTipDelete = $('#btnTipDelete');
688			if(donateType === 'normal') { // 일반기부
689				$setleTipAmt.val(amtValue);
690				$btnTipDelete.css('visibility', 'visible');
691				this.cmmTipAmtSetData();
692			} else if(donateType === 'donateBox') { // 나눔바구니
693			}
694		},
695		cmmTipAmtSetData: function () {
696			const $setleAmt = $('#setleAmt');
697			const $setleTotalAmt = $('#setleTotalAmt');
698			const $setleTotalAmt2 = $('#setleTotalAmt2');
699			const $donateTokenAmt = $('#donateTokenAmt');
700			const $setleTipAmt = $('#setleTipAmt');
701			let totalAmount = Number(bfcFmt.removeComma($setleAmt.val()));
702			if ($setleTipAmt.length > 0 && $setleTipAmt.val() !== "") {
703				totalAmount += Number(bfcFmt.removeComma($setleTipAmt.val()));
704			}
705			const formattedAmt = bfcFmt.addComma($setleAmt.val());
706			$setleTotalAmt.val(totalAmount);
707			$setleTotalAmt2.val(totalAmount);
708			$donateTokenAmt.val(totalAmount);
709
710			const totalAmtText = `₩${bfcFmt.addComma(totalAmount)}`;
711			$setleTotalAmt.text(totalAmtText);
712			$setleTotalAmt2.text(totalAmtText);
713			$donateTokenAmt.text(`₩${formattedAmt}`);
714		},
715		/**
716		 * 공통 결제금액 영역의 데이터를 설정
717		 * @param {boolean} onLoadChk - Onload 시점의 체크 여부
718		 * @param {number} setleAmt - 결제 금액
719		 * @param {number} finalUserPnt - 잔여 포인트
720		 * @param {boolean} setleChk - 결제 가능 여부 (UI 비활성화 제어)
721		 */
722		cmmSetleAmtSectionSetData: function(onLoadChk, setleAmt, finalUserPnt, setleChk) {
723			// 1. 공통 금액 표시 로직 호출
724			this._updateAmountDisplay(setleAmt);
725
726			// 2. 이 함수 고유의 로직: 잔여포인트 설정
727			$('#blceDonateTokenAmt').val(finalUserPnt).text(`${bfcFmt.addComma(finalUserPnt)}원`);
728
729			// 3. 이 함수 고유의 로직: UI 상태 변경
730			if (onLoadChk) {
731				$('.btnPrimaryTy01.next').prop('disabled', setleChk);	// 바로결제버튼 활성여부
732				$('input[name=chkCmpgn]').each(function() {		// 메시지 영역들을 순회하며 상태 변경
733					const $messageArea = $(`#msgCmpgn${this.value}`);
734					$messageArea.toggle(!setleChk);
735					$messageArea.prop('disabled', setleChk);
736				});
737			}
738		},
739		/* 공통 결제금액영역 데이터 셋팅 (금액) */
740		cmmSetleAmtSectionSetData2: function(amt) {
741			// 공통 금액 표시 로직만 호출하면 끝
742			this._updateAmountDisplay(amt);
743
744			// 이 함수는 잔여포인트를 처리하지 않음 (원본 주석 유지)
745			//$('#blceDonateTokenAmt').val(0);
746			//$('#blceDonateTokenAmt').text(bfcFmt.addComma(0) + '원');
747		},
748		/**
749		 * 금액 관련 UI를 공통으로 갱신하는 함수
750		 */
751		_updateAmountDisplay: function(amount) {
752			// 1. 자주 사용하는 jQuery 객체와 포맷된 금액을 변수에 할당
753			const $setleAmt = $('#setleAmt');
754			const $setleTotalAmt = $('#setleTotalAmt');
755			const $setleTotalAmt2 = $('#setleTotalAmt2');
756			const $donateTokenAmt = $('#donateTokenAmt');
757			const $svcMenuNm = $('#svcMenuNm');
758			const $cmpgnSn = $('#cmpgnSn');
759			const $setleTipAmt = $('#setleTipAmt');
760
761			let totalAmount = Number(amount);
762			if ($setleTipAmt.length > 0 && $setleTipAmt.val() !== "") {
763				totalAmount += Number(bfcFmt.removeComma($setleTipAmt.val()));
764			}
765			const formattedAmt = bfcFmt.addComma(amount);
766
767			$setleAmt.val(formattedAmt);
768			// $setleTotalAmt.val(amount);
769			// $setleTotalAmt2.val(amount);
770			// $donateTokenAmt.val(amount);
771			$setleTotalAmt.val(totalAmount);
772			$setleTotalAmt2.val(totalAmount);
773			$donateTokenAmt.val(totalAmount);
774
775			// 3. 텍스트(text) 설정
776			const isSpecialCampaign =
777				(cmmEnv.svcProfile.isDevelop() && $svcMenuNm.val() === 'cherryBtn' && $cmpgnSn.val() === '1003') ||
778				(cmmEnv.svcProfile.isProduct() && $svcMenuNm.val() === 'cherryBtn' && $cmpgnSn.val() === '12619');
779
780			// const totalAmtText = `₩${formattedAmt}`;
781			const totalAmtText = `₩${bfcFmt.addComma(totalAmount)}`;
782
783			$setleTotalAmt.text(totalAmtText);
784			$setleTotalAmt2.text(totalAmtText);
785			$donateTokenAmt.text(`₩${formattedAmt}`);
786		},
787		/**
788		 * 공통 체리포인트 결제 체크 (결제화면, 체리포인트, L.POINT, 결제금액)
789		 * @param {number} userChyPnt - 사용자 체리포인트
790		 * @param {number} userLpoint - 사용자 L.POINT
791		 * @param {number} totalAmt - 총 결제 금액
792		 */
793		cmmPntSetleChk: function(userChyPnt, userLpoint, totalAmt) {
794			// 체리포인트 결제 가능 여부 확인
795			if (userChyPnt > 0) {
796				this._checkPointAvailability('cpoint', userChyPnt, totalAmt);
797			}
798			// L.POINT 결제 가능 여부 확인
799			if ($('#lpointYn').val() === 'Y' && userLpoint > 0) {
800				this._checkPointAvailability('lpoint', userLpoint, totalAmt);
801			}
802		},
803		/**
804		 * 단일 포인트 유형의 결제 가능 여부를 확인하고 UI를 설정합니다.
805		 * @param {string} elementId - 확인할 체크박스의 ID (예: 'cpoint')
806		 * @param {number} userPoints - 사용자의 보유 포인트
807		 * @param {number} totalAmount - 총 결제 금액
808		 */
809		_checkPointAvailability: function(elementId, userPoints, totalAmount) {
810			const $pointCheckbox = $(`#${elementId}`);
811			// 결제 가능 조건: 총 결제금액이 0보다 크고, 보유 포인트가 결제금액 이상이어야 함
812			const isPayable = totalAmount > 0 && userPoints >= totalAmount;
813			// 조건에 따라 체크박스 활성/비활성 처리
814			$pointCheckbox.prop('disabled', !isPayable);
815			// 결제가 불가능하다면, 체크된 상태를 강제로 해제
816			if (!isPayable) {
817				$pointCheckbox.prop('checked', false);
818			}
819		},
820		/* 공통 결제수단 정보 설정 */
821		cmmSetleMeanSet: function() {
822			const setleMeanSeType = $('input:radio[name=setleMean]:checked').attr('id');
823			let setleMeanId;
824			switch (setleMeanSeType) {
825				case 'optKsnet': // 간편결제
826					setleMeanId = $('.swiper-container li.swiper-slide-active').attr('id');
827					break;
828				case 'optetc': // 다른결제수단
829					setleMeanId = $('input:radio[name=setleMeanEtc]:checked').attr('id');
830					break;
831				case 'optpnt': // 포인트결제
832					setleMeanId = $('input:radio[name=setleMeanPnt]:checked').attr('id');
833					break;
834				default: // 그 외 (카드, 휴대폰 등 직접 선택)
835					setleMeanId = setleMeanSeType;
836					break;
837			}
838			return { setleMeanSeType, setleMeanId };
839		},
840		/* 공통 결제금액 최소 최대 체크 */
841		cmmSetleAmtMaxMinCheck : function(setleMeanId, setleMeanSeType) {
842			if(bfcStr.isNullOrBlank(setleMeanId) || bfcStr.isNullOrBlank(setleMeanSeType)) {
843				cmmPop.alertError(window.i18n.payment.SELECT_PAYMENT_METHOD);
844				return true;
845			}
846			const $setleTotalAmt = $('#setleTotalAmt');
847			const $dntnMinAmt = $('#dntnMinAmt');
848			const $dntnMaxAmt = $('#dntnMaxAmt');
849			const $isIBoojaApp = $('#isIBoojaApp');
850			if($setleTotalAmt.val() === 0 || bfcStr.isNullOrBlank($setleTotalAmt.val())) { // 결제금액이 0원 혹은 null 케이스인 경우
851				if(setleMeanSeType === 'optpnt') {
852					cmmPop.alertError(window.i18n.payment.MIN_PAYMENT_POINT);
853					return true;
854				} else {
855					cmmPop.alertError(window.i18n.payment.MIN_PAYMENT.replace('{0}', bfcFmt.addComma(parseInt($dntnMinAmt.val()))));
856					return true;
857				}
858				
859			} else if(parseInt(bfcFmt.removeComma($setleTotalAmt.val())) >
859 parseInt($dntnMaxAmt.val())) { // 결제금액이 최대가능금액을 초과하는 경우
860				const isIBoojaApp = !bfcStr.isNull($isIBoojaApp.val()) && $isIBoojaApp.val() === 'true';
861				const maxLimitText = isIBoojaApp ? '50' : '200';
862				cmmPop.alertError(`1회 기부시 ${maxLimitText}만원까지 가능합니다.`, '확인', () => { cmmPayment.cmmSetleAmtSectionSetData2($('#dntnMaxAmt').val()); });
863			}
864		},
865		secureKeyboard : null,
866		/* 결제 비밀번호 오픈 */
867		pinloginPasswd : null,
868		doPasswdReady : function() {
869			$( '#pinDiv' ).html(
870				'<input id=\'pinPasswd\' name=\'pinPasswd\' type=\'password\' value=\'\' disabled /><br/>' +
871				'<input type=\'button\' class=\'pinButton\' name=\'1\' value=\'1\' id=\'1\' />' +
872				'<input type=\'button\' class=\'pinButton\' name=\'2\' value=\'2\' id=\'2\' />' +
873				'<input type=\'button\' class=\'pinButton\' name=\'3\' value=\'3\' id=\'3\' /><br>' +
874				'<input type=\'button\' class=\'pinButton\' name=\'4\' value=\'4\' id=\'4\' />' +
875				'<input type=\'button\' class=\'pinButton\' name=\'5\' value=\'5\' id=\'5\' />' +
876				'<input type=\'button\' class=\'pinButton\' name=\'6\' value=\'6\' id=\'6\' /><br>' +
877				'<input type=\'button\' class=\'pinButton\' name=\'7\' value=\'7\' id=\'7\' />' +
878				'<input type=\'button\' class=\'pinButton\' name=\'8\' value=\'8\' id=\'8\' />' +
879				'<input type=\'button\' class=\'pinButton\' name=\'9\' value=\'9\' id=\'9\' /><br>
879' +
880				'<input type=\'button\' class=\'pinButton clear\' name=\'-\' value=\'clear\' id=\'-\' />' +
881				'<input type=\'button\' class=\'pinButton\' name=\'0\' value=\'0\' id=\'0\' />' +
882				'<input type=\'button\' class=\'pinButton enter\' name=\'+\' value=\'enter\' id=\'+\' />'
883			);
884			function eventHandler(event, selector) {
885				event.stopPropagation();
886				event.preventDefault();
887				if (event.type === 'touchend'){
888					selector.off('click');
889				}
890			}
891			$('.pinButton').on('touchend click', function(event) {
892				$(this).removeClass('pinButtonActive')
893				eventHandler(event, $(this));
894				let val = $(this).val();
895				if(val === 'clear') clearForm();
896				else if(val === 'enter') submitForm(val);
897				else addNumber(val);
898			});
899			$('.pinButton, .pinButton clear, .pinButton enter').on({
900				'touchstart' : function () {
901					$(this).addClass('pinButtonActive');
902				}
903			});
904		},
905		
906		doOpenPasswd : function() {
907			if (!cmmPayment.checkTestSetle()) return;
908
909			const paymentMethod = cmmPayment.cmmSetleMeanSet();
910			const setleMeanId = paymentMethod.setleMeanId;
911			const setleMeanSeType = paymentMethod.setleMeanSeType;
912
913			if(cmmPayment.cmmSetleAmtMaxMinCheck(setleMeanId, setleMeanSeType)) {
914				return;
915			}
916			const menuType = ($('#setleCd').val() === 'D3') ? 'donateBox' : 'donate';
917
918			cmmPayment.cmmcheckTroubleSetleMean(setleMeanId,
919				function() {
920					cmmPayment.donateProcType =$('#donateType').val() === 'fdrm' ? 'fdrmDonate' : 'donate';
921					if(setleMeanSeType === 'optKsnet' || setleMeanId.endsWith('M')) { // 간편결제/마이통장
922						cmmCall.ajaxCall('/payment/ksnet/acnut/chkAcnutDefrayTime', null, function(data) {
923							if(data.result.setlePosblYn) {
924								if(cmmPayment.doCheckAmt(menuType)) {
925									if(setleMeanSeType === 'optKsnet') {
926										cmmPayment.cmmOpenNewPasswdPopupSub('cherry');
927									} else {
928										cmmPayment.doDonateProc()
929									}
930								}
931							} else {
932								cmmPop.alertError(data.result.setleMsg, '닫기');
933							}
934						});
935					} else if(setleMeanSeType === 'optpnt') { // 포인트
936						setTimeout(() => {
937							if(cmmPayment.doCheckAmt(menuType)) {
938								cmmPayment.cmmOpenNewPasswdPopupSub(setleMeanId.endsWith('P') ? 'cherry' : 'lpoint');
939							}
940						}, 200);
941					} else { // 다른결제수단
942						if(cmmPayment.doCheckAmt(menuType)) {
943							cmmPayment.doDonateProc();
944						}
945					}
946				},
947				function() {
948					cmmPop.alertError(xhr.status === 401 ? window.i18n.LOGIN_REQUIRED : window.i18n.payment.SERVER_PROCESSING_ERROR, function() {
949						if(xhr.status ===401) {
950							location.href='/public/member/webMemberLoginPage';
951						}
952					});
953				}
954			);
955		},
956		/**
957		 * 공통장애결제수단체크
958		 */
959		cmmcheckTroubleSetleMean : function(setleMeanId, succCallback, failCallback) {
960			const params = { setleMeanId };
961			cmmCall.ajaxCallNoAlert(
962				'/payment/checkTroubleSetleMeanAjax',
963				params,
964				({ val, title, msg }) => {	// 성공 콜백: 화살표 함수와 객체 구조 분해 할당 적용
965					if (val === 'TroubleSetleMean') {
966						cmmPop.alertError(`<b>${title}</b><br><br>${msg}`);
967					} else {
968						succCallback?.();	// succCallback이 존재할 경우에만 실행
969					}
970				},
971				(xhr) => {	// 실패 콜백
972					failCallback?.(xhr);	// failCallback이 존재할 경우에만 실행
973				}
974			);
975		},
976
977		/**
978		 * 공통비밀번호팝업 열기
979		 * @param {string} titleType - cherry / lpoint
980		 */
981		cmmOpenNewPasswdPopupSub : function(titleType) {
982			// 팝업 및 키패드 초기화
983			cmmPop.fullPopOpen('#pwdInputFullPopup');
984			$('#key_1').keyPad();
985			const isCherryType = (titleType === 'cherry');
986			// isCherryType이 true면 체리포인트 보임
987			$('.pointTitle.cherry').toggle(isCherryType);
988			$('.subTxt.cherry').toggle(isCherryType);
989			$('.sl_btnArrow').toggle(isCherryType);
990
991			// 'lpoint' 관련 요소들은 isCherryType과 반대로 동작
992			$('.pointTitle.lpoint').toggle(!isCherryType);
993			$('.subTxt.lpoint').toggle(!isCherryType);
994			$('.wp_fixmsg').toggle(!isCherryType);
995
996			if (isCherryType) {
997				this.pinCheckIncCount((data) => {
998					if (data.incCount > 4) {
999						cmmPop.alertError('5회 이상 실패로 PIN 재설정이 필요합니다.');
1000						clearAll();
1001					}
1002				});
1003			}
1004		},
1005
1006		pinCheck : function(setleMeanId, svcMenuNm) {
1007			cmmCall.ajaxCallNoAlert('/member/webMemberCheckPin', {
1008				pin: $('#authNo').val()
1009			}, function(result) {
1010				if(result.correct) {
1011					if(svcMenuNm === 'cherry') {
1012						cmmPayment.donateProcType = $('#donateType').val() === 'fdrm' ? 'fdrmDonate' : 'donate';
1013					} else {
1014						cmmPaymentSole.donateProcType = $('#pageInfo').val().indexOf('fdrm') > -1 ? 'fdrmDonate' : 'donate';
1015					}
1016
1017					if($('#fdrmType').val() === 'fdrmChg' && $('#pageInfo').val().indexOf('fdrm') > -1) { // 정기후원 변경
1018						let param = {
1019							fdrmType : $('#fdrmType').val(),
1020							userFdrmDonateReqstSn : $('#userFdrmDonateReqstSn').val(),
1021							userSn : $('#userSn').val(),
1022							cmpgnSn : $('#cmpgnSn').val(),
1023							fdrmDonateAmt : bfcFmt.removeComma($('#setleAmt').val()),
1024							fdrmDonateNextDe : $('.fdrmDonateNextDe').attr('value'),
1025							setleMeanId : $('#setleMeanId').val()
1026						}
1027
1028						cmmCall.ajaxCall('/payment/fdrmDonateReqstAjax', param,
1029							function(data) {
1030								if(data.result.code === '0000') {
1031									cmmCall.goPage('/payment/fdrmSetleComptPage?svcMenuNm=' + svcMenuNm + '&fdrmType=' + $('#fdrmType').val() + '&userFdrmDonateReqstSn=' + data.result.userFdrmDonateReqstSn + '&loc=' + $('#loc').val());
1032								}
1033							}
1034						);
1035					} else {
1036						if(svcMenuNm === 'cherry') {
1037							cmmPayment.toastMsgWait();
1038							cmmPayment.doDonateProc()
1039						} else {
1040							cmmPaymentSole.doDonateProc(setleMeanId);
1041						}
1042					}
1043
1044				} else {
1045					clearAll();
1046					if(result.incCount < 5 ) {
1047						cmmPop.alertError('PIN이 일치하지 않습니다. (' + result.incCount + '회 실패)<br>5회 연속 실패 시 서비스 사용이 제한됩니다.');
1048					} else {
1049						cmmPop.alertError('5회 이상 실패로 PIN 재설정이 필요합니다.');
1050					}
1051				}
1052
1053			}, function(result) {
1054				console.log('fail Res: ' + result);
1055			})
1056		},
1057
1058		pinCheckIncCount : function(okCallback) {
1059			cmmCall.ajaxCallNoAlert('/member/webMemberCheckPinIncorrectCount', {
1060				pin: $('#pinCheckSn').val()
1061			}, function(result) {
1062				okCallback(result);
1063			}, function(result) {
1064				console.log('pinCheckIncCount Fail: ' + result);
1065			});
1066		},
1067		
1068		/* 정기후원 */
1069		doOpenPasswdForFdrm : function() {
1070			setTimeout(() => {
1071				cmmPayment.cmmOpenNewPasswdPopupSub('cherry');
1072				if($('#svcMenuNm').val() !== 'sole') {
1073					cmmPayment.donateProcType = 'fdrmDonate';
1074				}
1075			}, 200);
1076		},
1077		
1078		/* 처리 대기 토스트 메세지 */
1079		toastMsgWait : function() {
1080			cmmPop.pushToastMsg('<img src=\'/assets/web/images/content/loadingToast.gif\' alt=\'로딩 이미지\' class=\'block_img\'>결제 진행중입니다.', 120);
1081		},
1082		
1083		/* 간편결제추가화면처리 */
1084		addSetleMean: function(type) {
1085			const basePath = ($('#svcMenuNm').val() === 'sole') ? '/payment/sole/ksnet' : '/payment/ksnet';
1086			const returnUrl = encodeURIComponent(location.pathname + location.search);
1087			const finalUrl = `${basePath}/${type}/registPage?returnUrl=${returnUrl}`;
1088			cmmPayment.addSetleMeanSub(finalUrl);
1089		},
1090
1091		addSetleMeanSub: function(url) {
1092			cmmCall.ajaxCallNoAlert('/setting/checkUserPin', null,
1093				({ isCheckUserPin }) => {	// 성공 콜백: 화살표 함수와 객체 구조 분해 할당 적용
1094					if (isCheckUserPin) {
1095						location.href = url;
1096					} else {
1097						cmmPop.confirmWarn('PIN 설정이 필요한 기능입니다.', 'PIN 설정하기', '취소', () => {
1098							cmmPop.fullAjaxPopOpenPlace('/setting/pinRgstPopup', { type: 'P', resUrl: url }, '#pinRgstPopup');
1099						});
1100					}
1101				},
1102				(error) => {	// 실패 콜백
1103					console.error('checkUserPin Error:', error);
1104				}
1105			);
1106		},
1107		/* WebApp URL 생성 */
1108		_doWebAppUrlSub: function (url) {
1109			const isCherryApp = cmmEnv.clientType.isCherryApp();
1110			const appParam = isCherryApp ? 'isApp=app' : 'isApp=web';
1111			const separator = url.includes('?') ? '&' : '?';
1112			return `${url}${separator}${appParam}`;
1113		},
1114		_doWebAppUrlNavigateTo: function(url) {
1115			if (cmmEnv.clientType.isCherryApp()) {
1116				cmmPayment.doWebAppUrlProcSub(url);
1117			} else {
1118				cmmCall.goCall(url);
1119			}
1120		},
1121		/* APP-WEB URL 처리 일반후원 */
1122		doWebAppUrlProc: function(url) {
1123			const finalUrl = this._doWebAppUrlSub(url);
1124			this._doWebAppUrlNavigateTo(finalUrl);
1125		},
1126		
1127		/* APP-WEB URL 처리 정기후원 */
1128		doWebAppUrlProcForFdrm: function(url, type) {
1129			cmmLogin.loginCheck(() => {
1130				const finalUrl = this._doWebAppUrlSub(url);
1131				if (type === 'fdrmChg') {
1132					cmmCall.ajaxCall('/payment/fdrmDonate/chgDtChk', null, (data) => {
1133						if (data.code === '9999') {
1134							cmmPop.alertError(data.msg, '확인');
1135						} else {
1136							this._doWebAppUrlNavigateTo(finalUrl);
1137						}
1138					});
1139				} else {
1140					cmmPayment.doCertCheckNew('C00', null, () => {
1141						this._doWebAppUrlNavigateTo(finalUrl);
1142					});
1143				}
1144			});
1145		},
1146		
1147		/* APP-WEB URL 처리 */
1148		doWebAppUrlProcSub : function(url) {
1149			if (!cmmEnv.clientType.isCherryApp()) {
1150				cmmMobApp.goToInApp(url);
1151				return;
1152			}
1153			// iOS 18 대응 시작
1154			// 2024.10.04 yeongeun.seo
1155			const isIOS = cmmMob.isIOS();
1156			caasToApp.getDeviceInfo('cmmPayment.getDeviceInfoPayment');
1157			caasToApp.getVersionString('cmmPayment.getCurrentAppVerPayment');
1158
1159			let isIOSTarget = false;
1160			if(isIOS && cmmPayment._deviceOsVerNm.includes("iPhone 18")) {
1161				isIOSTarget = cmmPayment._myAppVersion < "1.1.87";
1162			}
1163			// iOS 18 대응 종료
1164
1165			if(isIOS && isIOSTarget) {
1166				cmmPop.alertError(window.i18n.payment.IOS18_UPDATE_REQUIRED);
1167			} else {
1168				isIOS ? caasToApp.openInExtBrowserWithJWT(url) : caasToApp.openInExtBrowserWithJWT(encodeURIComponent(url));
1169			}
1170
1171		},
1172		
1173		// iOS 18 대응 시작
1174		// 2024.10.04 yeongeun.seo
1175		_deviceOsVerNm : "",
1176		_myAppVersion : "",
1177		getDeviceInfoPayment : function(_deviceMakerNm, _deviceModelNm, _deviceOsVerNm, _deviceTelecomNm, _trmnlUno){
1178			cmmPayment._deviceOsVerNm = _deviceOsVerNm;
1179		},
1180		getCurrentAppVerPayment : function(myVersion) {
1181			cmmPayment._myAppVersion = myVersion;
1182		},
1183		// iOS 18 대응 종료
1184
1185		// APP-WEB 뒤로가기 처리
1186		// webToApp : 웹에서 앱으로 돌아갈 때, 앱을 그대로 띄움.
1187		// webToAppReload : 웹에서 앱으로 돌아갈 때, 앱에 띄워진 화면을 새로고침함.
1188		doBackPage : function(type) {
1189			const $returnUrl = $('#returnUrl');
1190			const $isApp = $('#isApp');
1191			const $grpSn = $('#grpSn');
1192			const $loc = $('#loc');
1193			const mainPageUrl = '/public/mainPage';
1194			const mainPageEnc = encodeURIComponent(mainPageUrl);
1195			const myPageEnc = encodeURIComponent('/mycherry');
1196			let appUrl;
1197
1198			if(type === 'donate') {
1199				let pageType = $('#pageType').val();	// 01:모금함, 02:캠페인, 03:나눔바구니
1200				let pageInfo = $('#pageInfo').val();	// 화면유형정보 (donate, donateBox, fdrm, cherryRun, cmpgnEventPartcpt)
1201				let setleCd = $('#setleCd').val();		// 결제구분코드
1202				//console.log(`pageType=${pageType} || pageInfo=${pageInfo} || setleCd=${setleCd}`);
1203
1204				if(pageInfo === 'donate') { // 일반후원
1205					if(setleCd === 'D11') {
1206						if ($isApp.val() === 'web') {
1207							history.back();
1208						} else if (cmmEnv.device.isAndroidDevice()) {
1209							cmmMobApp.aos.gotoCharityAosInAppReload();
1210						} else {
1211							cmmMobApp.ios.gotoCharityIosInAppCurr();
1212						}
1213					} else if (['D1', 'D2'].includes(setleCd) || ['01', '02'].includes(pageType)) {
1214						if($isApp.val() === 'web') {
1215							history.back();
1216						} else if(cmmEnv.device.isAndroidDevice()) {
1217							cmmMobApp.aos.gotoCharityAosInAppReload();
1218						} else {
1219							//(2024.05.16) 정기후원과 동일하게 appUrl 를 설정해준다 (v2) (jina.lee)
1220							switch($loc.val()) {
1221								case 'fundBoxList':	appUrl = `/myGroup/getAllDBoxPage/${$grpSn.val()}?pageType=02&hstBckUrl=${mainPageEnc}`; 				break;
1222								case 'cmpgnDtl':	appUrl = `/public/campaign/cmpgnDtlPage/${$('#cmpgnSn').val()}?pageType=02&hstBckUrl=${mainPageEnc}`;	break;
1223								case 'myGrp':		appUrl = mainPageUrl; 																		break;
1224								case 'intrstList':	appUrl = `/my/myPageIntrstCmpgn?pageType=02&hstBckUrl=${myPageEnc}`; 						break;
1225								case 'srchList':	appUrl = `/public/wordSearch?pageType=02&hstBckUrl=${mainPageEnc}`; 						break;
1226								default :			appUrl = mainPageUrl;		 																break;
1227							}
1228							cmmPayment.doGoAppByOS(appUrl);
1229						}
1230					} else if(pageType === '03') {
1231						if(cmmEnv.device.isAndroidDevice()) {
1232							cmmMobApp.aos.gotoCharityAosInAppCurr();
1233						} else {
1234							cmmPayment.doGoAppByOS(mainPageUrl);
1235						}
1236					} else {
1237						history.back();
1238					}
1239				} else if(pageInfo === 'donateBox') { // 나눔바구니
1240					if(cmmEnv.device.isAndroidDevice()) {
1241						// 나눔바구니에서 이동시에는 Reload를 필요로 하므로 추가함
1242						cmmMobApp.aos.gotoCharityAosInAppReload();
1243					} else {
1244						cmmPayment.doGoAppByOS(mainPageUrl);
1245					}
1246				} else if(pageInfo === 'cherryRun' || pageInfo === 'cmpgnEventPartcpt') { // 이벤트
1247					if(pageInfo === 'cherryRun' || $isApp.val() === 'web') {
1248						history.back();
1249					} else if(location.pathname.indexOf('/payment/setleCnfirmPage') > -1) { // 정기결제 이벤트 //if(location.pathname.indexOf('/payment/fdrmDonateReqstPage') > -1)
1250						if(cmmEnv.device.isAndroidDevice()) {
1251							cmmMobApp.aos.gotoCharityAosInAppCurr();
1252						} else {
1253							switch($loc.val()) {
1254								case 'my':			appUrl = `/mypage/history/fdrm?pageType=01&hstBckUrl=${myPageEnc}`;										break;
1255								case 'grpFdrmMng':	appUrl = `/myGroup/fdrmDonateMngPage/${$grpSn.val()}?pageType=01&hstBckUrl=${mainPageEnc}`;				break;
1256								case 'fundBoxList':	appUrl = `/myGroup/getAllDBoxPage/${$grpSn.val()}?pageType=01&hstBckUrl=${mainPageEnc}`;				break;
1257								case 'grpDtl':		appUrl = `/public/group/${$grpSn.val()}?pageType=01&hstBckUrl=${mainPageEnc}`;							break;
1258								case 'cmpgnDtl':	appUrl = `/public/campaign/cmpgnDtlPage/${$('#cmpgnSn').val()}?pageType=02&hstBckUrl=${mainPageEnc}`;	break;
1259								case 'myGrp':		appUrl = mainPageUrl;	break;
1260								default :			appUrl = mainPageUrl;	break;
1261							}
1262							cmmPayment.doGoAppByOS(appUrl);
1263						}
1264					} else {
1265						history.back();
1266					}
1267				} else { // 정기후원
1268					if($isApp.val() === 'web') {
1269						history.back();
1270					} else if(cmmEnv.device.isAndroidDevice()) {
1271						//cmmPayment.doGoAppByOS('webToApp');
1272						cmmMobApp.aos.gotoCharityAosInAppCurr();
1273					} else {
1274						//(2024.05.16) 호출하는 케이스에 우리단체, 모금함 전체보기, 검색 화면, 관심리스트가 추가되었다. (v2) (jina.lee)
1275						switch($loc.val()) {
1276							case 'my':			appUrl = `/mypage/history/fdrm?pageType=01&hstBckUrl=${myPageEnc}`; 									break;
1277							case 'grpFdrmMng':	appUrl = `/myGroup/fdrmDonateMngPage/${$grpSn.val()}?pageType=01&hstBckUrl=${mainPageEnc}`; 			break;
1278							case 'fundBoxList':	appUrl = `/myGroup/getAllDBoxPage/${$grpSn.val()}?pageType=01&hstBckUrl=${mainPageEnc}`; 				break;
1279							// case 'grpDtl':		appUrl = '/public/group/' + $('#grpSn').val() + '?pageType=01&hstBckUrl=' + mainPageEnc; 					break;
1280							case 'cmpgnDtl':	appUrl = `/public/campaign/cmpgnDtlPage/${$('#cmpgnSn').val()}?pageType=02&hstBckUrl=${mainPageEnc}`;	break;
1281							case 'myGrp':		appUrl = mainPageUrl; 																					break;
1282							case 'intrstList':	appUrl = `/my/myPageIntrstCmpgn?pageType=01&hstBckUrl=${myPageEnc}`; 									break;
1283							case 'srchList':	appUrl = `/public/wordSearch?pageType=01&hstBckUrl=${mainPageEnc}`; 									break;
1284							default :			appUrl = mainPageUrl; 																					break;
1285						}
1286						cmmPayment.doGoAppByOS(appUrl);
1287					}
1288				}
1289			} else if(type === 'registAcnut') { // 간편계좌등록화면
1290				location.replace($returnUrl.val());
1291			} else if($returnUrl.val() === '/mypage/setting' || type === 'mySetleMn') { // 간편결제수단관리
1292				if($isApp.val() === 'app') { // APP에서 넘어왔을때
1293					if(cmmEnv.device.isAndroidDevice()) {
1294						cmmMobApp.aos.gotoCharityAosInAppCurr();
1295					} else {
1296						cmmPayment.doGoAppByOS($returnUrl.val() + '?hstBckUrl=' + myPageEnc);
1297					}
1298				} else { // WEB에서 넘어왔을때
1299					history.back();
1300				}
1301			}else {
1302				location.href=$returnUrl.val();
1303			}
1304		},
1305		
1306		/* 모바일 OS에 따른 이동처리 */
1307		doGoAppByOS : function(url) {
1308			const appFlag = $('#isApp').val();
1309			const isApp = ['true', 'app', true].includes(appFlag);
1310			// PC이거나 모바일 웹인 경우, 먼저 처리하고 함수를 조기 종료
1311			if (!cmmEnv.device.isMobileDevice() || !isApp) {
1312				location.replace(url);
1313				return;
1314			}
1315
1316			// OS에 따라 분기 처리
1317			if (cmmEnv.device.isAndroidDevice()) {
1318				// Android 인텐트(Intent) 처리
1319				const aosIntent = cmmMobApp.aos.getCharityAosIntent();
1320				window.location.replace(`intent:/${url}${aosIntent}`);
1321
1322			} else if (cmmEnv.device.isIOSDevice()) {
1323				// iOS 유니버설 링크(Universal Link) 처리
1324				const baseUrl = cmmEnv.svcProfile.isProduct() ? 'https://payment.cherry.charity' : 'https://dev-payment.letscherry.io';
1325				const iOSLink = `${baseUrl}/public/goApp?url=${encodeURIComponent(url)}`;
1326				location.replace(iOSLink);
1327			}
1328			// 현재 창을 닫기 위한 타임아웃
1329			setTimeout(() => cmmPayment.closeWindow(), 10000);
1330
1331		},
1332		closeWindow : function() {
1333			window.close();
1334			self.close();
1335			window.opener = window.location.href;
1336			self.close();
1337			window.open('about:blank', '_self').close();
1338			caasToApp.quitApp();
1339		},
1340		checkTestSetle : function() {
1341			switch($('#grpSn').val()) {
1342				case '2000000000000000095' : cmmPop.alertError('<span style=\'font-weight:bold;color:red;\'>[주의]</span><br>본 테스트교회는 온라인 헌금을 체험할 수 있도록 만든 가상의 교회입니다.<br>헌금액은 특정 단체나 교회에 기부되지 않습니다.');	return false;
1343				case '2000000000000000274' : cmmPop.alertError('<span style=\'font-weight:bold;color:red;\'>[주의]</span><br>본 테스트단체는 \'체리 플랫폼\'의 주요 기능을 체험할 수 있도록 만들어진 가상의 단체로, 결제가 이루어지지 않습니다.');		return false;
1344				case '2000000000000000365' : cmmPop.alertError('<span style=\'font-weight:bold;color:red;\'>[주의]</span><br>본 단체는 \'체리스니커즈데이\'의 주요 기능을 체험할 수 있도록 만들어진 가상의 단체로, 결제가 이루어지지 않습니다.');		return false;
1345				default : return true;
1346			}
1347		},
1348		
1349		addHistoryLengthUrl : function(str) {
1350			return str.indexOf('?') > -1 ? str + '&historyLength=' + history.length : str + '?historyLength=' + history.length;
1351		},
1352
1353		/**
1354		 * iframe 컨트롤용
1355		 * (*1) (2021.09.03) 본인인증 호출 목적이 개인정보 수정일 때 isUserCiNotEqual 체크 추가 (jina.lee)
1356		 * 		(*1-1) C07에 한해서 Toast 메세지 호출
1357		 * (*2) 구회원 본인인증 : 앞으로는 구유저 회원가입은 체리키즈 뿐이다. 따라서 본인인증이 완료되면 전환팝업을 다시 띄워준다.
1358		 * 		history.go(-2) -> 어떤 화면 이동이 없을 것이라는 판단으로 작업함
1359		 */
1360		iframe : {
1361			certIframeCloseNew : function(setleCd, type, msg, url) {
1362				let isUserCiNotEqual; //(*1)
1363				if(setleCd === 'C07' && msg.includes('::')){
1364					let imsi = msg;
1365					msg = imsi.split('::')[0];
1366					isUserCiNotEqual = imsi.split('::')[1];
1367				}
1368				cmmPop.fullPopClose('#certIframePopup');
1369				if(type === 'toast') {
1370					cmmPop.pushToastMsg(msg);
1371				} else if (type === 'popup') {
1372					cmmPop.alertPopup(msg, function() {
1373						if(url != null) {
1374							if(url === 'reload') {
1375								if(['C01', 'C07'].includes(setleCd)) {
1376									/**
1377									 * (2024.05.14) 설정 화면에서 본인인증을 여러번 호출한 경우 (jina.lee)
1378									 * 		히스토리가 쌓이는 이슈로 C01, C07 의 경우 returnUrl=reload 로 수정했다
1379									 */
1380									if(typeof(historyLength) != 'undefined'){
1381										let diff = window.history.length - historyLength;
1382										if(diff > 0){
1383											history.go(-1*diff);
1384										}
1385									}
1386									if(cmmEnv.device.isMobileDevice()) {
1387										if(setleCd === 'C07' && isUserCiNotEqual !== 'Y') { //(*1-1)
1388											cmmPop.pushToastMsgStorage('개인정보가 변경되었습니다.', 3);
1389										}
1390										location.reload();
1391									} else {
1392										if(setleCd === 'C07' && isUserCiNotEqual !== 'Y') { //(*1-1)
1393											opener.parent.pushToastMsg();
1394										}
1395										opener.parent.location.reload();
1396										window.close();
1397									}
1398
1399								} else if(setleCd === 'C12') {
1400									if(typeof(historyLength) != 'undefined'){
1401										let diff = window.history.length - historyLength;
1402										if(diff > 0){
1403											history.go(-1*diff);
1404										}
1405									}
1406									if(typeof(certCallbackFunc) != 'undefined'
1407											&& typeof(certCallbackFunc) === 'function'){
1408										certCallbackFunc();
1409									}else{
1410										$("#isCert").val("Y");
1411									}
1412								} else {
1413									location.reload();
1414								}
1415
1416							} else {
1417								if(url.indexOf('/public/member/loginUserPage') > -1) {
1418									let goUrl = '/public/member/logout?isCherryApp='+cmmEnv.clientType.isCherryApp();
1419									if(cmmEnv.device.isMobileDevice()) {
1420										cmmCall.goCall(goUrl);
1421									} else {
1422										opener.parent.location.href = goUrl;
1423										window.close();
1424									}
1425								} else if(['C01', 'C07'].includes(setleCd)) {
1426									// if(cmmEnv.device.isMobileDevice()) {
1427									// 	//location.reload();
1428									// 	if(setleCd === 'C07' && isUserCiNotEqual !== 'Y') { //(*1-1)
1429									// 		cmmPop.pushToastMsgStorage('개인정보가 변경되었습니다.', 3);
1430									// 	}
1431									// 	location.replace(url);
1432									// } else {
1433									// 	if(setleCd === 'C07' && isUserCiNotEqual !== 'Y') { //(*1-1)
1434									// 		opener.parent.pushToastMsg();
1435									// 	}
1436									// 	opener.parent.location.reload();
1437									// 	window.close();
1438									// }
1439								} else if(setleCd === 'C03'){
1440									let sttus = url.split('=')[1];
1441									if(sttus === '11'){
1442										location.href = '/public/member/loginUserPage';
1443									}else{ //(*2)
1444										cmmPop.fullAjaxPopOpenPlace('/public/member/convertGuidePopup', {fromType : 'regist'}, '#convertGuidePopup');
1445									}
1446								} else if(setleCd === 'C12'){
1447									location.replace(url);
1448								} else if(setleCd === 'C06' && location.pathname.indexOf('/member/webMemberRegistCmplt') > -1){
1449									if(url === '/public/member/loginUserPage') cruCall.goHome();
1450									else nextStep();
1451								} else if(setleCd === 'C21'){
1452									// 23.05.16 C21케이스 본인인증 성공 후 지정 url로 이동
1453									cmmCall.goCall(url);
1454								} else if(setleCd === 'C22'){
1455									console.log('setleCd=' + setleCd + '|| type=' + type + '|| msg=' + msg + '|| url=' + url)
1456									console.log(`C22 `);
1457									try {
1458										identityCallback(url)
1459									} catch (e){
1460										console.log(e);
1461										opener.parent.identityCallback(url);
1462									} finally {
1463										window.close();
1464									}
1465								} else {
1466									location.reload();
1467								}
1468							}
1469						} else {
1470							if(setleCd === 'C04') {
1471								if(location.pathname === '/public/member/mnemonicShowPage') {
1472									location.replace('/mypage/setting?hstBckUrl=/public/mainPage');
1473								}
1474							}
1475						}
1476					});
1477				} else {
1478					location.replace(url);
1479				}
1480			}
1481		},
1482		
1483		pg : {
1484			iosSubmitDelayMs : 1000,
1485			/**
1486			 * 화면 중앙에 팝업창을 열고, 팝업 차단 여부 확인
1487			 * @param {string} nextUrl - 팝업에 표시할 URL
1488			 * @param {number} width - 팝업창의 너비
1489			 * @param {number} height - 팝업창의 높이
1490			 * @returns {boolean|undefined} 팝업이 차단된 경우 false를 반환
1491			 */
1492			openWinPop: function(nextUrl, width, height) {
1493				const left = window.screenX + (window.innerWidth - width) / 2;
1494				const top = window.screenY + (window.innerHeight - height) / 2;
1495				const windowOptions = `
1496					width=${width},height=${height},
1497					left=${left},top=${top},
1498					toolbar=no,location=no,directories=no,status=yes,
1499					menubar=no,scrollbars=no,resizable=no
1500				`;
1501				const POPUP_NAME = 'payWindow';
1502				this.winPopup = window.open(nextUrl, POPUP_NAME, windowOptions.replace(/\s/g, ''));
1503
1504				try {
1505					if (!this.winPopup || this.winPopup.closed || typeof this.winPopup.closed === 'undefined') {
1506						cmmPop.alertError(window.i18n.payment.POPUP_BLOCKED_ERROR_1);
1507						return false;
1508					}
1509				} catch (e) {
1510					cmmPop.alertError(window.i18n.payment.POPUP_BLOCKED_ERROR_2);
1511					return false;
1512				}
1513			},
1514			/**
1515			 * 객체의 속성들을 <input type="hidden">으로 만들어 폼에 추가하는 함수
1516			 * @param {jQuery} $targetForm - input들을 추가할 jQuery 폼 객체
1517			 * @param {object} dataMap - input으로 변환할 데이터가 담긴 객체
1518			 * @param {boolean} [addId=false] - input에 id 속성을 추가할지 여부 (선택 사항)
1519			 */
1520			appendHiddenInputs : function($targetForm, dataMap, addId = false) {
1521				// dataMap이 유효하지 않으면 아무 작업도 하지 않음
1522				if (!dataMap) { return; }
1523				// 객체의 키와 값을 순회하며 input 생성
1524				Object.entries(dataMap).forEach(([key, value]) => {
1525					const attributes = {
1526						type: 'hidden',
1527						name: key,
1528						value: value,
1529					};
1530					// addId 파라미터가 true일 경우에만 id 속성 추가
1531					if (addId) { attributes.id = key; }
1532					$('<input>', attributes).appendTo($targetForm);
1533				});
1534			},
1535			smartroPayInfo: function(param) {
1536				cmmCall.ajaxCall('/payment/smartroPay/info', param, (data) => {
1537					if (!data.smartroPayMap) {
1538						cmmPop.alertError('SmartroPay 결제창 요청 실패', '닫기');
1539						$('#btnDonate').attr('disabled', false);
1540						return;
1541					}
1542					const FORM_ID = 'tranMgr';
1543					$(`#${FORM_ID}`).remove(); // 기존 폼 제거
1544					const $form = $('<form>', { method: 'post', id: FORM_ID, name: FORM_ID, });
1545					// 공통 객체 속성 생성
1546					this.appendHiddenInputs($form, data.smartroPayMap);
1547					$form.appendTo('body');
1548
1549					smartropay.init({ mode: data.smartroPayMap.mode });
1550
1551					const paymentOptions = {
1552						FormId: FORM_ID,
1553					};
1554					if (!cmmEnv.device.isMobileDevice()) {
1555						paymentOptions.Callback = (res) => {
1556							const approvalForm = document.approvalForm;
1557							approvalForm.Tid.value = res.Tid;
1558							approvalForm.TrAuthKey.value = res.TrAuthKey;
1559							approvalForm.action = data.smartroPayMap.ReturnUrl;
1560							approvalForm.submit();
1561						};
1562					}
1563					smartropay.payment(paymentOptions);
1564				});
1565			},
1566			myPayInfo: function(param) {
1567				cmmCall.ajaxCall('/payment/myPay/myPayInfo', param, (data) => {
1568					const THEME_COLOR = 'F4907E';
1569					const LOGO_TYPE = '1';
1570					const FORM_ID = 'myPayForm';
1571					let payload = {
1572						...data.myPayMap,
1573						sndRetParam: param.val,
1574						sndThemecolor: THEME_COLOR,
1575						sndLogotype: LOGO_TYPE,
1576					};
1577
1578					if (cmmEnv.device.isMobileDevice()) {
1579						if (param.svcMenuNm === 'cherry') { payload.sndCancelUrl = document.URL; }
1580						setTimeout(() => { cmmCall.goPost(payload.myPayUrl, payload); }, this.iosSubmitDelayMs);
1581						if (['D1', 'D2'].includes(param.setleCd)) { btnClearAmt(); }
1582					} else {
1583						const POPUP_WIDTH = 545;
1584						const POPUP_HEIGHT = 750;
1585						$(`#${FORM_ID}`).remove(); // 기존 폼 제거
1586
1587						const $form = $('<form>', {
1588							method: 'post',
1589							id: FORM_ID,
1590							name: FORM_ID,
1591							action: payload.myPayUrl,
1592							target: 'payWindow',
1593						});
1594
1595						// 공통 객체 속성 생성
1596						this.appendHiddenInputs($form, payload);
1597						this.openWinPop('', POPUP_WIDTH, POPUP_HEIGHT);
1598						$form.appendTo('body').submit();
1599					}
1600				});
1601			},
1602			ksPayInfo: function(param) {
1603				cmmCall.ajaxCall('/payment/ksPay/ksPayInfo', param, (data) => {
1604					const FORM_ID = 'ksPayForm';
1605					const payload = {
1606						...data.ksPayMap,
1607						ECHA: param.val,
1608						ECHB: data.ksPayMap.sndOrdernumber,
1609						ECHC: param.svcMenuNm === 'cherry' ? document.URL : cmmPayment.addHistoryLengthUrl(document.URL),
1610					};
1611
1612					if (cmmEnv.device.isMobileDevice()) {
1613						// 모바일 환경 처리
1614						setTimeout(() => { cmmCall.goPost(payload.ksPayUrl, payload); }, this.iosSubmitDelayMs);
1615						if (['D1', 'D2'].includes(param.setleCd)) { btnClearAmt(); }
1616					} else {
1617						const POPUP_WIDTH = 830;
1618						const POPUP_HEIGHT = 630;
1619						$(`#${FORM_ID}`).remove(); // 기존 폼 제거
1620						const $form = $('<form>', {
1621							method: 'post',
1622							id: FORM_ID,
1623							name: FORM_ID,
1624							action: payload.ksPayUrl,
1625							target: 'payWindow',
1626						});
1627						// 공통 객체 속성 생성
1628						this.appendHiddenInputs($form, payload, true);
1629						this.openWinPop('', POPUP_WIDTH, POPUP_HEIGHT);
1630						$form.appendTo('body').submit();
1631					}
1632				});
1633			},
1634			nPayReady : function(param) {
1635				let isTicket = $("#cmpgnEventSeCode").val() === '008';
1636				let nextUrl = param.nextUrl;
1637				let nPayJsonArray = [];
1638				const $cmpgnSn = $('#cmpgnSn');
1639				const $cmpgnNm = $('#cmpgnNm');
1640				if(['D1', 'D2', 'D11'].includes(param.setleCd)) {
1641					let nPayJson = {};
1642					nPayJson.categoryType = isTicket ? 'PLAY' : 'PRODUCT';
1643					nPayJson.categoryId = isTicket ? 'TICKET' : 'SUPPORT';
1644					nPayJson.uid = $cmpgnSn.val();
1645					nPayJson.name = $cmpgnNm.val();
1646					nPayJson.count = 1;
1647					nPayJsonArray.push(nPayJson);
1648					param.cmpgnSn = $cmpgnSn.val();
1649
1650				} else if(['D3'].includes(param.setleCd)) {
1651					$('input:hidden[name=userDonateBoxSn]').each(function() {
1652						let nPayJson = {};
1653						nPayJson.categoryType = 'PRODUCT';
1654						nPayJson.categoryId = 'SUPPORT';
1655						nPayJson.uid = $('#cmpgnSn' + $(this).val()).val();
1656						nPayJson.name = $('#cmpgnNm' + $(this).val()).val();
1657						nPayJson.count = 1;
1658						nPayJsonArray.push(nPayJson);
1659					});
1660					if(nPayJsonArray.length > 1) {
1661						param.cmpgnSn = nPayJsonArray[0]['uid'];
1662					}
1663				} else {
1664					return false;
1665				}
1666				
1667				if(param.setleAmt < 1000) {
1668					cmmPop.alertError('Npay ' + window.i18n.payment.MIN_PAYMENT.replace('{0}', '1,000'));
1669					return false;
1670				}
1671				
1672				cmmCall.ajaxCall('/payment/npay/mode', param, function(data) {
1673					let opt = {
1674						'mode' : data.mode,
1675						'payType' : data.payType,
1676						'clientId': data.clientId,
1677						'chainId' : data.chainId,
1678						'openType': cmmEnv.device.isMobileDevice() ? 'page' : 'popup',
1679						'useNaverAppLogin': true
1680					};
1681
1682					if(!cmmEnv.device.isMobileDevice()) {
1683						opt.onAuthorize = function(oData) {
1684							oData.openType = 'popup';
1685							let ajaxUrl = oData.returnUrl.replaceAll(location.protocol + '//' + location.hostname, '');
1686							if(oData.resultCode === 'Success') {
1687								cmmCall.ajaxCall(ajaxUrl, oData, function(data) {
1688									if(data.flag === 'Y') {
1689										if(data.fdrmType === 'fdrmReq') {
1690											cmmCall.goPage(`/payment/fdrmSetleComptPage?svcMenuNm=${param.svcMenuNm}&fdrmType=${data.fdrmType}&userFdrmDonateReqstSn=${data.userFdrmDonateReqstSn}&val=${data.val}`);
1691										} else {
1692											if(param.svcMenuNm === 'cherryBtn' && (['sbslove', 'itmc2023', 'icmda2026'].includes(data.channelSid)) && !bfcStr.isNull(data.paymentRetrunUrl)) {
1693												cmmCall.goPage(data.paymentRetrunUrl);
1694											} else {
1695												cmmCall.goPage(`/payment/setleComptPage?svcMenuNm=${param.svcMenuNm}&val=${data.val}`);
1696											}
1697										}
1698									} else {
1699										cmmPop.alertError(decodeURIComponent(data.message), '확인', function() {
1700											param.svcMenuNm === 'cherryBtn' ? cmmCall.goPage(`/cherrybtn/${$cmpgnSn.val()}`) : (param.svcMenuNm === 'sole' ? soleCall.goHome() : cmmLogin.goHome());
1701										});
1702									}
1703								});
1704							} else {
1705								if(oData.resultMessage === 'userCancel' || oData.resultMessage === 'UserCancel') {
1706									param.donateType === 'fdrmDonate' ? cmmPop.alertExpError('정기결제 등록이 취소되었습니다.') : cmmPop.alertExpError('결제가 취소되었습니다.');
1707								} else {
1708									cmmCall.ajaxCall(ajaxUrl, oData, function(data) {
1709										cmmPop.alertError(decodeURIComponent(data.message), '확인', function() {
1710											param.svcMenuNm === 'cherryBtn' ? cmmCall.goPage(`/cherrybtn/${$cmpgnSn.val()}`) : (param.svcMenuNm === 'sole' ? soleCall.goHome() : cmmLogin.goHome());
1711										});
1712										
1713									});
1714								}
1715							}
1716						}
1717					}
1718					let oPay = Naver.Pay.create(opt);
1719					if(param.donateType === 'fdrmDonate') {
1720						oPay.open({
1721							'actionType' : 'NEW',
1722							'productCode': $('#userSn').val() + '||' + $cmpgnSn.val(),
1723							'productName': $('#cmpgnNm').val(),
1724							'totalPayAmount': parseInt(param.setleAmt),
1725							'returnUrl': nextUrl + '&donateType=fdrm&cancelUrl=' + encodeURIComponent(document.URL)
1726						});
1727						
1728					} else {
1729						let taxScopeAmount = isTicket ? parseInt(param.setleAmt) : 0;
1730						let taxExScopeAmount = isTicket ? 0 : parseInt(param.setleAmt);
1731
1732						oPay.open({
1733							'merchantPayKey': bfcCom.getUuid(),
1734							'merchantUserKey': $('#userSn').val(),
1735							'productName': nPayJsonArray[0].name,
1736							'productCount': nPayJsonArray.length,
1737							'totalPayAmount': parseInt(param.setleAmt),
1738							'taxScopeAmount': taxScopeAmount,
1739							'taxExScopeAmount': taxExScopeAmount,
1740							'returnUrl': param.svcMenuNm === 'sole' ? (nextUrl + '&cancelUrl=' + encodeURIComponent(cmmPayment.addHistoryLengthUrl(document.URL))) : (nextUrl + '&cancelUrl=' + encodeURIComponent(document.URL)),
1741							'productItems': nPayJsonArray
1742						});
1743						
1744						if(cmmEnv.device.isMobileDevice() && ['D1', 'D2', 'D11'].includes(param.setleCd)) {
1745							btnClearAmt();
1746						}
1747					}
1748				});
1749			},
1750			kakaoPayReady : function(param) {
1751				cmmCall.ajaxCall('/payment/kakaoPay/ready', param, (data) => {
1752					if (!data.nextUrl) {
1753						cmmPop.alertError('카카오페이 응답 URL 오류입니다.<br/>다른 결제수단으로 이용 부탁드립니다.');
1754						return;
1755					}
1756					if ((data.setleEnv === 'mobile') || cmmEnv.device.isMobileDevice()) {
1757						location.href = data.nextUrl;
1758					} else {
1759						const POPUP_WIDTH = 545;
1760						const POPUP_HEIGHT = 750;
1761						cmmPayment.pg.openWinPop(data.nextUrl, POPUP_WIDTH, POPUP_HEIGHT);
1762					}
1763				});
1764			},
1765			hanabankReady : function(param) {
1766				if(cmmSole.isCustomExist() && ibjComm.isInApp() && $('#soleSsid').val() === 'ibooja') {
1767					cmmCall.ajaxCall('/payment/hanabank/info', param, (data) => {
1768						const { hanabankMap } = data;
1769						hanabankMap.rsevTmsgCtt = param.val;
1770						HanaPartner.openPopup('01', cmmPayment.pg.hanabankCallback, JSON.stringify(hanabankMap));
1771					});
1772				} else {
1773					cmmPop.alertError('아이부자앱을 통한 접속이 아닙니다.');
1774				}
1775			},
1776			
1777			hanabankCallback : function(data) {
1778				const $soleSsid = $('#soleSsid');
1779				if(cmmSole.isCustomExist() && ibjComm.isInApp() && $soleSsid.val() === 'ibooja') {
1780					if(data.resultCode === 0) {
1781						let scssYn = JSON.parse(data.result).scssYn;
1782						if(bfcStr.isNull(scssYn)) {
1783							cmmPop.alertError('서버 오류가 발생했습니다.<br>(scssYn 값 미존재)<br>data : ' + JSON.stringify(data.result));
1784						} else {
1785							let errorMessage = JSON.parse(data.result).errorMessage;
1786							let param = {
1787								ssid: $soleSsid.val(),
1788								scssYn: scssYn,
1789								trscSeqNo: JSON.parse(data.result).trscSeqNo,
1790								val: encodeURIComponent(JSON.parse(data.result).rsevTmsgCtt),
1791								respHanabankMap: JSON.parse(data.result)
1792							}
1793							
1794							if(scssYn === 'Y') {
1795								param.trscDt=JSON.parse(data.result).trscDt;
1796								param.trscTm=JSON.parse(data.result).trscTm;
1797							} else {
1798								param.errorMessage=errorMessage;
1799							}
1800
1801							cmmCall.ajaxCall('/callback/payment/hanabank/setle', param, (data) => {
1802								if(data.hanabankMap.code === '9999') {
1803									cmmPop.alertError(data.hanabankMap.message, '확인', () => { history.back(); });
1804								} else if(data.hanabankMap.code === '9998') {
1805									console.log('사용자취소');
1806								} else {
1807									let val = param.val.length < 45 ? encodeURIComponent(param.val) : param.val;
1808									location.replace(`/sole/${$soleSsid.val()}/payment/setleComptPage?svcMenuNm=sole&val=${val}`);
1809								}
1810							});
1811						}
1812					} else {
1813						cmmPop.alertError('서버 오류로 결제가 취소되었습니다.');
1814					}
1815				} else {
1816					cmmPop.alertError('아이부자앱을 통한 접속이 아닙니다.');
1817				}
1818			}
1819		}
1820	}
1821})(jQuery);

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.