diff --git a/build.gradle b/build.gradle index 3ce970d..e767af3 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,8 @@ dependencies { implementation 'io.springfox:springfox-boot-starter:3.0.0' implementation 'io.springfox:springfox-swagger-ui:3.0.0' + // gson + implementation 'com.google.code.gson:gson:2.10' } tasks.named('test') { diff --git a/src/main/java/com/sesac/gmd/config/BaseResponseStatus.java b/src/main/java/com/sesac/gmd/config/BaseResponseStatus.java index 7deb888..a45a22d 100644 --- a/src/main/java/com/sesac/gmd/config/BaseResponseStatus.java +++ b/src/main/java/com/sesac/gmd/config/BaseResponseStatus.java @@ -30,13 +30,14 @@ public enum BaseResponseStatus { POST_USERS_EMPTY_LOCATION(false, 2014, "위치를 입력해주세요."), POST_USERS_EMPTY_PUSH(false, 2015, "푸시 아이디를 입력해주세요."), - POST_USERS_EMPTY_OAUTH(false, 2016, "소셜 아이디를 입력해주세요."), + POST_USERS_EMPTY_ACCESS_TOKEN(false, 2016, "소셜 아이디를 입력해주세요."), POST_USERS_INVAlID_GENDER(false, 2020, "성별을 확인해주세요."), POST_USERS_INVAlID_AGE(false, 2021, "나이를 확인해주세요."), POST_USERS_INVALID_EMAIL(false, 2022, "이메일 형식을 확인해주세요."), POST_USERS_EXISTS_EMAIL(false,2030,"중복된 이메일입니다."), POST_USERS_EXISTS_NICKNAME(false,2031,"중복된 닉네임입니다."), + POST_USERS_NO_EXISTS_EMAIL(false,2032,"존재하지 않는 이메일입니다."), // pins POST_PINS_EMPTY_TITLE(false, 2040, "제목을 입력해주세요."), diff --git a/src/main/java/com/sesac/gmd/src/test/TestController.java b/src/main/java/com/sesac/gmd/src/test/TestController.java index 276f5da..7a8f3fc 100644 --- a/src/main/java/com/sesac/gmd/src/test/TestController.java +++ b/src/main/java/com/sesac/gmd/src/test/TestController.java @@ -7,7 +7,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.annotations.ApiIgnore; +@ApiIgnore @RestController @RequestMapping("/test") public class TestController { diff --git a/src/main/java/com/sesac/gmd/src/user/UserController.java b/src/main/java/com/sesac/gmd/src/user/UserController.java index dc0c978..9c36a7b 100644 --- a/src/main/java/com/sesac/gmd/src/user/UserController.java +++ b/src/main/java/com/sesac/gmd/src/user/UserController.java @@ -13,6 +13,7 @@ import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import springfox.documentation.annotations.ApiIgnore; import java.util.List; @@ -37,9 +38,19 @@ public UserController(UserProvider userProvider, UserService userService, JwtSer this.jwtService = jwtService; } - /* 회원가입 API (카카오 제외) */ - @ApiOperation("임시 회원가입") - @PostMapping("/sign-up") + /* 카카오 로그인 (프론트가 없는 경우) */ + @ApiIgnore + @ResponseBody + @GetMapping("/kakao") + public void kakaoCallback(@RequestParam String code) { + // 코드를 통해 Access Token을 받아옴 + String token = userService.getKaKaoAccessToken(code); + userService.createKakaoUser(token); + } + + /* 회원가입 API */ + @ApiOperation("회원 가입") + @PostMapping("/sign-up/kakao") public BaseResponse createUser(@RequestBody PostUserReq postUserReq) { // NULL 값 체크 BaseResponseStatus status = userValidation(postUserReq); @@ -50,6 +61,12 @@ public BaseResponse createUser(@RequestBody PostUserReq postUserReq return new BaseResponse<>(POST_USERS_INVALID_EMAIL); } + // 카카오 이메일 비교 + String kakaoEmail = userService.createKakaoUser(postUserReq.getAccessToken()); + if(!kakaoEmail.equals(postUserReq.getEmail())) { + return new BaseResponse<>(POST_USERS_NO_EXISTS_EMAIL); + } + try { PostUserRes postUserRes = userService.createUser(postUserReq); return new BaseResponse<>(postUserRes); diff --git a/src/main/java/com/sesac/gmd/src/user/UserDao.java b/src/main/java/com/sesac/gmd/src/user/UserDao.java index be30299..e88848f 100644 --- a/src/main/java/com/sesac/gmd/src/user/UserDao.java +++ b/src/main/java/com/sesac/gmd/src/user/UserDao.java @@ -22,11 +22,11 @@ public void setDataSource(DataSource dataSource) { /* 회원 가입 API */ public int createUser(PostUserReq postUserReq) { - String query = "insert into user_tbl values(null, ?, ?, ?, ?, ?, ?, ?, ?, ?, default, default, default, default)"; + String query = "insert into user_tbl values(null, ?, ?, ?, ?, ?, ?, ?, ?, default, default, default, default)"; Object[] params = new Object[] { postUserReq.getNickname(), postUserReq.getGender(), postUserReq.getAge(), postUserReq.getEmail(), postUserReq.getState(), postUserReq.getCity(), postUserReq.getStreet(), - postUserReq.getPushId(), postUserReq.getAccessToken() }; + postUserReq.getPushId() }; this.jdbcTemplate.update(query, params); diff --git a/src/main/java/com/sesac/gmd/src/user/UserService.java b/src/main/java/com/sesac/gmd/src/user/UserService.java index 41ae875..1fc92d4 100644 --- a/src/main/java/com/sesac/gmd/src/user/UserService.java +++ b/src/main/java/com/sesac/gmd/src/user/UserService.java @@ -1,5 +1,7 @@ package com.sesac.gmd.src.user; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import com.sesac.gmd.config.BaseException; import com.sesac.gmd.src.user.model.PatchLocationReq; import com.sesac.gmd.src.user.model.PatchNicknameReq; @@ -9,6 +11,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; + import static com.sesac.gmd.config.BaseResponseStatus.*; @Service @@ -26,6 +32,8 @@ public UserService(UserProvider userProvider, UserDao userDao, JwtService jwtSer this.jwtService = jwtService; } + /** API **/ + /* 회원 가입 API */ public PostUserRes createUser(PostUserReq postUserReq) throws BaseException { // 이메일 중복 체크 @@ -109,5 +117,113 @@ public String patchIsPushed(int userIdx) throws BaseException { throw new BaseException(DATABASE_ERROR); } } + + /** 카카오 로그인 **/ + + /* 카카오 A.T 받기 (프론트가 없는 경우) */ + public String getKaKaoAccessToken(String code) { + String access_Token=""; + String refresh_Token =""; + String reqURL = "https://kauth.kakao.com/oauth/token"; + + try{ + URL url = new URL(reqURL); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + //POST 요청을 위해 기본값이 false인 setDoOutput을 true로 + conn.setRequestMethod("POST"); + conn.setDoOutput(true); + + //POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송 + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream())); + StringBuilder sb = new StringBuilder(); + sb.append("grant_type=authorization_code"); + sb.append("&client_id=be43e245f4aedc78d201da5b853a1a4e"); // REST_API_KEY 입력 + sb.append("&redirect_uri=http://localhost:9000/users/kakao"); // 인가코드 받은 redirect_uri 입력 + sb.append("&code=").append(code); + bw.write(sb.toString()); + bw.flush(); + + //결과 코드가 200이라면 성공 + int responseCode = conn.getResponseCode(); + System.out.println("responseCode : " + responseCode); + //요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기 + BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line = ""; + StringBuilder result = new StringBuilder(); + + while ((line = br.readLine()) != null) { + result.append(line); + } + System.out.println("response body : " + result); + + //Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성 + JsonParser parser = new JsonParser(); + JsonElement element = parser.parse(result.toString()); + + access_Token = element.getAsJsonObject().get("access_token").getAsString(); + refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString(); + + System.out.println("access_token : " + access_Token); + System.out.println("refresh_token : " + refresh_Token); + + br.close(); + bw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + return access_Token; + } + + /* Access Token을 사용하여 사용자 정보 받아오기 */ + public String createKakaoUser(String token) { + + String reqURL = "https://kapi.kakao.com/v2/user/me"; + String email = ""; + + //access_token을 이용하여 사용자 정보 조회 + try { + URL url = new URL(reqURL); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + conn.setRequestMethod("POST"); + conn.setDoOutput(true); + conn.setRequestProperty("Authorization", "Bearer " + token); //전송할 header 작성, access_token전송 + + //결과 코드가 200이라면 성공 + int responseCode = conn.getResponseCode(); + System.out.println("responseCode : " + responseCode); + + //요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기 + BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line = ""; + StringBuilder result = new StringBuilder(); + + while ((line = br.readLine()) != null) { + result.append(line); + } + System.out.println("response body : " + result); + + //Gson 라이브러리로 JSON파싱 + JsonParser parser = new JsonParser(); + JsonElement element = parser.parse(result.toString()); + + boolean hasEmail = element.getAsJsonObject().get("kakao_account").getAsJsonObject().get("has_email").getAsBoolean(); + if (hasEmail) { + email = element.getAsJsonObject().get("kakao_account").getAsJsonObject().get("email").getAsString(); + } + + System.out.println("email : " + email); + + br.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + + return email; + } + } diff --git a/src/main/java/com/sesac/gmd/utils/Validation.java b/src/main/java/com/sesac/gmd/utils/Validation.java index 1fabf31..4e059c5 100644 --- a/src/main/java/com/sesac/gmd/utils/Validation.java +++ b/src/main/java/com/sesac/gmd/utils/Validation.java @@ -28,7 +28,7 @@ public static BaseResponseStatus userValidation(PostUserReq postUserReq) { return POST_USERS_EMPTY_PUSH; } if(postUserReq.getAccessToken().isBlank()) { - return POST_USERS_EMPTY_OAUTH; + return POST_USERS_EMPTY_ACCESS_TOKEN; } // 성별을 제대로 적었는지 확인