“REST API - 사용자 정보 가져오기”
[질문]
java에서 String[] 형식으로 property_keys 를 포함하면 400error가 반환 되네요.
뭐가 잘못된 걸까요?
[코드]
// HttpBody 오브젝트 생성
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add(“property_keys”, new String[]{“kakao_account.profile”, “kakao_account.name”,“kakao_account.email”});
[error]
{
“status”: 500,
“data”: “org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: “{“msg”:“failed to parse parameter. name=property_keys, stringToParse=-, paramString=-, paramStringAlias=null”,“code”:-2}””
}
[참고]
-
사전 설정 (플랫폼 등록, 카카오 로그인 활성화, 동의 항목), access 토큰은 callback url로 받아서 header에 잘 포함 시킴, post방식
-
spring환경에서 org.springframework.web.client.RestTemplate사용해서 http 요청함
-
java 코드로 property_keys 를 제외하고 요청 시 잘 됨 ( 동의한 항목에 대해 전체 사용자 정보 반환)
-
postman 으로 요청 시에는 잘 됨.
property_keys = [“kakao_account.profile”,“kakao_account.name”,“kakao_account.email”]
[요청 부분 전체 코드]
package 지정 ㄱㄱ
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
public class UserController {
private Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/auth/kakao/callback")
public @ResponseBody String kakaoCallback(@RequestParam String code // @ResponseBody를 붙이면 Data를 리턴해주는 컨트롤러함수가 된다.
, @Value("${kakao.springboot_blog_project.REST_API_KEY}") String REST_API_KEY
, @Value("${kakao.springboot_blog_project.REDIRECT_URI}") String REDIRECT_URI
) {
OauthToken KakaoTokenResponse = getKakaoTokenRequest(code, REST_API_KEY, REDIRECT_URI);
// HttpHeader 오브젝트 생성
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
headers.add("Authorization", "Bearer " +KakaoTokenResponse.getAccess_token());
// HttpBody 오브젝트 생성
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("property_keys", new String[]{"kakao_account.profile", "kakao_account.name","kakao_account.email"});
// HttpHeader와 HttpBody를 하나의 오브젝트에 담기 ( 이유 : exchange에서 HttpEntity<?>를 받기 때문)
HttpEntity<MultiValueMap<String, Object>> kakaoUserInfoRequest =
new HttpEntity<>(params, headers);
// Http 요청 후 response에 응답 받음
RestTemplate rt = new RestTemplate();
ResponseEntity<String> response = rt.exchange(
"https://kapi.kakao.com/v2/user/me",
HttpMethod.POST,
kakaoUserInfoRequest,
String.class
);
return response.getBody();
}
/**
* 카카오 서버로 요청 (POST 방식으로 key=value 데이터 형식)
* ( java POST요청은 보통 Retorfit2, OkHttp, RestTemplate 방식들 중 한개를 사용함)
*
* @param code
* @param REST_API_KEY
* @param REDIRECT_URI
* @return
*/
private OauthToken getKakaoTokenRequest(String code, String REST_API_KEY, String REDIRECT_URI) {
// HttpHeader 오브젝트 생성
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
// HttpBody 오브젝트 생성
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "authorization_code"); // authorization_code로 고정
params.add("client_id", REST_API_KEY); // 앱 REST API 키
params.add("redirect_uri", REDIRECT_URI); // 인가 코드가 리다이렉트된 URI
params.add("code", code); // 인가 코드 받기 요청으로 얻은 인가 코드
// HttpHeader와 HttpBody를 하나의 오브젝트에 담기 ( 이유 : exchange에서 HttpEntity<?>를 받기 때문)
HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest =
new HttpEntity<>(params, headers);
// Http 요청 후 response에 응답받음
RestTemplate rt = new RestTemplate();
ResponseEntity<String> response = rt.exchange(
"https://kauth.kakao.com/oauth/token",
HttpMethod.POST,
kakaoTokenRequest,
String.class
);
// Json데이터 파싱 라이브러리 사용 ( 예시)Gson, Json Simple, ObjectMapper)
ObjectMapper objectMapper = new ObjectMapper();
OauthToken oauthToken = null;
try { // readValue(파싱) 과정에서 데이터 받는 클래스의 변수명이 다르거나 setter가 없는 경우 error 발생! try-catch문으로 처리
oauthToken = objectMapper.readValue(response.getBody(), OauthToken.class);
} catch (JsonProcessingException e) {
logger.error("{}", e);
}
logger.info("oauthToken.getAccess_token : {}", oauthToken.getAccess_token());
return oauthToken;
}
}
package 패키지 지정 ㄱㄱ
import lombok.Data;
@Data
public class OauthToken {
private String access_token;
private String token_type;
private String refresh_token;
private String expires_in;
private String scope;
private String refresh_token_expires_in;
}