사용자 정보 가져오기- property_keys 파라미터 java 코드 작성법 문의

“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}””
}

[참고]

  1. 사전 설정 (플랫폼 등록, 카카오 로그인 활성화, 동의 항목), access 토큰은 callback url로 받아서 header에 잘 포함 시킴, post방식

  2. spring환경에서 org.springframework.web.client.RestTemplate사용해서 http 요청함

  3. java 코드로 property_keys 를 제외하고 요청 시 잘 됨 ( 동의한 항목에 대해 전체 사용자 정보 반환)

  4. 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;
}

property_keys 포함 안 하면 잘 되는데… RestTemplate 사용해서 HTTP 요청할 때 String[] 형식이 인식이 안되나…

안녕하세요.

Array를 사용하지 마시고 string으로 해보시겠어요?
(Json String Array 형식)

 params.add("property_keys", "[\"kakao_account.profile\",\"kakao_account.name\",\"kakao_account.email\"]");
1개의 좋아요

잘 됩니다. 감사해요.

REST API 문서 헷갈리지 않게 수정 필요할 듯 해요.

string → string

["kakao_account.email"]  ->  "[\"kakao_account.profile\",\"kakao_account.name\",\"kakao_account.email\"]"

1개의 좋아요