Procházet zdrojové kódy

Merge remote-tracking branch 'origin/order' into xodud1202

xodud1202 před 5 roky
rodič
revize
7197cde27b
27 změnil soubory, kde provedl 1661 přidání a 330 odebrání
  1. 5 1
      pom.xml
  2. 12 0
      src/main/java/com/style24/front/biz/dao/TsfCouponDao.java
  3. 13 0
      src/main/java/com/style24/front/biz/dao/TsfCustomerDao.java
  4. 1 2
      src/main/java/com/style24/front/biz/service/TsfCartService.java
  5. 36 0
      src/main/java/com/style24/front/biz/service/TsfCouponService.java
  6. 165 9
      src/main/java/com/style24/front/biz/service/TsfCustomerService.java
  7. 116 21
      src/main/java/com/style24/front/biz/thirdparty/KaKaoLogin.java
  8. 28 11
      src/main/java/com/style24/front/biz/thirdparty/NaverLogin.java
  9. 33 31
      src/main/java/com/style24/front/biz/web/TsfCustomerController.java
  10. 151 0
      src/main/java/com/style24/front/biz/web/TsfIndexController.java
  11. 136 2
      src/main/java/com/style24/front/biz/web/TsfMypageController.java
  12. 30 26
      src/main/java/com/style24/front/biz/web/TsfOrderController.java
  13. 3 0
      src/main/java/com/style24/persistence/domain/Coupon.java
  14. 38 0
      src/main/java/com/style24/persistence/domain/CustSnsInfo.java
  15. 58 0
      src/main/java/com/style24/persistence/mybatis/shop/TsfCoupon.xml
  16. 69 0
      src/main/java/com/style24/persistence/mybatis/shop/TsfCustomer.xml
  17. 1 0
      src/main/java/com/style24/persistence/mybatis/shop/TsfOrder.xml
  18. 14 14
      src/main/resources/config/application.yml
  19. 4 0
      src/main/resources/i18n/messages/message_ko_KR.properties
  20. 31 16
      src/main/webapp/WEB-INF/views/web/SigninFormWeb.html
  21. 48 0
      src/main/webapp/WEB-INF/views/web/SnsCallBackFormWeb.html
  22. 6 12
      src/main/webapp/WEB-INF/views/web/mypage/MypageExchangeFormWeb.html
  23. 65 10
      src/main/webapp/WEB-INF/views/web/mypage/MypageOrderListFormWeb.html
  24. 335 0
      src/main/webapp/WEB-INF/views/web/mypage/MypageReturnFormWeb.html
  25. 197 172
      src/main/webapp/WEB-INF/views/web/order/OrderFormWeb.html
  26. 11 1
      src/main/webapp/ux/pc/js/cart.js
  27. 55 2
      src/main/webapp/ux/style24_link.js

+ 5 - 1
pom.xml

@@ -59,7 +59,11 @@
 			<artifactId>commons-io</artifactId>
 			<version>2.6</version>
 		</dependency>
-		
+		<dependency>
+			<groupId>com.googlecode.libphonenumber</groupId>
+			<artifactId>libphonenumber</artifactId>
+			<version>8.12.16</version>
+		</dependency>
 		<!-- /// WEB-INF lib -->
 		<dependency>
 			<groupId>com.gagaframework</groupId>

+ 12 - 0
src/main/java/com/style24/front/biz/dao/TsfCouponDao.java

@@ -1,5 +1,7 @@
 package com.style24.front.biz.dao;
 
+import java.util.Collection;
+
 import com.style24.core.support.annotation.ShopDs;
 import com.style24.persistence.domain.Cart;
 import com.style24.persistence.domain.Coupon;
@@ -28,4 +30,14 @@ public interface TsfCouponDao {
 	 * @since 2021. 02. 17
 	 */
 	Coupon getSearchSerialCpnInfo(Coupon param);
+
+	/**
+	 * 마이페이지 등급쿠폰 다운가능 쿠폰 정보 조회
+	 * 
+	 * @param coupon
+	 * @return Collection<Coupon>
+	 * @author card007
+	 * @since 2021.02.25
+	 */
+	Collection<Coupon> getCustGradeCouponInfo(Coupon coupon);
 }

+ 13 - 0
src/main/java/com/style24/front/biz/dao/TsfCustomerDao.java

@@ -1,6 +1,7 @@
 package com.style24.front.biz.dao;
 
 import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.CustSnsInfo;
 import com.style24.persistence.domain.Customer;
 
 /**
@@ -47,4 +48,16 @@ public interface TsfCustomerDao {
 	 * @since 2021. 02. 22
 	 */
 	int createCustomerSns(Customer customer);
+
+	/**
+	 * 활동, 휴면 테이블 조회
+	 * @param customer - 고객정보
+	 * @return 고객정보
+	 * @author jsshin
+	 * @since 2021. 02. 24
+	 */
+	Customer getCusomterActiveAndDormant(Customer customer);
+
+
+	Customer getCusomterSnsFind(CustSnsInfo custSnsInfo);
 }

+ 1 - 2
src/main/java/com/style24/front/biz/service/TsfCartService.java

@@ -351,6 +351,7 @@ public class TsfCartService {
 
 		// 섹션 정보 조회 후 할인 여부 판단
 		Collection<Order> tmtbSectionList = cartDao.selectTmtbSectionValList(applySq);
+		
 		for(Order applyInfo : tmtbApplyList) {													// 기준 상품 및 다다익선 정보 조회
 			// 다다익선 할인 조건 조회
 			for(Order section : tmtbSectionList) {
@@ -396,8 +397,6 @@ public class TsfCartService {
 			}
 		});
 
-
-
 		// 수량 다다익선 적용 상품 할인 금액 계산
 		int leftAmt = 0;
 		int i = 0;

+ 36 - 0
src/main/java/com/style24/front/biz/service/TsfCouponService.java

@@ -186,4 +186,40 @@ public class TsfCouponService {
 		coreCouponDao.updateGiveRandomCoupon(custCoupon);		// 랜덤쿠폰 CUST_NO UPDATE
 		coreCouponDao.saveCouponCustPub(custCoupon);			// 랜덤쿠폰 고객 지급
 	}
+
+	/**
+	 * 마이페이지 등급쿠폰 다운 처리
+	 *
+	 * @param coupon
+	 * @return Collection<Coupon>
+	 * @author card007
+	 * @since 2021.02.25
+	 */
+	@Transactional("shopTxnManager")
+	public int createCustGradeAllCoupon(Coupon coupon) {
+		int count = 0;
+		
+		Collection<Coupon> couponList = couponDao.getCustGradeCouponInfo(coupon);
+		
+		for(Coupon tmpCoupon : couponList) {
+			int downloadCnt = tmpCoupon.getDownloadCnt();
+			for (int i = 0; i < downloadCnt; i++) {
+				CustCoupon custCoupon = new CustCoupon();
+				custCoupon.setCustNo(tmpCoupon.getCustNo());
+				custCoupon.setCpnId(tmpCoupon.getCpnId());
+				custCoupon.setAvailStdt(tmpCoupon.getAvailStdt());
+				custCoupon.setAvailEddt(tmpCoupon.getAvailEddt());
+				custCoupon.setPubReason(TscConstants.PubReason.DOWNLOAD.value());
+				custCoupon.setEndAlimSendYn(tmpCoupon.getEndAlimYn());
+				custCoupon.setRegNo(tmpCoupon.getCustNo());
+				custCoupon.setUpdNo(tmpCoupon.getCustNo());
+
+				coreCouponDao.saveCouponCustPub(custCoupon);
+
+				count++;
+			}
+		}
+		
+		return count;
+	}
 }

+ 165 - 9
src/main/java/com/style24/front/biz/service/TsfCustomerService.java

@@ -1,12 +1,16 @@
 package com.style24.front.biz.service;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.gagaframework.web.parameter.GagaMap;
 import com.gagaframework.web.security.GagaPasswordEncoder;
 import com.style24.core.biz.service.TscCustomerService;
 import com.style24.core.support.env.TscConstants;
 import com.style24.core.support.session.TscSession;
+import com.style24.core.support.util.CryptoUtils;
 import com.style24.front.support.security.TsfLoginDetails;
+import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.domain.Coupon;
+import com.style24.persistence.domain.CustSnsInfo;
 import com.style24.persistence.domain.Customer;
 import com.style24.persistence.domain.Login;
 import com.style24.persistence.domain.Point;
@@ -47,6 +51,9 @@ public class TsfCustomerService {
 	@Autowired
 	private TsfLoginService loginService;
 
+	@Autowired
+	private ObjectMapper objectMapper;
+
 
 	/**
 	 * 고객아이디 찾기
@@ -60,9 +67,27 @@ public class TsfCustomerService {
 		TscSession.setAttribute("maskingYn","Y");
 		customer.setSiteCd(TscConstants.Site.STYLE24.value());
 		customer.encryptData(); // 데이터 암호하
+		return customerDao.getCusomterActiveAndDormant(customer);
+	}
+
+	/**
+	 * 고객정보찾기 -
+	 *
+	 * @param custNo - 고객번호
+	 * @return Customer 고객정보
+	 * @author jsshin
+	 * @since 2021. 02. 24
+	 */
+	public Customer getCustomerFindByCustNo(Integer custNo) {
+		Customer customer = new Customer();
+		customer.setCustNo(custNo);
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.encryptData();
 		return coreCustomerService.getCustomerInfo(customer);
 	}
 
+
 	/**
 	 * 임시비밀번호 조회
 	 * @param length - 비밀번호 자릿수
@@ -122,9 +147,27 @@ public class TsfCustomerService {
 		return result > 0;
 	}
 
+	/**
+	 * 해당 휴대전화로 가입된 이력이 있는지 확인
+	 * @param cellPhnno - 휴대전화
+	 * @return boolean - 있으면 TRUE/ 없으면 FALSE
+	 * @author jsshin
+	 * @since 2021. 02. 15
+	 */
+	public boolean getCustomerFindByCellPhnnoCount(String cellPhnno) {
+		Customer customer = new Customer();
+		customer.setCellPhnno(cellPhnno);
+		customer.setHypenCellPhone(); // 010-0000-0000
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.encryptData();
+		int result = customerDao.getCustomerInfoCount(customer);
+
+		return result > 0;
+	}
+
 	/**
 	 * 해당 CI로 가입된 이력이 있는지 확인
-	 * @param ci - ci
+	 * @param ci - 연계정보
 	 * @return boolean - 있으면 TRUE/ 없으면 FALSE
 	 * @author jsshin
 	 * @since 2021. 02. 15
@@ -141,7 +184,7 @@ public class TsfCustomerService {
 	/**
 	 * 해당 휴대폰 번호로 가입된 이력이 있는지 확인
 	 * @param cellPhnno - 휴대전화번호
-	 * @return boolean - 있으면 TRUE/ 없으면 FALSE
+	 * @return Customer - 고객정보
 	 * @author jsshin
 	 * @since 2021. 02. 15
 	 */
@@ -201,8 +244,9 @@ public class TsfCustomerService {
 	}
 
 	/**
-	 * 회원가입 처리
-	 * @param customer - 일반가입, SNS 가입
+	 * 회원가입 처리 - 일반가입
+	 * @param customer - 일반가입
+	 * @return boolean - 가입 성공 true / 실패 false
 	 * @author jsshin
 	 * @since 2021. 02. 19
 	 */
@@ -210,17 +254,50 @@ public class TsfCustomerService {
 	public boolean saveJoinCustomer(Customer customer) {
 		boolean isJoin = true;
 		// 1. validation
+		customer.setHypenCellPhone();
 		customer.encryptData();
-		if (StringUtils.isNotBlank(customer.getSnsId())) {
-			customer.setEncodedPasswd(" ");
-			customer.setCustId(customer.getSnsType()+"_"+customer.getSnsId());
+		customer.setEncodedPasswd(passwordEncoder.encode(customer.getPasswd()));
+
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer.setCustGb(TscConstants.CustGb.NORMAL.value());
+		customer.setCustGrade(TscConstants.CustGrade.WELCOME.value());
+
+		int custCnt = customerDao.createCustomer(customer);
+
+		if (custCnt > 0) {
+			saveJoinPostProcessing(customer);
 		} else {
-			customer.setEncodedPasswd(passwordEncoder.encode(customer.getPasswd()));
+			isJoin = false;
 		}
+
+		return isJoin;
+	}
+
+	/**
+	 * 회원가입 처리 - SNS 간편가입
+	 * @param customer - SNS 정보
+	 * @return boolean - 가입 성공 true / 실패 false
+	 * @author jsshin
+	 * @since 2021. 02. 19
+	 */
+	public boolean saveJoinCustomerSns (Customer customer) {
+		boolean isJoin = true;
+		customer.setEncodedPasswd(" ");
+		customer.setCustId(customer.getSnsType()+"_"+customer.getSnsId());
+		customer.setEncodedPasswd(passwordEncoder.encode(customer.getPasswd()));
+		customer.encryptData();
+
+		String gender = "G007_"+customer.getSexGb();
+		customer.setSexGb(gender);
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.setFrontGb(TsfSession.getFrontGb());
+		customer.setAfLinkCd(TsfSession.getAttribute("afLinkCd"));
 		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
 		customer.setCustGb(TscConstants.CustGb.NORMAL.value());
 		customer.setCustGrade(TscConstants.CustGrade.WELCOME.value());
+
 		int custCnt = customerDao.createCustomer(customer);
+		customerDao.createCustomerSns(customer);
 
 		if (custCnt > 0) {
 			saveJoinPostProcessing(customer);
@@ -229,6 +306,7 @@ public class TsfCustomerService {
 		}
 
 		return isJoin;
+
 	}
 
 	/**
@@ -249,9 +327,87 @@ public class TsfCustomerService {
 
 	}
 
+
+	/**
+	 * Sns 정보에대한 상태 처리
+	 * @param custSnsInfo
+	 * @author jsshin
+	 * @since 2021. 02. 19
+	 */
+	@Transactional("shopTxnManager")
+	public GagaMap customerSnsProcessing (CustSnsInfo custSnsInfo) {
+		GagaMap resultMap = new GagaMap();
+		Customer custInfo;
+
+		// 1. snsId, snsType 값으로 연동되어져 있는지 확인
+		custInfo = customerDao.getCusomterSnsFind(custSnsInfo);
+		if (custInfo != null) {
+			resultMap.setString("custStat", "SUCC_CUST");
+			return resultMap;
+		}
+
+		// 2. CI(연계정보)로 가입 되어져 있는 고객이 있는지 ?
+		custInfo = getCustomerFindByCi(custSnsInfo.getCi());
+
+		if (custInfo != null) { // 2-1. 고객정보 있는경우
+			if (TscConstants.CustStat.SECEDE.value().equals(custInfo.getCustStat())) {
+				resultMap.setString("custStat", "SECEDE_CUST"); // 탈퇴 회원
+				return resultMap;
+			}
+			if (TscConstants.CustStat.DORMANT.value().equals(custInfo.getCustStat())) {
+				resultMap.setString("custStat", "DORMANT_CUST"); // 휴면 회원
+				return resultMap;
+			}
+			if (TscConstants.CustStat.ACTIVE.value().equals(custInfo.getCustStat())) {
+
+				if (StringUtils.isBlank(custSnsInfo.getCellPhnno())) {
+					resultMap.setString("custStat", "EMPTY_PHONE_CUST");
+					return resultMap;
+				}
+				custInfo.setSnsId(custSnsInfo.getSnsId());
+				custInfo.setSnsType(custSnsInfo.getSnsType());
+				customerDao.createCustomerSns(custInfo);
+				resultMap.setString("custStat", "SUCC_CUST");
+				return resultMap;
+			}
+		} else { // 2-2. 고객정보 없는 경우
+
+			if (StringUtils.isBlank(custSnsInfo.getCellPhnno())) { // 휴대전화번호가 없는 경우
+				resultMap.setString("custStat", "EMPTY_PHONE_CUST");
+				return resultMap;
+			}
+
+			boolean isFindByPhone =getCustomerFindByCellPhnnoCount(custSnsInfo.getCellPhnno().replace("-",""));
+			if (isFindByPhone) {
+				resultMap.setString("custStat", "DUP_PHONE_CUST");
+				return resultMap;
+			}
+
+			boolean isFindByEmail = getCustomerFindByEmail(custSnsInfo.getEmail());
+			if (isFindByEmail) {
+				resultMap.setString("custStat", "DUP_EMAIL_CUST"); // 이메일 중복
+				return resultMap;
+			}
+
+			Customer customer = objectMapper.convertValue(custSnsInfo, Customer.class);
+
+			boolean isJoin = saveJoinCustomerSns(customer);
+
+			if (isJoin) {
+				resultMap.setString("custStat", "SUCC_CUST");
+			} else {
+				resultMap.setString("custStat", "FAIL_CUST");
+			}
+
+		}
+
+		return resultMap;
+	}
+
+
 	/**
 	 * 로그인 처리
-	 * @param custNo - 고객번호
+	 * @param custId - 고객아이디
 	 * @param request - 요청
 	 * @author jsshin
 	 * @since 2021. 02. 18

+ 116 - 21
src/main/java/com/style24/front/biz/thirdparty/KaKaoLogin.java

@@ -2,8 +2,12 @@ package com.style24.front.biz.thirdparty;
 
 import com.gagaframework.web.parameter.GagaMap;
 import com.gagaframework.web.util.GagaFileUtil;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
 import com.style24.front.support.security.session.TsfSession;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -20,6 +24,7 @@ import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.PostConstruct;
 import java.net.URI;
+import java.util.Locale;
 
 
 /**
@@ -38,6 +43,8 @@ public class KaKaoLogin {
 	@Autowired
 	private RestTemplate restTemplate;
 
+	public static final String PROTOCOL = "http://";
+
 	private String callBackUrl;
 	private String restApiKey;
 	private String profiles;
@@ -66,17 +73,39 @@ public class KaKaoLogin {
 		log.info("\n--- Kakao initialization completed ----\n");
 	}
 
+	/**
+	 * 카카오 로그인 창
+	 * @param state - 콜백 시 해당 값으로 비교 및 모바일을 redirect 값이 있음
+	 * @return String - 호출 url정보
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public String getAuthorizeUrl(String state) {
-		String apiUrl = authorizeUrl;
-		String redirectUri = GagaFileUtil.getConcatenationPath("https://" + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
-		apiUrl += "?client_id=" + restApiKey + "&redirect_uri=" + redirectUri + "&response_type=code&state=" + state;
-		log.info("api ===> {}", apiUrl);
-		return apiUrl;
+		StringBuilder apiUrlBuilder = new StringBuilder();
+		String redirectUri = GagaFileUtil.getConcatenationPath(PROTOCOL + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
+		apiUrlBuilder.append(authorizeUrl)
+				.append("?client_id=")
+				.append(restApiKey)
+				.append("&redirect_uri=")
+				.append(redirectUri)
+				.append("&response_type=code&state=")
+				.append(state);
+		log.info("apiUrlBuilder ===> {}", apiUrlBuilder.toString());
+		return apiUrlBuilder.toString();
 	}
 
+	/**
+	 * 카카오 전달 받은 코드 값으로 토근값을 받아옴(API)
+	 *
+	 * @param code - 카카오에서 전달 해준 값
+	 * @param state - 콜백 시 해당 값으로 비교 및 모바일을 redirect 값이 있음
+	 * @return GagaMap - 통신으로 받아온 정보
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap getAccessTocken(String code, String state) {
 		GagaMap resultMap = new GagaMap();
-		String redirectUri = GagaFileUtil.getConcatenationPath("https://" + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
+		String redirectUri = GagaFileUtil.getConcatenationPath(PROTOCOL + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
 		String requestGb = "";
 		try {
 			MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
@@ -89,7 +118,7 @@ public class KaKaoLogin {
 			// state 값에 리다이렉트 url 같이 넘겨줌
 			if (StringUtils.isNotBlank(state)) {
 				String[] stateArr = StringUtils.split(state, "!@!");
-				   requestGb = stateArr[1];
+				requestGb = stateArr[1];
 			}
 
 			// Header
@@ -106,17 +135,24 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-
-			resultMap.setString("access_token", obj.get("access_token").toString());
-			resultMap.setString("refresh_token", obj.get("refresh_token").toString());
+			Gson gson = new GsonBuilder().create();
+			resultMap = gson.fromJson(jsonResult, GagaMap.class); //access_token, refresh_token
 			resultMap.setString("requestGb", requestGb);
+
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
 		return resultMap;
 	}
 
+	/**
+	 * 카카오 사용자 정보
+	 *
+	 * @param accessToken - 해당 값으로 사용자 정보를 가져옴
+	 * @return GagaMap - 사용자 정보
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap getKakaoUserInfo(String accessToken) {
 		GagaMap resultMap = new GagaMap();
 		try {
@@ -137,12 +173,34 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
+			Gson gson = new GsonBuilder().create();
+
+			JsonObject obj = gson.fromJson(jsonResult, JsonObject.class);
+			GagaMap properties = gson.fromJson(obj.get("properties"), GagaMap.class);
+			GagaMap kakaoAccount = gson.fromJson(obj.get("kakao_account"), GagaMap.class);
+
+			Locale locale = Locale.KOREA;
+			String cellPhnno = getPhoneNumber(kakaoAccount.getString("phone_number"), locale.getCountry());
+			String birthYmd = kakaoAccount.getString("birthyear") + kakaoAccount.getString("birthday");
+
+			String sexGb = "";
+			if (StringUtils.isNotBlank(kakaoAccount.getString("gender"))) {
+				sexGb = kakaoAccount.getString("gender").equals("male") ? "M" : "F";
+			}
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			JsonObject properties = obj.get("properties").getAsJsonObject();
+			String birthSm = "";
+			if (StringUtils.isNotBlank(kakaoAccount.getString("birthday_type"))) {
+				birthSm = kakaoAccount.getString("birthday_type").equals("SOLAR") ? "S":"L";
+			}
 
-			resultMap.setString("id", obj.get("id").toString());
-			resultMap.setString("name", properties.get("nickname").toString());
+			resultMap.setString("snsId", obj.get("id").toString());
+			resultMap.setString("custNm", properties.getString("nickname"));
+			resultMap.setString("email", kakaoAccount.getString("email"));
+			resultMap.setString("ci", kakaoAccount.getString("ci"));
+			resultMap.setString("cellPhnno", cellPhnno);
+			resultMap.setString("birthYmd", birthYmd);
+			resultMap.setString("birthSm", birthSm);
+			resultMap.setString("sexGb", sexGb);
 
 		} catch (Exception e) {
 			log.error(e.getMessage());
@@ -150,6 +208,14 @@ public class KaKaoLogin {
 		return resultMap;
 	}
 
+	/**
+	 * 카카오 access_token 새로 발급
+	 *
+	 * @param refreshToken - 해당 값으로 사용자 정보를 가져옴
+	 * @return GagaMap - access_token 값을 준다.
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap getRefreshTocken(String refreshToken) {
 		GagaMap resultMap = new GagaMap();
 		try {
@@ -172,15 +238,22 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			resultMap.setString("access_token", obj.get("access_token").toString());
-
+			Gson gson = new GsonBuilder().create();
+			resultMap = gson.fromJson(jsonResult, GagaMap.class); //access_token
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
 		return resultMap;
 	}
 
+	/**
+	 * 카카오 계정 연동해제
+	 *
+	 * @param accessToken - 토근값
+	 * @return GagaMap - snsId 값이 있으면 연동해제 성공
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap saveUnlink(String accessToken) {
 		GagaMap resultMap = new GagaMap();
 		try {
@@ -199,12 +272,34 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			resultMap.setString("id", obj.get("id").toString());
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj =  gson.fromJson(jsonResult, JsonObject.class);
+
+			resultMap.setString("snsId", obj.get("id").toString());
 
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
 		return resultMap;
 	}
+
+	/**
+	 * 국가번호 붙여서 넘겨온 전화번호 변호
+	 * +82) 010 1234 5678 -> 010-1234-5678
+	 * @param cellPhnno - 휴대전화번호
+	 * @param country - 국가
+	 * @return String - 010-1234-5678
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
+	public String getPhoneNumber(String cellPhnno, String country) throws Exception {
+		String result = "";
+		if (StringUtils.isNotBlank(cellPhnno)) {
+			PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+			Phonenumber.PhoneNumber numberProto = phoneUtil.parse(cellPhnno, "KR");
+			result = phoneUtil.format(numberProto, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+		}
+
+		return result;
+	}
 }

+ 28 - 11
src/main/java/com/style24/front/biz/thirdparty/NaverLogin.java

@@ -4,6 +4,8 @@ import java.net.URI;
 
 import javax.annotation.PostConstruct;
 
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.style24.front.support.security.session.TsfSession;
@@ -41,6 +43,8 @@ public class NaverLogin {
 	@Autowired
 	private RestTemplate restTemplate;
 
+	public static final String PROTOCOL = "http://";
+
 	private String callBackUrl;
 	private String clientId;
 	private String clientSecret;
@@ -71,11 +75,18 @@ public class NaverLogin {
 	}
 
 	public String getAuthorizeUrl(String state) {
-		String apiUrl = authorizeUrl;
-		String redirectUri = GagaFileUtil.getConcatenationPath("https://" + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
-		apiUrl += "?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&state=" + state;
-		log.info("api ===> {}", apiUrl);
-		return apiUrl;
+		StringBuilder apiUrlBuilder = new StringBuilder();
+		String redirectUri = GagaFileUtil.getConcatenationPath(PROTOCOL + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
+		apiUrlBuilder.append(authorizeUrl)
+				.append("?response_type=code&client_id=")
+				.append(clientId)
+				.append("&redirect_uri=")
+				.append(redirectUri)
+				.append("&state=")
+				.append(state);
+
+		log.info("apiUrlBuilder ===> {}", apiUrlBuilder.toString());
+		return apiUrlBuilder.toString();
 	}
 
 	public GagaMap getAccessTocken(String code, String state) {
@@ -109,11 +120,13 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("getAccessTocken responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj = gson.fromJson(jsonResult, JsonObject.class);
 
 			resultMap.setString("access_token", obj.get("access_token").toString());
 			resultMap.setString("refresh_token", obj.get("refresh_token").toString());
 			resultMap.setString("requestGb", requestGb);
+
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
@@ -140,10 +153,11 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("getNaverUserInfo responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			JsonObject response = obj.get("response").getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj = gson.fromJson(jsonResult, JsonObject.class);
+			JsonObject response = gson.fromJson(obj.get("response"), JsonObject.class);
 
-			resultMap.setString("id", response.get("id").toString());
+			resultMap.setString("snsId", response.get("id").toString());
 			resultMap.setString("email", response.get("email").toString());
 
 		} catch (Exception e) {
@@ -175,7 +189,9 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("getRefreshTocken responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj =  gson.fromJson(jsonResult, JsonObject.class);
+
 			resultMap.setString("access_token", obj.get("access_token").toString());
 
 		} catch (Exception e) {
@@ -208,7 +224,8 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("saveUnlink : responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj =  gson.fromJson(jsonResult, JsonObject.class);
 
 			resultMap.setString("access_token", obj.get("access_token").toString());
 			resultMap.setString("result", obj.get("result").toString());

+ 33 - 31
src/main/java/com/style24/front/biz/web/TsfCustomerController.java

@@ -1,22 +1,15 @@
 package com.style24.front.biz.web;
 
 import com.gagaframework.web.parameter.GagaMap;
-import com.gagaframework.web.security.GagaPasswordEncoder;
 import com.style24.core.biz.service.TscClauseService;
 import com.style24.core.support.env.TscConstants;
 import com.style24.core.support.session.TscSession;
 import com.style24.front.biz.service.TsfKakaoService;
-import com.style24.front.biz.service.TsfLoginService;
 import com.style24.front.biz.thirdparty.NiceCertify;
-import com.style24.front.support.env.TsfConstants;
-import com.style24.front.support.security.TsfLoginDetails;
 import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.domain.Customer;
-import com.style24.persistence.domain.Login;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -33,9 +26,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import java.util.ArrayList;
-import java.util.List;
+
 
 /**
  * 고객(회원) Controller
@@ -281,11 +272,9 @@ public class TsfCustomerController extends TsfBaseController {
 			return mav;
 		}
 
-		Customer params = new Customer();
-		params.setCustNo(Integer.valueOf(custNo));
-
 		// 고객정보 찾기
-		Customer custInfo = customerService.getCustomerFindId(params);
+		Customer custInfo = customerService.getCustomerFindByCustNo(Integer.valueOf(custNo));
+
 		if (custInfo != null) {
 			mav.addObject("custId", custInfo.getCustId());
 		}
@@ -312,10 +301,9 @@ public class TsfCustomerController extends TsfBaseController {
 			throw new IllegalStateException("고객 정보가 없습니다. 다시 확인 해주세요.");
 		}
 
-		Customer params = new Customer();
-		params.setCustNo(Integer.valueOf(custNo));
 		// 고객정보 찾기
-		Customer custInfo = customerService.getCustomerFindId(params);
+		Customer custInfo = customerService.getCustomerFindByCustNo(Integer.valueOf(custNo));
+
 		if (custInfo != null) {
 			customer.setTempPasswdYn("N"); // 임시비밀번호여부
 			customer.setRegNo(custInfo.getCustNo());
@@ -325,6 +313,7 @@ public class TsfCustomerController extends TsfBaseController {
 			customerService.saveCustomerPassword(customer);
 			isSuccess = true;
 		}
+
 		result.setBoolean("isSuccess", isSuccess);
 		return result;
 	}
@@ -402,7 +391,7 @@ public class TsfCustomerController extends TsfBaseController {
 		ModelAndView mav = new ModelAndView();
 		GagaMap result = niceCertify.certifyCellPhone();
 
-		if (TscConstants.FrontGb.MOBIEL.vale().equals(TsfSession.getFrontGb())) {
+		if (TscConstants.FrontGb.MOBIEL.value().equals(TsfSession.getFrontGb())) {
 			mav.addObject("redirectUrl", redirectUrl); // 모바일만 사용
 		}
 
@@ -424,7 +413,7 @@ public class TsfCustomerController extends TsfBaseController {
 		ModelAndView mav = new ModelAndView();
 		GagaMap result = niceCertify.certifyIpin();
 
-		if (TscConstants.FrontGb.MOBIEL.vale().equals(TsfSession.getFrontGb())) {
+		if (TscConstants.FrontGb.MOBIEL.value().equals(TsfSession.getFrontGb())) {
 			mav.addObject("redirectUrl", redirectUrl); // 모바일만 사용
 		}
 
@@ -459,7 +448,7 @@ public class TsfCustomerController extends TsfBaseController {
 			authMethod = TscConstants.AuthMethod.IPIN.value();
 		}
 
-		if (TscConstants.FrontGb.MOBIEL.vale().equals(TsfSession.getFrontGb())) {
+		if (TscConstants.FrontGb.MOBIEL.value().equals(TsfSession.getFrontGb())) {
 			mav.addObject("redirectUrl", redirectUrl);
 		}
 
@@ -561,7 +550,7 @@ public class TsfCustomerController extends TsfBaseController {
 
 		GagaMap authInfo = niceCertify.getCertifyCellPhoneResultInfo(customer);
 		customer.setCi(authInfo.getString("sCi"));
-		//customer.setCellPhnno(authInfo.getString("sMobileNo"));
+		customer.setCellPhnno(authInfo.getString("sMobileNo"));
 		//customer.setCellPhnno("01025906246");
 
 		if ("N".equals(authInfo.getString("adult"))) {
@@ -581,7 +570,7 @@ public class TsfCustomerController extends TsfBaseController {
 	}
 
 	/**
-	 * 가입
+	 * 가입처리
 	 *
 	 * @param customer - 고객정보
 	 * @return GagaMap - 결과정보
@@ -612,17 +601,30 @@ public class TsfCustomerController extends TsfBaseController {
 
 		// 3.고객정보 생성 및 혜택 처리
 		boolean isJoin = customerService.saveJoinCustomer(customer);
-		// 4.알림톡 및 메일 발송
-		try {
-			if(StringUtils.isNotBlank(customer.getCellPhnno())) {
-				kakaoService.sendJoinCongrat(customer);
-			}
-		} catch (Exception e) {
-			log.error("error", e);
-		}
+
 
 		if (isJoin) {
-			customerService.getLogin(customer.getCustId(),request);
+			// 4.알림톡 발송
+			try {
+				if (StringUtils.isNotBlank(customer.getCellPhnno())) {
+					kakaoService.sendJoinCongrat(customer);
+				}
+			} catch (Exception e) {
+				log.error("error", e);
+			}
+
+			// 5. 이메일 발송
+			try {
+				if (StringUtils.isNotBlank(customer.getEmail())) {
+					// TODO : 2021.02.23 이메일 모듈 개발 필요 jsshin
+				}
+			} catch (Exception e) {
+				log.error("error", e);
+			}
+
+			// 6. 가입성공시 로그인 처리 실패시
+			customerService.getLogin(customer.getCustId(), request);
+
 		} else {
 			TsfSession.setAttribute("maskingCustId",customer.getMaskingCustId());
 		}

+ 151 - 0
src/main/java/com/style24/front/biz/web/TsfIndexController.java

@@ -1,17 +1,30 @@
 package com.style24.front.biz.web;
 
 import java.io.IOException;
+import java.math.BigInteger;
+import java.security.SecureRandom;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.gagaframework.web.parameter.GagaMap;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.style24.core.support.env.TscConstants;
+import com.style24.front.biz.service.TsfCustomerService;
+import com.style24.front.biz.thirdparty.KaKaoLogin;
+import com.style24.front.biz.thirdparty.NaverLogin;
+import com.style24.persistence.domain.CustSnsInfo;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.HttpRequestMethodNotSupportedException;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.servlet.ModelAndView;
 
@@ -39,6 +52,18 @@ public class TsfIndexController extends TsfBaseController {
 	@Autowired
 	private TscMessageByLocale message;
 
+	@Autowired
+	private TsfCustomerService customerService;
+
+	@Autowired
+	private KaKaoLogin kakaoLogin;
+
+	@Autowired
+	private NaverLogin naverLogin;
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
 	/**
 	 * 에러 페이지
 	 * @return
@@ -131,4 +156,130 @@ public class TsfIndexController extends TsfBaseController {
 		return mav;
 	}
 
+	/**
+	 * 카카오 로그인 페이지 호출
+	 *
+	 * @return String
+	 * @author jsshin
+	 * @since 2021. 02. 23
+	 */
+	@GetMapping("/signin/kakologin")
+	public String signinKaKaoLogin(@RequestParam(value = "rememberMe", required = false) String rememberMe, @RequestParam(value = "requestGb", required = false) String requestGb) {
+
+		if (StringUtils.isNotBlank(rememberMe)) {
+			// RememberMe 세션 저장
+			TsfSession.setAttribute("rememberMe", rememberMe);
+		}
+		// CSRF 방지를 위한 상태 토큰 생성 코드
+		SecureRandom random = new SecureRandom();
+		String state = new BigInteger(130, random).toString(32);
+		state += "!@!" + requestGb;
+		TsfSession.setAttribute("state", state);
+
+		String redirectUrl = kakaoLogin.getAuthorizeUrl(state);
+
+		return "redirect:" + redirectUrl;
+	}
+
+	/**
+	 * 네이버 로그인 페이지 호출
+	 *
+	 * @return String
+	 * @author jsshin
+	 * @since 2020. 5. 25
+	 */
+	@GetMapping("/signin/naverlogin")
+	public String signinNaverLogin(@RequestParam(value = "rememberMe", required = false) String rememberMe, @RequestParam(value = "requestGb", required = false) String requestGb) {
+
+		if (StringUtils.isNotBlank(rememberMe)) {
+			// RememberMe 세션 저장
+			TsfSession.setAttribute("rememberMe", rememberMe);
+		}
+		// CSRF 방지를 위한 상태 토큰 생성 코드
+		SecureRandom random = new SecureRandom();
+		String state = new BigInteger(130, random).toString(32);
+		state += "!@!" + requestGb;
+		TsfSession.setAttribute("state", state);
+
+		String redirectUrl = naverLogin.getAuthorizeUrl(state);
+
+		return "redirect:" + redirectUrl;
+	}
+
+
+	/**
+	 * SNS 로그인
+	 *
+	 * @param session - HttpSession
+	 * @param snsType - SNS유형(NV:네이버, KK:카카오)
+	 * @return ModelAndView
+	 * @author jsshin
+	 * @since 2021. 02. 23
+	 */
+	@RequestMapping("/signin/snsLoginCallback")
+	public ModelAndView signinSnsLoginCallback(@RequestParam(value = "snsType", required = false) String snsType, HttpSession session
+			, @RequestParam(value = "code", required = false) String code, @RequestParam(value = "state", required = false) String state
+			, @RequestParam(value = "error", required = false) boolean isError) {
+
+		ModelAndView mav = new ModelAndView();
+
+		log.info("isError: {}", isError);
+
+		if (isError) {
+			Exception ex = (Exception)session.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
+			log.debug("e.getMessage(): {}", ex.getMessage());
+			mav.addObject("error", ex.getMessage());
+		}
+
+		GagaMap userInfo = new GagaMap();
+		boolean isSnsLoing = false;
+		if (StringUtils.isNotBlank(code) && TscConstants.SnsType.KAKAO.value().equals(snsType)) {
+			String sessionState = TsfSession.getAttribute("state");
+			if (sessionState.equals(state)) {
+				GagaMap tokenInfo = kakaoLogin.getAccessTocken(code, state);
+				userInfo = kakaoLogin.getKakaoUserInfo(tokenInfo.getString("access_token"));
+				userInfo.setString("accessToken", tokenInfo.getString("access_token"));
+				userInfo.setString("refreshToken", tokenInfo.getString("refresh_token"));
+				userInfo.setString("snsType", snsType);
+				userInfo.setString("requestGb", tokenInfo.getString("requestGb"));
+				isSnsLoing = true;
+			}
+		}
+
+		if (StringUtils.isNotBlank(code) && TscConstants.SnsType.NAVER.value().equals(snsType)) {
+			String sessionState = TsfSession.getAttribute("state");
+			if (sessionState.equals(state)) {
+				GagaMap tokenInfo = naverLogin.getAccessTocken(code, state);
+				userInfo = naverLogin.getNaverUserInfo(tokenInfo.getString("access_token"));
+				userInfo.setString("accessToken", tokenInfo.getString("access_token"));
+				userInfo.setString("refreshToken", tokenInfo.getString("refresh_token"));
+				userInfo.setString("snsType", snsType);
+				userInfo.setString("requestGb", tokenInfo.getString("requestGb"));
+				isSnsLoing = true;
+			}
+		}
+
+		// SNS 로그인 성공시 정보 세션 저장
+		GagaMap resultMap = new GagaMap();
+		if (isSnsLoing) {
+			CustSnsInfo custSnsInfo = objectMapper.convertValue(userInfo, CustSnsInfo.class);
+			//상태 체크
+			resultMap = customerService.customerSnsProcessing(custSnsInfo);
+
+		}
+
+		// RememberMe 값이 있고 true이면
+		if (StringUtils.isNotBlank(TsfSession.getAttribute("rememberMe")) && Boolean.valueOf(TsfSession.getAttribute("rememberMe"))) {
+			userInfo.setBoolean("rememberMe", true);
+		}
+
+		mav.addObject("resultMap", resultMap);
+		mav.addObject("snsId", userInfo.getString("snsId"));
+		mav.addObject("snsType", snsType);
+
+		mav.setViewName(super.getDeviceViewName("SnsCallBackForm"));
+
+		return mav;
+	}
+
 }

+ 136 - 2
src/main/java/com/style24/front/biz/web/TsfMypageController.java

@@ -34,6 +34,7 @@ import com.style24.front.biz.service.TsfWishlistService;
 import com.style24.front.support.controller.TsfBaseController;
 import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.TscPageRequest;
+import com.style24.persistence.domain.Coupon;
 import com.style24.persistence.domain.Customer;
 import com.style24.persistence.domain.Order;
 
@@ -299,8 +300,6 @@ public class TsfMypageController extends TsfBaseController {
 	public ModelAndView exchangeForm(Order order) {
 		ModelAndView mav = new ModelAndView();
 		
-		log.info("order >>> {}", order);
-		
 		// 주문번호 설정
 		mav.addObject("ordNo", order.getOrdNo());
 
@@ -340,4 +339,139 @@ public class TsfMypageController extends TsfBaseController {
 		return mav;
 	}
 
+	/**
+	 * 마이페이지 등급쿠폰 다운 처리
+	 *
+	 * @return
+	 * @author card007
+	 * @since 2021. 02. 17
+	 */
+	@PostMapping("/coupon/download/all")
+	@ResponseBody
+	public GagaMap createCustGradeAllCoupon(@RequestBody Coupon coupon) {
+		GagaMap result = new GagaMap();
+
+		// 고객정보 조회
+		Customer customer = new Customer();
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.setCustNo(coupon.getCustNo());
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer = coreCustomerService.getCustomerInfo(customer);
+
+		// 고객정보 설정
+		coupon.setCustGb(customer.getCustGb());
+		coupon.setCustGrade(customer.getCustGrade());
+
+		// 등급쿠폰 다운 처리
+		int count = couponService.createCustGradeAllCoupon(coupon);
+		
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+		
+		if (count == 0) {
+			result.set("message", message.getMessage("COUPON_0002"));
+		} else {
+			result.set("message", message.getMessage("COUPON_0001", new Object[] {count}));
+		}
+
+		return result;
+	}
+
+	/**
+	 * 마이페이지 쿠폰 수량 조회
+	 *
+	 * @return
+	 * @author card007
+	 * @since 2021. 02. 25
+	 */
+	@PostMapping("/coupon/count")
+	@ResponseBody
+	public GagaMap fnReloadCouponCount(@RequestBody Order order) {
+		GagaMap result = new GagaMap();
+
+		// 쿠폰정보 조회
+		result.set("couponCnt", coreOrderService.getCouponInfo(order));
+
+		order.setExpiredSoon("Y");
+		result.set("expiredSoonCouponCnt", coreOrderService.getCouponInfo(order));
+
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+
+		return result;
+	}
+
+	/**
+	 * 마이페이지 상태별 수량 조회
+	 *
+	 * @return
+	 * @author card007
+	 * @since 2021. 02. 25
+	 */
+	@PostMapping("/status/count")
+	@ResponseBody
+	public GagaMap fnReloadStatusCount(@RequestBody Order order) {
+		GagaMap result = new GagaMap();
+
+		// 쿠폰정보 조회
+		result.set("orderCount", orderService.getOrderStatCount(order));
+
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+
+		return result;
+	}
+
+	/**
+	 * 마이페이지 반품신청 화면
+	 *
+	 * @param Order
+	 * @return ModelAndView
+	 * @author card007
+	 * @since 2021. 02. 25
+	 */
+	@PostMapping("/cancel/form")
+	@ResponseBody
+	public ModelAndView returnForm(Order order) {
+		ModelAndView mav = new ModelAndView();
+
+		// 주문번호 설정
+		mav.addObject("ordNo", order.getOrdNo());
+
+		// 고객번호 설정
+		int custNo = TsfSession.getInfo().getCustNo();
+		order.setCustNo(custNo);
+		mav.addObject("custNo", custNo);
+
+		// 고객정보 조회
+		Customer customer = new Customer();
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.setCustNo(custNo);
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer = coreCustomerService.getCustomerInfo(customer);
+
+		mav.addObject("customerInfo", customer);
+
+
+		// 주문목록 조회
+		Collection<GagaMap> orderList = orderService.getOrderListForMypage(order);
+
+		if (orderList.size() == 0) {
+			mav.setViewName("redirect:/mypage/order/list/form");
+			return mav;
+		}
+
+		mav.addObject("orderList", orderList);
+
+		// 주문 결제정보 조회
+		mav.addObject("paymentInfo", orderService.getPaymentInfoForMypage(order));
+
+		// 주문 배송지 정보 조회
+		mav.addObject("deliveryAddrInfo", orderService.getOrderDeliveryAddrInfo(order));
+
+		// 교환 사유 목록 조회
+		mav.addObject("exchangeReason", rendererService.getCommonCodeList("G688", "Y"));
+
+		mav.setViewName(super.getDeviceViewName("/mypage/MypageReturnForm"));
+
+		return mav;
+	}
+
 }

+ 30 - 26
src/main/java/com/style24/front/biz/web/TsfOrderController.java

@@ -151,7 +151,7 @@ public class TsfOrderController extends TsfBaseController {
 		// 2.1 배송단위별 상품 목록 조회 (장바구니)
 		Collection<Order> tmtbGoodsApplyList = cartService.getMoreBetterAmtList(order);
 		
-		// 상품금액, 선포인트, 다다익선할인금액
+		// 2.1.0 상품금액, 선포인트, 다다익선할인금액
 		GagaMap goodsDcAmtMap = coreOrderService.getGoodsDcAmt(tmtbGoodsApplyList);
 		
 		// 2.2 배송단위별 장바구니 상품 건수 조회 (장바구니상품)
@@ -167,7 +167,8 @@ public class TsfOrderController extends TsfBaseController {
 		// 3.2.1 상품기준 ---> 상품쿠폰 적용된 상품 목록
 		Collection<Order> goodsApplyCpnList = coreOrderService.getGoodsCpnApplyList(tmtbGoodsApplyList, goodsCpnList);
 		
-		//cartCpnList = coreOrderService.getGoodsCpnApplyList(tmtbGoodsApplyList, cartCpnList);
+		// 3.2.2 장바구니쿠폰기준 ---> 상품목록
+		cartCpnList = coreOrderService.getCartCpnApplyList(tmtbGoodsApplyList, cartCpnList);
 		
 		// 3.3 배송비쿠폰목록 조회
 		Collection<Order> delvCpnList = coreOrderService.getDelvCpnList(order);
@@ -183,36 +184,39 @@ public class TsfOrderController extends TsfBaseController {
 		GagaMap  resultMap = coreFreegiftService.getOrderFreegift(order);
 
 		// 101. 상품정보
-		mav.addObject("cartGoodsList"					, tmtbGoodsApplyList);					// 장바구니상품목록 (즉시할인쿠폰적용)
-		mav.addObject("delvTotCnt" 						, delvOrderMap.get("delvTotCnt"));		// 총상품건수
-		mav.addObject("delvFeeTotCnt"					, delvOrderMap.get("delvFeeTotCnt"));	// 총배송타입건수
-		mav.addObject("wmsCnt" 							, delvOrderMap.get("wmsCnt"));			// 자사상품건수
-		mav.addObject("resCnt" 							, delvOrderMap.get("resCnt"));			// 자사예약상품건수
-		mav.addObject("delvCnt" 						, delvOrderMap.get("delvCnt"));			// 입점업체상품건수
-		mav.addObject("wmsCartList" 					, delvOrderMap.get("wmsCartList"));		// 자사장바구니상품목록
-		mav.addObject("resCartList" 					, delvOrderMap.get("resCartList"));		// 자사장바구니예약상품목
-		mav.addObject("delvCartList" 					, delvOrderMap.get("delvCartList"));	// 입점업체장바구니상품목록
-		mav.addObject("sumDelvFee" 						, delvOrderMap.get("sumDelvFee"));		// 배송비합계
+		mav.addObject("cartGoodsList"					, tmtbGoodsApplyList);						// 장바구니상품목록 (즉시할인쿠폰적용)
+		mav.addObject("delvTotCnt" 						, delvOrderMap.get("delvTotCnt"));			// 총상품건수
+		mav.addObject("delvFeeTotCnt"					, delvOrderMap.get("delvFeeTotCnt"));		// 총배송타입건수
+		mav.addObject("wmsCnt" 							, delvOrderMap.get("wmsCnt"));				// 자사상품건수
+		mav.addObject("resCnt" 							, delvOrderMap.get("resCnt"));				// 자사예약상품건수
+		mav.addObject("delvCnt" 						, delvOrderMap.get("delvCnt"));				// 입점업체상품건수
+		
+		mav.addObject("shotCartList" 					, delvOrderMap.get("shotCartList"));		// 자사총알배송상품목록
+		mav.addObject("wmsCartList" 					, delvOrderMap.get("wmsCartList"));			// 자사일반배송상품목록
+		mav.addObject("delvCartList" 					, delvOrderMap.get("delvCartList"));		// 입점업체상품목록
+		mav.addObject("resCartList" 					, delvOrderMap.get("resCartList"));			// 자사예약배송상품목록
+		mav.addObject("delvAllCartList" 				, delvOrderMap.get("delvAllCartList"));		// 전체배송목록
+		mav.addObject("sumDelvFee" 						, delvOrderMap.get("sumDelvFee"));			// 배송비합계
 		
 		// 102. 고객정보
-		mav.addObject("custemerInfo"					, custemerInfo);						// 고객정보
-		mav.addObject("deliveryAddrInfo"				, deliveryAddrInfo);					// 배송지정보
-		mav.addObject("shotDelvYn" 						, order.getShotDelvYn());				// 장바구니 총알배송여부
+		mav.addObject("custemerInfo"					, custemerInfo);							// 고객정보
+		mav.addObject("deliveryAddrInfo"				, deliveryAddrInfo);						// 배송지정보
+		mav.addObject("shotDelvYn" 						, order.getShotDelvYn());					// 장바구니 총알배송여부
 		
 		// 103. 할인정보
-		mav.addObject("tmtbGoodsApplyList"				, tmtbGoodsApplyList);					// 다다익선상품 적용목록
-		mav.addObject("goodsApplyCpnList"				, goodsApplyCpnList);					// 상품적용쿠폰
-		mav.addObject("cartCpnList"						, cartCpnList);							// 장바구니쿠폰목록
-		mav.addObject("delvCpnList"						, delvCpnList);							// 배송비쿠폰목록
-		mav.addObject("prePntDcAmt"						, goodsDcAmtMap.get("prePntDcAmt"));	// 선포인트정보
-		mav.addObject("goodsSumAmt"						, goodsDcAmtMap.get("goodsSumAmt"));	// 상품금액합계
-		mav.addObject("tmtbDcSumAmt"					, goodsDcAmtMap.get("tmtbDcSumAmt"));	// 다다익선할인금액합계
-		mav.addObject("rmPntAmt"						, rmPntAmt);							// 고객포인트정보
-		mav.addObject("rmGfcdAmt"						, rmGfcdAmt);							// 고객상품권정보
+		mav.addObject("tmtbGoodsApplyList"				, tmtbGoodsApplyList);						// 다다익선상품 적용목록
+		mav.addObject("goodsApplyCpnList"				, goodsApplyCpnList);						// 상품적용쿠폰
+		mav.addObject("cartCpnList"						, cartCpnList);								// 장바구니쿠폰목록
+		mav.addObject("delvCpnList"						, delvCpnList);								// 배송비쿠폰목록
+		mav.addObject("prePntDcAmt"						, goodsDcAmtMap.get("prePntDcAmt"));		// 선포인트정보
+		mav.addObject("goodsSumAmt"						, goodsDcAmtMap.get("goodsSumAmt"));		// 상품금액합계
+		mav.addObject("tmtbDcSumAmt"					, goodsDcAmtMap.get("tmtbDcSumAmt"));		// 다다익선할인금액합계
+		mav.addObject("rmPntAmt"						, rmPntAmt);								// 고객포인트정보
+		mav.addObject("rmGfcdAmt"						, rmGfcdAmt);								// 고객상품권정보
 		
 		// 104. 사은품정보
-		mav.addObject("freegiftGoodsList"				, resultMap.get("freegiftGoodsList"));	// 사은품상품정보 목록
-		mav.addObject("freegiftList"					, resultMap.get("freegiftList"));		// 사은품정보 목록
+		mav.addObject("freegiftGoodsList"				, resultMap.get("freegiftGoodsList"));		// 사은품상품정보 목록
+		mav.addObject("freegiftList"					, resultMap.get("freegiftList"));			// 사은품정보 목록
 		
 		mav.setViewName(super.getDeviceViewName("order/OrderForm"));
 		

+ 3 - 0
src/main/java/com/style24/persistence/domain/Coupon.java

@@ -21,6 +21,8 @@ public class Coupon extends TscBaseDomain {
 	private int[] currPrices;		// 상품가격 배열
 	private int cpnId;				// 쿠폰번호
 	private int custNo;				// 회원번호
+	private String custGb;			// 회원구분
+	private String custGrade;		// 회원등급
 	private int availDays;			// 쿠폰 다운로드 후 유효기간일
 	private int rdCpnId;			// 랜덤쿠폰번호
 	private int dcAmt;				// 할인적용금액
@@ -38,4 +40,5 @@ public class Coupon extends TscBaseDomain {
 	private String availYn;			// 지급 받은 쿠폰 사용 가능 유무
 	private String dcWay;			// 할인금액/율 구분
 	private String cpnDesc;			// 쿠폰설명
+	private int downloadCnt;		// 다운로드수
 }

+ 38 - 0
src/main/java/com/style24/persistence/domain/CustSnsInfo.java

@@ -0,0 +1,38 @@
+package com.style24.persistence.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.style24.persistence.TscBaseDomain;
+import lombok.Data;
+
+/**
+ * 고객 Sns 정보 Domain
+ * @JsonSerialize 애노테이션을 지정해야 세션을 레디스에 저장할 수 있다.
+ * @author jsshin
+ * @since 2021. 02. 24
+ */
+@SuppressWarnings("serial")
+@Data
+@JsonSerialize
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CustSnsInfo extends TscBaseDomain {
+
+	// 세션을 JSON 형식으로 레디스에 저장하려면 기본 생성자를 반드시 명시해야 한다
+	public CustSnsInfo (){
+
+	}
+	private String snsId;
+	private String snsType;
+	private String accessToken;
+	private String refreshToken;
+	private String custNm;
+	private String email;
+	private String ci;
+	private String cellPhnno;
+	private String birthYmd;
+	private String birthSm;
+	private String sexGb;
+	private Integer custNo;
+
+	private String requestGb;
+}

+ 58 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsfCoupon.xml

@@ -55,4 +55,62 @@
 		<!-- 랜덤쿠폰은 RD_CPN_NM이 1개이나, 시리얼 쿠폰은 다수개이므로 하나의 정보만 조회 -->
 		LIMIT  1
 	</select>
+	
+	<!-- 마이페이지 등급쿠폰 다운가능 쿠폰 정보 조회 -->
+	<select id="getCustGradeCouponInfo" parameterType="Coupon" resultType="Coupon">
+		/* TsfCoupon.getCustGradeCouponInfo */
+		SELECT Z.CUST_NO
+		     , Z.CPN_ID
+		     , Z.AVAIL_STDT
+		     , Z.AVAIL_EDDT
+		     , Z.END_ALIM_YN
+		     , Z.DOWNLOAD_CNT
+		  FROM (SELECT A.*
+					 , CASE WHEN A.CNT <![CDATA[<=]]> 0 THEN 0
+							WHEN A.CNT > (A.DN_ABLE_CNT * A.ONE_PUB_QTY) THEN (A.DN_ABLE_CNT * A.ONE_PUB_QTY)
+							ELSE A.CNT
+						END AS DOWNLOAD_CNT
+				  FROM (SELECT #{custNo} AS CUST_NO
+							 , C.CPN_ID
+							 , C.CPN_NM
+							 , C.CUST_PUB_LIMIT_QTY
+							 , C.ONE_PUB_QTY
+							 , IF(C.PD_GB = 'P', C.AVAIL_STDT, NOW()) AS AVAIL_STDT
+							 , IF(C.PD_GB = 'P', C.AVAIL_EDDT, CONCAT(CURRENT_DATE + INTERVAL C.AVAIL_DAYS DAY, ' 23:59:59')) AS AVAIL_EDDT
+				             , C.END_ALIM_YN
+							 , IFNULL(CC.CPN_CNT, 0) AS DN_CNT
+				             , IF(C.CUST_PUB_LIMIT_QTY = 0 OR C.CUST_PUB_LIMIT_QTY - CC.CPN_CNT > 0, 1, 0) AS DN_ABLE_CNT
+				             , IF(C.TOT_PUB_LIMIT_QTY > 0, C.TOT_PUB_LIMIT_QTY - CC2.CPN_CNT, 99999) AS CNT
+						  FROM TB_COUPON C
+						 INNER JOIN TB_COUPON_CUST_GBN CCGB
+							ON C.CPN_ID = CCGB.CPN_ID
+						   AND CCGB.USABLE_CUST_GB IN ('G100_00', IFNULL(#{custGb}, 'G100_00'))
+						 INNER JOIN TB_COUPON_CUST_GRADE CCGR
+							ON C.CPN_ID = CCGR.CPN_ID
+						   AND CCGR.USABLE_CUST_GRADE = #{custGrade}
+						  LEFT OUTER JOIN (SELECT CPN_ID
+												, CUST_NO
+												, COUNT(*) AS CPN_CNT
+											 FROM TB_CUST_COUPON
+											GROUP BY CPN_ID, CUST_NO) CC
+							ON C.CPN_ID = CC.CPN_ID
+						   AND CC.CUST_NO = #{custNo}
+						  LEFT OUTER JOIN (SELECT CPN_ID
+												, COUNT(*) AS CPN_CNT
+											 FROM TB_CUST_COUPON
+											GROUP BY CPN_ID) CC2
+							ON C.CPN_ID = CC2.CPN_ID
+						 WHERE C.DOWN_ABL_YN = 'Y'
+						   AND NOW() BETWEEN C.DOWN_STDT AND C.DOWN_EDDT
+						   AND C.CPN_STAT = 'G232_11'  -- 진행
+						   AND CASE WHEN C.TOT_PUB_LIMIT_QTY = 0 THEN 1
+									WHEN C.TOT_PUB_LIMIT_QTY - CC2.CPN_CNT > 0 THEN 1
+									ELSE 0
+								END = 1
+						   AND IF(C.NEW_CUST_YN = 'Y', (SELECT COUNT(*) FROM TB_CUSTOMER WHERE CUST_NO = #{custNo} AND REG_DT BETWEEN C.CUST_JOIN_STDT AND C.CUST_JOIN_EDDT), 1) = 1
+						   AND IF(C.FIRST_ORD_YN = 'Y', (SELECT COUNT(*) FROM TB_ORDER WHERE CUST_NO = #{custNo} AND ORD_DT BETWEEN C.BUY_STDT AND C.BUY_EDDT), 0) = 0
+						) A
+				) Z
+		 WHERE Z.DOWNLOAD_CNT > 0
+	</select>
 </mapper>

+ 69 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsfCustomer.xml

@@ -264,4 +264,73 @@
 		)
 	</insert>
 
+	<select id="getCusomterActiveAndDormant" parameterType="Customer" resultType="Customer">
+		/* TsfCustomer.getCusomterActiveAndDormant */
+		SELECT CUST_NO
+		     , CUST_ID
+		     , EMAIL
+		     , CELL_PHNNO
+		     , CUST_STAT
+		     , DATE_FORMAT(JOIN_DT, '%Y%m%d%H%i%S')   AS JOIN_DT
+		     , ''                                     AS DORMANT_DT
+		FROM   TB_CUSTOMER
+		WHERE  CUST_STAT = 'G104_10'
+		<if test="custId != null and custId !=''">
+		AND    CUST_ID = #{custId}
+		</if>
+		<if test="encodedCustNm != null and encodedCustNm != ''">
+		AND    CUST_NM = #{encodedCustNm}
+		</if>
+		<if test="encodedEmail != null and encodedEmail != ''">
+		AND    EMAIL = #{encodedEmail}
+		</if>
+		<if test="encodedBirthYmd != null and encodedBirthYmd != ''">
+		AND    BIRTH_YMD = #{encodedBirthYmd}
+		</if>
+		<if test="ci != null and ci != ''">
+		AND    CI = #{ci}
+		</if>
+		UNION ALL
+		SELECT CUST_NO
+		     , CUST_ID
+		     , EMAIL
+		     , CELL_PHNNO
+		     , CUST_STAT
+		     , ''                                      AS JOIN_DT
+		     , DATE_FORMAT(DORMANT_DT, '%Y%m%d%H%i%S') AS DORMANT_DT
+		FROM   TB_DORMANT_CUST
+		WHERE  1 = 1
+		<if test="custId != null and custId !=''">
+		AND    CUST_ID = #{custId}
+		</if>
+		<if test="encodedCustNm != null and encodedCustNm != ''">
+		AND    CUST_NM = #{encodedCustNm}
+		</if>
+		<if test="encodedEmail != null and encodedEmail != ''">
+		AND    EMAIL = #{encodedEmail}
+		</if>
+		<if test="encodedBirthYmd != null and encodedBirthYmd != ''">
+		AND    BIRTH_YMD = #{encodedBirthYmd}
+		</if>
+		<if test="ci != null and ci != ''">
+		AND    CI = #{ci}
+		</if>
+	</select>
+
+	<select id="getCusomterSnsFind" parameterType="CustSnsInfo" resultType="Customer">
+		SELECT C.CUST_NO
+		     , C.CUST_ID
+		     , C.CUST_NM
+		     , C.CELL_PHNNO
+		     , C.EMAIL
+		     , C.CUST_STAT
+		     , C.CI
+		FROM   TB_CUSTOMER C
+		LEFT JOIN
+		       TB_CUSTOMER_SNS CS
+		ON     C.CUST_NO = CS.CUST_NO
+		WHERE  CS.SNS_TYPE = #{snsType}
+		AND    CS.SNS_ID = #{snsId}
+	</select>
+
 </mapper>

+ 1 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsfOrder.xml

@@ -221,6 +221,7 @@
 		     , ORD_NO
 		     , PAY_DT
 		     , PAY_MEANS
+		     , FN_GET_CODE_NM('G014', PAY_MEANS) AS PAY_MEANS_NM
 		     , PAY_AMT
 		     , PG_CPN_AMT
 		     , NPAY_PNT_AMT

+ 14 - 14
src/main/resources/config/application.yml

@@ -48,20 +48,20 @@ naver:
 
 #카카오 API
 kakao:
-#    appId: 442702
-#    appName: 아이스타일24
-#    companyName: 예스이십사
-#    nativeAppKey: 5d97db2ee36fa0e121d962b2531ae0c1
-#    restApiKey: 46d601394bd887cbada3cf00fdddef54
-#    javascriptKey: b3c9ee69171042c3637e8d714a4c8a75
-#    adminKey: 7cc33b2ef96d785c4caf3376f9dc9254
-    appId : 399207
-    appName : 구축용 테스트앱
-    companyName : 예스이십사
-    nativeAppKey : f961e612e07b47aa2d1884714518a194
-    restApiKey: b3955cef0328a09156c7e25f18552164
-    javascriptKey : 06cab652ad5d25be2190388d11a88fa4
-    adminKey : a25ca74dde640f3a63a8d8442fe35fcd
+    appId: 442702
+    appName: 아이스타일24
+    companyName: 예스이십사
+    nativeAppKey: 5d97db2ee36fa0e121d962b2531ae0c1
+    restApiKey: 46d601394bd887cbada3cf00fdddef54
+    javascriptKey: b3c9ee69171042c3637e8d714a4c8a75
+    adminKey: 7cc33b2ef96d785c4caf3376f9dc9254
+#    appId : 399207
+#    appName : 구축용 테스트앱
+#    companyName : 예스이십사
+#    nativeAppKey : f961e612e07b47aa2d1884714518a194
+#    restApiKey: b3955cef0328a09156c7e25f18552164
+#    javascriptKey : 06cab652ad5d25be2190388d11a88fa4
+#    adminKey : a25ca74dde640f3a63a8d8442fe35fcd
     addressApiRequestUrl : https://dapi.kakao.com/v2/local/search/address.json?page=1&query=
     login.callbackUrl: /signin/snsLoginCallback?snsType=KK
     tokenUrl: https://kauth.kakao.com/oauth/token

+ 4 - 0
src/main/resources/i18n/messages/message_ko_KR.properties

@@ -86,3 +86,7 @@ SABANGNET_0007=\uAD50\uD658\uC8FC\uBB38\uC774 \uC218\uC9D1\uB418\uC5C8\uC2B5\uB2
 SABANGNET_0008=\uBC18\uD488\uC8FC\uBB38\uC774 \uC218\uC9D1\uB418\uC5C8\uC2B5\uB2C8\uB2E4.(\uCD1D {0}\uAC74 \uC911 {1}\uAC74 \uC2E4\uD328 {2}\uAC74 \uC131\uACF5)
 SABANGNET_0009=\uC720\uD6A8\uC131 \uAC80\uC99D \uC2E4\uD328\uB85C \uCC98\uB9AC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
 SABANGNET_0010=\uCD9C\uACE0\uB97C \uC704\uD574 ERP\uB85C \uC804\uC1A1\uD558\uC600\uC2B5\uB2C8\uB2E4.(\uC131\uACF5: {0}\uAC74, \uC2E4\uD328: {1}\uAC74)
+
+#\uCFE0\uD3F0
+COUPON_0001=\uCD1D {0}\uC7A5\uC758 \uCFE0\uD3F0\uC744 \uB2E4\uC6B4\uB85C\uB4DC \uD558\uC600\uC2B5\uB2C8\uB2E4.
+COUPON_0002=\uC774\uBBF8 \uB2E4\uC6B4\uB85C\uB4DC\uB97C \uC644\uB8CC \uD558\uC168\uC2B5\uB2C8\uB2E4.

+ 31 - 16
src/main/webapp/WEB-INF/views/web/SigninFormWeb.html

@@ -95,13 +95,13 @@
 							<h5 class="sr-only">간편로그인</h5>
 							<ul>
 								<li>
-									<a href="javascript:void(0)">
+									<a href="javascript:void(0)" onclick="cfnLoginKakao();">
 										<i class="ico ico_snslogin kakao"></i>
 										<span>카카오로 시작하기</span>
 									</a>
 								</li>
 								<li>
-									<a href="javascript:void(0)">
+									<a href="javascript:void(0)" onclick="cfnLoginNaver();">
 										<i class="ico ico_snslogin naver"></i>
 										<span>네이버로 시작하기</span>
 									</a>
@@ -230,23 +230,38 @@
 	let fnReloadCaptchaImage = function() {
 		$('#imgCaptcha').attr('src', '/common/captcha.do?dummy=' + new Date());
 	}
-	
-	// 카카오 로그인
-	var fnLoginKakao = function() {
-		document.location.href = _frontUrl + '/signin/kakologin';
-	};
-	
-	// 네이버 로그인
-	var fnLoginNaver = function() {
-		document.location.href = _frontUrl + '/signin/naverlogin';
+
+	// SNS 로그인 콜백함수
+	var fnSnsSigninCallback = function(userInfo) {
+		console.log('userInfo', userInfo);
+		let params = {};
+		params.snsType = userInfo.snsType;
+		params.snsJoinId = [[${snsLoginPrefix}]] + userInfo.snsId;
+		// $.post(_frontUrl + '/login'
+		// 	, $.param(params)
+		// 	, function(result) {
+		// 		fnReloadAfterLogin(result);
+		// 	}
+		// 	, "json");
 	};
-	
-	// YES24 로그인
-	var fnLoginYes24 = function() {
-		document.location.href = _frontUrl + '/signin/yes24login';
+
+	var fnReloadAfterLogin = function(result) {
+		if (result.status === 'OK') {
+			document.location.href = result.returnUrl;
+		} else if (result.status === 'EMAIL_DUP') {
+
+		} else if(result.status === 'DORMANT_CUST') {
+			cfnGoToPage(_PAGE_CUSTOMER_DORMANT);
+		} else if(result.status === 'SECEDE_CUST') {
+
+		} else {
+			//cfnGoToPage(_PAGE_CUSTOMER_JOIN_CERTIFY_SNS);
+		}
 	};
 
-	$(document).ready(function() {
+
+
+$(document).ready(function() {
 		$('#loginForm input[name=loginId]').val(gagajf.getCookie(ckLoginId));
 		if (gagajf.isNull($('#loginForm input[name=loginId]').val())) {
 			$('#loginForm input[name=loginId]').focus();

+ 48 - 0
src/main/webapp/WEB-INF/views/web/SnsCallBackFormWeb.html

@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : SigninFormWeb.html
+ * @desc    : 로그인 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.02.15   gagamel     최초 작성
+ *******************************************************************************
+ -->
+<head th:replace="~{web/common/fragments/HeadWeb :: head}"></head>
+<th:block th:replace="~{web/common/fragments/VariablesWeb :: variables}"></th:block>
+<th:block th:replace="~{web/common/fragments/ScriptsWeb :: scripts}"></th:block>
+<body>
+
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	const snsType = [[${snsType}]];
+	const snsId = [[${snsId}]];
+
+	if (snsType === 'KK') {
+		if (gagajf.isNull(snsId)){
+			mcxDialog.alertC("인증에 실패하였습니다.<br> 로그인 정보를 확인해주시기 바랍니다.", {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					self.close();
+				}
+			});
+		} else {
+			opener.fnSnsSigninCallback(snsId);
+			self.close();
+		}
+	}
+
+
+/*]]>*/
+</script>
+
+
+</body>
+</html>

+ 6 - 12
src/main/webapp/WEB-INF/views/web/mypage/MypageExchangeFormWeb.html

@@ -126,8 +126,8 @@
 							</tr>
 							<tr>
 								<td>
-									<textarea class="doc_exchange" name="chgMemo" id="chgMemo" placeholder="자세한 사유를 입력해주세요." onkeyup="cfnGetTextLength(this, 500, $('#exchange_cnt'));"></textarea>
-									<p class="txt_cnt"><span id="exchange_cnt" class="c_primary">0</span>/500</p>
+									<textarea class="doc_exchange" name="chgMemo" id="chgMemo" placeholder="자세한 사유를 입력해주세요." onkeyup="cfnGetTextLength(this, 200, $('#exchange_cnt'));"></textarea>
+									<p class="txt_cnt"><span id="exchange_cnt" class="c_primary">0</span>/200</p>
 								</td>
 							</tr>
 							</tbody>
@@ -137,7 +137,7 @@
 				<section class="order_row" id="chgerLocation">
 					<div class="order_tit">
 						<h3 class="subH3">상품 회수지</h3>
-						<span class="del_t">교환받을 상품을 수령할 장소 선택</span>
+						<span class="del_t">택배사에서 반품 상품을 직접 회수할 장소 선택</span>
 						<button type="button" class="btn_popup" onclick="fnChangeDeliveryAddr('chger');"><span>회수지 선택</span></button>
 					</div>
 					<div class="tbl type1">
@@ -201,7 +201,7 @@
 				<section class="order_row">
 					<div class="order_tit">
 						<h3 class="subH3">교환 상품 받으실 주소</h3>
-						<span class="del_t">택배사에서 반품 상품을 직접 회수할 장소 선택</span>
+						<span class="del_t">교환받을 상품을 수령할 장소 선택</span>
 						<button type="button" class="btn_popup" onclick="fnChangeDeliveryAddr('recip');"><span>회수지 선택</span></button>
 					</div>
 					<div class="tbl type1">
@@ -253,19 +253,13 @@
 		// 마이페이지 location 설정
 		fnSetMypageLocation('취소/반품/환불내역', '_PAGE_MYPAGE_CRS_LIST', '교환 신청');
 	});
-	
+
 	// 교환 옵션 변경 팝업
 	var fnChangeOption = function(param) {
 		// TODO
 		// 옵션변경 처리
 	}
-	
-	// 회수지, 교환지 설정 팝업
-	var fnChangeDeliveryAddr = function(param) {
-		// TODO
-		// 회수지, 교환지 설정
-	}
-	
+
 	// 교환 처리
 	var fnExchange = function() {
 		// TODO

+ 65 - 10
src/main/webapp/WEB-INF/views/web/mypage/MypageOrderListFormWeb.html

@@ -39,14 +39,14 @@
 					<div th:class="|rank_icon ${#strings.toLowerCase(customerInfo.custGradeNm)}|" th:text="${#strings.substring(customerInfo.custGradeNm, 0, 1)}"></div>
 					<div class="rank_txt01" th:text="${customerInfo.custGradeNm}"></div>
 					<div class="rank_txt02">
-						<button type="button">등급혜택  보기</button>
-						<button type="button" id="cp_down">등급쿠폰 다운</button>
+						<button type="button" onclick="fnGoToCustomerBenefit();">등급혜택  보기</button>
+						<button type="button" id="cp_down" onclick="fnDownloadCoupon();">등급쿠폰 다운</button>
 					</div>
 				</div>
 				<div class="mem_box">
 					<div class="mem_coupon">
 						<p class="tit">보유쿠폰&nbsp;/&nbsp;<span class="c_primary">만료예정</span></p>
-						<span class="coupon_txt01"><span class="big_txt" th:text="${couponCnt}"></span>장</span>&nbsp;/&nbsp;<span class="coupon_txt02 c_primary" th:text="|${expiredSoonCouponCnt}장|">13장</span>
+						<span class="coupon_txt01"><span class="big_txt" id="couponCnt" th:text="${couponCnt}"></span>장</span>&nbsp;/&nbsp;<span class="coupon_txt02 c_primary" id="expiredSoonCouponCnt" th:text="|${expiredSoonCouponCnt}장|"></span>
 					</div>
 					<div class="mem_point">
 						<p class="tit">STYLE  24 포인트</p>
@@ -65,32 +65,32 @@
 				<ul class="clear">
 					<li>
 						<p class="or_p">주문접수</p>
-						<p class="count"><span th:text="${orderCount.orderReceiptCount}">0</span></p>
+						<p class="count"><span id="orderReceiptCount" th:text="${orderCount.orderReceiptCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">결제완료</p>
-						<p class="count"><span th:text="${orderCount.paymentCompleteCount}">0</span></p>
+						<p class="count"><span id="paymentCompleteCount" th:text="${orderCount.paymentCompleteCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">상품 준비 중</p>
-						<p class="count"><span th:text="${orderCount.goodsPrepareCount}">0</span></p>
+						<p class="count"><span id="goodsPrepareCount" th:text="${orderCount.goodsPrepareCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">배송 준비 중</p>
-						<p class="count"><span th:text="${orderCount.shipPrepareCount}">0</span></p>
+						<p class="count"><span id="shipPrepareCount" th:text="${orderCount.shipPrepareCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">배송 중</p>
-						<p class="count"><span th:text="${orderCount.shippingCount}">0</span></p>
+						<p class="count"><span id="shippingCount" th:text="${orderCount.shippingCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">배송 완료</p>
-						<p class="count"><span th:text="${orderCount.shipCompleteCount}">0</span></p>
+						<p class="count"><span id="shipCompleteCount" th:text="${orderCount.shipCompleteCount}">0</span></p>
 					</li>
 				</ul>
 				<div class="order_right">
 					<p class="or_p">취소/교환/반품</p>
-					<p class="count"><span th:text="${orderCount.cancelCount + orderCount.returnCount + orderCount.exchangeCount}">0</span></p>
+					<p class="count"><span id="orderCrsCount" th:text="${orderCount.cancelCount + orderCount.returnCount + orderCount.exchangeCount}">0</span></p>
 				</div>
 			</div>
 			<!-- //주문 경로 -->
@@ -219,6 +219,61 @@
 			}
 		}
 	}
+	
+	// 등급혜택 보기 클릭 이벤트
+	var fnGoToCustomerBenefit = function() {
+		// TODO
+		// 등급혜택보기 페이지 이동
+	}
+	
+	// 등급쿠폰 다운 클릭 이벤트
+	var fnDownloadCoupon = function() {
+		let url = '/mypage/coupon/download/all';
+
+		let data = {};
+		data.custNo = customerInfo.custNo;
+
+		let jsonData = JSON.stringify(data);
+
+		gagajf.ajaxJsonSubmit(url, jsonData, function() {
+			fnReloadCouponCount();
+		});
+	}
+	
+	// 보유쿠폰 수량 업데이트 처리
+	var fnReloadCouponCount = function() {
+		let url = '/mypage/coupon/count';
+		
+		let data = {};
+		data.custNo = customerInfo.custNo;
+		
+		let jsonData = JSON.stringify(data);
+		
+		gagajf.ajaxJsonSubmit(url, jsonData, function(result) {
+			$('#couponCnt').text(result.couponCnt);
+			$('#expiredSoonCouponCnt').text(result.expiredSoonCouponCnt + '장');
+		});
+	}
+	
+	// 상태값 별 수량 업데이트 처리
+	var fnReloadStatusCount = function() {
+		let url = '/mypage/status/count';
+		
+		let data = {};
+		data.custNo = customerInfo.custNo;
+		
+		let jsonData = JSON.stringify(data);
+		
+		gagajf.ajaxJsonSubmit(url, jsonData, function(result) {
+			$('#orderReceiptCount').text(result.orderCount.orderReceiptCount);
+			$('#paymentCompleteCount').text(result.orderCount.paymentCompleteCount);
+			$('#goodsPrepareCount').text(result.orderCount.goodsPrepareCount);
+			$('#shipPrepareCount').text(result.orderCount.shipPrepareCount);
+			$('#shippingCount').text(result.orderCount.shippingCount);
+			$('#shipCompleteCount').text(result.orderCount.shipCompleteCount);
+			$('#orderCrsCount').text(result.orderCount.cancelCount + result.orderCount.returnCount + result.orderCount.exchangeCount);
+		});
+	}
 /*]]>*/
 </script>
 

+ 335 - 0
src/main/webapp/WEB-INF/views/web/mypage/MypageReturnFormWeb.html

@@ -0,0 +1,335 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org"
+	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+	layout:decorator="web/common/layout/MypageLayoutWeb">
+<!--
+ *******************************************************************************
+ * @source  : MypageReturnFormWeb.html
+ * @desc    : 마이페이지 > 반품신청 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.02.25   card007     최초 작성
+ *******************************************************************************
+ -->
+<body>
+
+<th:block layout:fragment="content">
+	<div class="my_cont">
+		<div class="sec_head">
+			<h3>반품 신청</h3>
+			<div class="od_detail">
+				(주문번호 : <span class="num" th:text="${ordNo}"></span>)
+			</div>
+		</div>
+		<div class="sec_body mypage_body">
+			<form class="form_wrap" role="form">
+				<div class="order_list">
+					<section class="order_row">
+						<th:block th:if="${orderList}" th:each="oneData, status : ${orderList}">
+							<div class="part_deliver">
+								<div class="tbl_tit">
+									<!-- 주문일/선물일 설정 -->
+									<span class="start_t" th:unless="${oneData.giftPackYn == 'Y'}">주문일</span>
+									<span class="gift_t" th:if="${oneData.giftPackYn == 'Y'}">선물일</span>
+									<!-- //주문일/선물일 설정 -->
+	
+									<span class="order_date" th:text="${oneData.ordDt}"></span>
+	
+									<!-- 배송구분 설정 -->
+									<span class="order_label02" th:if="${oneData.shotDelv}">총알배송</span>
+									<span class="order_label01" th:if="${oneData.selfMall}">STYLE24 일반배송</span>
+									<span class="order_label01" th:if="${oneData.supplyMall}">업체직배송</span>
+									<!-- //배송구분 설정 -->
+									<a href="javascript:void(0)" class="detail_btn" th:attr="ordNo=${oneData.ordNo}" onclick="fnGoToOrderDetail(this)">주문상세보기</a>
+								</div>
+								<th:block th:if="${oneData.orderList}" th:each="order, status : ${oneData.orderList}">
+									<div class="tbl type2">
+										<table id="returnList">
+											<colgroup>
+												<col width="1020">
+												<col width="180">
+											</colgroup>
+											<tbody>
+											<th:block th:if="${order.ordDtlList}" th:each="ordDtl, status : ${order.ordDtlList}" th:with="imageUrl=${@environment.getProperty('upload.goods.view')}">
+												<input type="hidden" name="ordDtlNo" th:value="${ordDtl.ordDtlNo}"/>
+												<input type="hidden" name="ordDtlStat" th:value="${ordDtl.ordDtlStat}"/>
+												<input type="hidden" name="reviewSq" th:value="${ordDtl.reviewSq}"/>
+												<tr>
+													<td>
+														<div class="info_item">
+															<div class="thumb_box">
+																<a href="">
+																	<img th:src="${imageUrl + '/' + ordDtl.sysImgNm}" width="100%" alt="">
+																</a>
+															</div>
+															<div class="info_box">
+																<p class="od_name">
+																	<a href="">
+																		<span class="brand" th:text="${ordDtl.brandNm}"></span>
+																		<span class="name" th:text="${ordDtl.goodsNm}"></span>
+																	</a>
+																</p>
+																<p class="od_opt">
+																	<span class="option"><em th:text="${ordDtl.optCd1}"></em><em th:text="${ordDtl.optCd2}"></em></span>
+																	<span class="count">수량 <em th:text="${ordDtl.ordQty}"></em>개</span>
+																</p>
+															</div>
+															<div class="info_calc">
+																<p class="price">
+																	<span class="selling_price" th:text="|${#numbers.formatInteger(ordDtl.ordAmt, 1, 'COMMA')}원|"></span>
+																</p>
+																<p class="point"><span th:text="${#numbers.formatInteger(ordDtl.savePntAmt, 1, 'COMMA')}"></span>p</p>
+															</div>
+														</div>
+													</td>
+													<td class="cnt_sel">
+														<span class="cnt_t">수량</span>
+														<select class="select_dress" name="chgQty" onchange="fnChangeQty();">
+															<option value="">선택</option>
+															<option th:if="${ordDtl.ordQty > 0}" th:each="num : ${#numbers.sequence(1,ordDtl.ordQty)}" th:value="${num}" th:text="${num}"></option>
+														</select>
+													</td>
+												</tr>
+											</th:block>
+											</tbody>
+										</table>
+									</div>
+								</th:block>
+								<div class="order_confirm">
+									<p class="cf_txt cf_desc c_primary">반품하실 상품의 수량을 선택하신 후 반품 신청을 하실 수 있습니다.</p>
+								</div>
+							</div>
+						</th:block>
+					</section>
+					<section class="order_row">
+						<div class="tbl_tit">
+							<h3 class="subH3">반품 사유</h3>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<td>
+										<select id="mounth" name="chgReason" onchange="fnChangeReason(this);">
+											<option value="">반품 사유를 선택하세요</option>
+											<option th:if="${returnReason}" th:each="oneData, status : ${returnReason}" th:value="${oneData.cd}" th:text="${oneData.cdNm}"></option>
+										</select>
+									</td>
+								</tr>
+								<tr>
+									<td>
+										<textarea class="doc_exchange" name="chgMemo" id="chgMemo" placeholder="자세한 사유를 입력해주세요." onkeyup="cfnGetTextLength(this, 200, $('#return_cnt'));"></textarea>
+										<p class="txt_cnt"><span id="return_cnt" class="c_primary">0</span>/200</p>
+									</td>
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row">
+						<div class="order_tit">
+							<h3 class="subH3">반품 방식 선택</h3>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<td>
+										<div class="form_field radio_field">
+											<div class="">
+												<input type="radio" name="wdGb" id="withdraw" value="W" onclick="fnChangeWdGb();" checked>
+												<label for="withdraw"><span>방문회수 <b class="c_primary">택배사에서 방문하여 회수</b></span></label>
+											</div>
+											<div class="">
+												<input type="radio" name="wdGb" id="direct" value="D" onclick="fnChangeWdGb();">
+												<label for="direct"><span>직접반송 <b class="c_primary">고객이 직접 반송처리</b></span></label>
+											</div>
+										</div>
+									</td>
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row" id="chgerLocation">
+						<div class="order_tit">
+							<h3 class="subH3">상품 회수지</h3>
+							<span class="del_t">택배사에서 반품 상품을 직접 회수할 장소 선택</span>
+							<button type="button" class="btn_popup" onclick="fnChangeDeliveryAddr('chger');"><span>회수지 선택</span></button>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="200">
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<th>성명</th>
+									<td id="chgerNm" th:text="${deliveryAddrInfo.recipNm}"></td>
+									<input type="hidden" name="chgerNm" th:value="${deliveryAddrInfo.recipNm}">
+								</tr>
+								<tr>
+									<th>연락처</th>
+									<td id="chgerPhnno" th:text="${deliveryAddrInfo.recipPhnno}"></td>
+									<input type="hidden" name="chgerPhnno" th:value="${deliveryAddrInfo.recipPhnno}">
+								</tr>
+								<tr>
+									<th>주소</th>
+									<td id="chgerAddr" th:text="|${deliveryAddrInfo.recipBaseAddr} ${deliveryAddrInfo.recipDtlAddr}|"></td>
+									<input type="hidden" name="chgerBaseAddr" th:value="${deliveryAddrInfo.recipBaseAddr}">
+									<input type="hidden" name="chgerDtlAddr" th:value="${deliveryAddrInfo.recipDtlAddr}">
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row" id="returnLocation" style="display:none">
+						<div class="order_tit">
+							<h3 class="subH3">반품하실 배송지</h3>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="200">
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<th>성명</th>
+									<td th:text="${deliveryAddrInfo.rtnLocNm}"></td>
+									<input type="hidden" name="rtnLocNm" th:value="${deliveryAddrInfo.rtnLocNm}">
+								</tr>
+								<tr>
+									<th>연락처</th>
+									<td th:text="${deliveryAddrInfo.rtnLocTelno}"></td>
+									<input type="hidden" name="rtnLocTelno" th:value="${deliveryAddrInfo.rtnLocTelno}">
+								</tr>
+								<tr>
+									<th>주소</th>
+									<td th:text="|${deliveryAddrInfo.rtnLocBaseAddr} ${deliveryAddrInfo.rtnLocDtlAddr}|"></td>
+									<input type="hidden" name="rtnLocBaseAddr" th:value="${deliveryAddrInfo.rtnLocBaseAddr}">
+									<input type="hidden" name="rtnLocDtlAddr" th:value="${deliveryAddrInfo.rtnLocDtlAddr}">
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row">
+						<div class="order_tit">
+							<h3 class="subH3">환불 정보</h3>
+							<button type="button" class="btn_popup"><span>취소 전표 보기</span></button>
+						</div>
+						<div class="tbl type1 re_info_tbl">
+							<div class="r_left">
+								<dl>
+									<dt>환불(예정) 금액</dt>
+									<dd>
+										<span class="big_t"><strong id="returnAmt">0</strong>원</span>
+									</dd>
+								</dl>
+								<dl>
+									<dt>상품취소 금액</dt>
+									<dd>
+										<span id="goodsCancelAmt">0</span>원
+									</dd>
+								</dl>
+								<dl>
+									<dt>배송비</dt>
+									<dd>
+										<span id="deliveryFee">0</span>원
+									</dd>
+								</dl>
+								<dl>
+									<dt>할인금액 차감</dt>
+									<dd>
+										<span id="deductDcAmt">0</span>원
+									</dd>
+								</dl>
+							</div>
+							<div class="r_right">
+								<dl>
+									<dt>환불수단</dt>
+									<dd>
+										<span th:text="${paymentInfo.payMeansNm}"></span>
+									</dd>
+								</dl>
+								<dl>
+									<dt>결제금액 환불</dt>
+									<dd>
+										<span id="refundPayAmt">0</span>원
+									</dd>
+								</dl>
+								<dl>
+									<dt>포인트 환불</dt>
+									<dd>
+										<span id="refundPoint">0</span>P
+									</dd>
+								</dl>
+								<dl>
+									<dt>상품권 환불</dt>
+									<dd>
+										<span id="refundGiftCard">0</span>원
+									</dd>
+								</dl>
+							</div>
+						</div>
+						<p class="alert_t">※ 카드사로 결제 취소 요청이 전달된 후 환불까지는 평일 기준 3 ~7일이 소요될 수 있습니다.</p>
+					</section>
+					<section class="order_row" id="addDeliveryFee" style="display:none">
+						<div class="ship_fee">
+							<p><span class="c_primary" id="addPayCost">2,500원</span> 배송비 추가 결제가 필요합니다.</p>
+							<input type="hidden" name="addPayCost"/>
+						</div>
+					</section>
+					<div class="btn_wrap">
+						<button type="button" class="btn btn_default cancle_btn" onclick="cfnGoToPage(_PAGE_MYPAGE_CRS_LIST)"><span>반품 취소</span></button>
+						<button tyep="submit" class="btn btn_primary submit_btn" onclick="fnReturn()"><span id="returnButton">반품 신청</span></button>
+					</div>
+				</div>
+			</form>
+		</div>
+	</div>
+<script src="/ux/plugins/gaga/gaga.paging.js"></script>
+<script th:inline="javascript">
+	$(document).ready(function() {
+		// 마이페이지 LNB 설정
+		fnSetMypageLnbList(2);
+		
+		// 마이페이지 location 설정
+		fnSetMypageLocation('취소/반품/환불내역', '_PAGE_MYPAGE_CRS_LIST', '반품 신청');
+	});
+	
+	// 반품 처리
+	var fnReturn = function() {
+		// TODO
+		// 반품신청 처리
+	}
+	
+	// 반품 수량 변경 이벤트 처리
+	var fnChangeQty = function(param) {
+		// TODO
+		// 반품 수량 변경 처리
+	}
+	
+	var fnChangeWdGb = function() {
+		let wdGb = $('input[name=wdGb]:radio:checked').val();
+		console.log(wdGb);
+	}
+</script>
+
+</th:block>
+
+</body>
+</html>

+ 197 - 172
src/main/webapp/WEB-INF/views/web/order/OrderFormWeb.html

@@ -323,7 +323,7 @@
 															<div class="form_field">
 																<input id="chk-maxdisc" type="checkbox" checked="">
 																<label for="chk-maxdisc">
-																	<span>최대 할인혜택을 바로 적용하세요 <em class="maxdisc_amount">(-3,000원)</em></span>
+																	<span>최대 할인혜택을 바로 적용하세요 <em class="maxdisc_amount"></em></span>
 																</label>
 															</div>
 														</div>
@@ -376,6 +376,7 @@
 																						<div class="form_field">
 																							<div class="select_custom type1">
 																								<div class="combo">
+																									<input type="hidden" name="cpnCartSq" th:value="${goods.cartSq}"/>
 																									<input type="hidden" name="custCpnSq" value="0"/>
 																									<input type="hidden" name="cpnDcAmt" value="0"/>
 																									
@@ -413,7 +414,12 @@
 																								<ul class="list">
 																									<li value="0">선택없음</li>
 																									<th:block th:each="cartCpn, k : ${cartCpnList}">
-																										<li th:value="${cartCpn.custCpnSq}" th:data="${cartCpn.cpnDcAmt}" th:text="${cartCpn.cpnNm}"></li>
+																										<li th:value="${cartCpn.custCpnSq}" th:data="${cartCpn.cpnDcAmt}">
+																											<th:block th:text="${cartCpn.cpnNm}"></th:block>
+																											<th:block th:each="cartCpnCartSq, kokok : ${cartCpn.cartCpnCartSqArr}"> 
+																												<input type="text" name="cartCpnCartSq" th:value="${cartCpnCartSq}" />
+																											</th:block>
+																										</li>
 																									</th:block>
 																								</ul>
 																							</div>
@@ -798,148 +804,91 @@
 							<div class="area_order">
 								<div class="tit_box">
 									<h3 class="subH2">주문내역</h3>
-									<span> <em class="number" th:text="${delvTotCnt}"></em>개의 상품
-									</span>
+									<span> <em class="number" th:text="${delvTotCnt}"></em>개의 상품</span>
 								</div>
 								<div class="od_item_box">
-									<!-- 총알배송, 일반배송-->
-									<th:block th:if="${wmsCartList != null and #lists.size(wmsCartList) > 0}">
-										<div class="part_dlvr">
-											<h4 class="subH3 mb20" id="shotDelvTitle">STYLE24 총알배송<span>오늘 자정까지 도착</span></h4>
-											<h4 class="subH3 mb20" id="wmsDelvTitle">STYLE24 일반배송</h4>
-											<div class="gd_list">
-												<th:block th:each="goods, i : ${wmsCartList}">
-													<div class="item_gd">
-														<input type="text" name="cartSq" 			th:value="${goods.cartSq}"/>
-														<input type="text" name="goodscd" 			th:value="${goods.goodsCd}"/>
-														<input type="text" name="ordQty" 			th:value="${goods.goodsQty}"/>
-														<input type="text" name="itemCd" 			th:value="${goods.itemCd}"/>
-														<input type="text" name="optCd" 			th:value="${goods.optCd}"/>
-														<input type="text" name="optCd1" 			th:value="${goods.optCd1}"/>
-														<input type="text" name="optCd2" 			th:value="${goods.optCd2}"/>
-														
-														<input type="text" name="currPrice" 		th:value="${goods.orgCurrPrice}"/>
-														<input type="text" name="cpn1CpnSq" 		th:value="${goods.cpn1CpnSq}"/>
-														<input type="text" name="cpn1DcAmt" 		th:value="${goods.orgCurrPrice} - ${goods.currPrice}"/>
-														
-														<th:block th:if="${goods.applyQtySectionYn} == 'Y' and ${goods.qtyTmtbSq} > 0">
-															<input type="text" name="tmtb1Sq" 		th:value="${goods.qtyTmtbSq}"/>
-															<input type="text" name="tmtb1DcAmt" 	th:value="${goods.tmtb1DcAmt}"/>
-														</th:block>
-														<th:block th:if="${goods.applyQtySectionYn} != 'Y'">
-															<input type="text" name="tmtb1Sq" 		value="0"/>
-															<input type="text" name="tmtb1DcAmt" 	value="0"/>
-														</th:block>
-														
-														<th:block th:if="${goods.applyAmtSectionYn} == 'Y' and ${goods.amtTmtbSq} > 0">
-															<input type="text" name="tmtb2Sq" 		th:value="${goods.amtTmtbSq}"/>
-															<input type="text" name="tmtb2DcAmt" 	th:value="${goods.tmtb2DcAmt}"/>
-														</th:block>
-														<th:block th:if="${goods.applyAmtSectionYn} != 'Y'">
-															<input type="text" name="tmtb2Sq" 		value="0"/>
-															<input type="text" name="tmtb2DcAmt" 	value="0"/>
-														</th:block>
-														
-														<input type="text" name="goodsCpnSq" 		value=""/>
-														<input type="text" name="goodsCpnDcAmt" 	value=""/>
-														<input type="text" name="cartCpnSq" 		value=""/>
-														<input type="text" name="cartCpnDcAmt" 		value=""/>
-														
-														<figure>
-															<span class="thumb"><img src="/images/pc/thumb/tmp_odSide1.jpg" alt=""></span>
-															<figcaption>
-																<div class="brand" th:text="${goods.brandEnm} + ' ' + ${goods.brandKnm}"></div>
-																<div class="name" th:text="${goods.goodsNm}"></div>
-																<div class="option" th:each="opt, index : ${goods.itemNmArr}">
-																	<span th:text="${goods.optCdArr[index.index]}"></span> 
-																	<span>수량:<em th:text="${goods.goodsQty}"></em>개</span>
-																</div>
-																<div class="price">
-																	<th:block th:if="${goods.tmtbDcAmt} > 0">
-																		<span class="selling_price"  th:text="${#numbers.formatInteger(goods.tmtbDcAmt, 1, 'COMMA')}"></span>
-																	</th:block>
-																	<th:block th:if="${goods.tmtbDcAmt} < 1">
-																		<span class="selling_price"  th:text="${#numbers.formatInteger(goods.currPrice, 1, 'COMMA')}"></span>
-																	</th:block>
-																</div>
-															</figcaption>
-														</figure>
-													</div>
+								
+									<!-- 전체배송목록 sort --> 
+									<th:block th:each="delvAllCart, i : ${delvAllCartList}">
+										<th:block th:if="${delvAllCart != null and #lists.size(delvAllCart) > 0}">
+											<div class="part_dlvr">
+												<th:block th:if="${i.index} == 0">
+													<th:block th:if="${delvAllCart != null and #lists.size(delvAllCart) > 0}">
+														<h4 class="subH3 mb20">STYLE24 총알배송<span>오늘 자정까지 도착</span></h4>
+													</th:block>
 												</th:block>
-											</div>
-										</div>
-									</th:block>
-									<!-- //총알배송, 일반배송 -->
-									
-									<!-- 업체직배송 -->
-									<th:block th:if="${delvCartList != null and #lists.size(delvCartList) > 0}">
-										<div class="part_dlvr">
-											<h4 class="subH3 mb20">업체직배송</h4>
-											<div class="gd_list">
-												<th:block th:each="goods, i : ${delvCartList}">
-													<div class="item_gd">
-														<figure>
-															<span class="thumb"><img src="/images/pc/thumb/tmp_odSide1.jpg" alt=""></span>
-															<figcaption>
-																<div class="brand" th:text="${goods.brandEnm} + ' ' + ${goods.brandKnm}"></div>
-																<div class="name" th:text="${goods.goodsNm}"></div>
-																<div class="option">
-																	<span th:text="${goods.optCd}"></span> 
-																	<span>수량:<em th:text="${goods.goodsQty}"></em>개</span>
-																</div>
-																<div class="price">
-																	<th:block th:if="${goods.tmtbDcAmt} > 0">
-																		<span class="selling_price"  th:text="${#numbers.formatInteger(goods.tmtbDcAmt, 1, 'COMMA')}"></span>
-																	</th:block>
-																	<th:block th:if="${goods.tmtbDcAmt} < 1">
-																		<span class="selling_price"  th:text="${#numbers.formatInteger(goods.currPrice, 1, 'COMMA')}"></span>
-																	</th:block>
-																</div>
-															</figcaption>
-														</figure>
-													</div>
+												<th:block th:if="${i.index} == 1">
+													<th:block th:if="${delvAllCart != null and #lists.size(delvAllCart) > 0}">
+														<h4 class="subH3 mb20" id="wmsDelvTitle">STYLE24 일반배송</h4>
+													</th:block>
 												</th:block>
-											</div>
-										</div>
-									</th:block>
-									<!-- //업체직배송 -->
-									
-									<!-- 예약배송 -->
-									<th:block th:if="${resCartList != null and #lists.size(resCartList) > 0}">
-										<div class="part_dlvr">
-											<h4 class="subH3 mb20">예약배송</h4>
-											<div class="gd_list">
-												<th:block th:each="goods, i : ${resCartList}">
-													<div class="item_gd">
-														<figure>
-															<span class="thumb"><img src="/images/pc/thumb/tmp_odSide1.jpg" alt=""></span>
-															<figcaption>
-																<div class="brand" th:text="${goods.brandEnm} + ' ' + ${goods.brandKnm}"></div>
-																<div class="name" th:text="${goods.goodsNm}"></div>
-																<div class="option">
-																	<span th:text="${goods.optCd}"></span>
-																	<span>수량:<em th:text="${goods.goodsQty}"></em>개</span>
-																</div>
-																<div class="price">
-																	<th:block th:if="${goods.tmtbDcAmt} > 0">
-																		<span class="selling_price"  th:text="${#numbers.formatInteger(goods.tmtbDcAmt, 1, 'COMMA')}"></span>
-																	</th:block>
-																	<th:block th:if="${goods.tmtbDcAmt} < 1">
-																		<span class="selling_price"  th:text="${#numbers.formatInteger(goods.currPrice, 1, 'COMMA')}"></span>
-																	</th:block>
-																</div>
-															</figcaption>
-														</figure>
-														<p class="info_reserv">
-															<i class="ico ico_calender"></i><span th:text="${goods.delvResDt}"></span>
-															배송예정상품
-														</p>
-													</div>
+												<th:block th:if="${i.index} == 2">
+													<th:block th:if="${delvAllCart != null and #lists.size(delvAllCart) > 0}">
+														<h4 class="subH3 mb20">업체직배송</h4>
+													</th:block>
 												</th:block>
+												<th:block th:if="${i.index} == 3">
+													<th:block th:if="${delvAllCart != null and #lists.size(delvAllCart) > 0}">
+														<h4 class="subH3 mb20">예약배송</h4>
+													</th:block>
+												</th:block>
+												
+												<div class="gd_list">
+													<th:block th:each="goods, i : ${delvAllCart}">
+														<div class="item_gd">
+															<input type="text" name="cartSq" 			th:value="${goods.cartSq}"/>
+															<input type="text" name="cpn1CpnSq" 		th:value="${goods.cpn1CpnSq}"/>
+															<input type="text" name="cpn1DcAmt" 		th:value="${goods.orgCurrPrice} - ${goods.currPrice}"/>
+															
+															<th:block th:if="${goods.applyQtySectionYn} == 'Y' and ${goods.qtyTmtbSq} > 0">
+																<input type="text" name="tmtb1Sq" 		th:value="${goods.qtyTmtbSq}"/>
+																<input type="text" name="tmtb1DcAmt" 	th:value="${goods.tmtb1DcAmt}"/>
+															</th:block>
+															<th:block th:if="${goods.applyQtySectionYn} != 'Y'">
+																<input type="text" name="tmtb1Sq" 		value="0"/>
+																<input type="text" name="tmtb1DcAmt" 	value="0"/>
+															</th:block>
+															
+															<th:block th:if="${goods.applyAmtSectionYn} == 'Y' and ${goods.amtTmtbSq} > 0">
+																<input type="text" name="tmtb2Sq" 		th:value="${goods.amtTmtbSq}"/>
+																<input type="text" name="tmtb2DcAmt" 	th:value="${goods.tmtb2DcAmt}"/>
+															</th:block>
+															<th:block th:if="${goods.applyAmtSectionYn} != 'Y'">
+																<input type="text" name="tmtb2Sq" 		value="0"/>
+																<input type="text" name="tmtb2DcAmt" 	value="0"/>
+															</th:block>
+															
+															<input type="text" name="goodsCpnSq" 		value=""/>
+															<input type="text" name="goodsCpnDcAmt" 	value=""/>
+															<input type="text" name="cartCpnSq" 		value=""/>
+															<input type="text" name="cartCpnDcAmt" 		value=""/>
+															
+															<figure>
+																<span class="thumb"><img src="/images/pc/thumb/tmp_odSide1.jpg" alt=""></span>
+																<figcaption>
+																	<div class="brand" th:text="${goods.brandEnm} + ' ' + ${goods.brandKnm}"></div>
+																	<div class="name" th:text="${goods.goodsNm}"></div>
+																	<div class="option" th:each="opt, index : ${goods.itemNmArr}">
+																		<span th:text="${goods.optCdArr[index.index]}"></span> 
+																		<span>수량:<em th:text="${goods.goodsQty}"></em>개</span>
+																	</div>
+																	<div class="price">
+																		<th:block th:if="${goods.tmtbDcAmt} > 0">
+																			<span class="selling_price"  th:text="${#numbers.formatInteger(goods.tmtbDcAmt, 1, 'COMMA')}"></span>
+																		</th:block>
+																		<th:block th:if="${goods.tmtbDcAmt} < 1">
+																			<span class="selling_price"  th:text="${#numbers.formatInteger(goods.currPrice, 1, 'COMMA')}"></span>
+																		</th:block>
+																	</div>
+																</figcaption>
+															</figure>
+														</div>
+													</th:block>
+												</div>
 											</div>
-										</div>
+										</th:block>
 									</th:block>
-									<!-- //예약배송 -->
+									<!-- //전체배송목록 sort -->
 								</div>
 								
 								<div class="od_amount_box">
@@ -1267,59 +1216,47 @@ $(document).ready( function() {
 </script>
 
 <script th:inline="javascript">
-	var custCpnSq 	= 0;
-	var cpnIndex	= 0;
+	var custCpnSq 		= 0;
+	var cpnIndex		= 0;
+	var cpnApplyTemp	= false;
 	
 	// 컨텐츠 호출
 	$(document).ready( function() {
 		// 1. 총알배송가능 지역, 총알배송 가능 시간 체크
 		fnGetDailyDeliveryCheck();
 		
-		// 2. 배송목록 화면 노출, 비노출 처리
-		// 2.1 자사일반배송노출
-		if (wmsCnt > 0) {
-			$("#wmsDelvArea").css("display", "block");
-		}
-		
-		// 2.2 입점업체일반배송노출
-		if (delvCnt > 0) {
-			$("#delvDelvArea").css("display", "block");
-		}
-		
-		// 2.3 자사예약배송노출
-		if (resCnt > 0) {
-			$("#resDelvArea").css("display", "block");
-		}
-
-		// 3. 쿠폰 SELECT BOX 설정
+		// 2. 쿠폰 SELECT BOX 기능 설정(js적용)
 		$('.select_custom.type1').each(function(index){
 			var selecter01 	= new sCombo($(this));
-			var cpnIndex 	= 0;
 			
-			// select 박스 반복문 실행
+			// 선택박스 버튼기능 구현
 			$(this).find("ul li").each(function(i){
-				cpnIndex++;
-				
-				// 1이상부터 중복 체크
-				if (cpnIndex > 1) {
-					if (cpnDuplicationCheck($(this).prop("value"), index)) {
-						// 쿠폰적용
-						custCpnApply($(this));
-					}
-				}
 				
 				// SELECT BOX 버튼 기능 설정
 				$(this).on("click", function(){
-					// 선택없음
+					// 쿠폰 선택없음
 					if ($(this).prop("value") == 0) {
+						// select box 쿠폰 적용
+						var cpnCartSq = $(this).parent().parent().find("input[name='cpnCartSq']").val();
+						
+						// 장바구니시퀀스 체크
+						$("input[name='cartSq']").each(function(){
+							if (cpnCartSq == $(this).val()) {
+								$(this).parent().find("input[name='goodsCpnSq']").val("0");			// 상품쿠폰시퀀스
+								$(this).parent().find("input[name='goodsCpnDcAmt']").val("0");		// 상품쿠폰할인금액
+							}
+						});
+						
 						$(this).parent().parent().find("input[name='custCpnSq']").val("0");
 						$(this).parent().parent().find("input[name='cpnDcAmt']").val("0");
 						
 						$(this).parent().parent().find(".select").text("선택없음");
 						$(this).parent().parent().parent().parent().parent().find(".cp_discount").css("display", "none");
-					} else {
+					}
+					// 쿠폰선택
+					else {
 						// 쿠폰중복체크 후 적용
-						if (cpnDuplicationCheck($(this).prop("value"), index)) {
+						if (custCpnDuplicationCheck($(this).prop("value"), index)) {
 							// 쿠폰적용
 							custCpnApply($(this));
 						} else {
@@ -1329,13 +1266,81 @@ $(document).ready( function() {
 							custCpnNotApply($(this));
 						}
 					}
+					
+					// 최대할인혜택적용 체크해제
+					if ($("#chk-maxdisc").is(":checked")) {
+						$("#chk-maxdisc").attr("checked", false);
+					}
+					
+					// 쿠폰할인금액 SUM
+					custCpnSumAmtCal();
 				});
 			});
 		});
+		
+		// 3. 쿠폰 최대할인금액 초기화 버튼 설정
+		$("#chk-maxdisc").on("click", function(){
+			if ($(this).is(":checked")) {
+				custCpnInit();
+			}
+		});
+		
+		// 3. 쿠폰적용초기화(할인율최고)
+		custCpnInit();
 	});
 	
+	// 쿠폰 최대할인율 쿠폰적용
+	var custCpnInit = function() {
+		
+		// 쿠폰적용없음적용
+		$(".select_custom.type1").each(function(index){
+			// select box 쿠폰 적용
+			var cpnCartSq = $(this).find("input[name='cpnCartSq']").val();
+			
+			// 장바구니시퀀스 체크
+			$("input[name='cartSq']").each(function(){
+				if (cpnCartSq == $(this).val()) {
+					$(this).parent().find("input[name='goodsCpnSq']").val("0");			// 상품쿠폰시퀀스
+					$(this).parent().find("input[name='goodsCpnDcAmt']").val("0");		// 상품쿠폰할인금액
+				}
+			});
+			
+			$(this).find("input[name='custCpnSq']").val("0");
+			$(this).find("input[name='cpnDcAmt']").val("0");
+			
+			$(this).find(".select").text("선택없음");
+			$(this).find(".cp_discount").css("display", "none");
+		});
+		
+		// 최대할인율 쿠폰적용
+		$('.select_custom.type1').each(function(index){
+			cpnIndex 		= 0;
+			cpnApplyTemp 	= false;
+			
+			// select 박스 반복문 실행
+			$(this).find("ul li").each(function(i){
+				cpnIndex++;
+				
+				// 1이상부터 중복 체크
+				if (cpnApplyTemp == false) {
+					if (cpnIndex > 1) {
+						if (custCpnDuplicationCheck($(this).prop("value"), index)) {
+							// 쿠폰적용
+							custCpnApply($(this));
+							
+							cpnApplyTemp = true;
+						}
+					}
+				}
+			});
+		});
+		
+		// 쿠폰할인금액 SUM
+		custCpnSumAmtCal();
+	}
+	
 	// 쿠폰중복사용체크
-	var cpnDuplicationCheck = function(custCpnSq, index) {
+	var custCpnDuplicationCheck = function(custCpnSq, index) {
 		var selCustSq 	= 0;
 		var cnt 		= 0;
 
@@ -1365,6 +1370,17 @@ $(document).ready( function() {
 		var dcAmtStr = "- " + parseInt(obj.attr("data")).addComma() + " 원 할인적용";
 		obj.parent().parent().parent().parent().parent().find(".cp_amount").text(dcAmtStr);
 		
+		// select box 쿠폰 적용
+		var cpnCartSq = obj.parent().parent().find("input[name='cpnCartSq']").val();
+		
+		// 장바구니시퀀스 체크
+		$("input[name='cartSq']").each(function(){
+			if (cpnCartSq == $(this).val()) {
+				$(this).parent().find("input[name='goodsCpnSq']").val(obj.prop("value"));		// 상품쿠폰시퀀스
+				$(this).parent().find("input[name='goodsCpnDcAmt']").val(obj.attr("data"));		// 상품쿠폰할인금액
+			}
+		});
+		
 		// select box 쿠폰 적용
 		obj.parent().parent().find("input[name='custCpnSq']").val(obj.prop("value"));
 		obj.parent().parent().find("input[name='cpnDcAmt']").val(obj.attr("data"));
@@ -1379,7 +1395,7 @@ $(document).ready( function() {
 	var custCpnNotApply = function(obj) {
 		// 이전에 등록된 쿠폰시퀀스  
 		var custCpnSq = obj.parent().parent().find("input[name='custCpnSq']").val();
-		
+
 		// 이전에 등록된 쿠폰시퀀스 비교후 데이타 원복
 		obj.parent().find("li").each(function(){
 			if ($(this).prop("value") == custCpnSq) {
@@ -1394,6 +1410,15 @@ $(document).ready( function() {
 		});
 	}
 	
+	// 쿠폰할인금액합계설정
+	var custCpnSumAmtCal = function() {
+		var cpnDcSumAmt = 0;
+		$("input[name='cpnDcAmt']").each(function(){
+			cpnDcSumAmt = cpnDcSumAmt + parseInt($(this).val());
+		});
+		$(".maxdisc_amount").text("(-" + cpnDcSumAmt.addComma() + "원)");
+	};
+	
 	// 사은품선택 라디오 버튼 기능
 	$(".freegiftRdo").on("click", function() {
 		var total_gift 		= 0;

+ 11 - 1
src/main/webapp/ux/pc/js/cart.js

@@ -43,7 +43,11 @@ var fnDecideOrder = function(param) {
 			gagajf.ajaxJsonSubmit('/mypage/order/decision'
 				, jsonData
 				, function() {
-					cfnGoToPage(_PAGE_MYPAGE_ORDER_DETAIL + ordNo);
+					if (typeof(fnReloadStatusCount) == 'function') {
+						fnReloadStatusCount();
+					} else {
+						cfnGoToPage(_PAGE_MYPAGE_ORDER_DETAIL + ordNo);
+					}
 				});
 		}
 	});
@@ -189,6 +193,12 @@ var fnDeleteOrder = function() {
 	});
 };
 
+// 회수지, 교환지 설정 팝업
+var fnChangeDeliveryAddr = function(param) {
+	// TODO
+	// 회수지, 교환지 설정
+}
+
 // 문자열 길이를 체크
 var cfnGetTextLength = function(obj, maxLen, dpLoc) {
 	var valLen = $(obj).val().length;

+ 55 - 2
src/main/webapp/ux/style24_link.js

@@ -58,7 +58,7 @@ const _PAGE_NOTICE = _frontUrl + "/callcenter/notice/form";								// 고객센
  * @access : public
  * @desc   : page 이동
  * <pre>
- *		 cfnGoToPage(PAGE_LOGIN);
+ *     cfnGoToPage(PAGE_LOGIN);
  * </pre>
  * @param  : page - page
  * @return : None
@@ -179,7 +179,7 @@ var cfnOpenIpinCertify = function (redirectUrl) {
  */
 function cfnAddCart(cartList) {
 	let jsonData = JSON.stringify(cartList);
-	
+
 	$.ajax( {
 		type: "POST",
 		url : '/cart/save',
@@ -191,3 +191,56 @@ function cfnAddCart(cartList) {
 		}
 	});
 }
+
+
+/**
+ * @type   : function
+ * @access : public
+ * @desc   :  네이버 로그인
+ * <pre>
+ *     cfnLoginNaver();
+ *     호출된 페이지에서
+ *     PC: fnSnsSigninCallback(userInfo) 콜백 함수 생성 후 가지고 호출 처리
+ *     MO :
+ * </pre>
+ * @since  : 2021/02/23
+ * @author : jsshin
+ */
+var cfnLoginNaver = function (requestGb, chkRememberMe) {
+	var actionUrl = _frontUrl + '/signin/naverlogin?rememberMe=' + chkRememberMe;
+	var popupHeight = 800;
+	var popupWidth = 600;
+	var popupX = (window.screen.width / 2) - (popupWidth / 2);
+	var popupY = (window.screen.height / 3) - (popupHeight / 3);
+	if ('P' === _frontGb) {
+		window.open(actionUrl, 'naverLogin', 'top=' + popupY + ',left=' + popupX + ',height=' + popupHeight + ',width=' + popupWidth + ', fullscreen=no,menubar=no,status=no,toolbar=no,titlebar=yes,location=no,scrollbars=yes', '');
+	} else {
+		document.location.href = actionUrl + '&requestGb=' + requestGb;
+	}
+};
+
+/**
+ * @type   : function
+ * @access : public
+ * @desc   : 카카오 로그인
+ * <pre>
+ *     cfnLoginKakao();
+ *     호출된 페이지에서
+ *     PC: fnSnsSigninCallback(userInfo) 콜백 함수 생성 후 가지고 호출 처리
+ *     MO :
+ * </pre>
+ * @since  : 2021/02/23
+ * @author : jsshin
+ */
+var cfnLoginKakao = function (requestGb, chkRememberMe) {
+	var actionUrl = _frontUrl + '/signin/kakologin?rememberMe=' + chkRememberMe;
+	var popupWidth = 450;
+	var popupHeight = 700;
+	var popupX = (window.screen.width / 2) - (popupWidth / 2);
+	var popupY = (window.screen.height / 3) - (popupHeight / 3);
+	if ('P' === _frontGb) {
+		window.open(actionUrl, 'kakaoLogin', 'top=' + popupY + ',left=' + popupX + ',height=' + popupHeight + ',width=' + popupWidth + ', fullscreen=no,menubar=no,status=no,toolbar=no,titlebar=yes,location=no,scrollbars=yes', '');
+	} else {
+		document.location.href = actionUrl + '&requestGb=' + requestGb;
+	}
+};