API를 호출하기전에 SDK를 통해서 로그인을 해서 access token 을 발급 받으신 다음에 테스트 하시면 수월합니다.
access token 받는 방법은 아래 링크를 확인해 주세요.
Kakao API 사용 초기에 테스트를 위한 목적으로 작성된 코드이므로 그대로 사용하는 것을 지양합니다.
Kakao API Helper Class
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
//import com.google.gson.Gson;
public class KakaoRestApiHelper {
public enum HttpMethodType { POST, GET, DELETE }
private static final String API_SERVER_HOST = "https://kapi.kakao.com";
private static final String USER_SIGNUP_PATH = "/v1/user/signup";
private static final String USER_UNLINK_PATH = "/v1/user/unlink";
private static final String USER_LOGOUT_PATH = "/v1/user/logout";
private static final String USER_ME_PATH = "/v1/user/me";
private static final String USER_UPDATE_PROFILE_PATH = "/v1/user/update_profile";
private static final String USER_IDS_PATH = "/v1/user/ids";
private static final String STORY_PROFILE_PATH = "/v1/api/story/profile";
private static final String STORY_ISSTORYUSER_PATH = "/v1/api/story/isstoryuser";
private static final String STORY_MYSTORIES_PATH = "/v1/api/story/mystories";
private static final String STORY_MYSTORY_PATH = "/v1/api/story/mystory";
private static final String STORY_DELETE_MYSTORY_PATH = "/v1/api/story/delete/mystory";
private static final String STORY_POST_NOTE_PATH = "/v1/api/story/post/note";
private static final String STORY_UPLOAD_MULTI_PATH = "/v1/api/story/upload/multi";
private static final String STORY_POST_PHOTO_PATH = "/v1/api/story/post/photo";
private static final String STORY_LINKINFO_PATH = "/v1/api/story/linkinfo";
private static final String STORY_POST_LINK_PATH = "/v1/api/story/post/link";
private static final String TALK_PROFILE_PATH = "/v1/api/talk/profile";
private static final String PUSH_REGISTER_PATH = "/v1/push/register";
private static final String PUSH_TOKENS_PATH = "/v1/push/tokens";
private static final String PUSH_DEREGISTER_PATH = "/v1/push/deregister";
private static final String PUSH_SEND_PATH = "/v1/push/send";
private static final ObjectMapper JACKSON_OBJECT_MAPPER = new ObjectMapper();
//private static final Gson GSON = new Gson();
private static final String PROPERTIES_PARAM_NAME = "properties";
private static final List<String> adminApiPaths = new ArrayList<String>();
static {
adminApiPaths.add(USER_IDS_PATH);
adminApiPaths.add(PUSH_REGISTER_PATH);
adminApiPaths.add(PUSH_TOKENS_PATH);
adminApiPaths.add(PUSH_DEREGISTER_PATH);
adminApiPaths.add(PUSH_SEND_PATH);
}
private String accessToken;
private String adminKey;
public void setAccessToken(final String accessToken) {
this.accessToken = accessToken;
}
public void setAdminKey(final String adminKey) {
this.adminKey = adminKey;
}
///////////////////////////////////////////////////////////////
// User Management
///////////////////////////////////////////////////////////////
public String signup() {
return request(HttpMethodType.POST, USER_SIGNUP_PATH);
}
public String signup(final Map<String, String> params) {
return request(HttpMethodType.POST, USER_SIGNUP_PATH, PROPERTIES_PARAM_NAME + "=" + mapToJsonStr(params));
}
public String unlink() {
return request(HttpMethodType.POST, USER_UNLINK_PATH);
}
public String logout() {
return request(HttpMethodType.POST, USER_LOGOUT_PATH);
}
public String me() {
return request(USER_ME_PATH);
}
public String updatProfile(final Map<String, String> params) {
return request(HttpMethodType.POST, USER_UPDATE_PROFILE_PATH, PROPERTIES_PARAM_NAME + "=" + mapToJsonStr(params));
}
public String getUserIds() {
return request(USER_IDS_PATH);
}
public String getUserIds(final Map<String, String> params) {
return request(HttpMethodType.GET, USER_IDS_PATH, mapToParams(params));
}
///////////////////////////////////////////////////////////////
// Kakao Story
///////////////////////////////////////////////////////////////
public String isStoryUser() {
return request(STORY_ISSTORYUSER_PATH);
}
public String storyProfile() {
return request(STORY_PROFILE_PATH);
}
public String postNote(final Map<String, String> params) {
return request(HttpMethodType.POST, STORY_POST_NOTE_PATH, mapToParams(params));
}
public String postLink(final Map<String, String> params) {
return request(HttpMethodType.POST, STORY_POST_LINK_PATH, mapToParams(params));
}
public String postPhoto(final Map<String, String> params) {
return request(HttpMethodType.POST, STORY_POST_PHOTO_PATH, mapToParams(params));
}
public String getMyStory(final Map<String, String> params) {
return request(HttpMethodType.GET, STORY_MYSTORY_PATH, mapToParams(params));
}
public String getMyStories() {
return request(STORY_MYSTORIES_PATH);
}
public String getMyStories(final Map<String, String> params) {
return request(HttpMethodType.GET, STORY_MYSTORIES_PATH, mapToParams(params));
}
public String deleteMyStory(final String id) {
return request(HttpMethodType.DELETE, STORY_DELETE_MYSTORY_PATH, "?id=" + id);
}
public String deleteMyStory(final Map<String, String> params) {
return request(HttpMethodType.DELETE, STORY_DELETE_MYSTORY_PATH, mapToParams(params));
}
public String getLinkInfo(String url) {
return request(HttpMethodType.GET, STORY_LINKINFO_PATH, "?url=" + url);
}
public String uploadMulti(File[] files) {
if (files.length == 0)
return null;
String CRLF = "\r\n";
String TWO_HYPHENS = "--";
String BOUNDARY = "---------------------------012345678901234567890123456";
HttpsURLConnection conn = null;
DataOutputStream dos = null;
FileInputStream fis = null;
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
// Request
try {
URL url = new URL(API_SERVER_HOST + STORY_UPLOAD_MULTI_PATH);
conn = (HttpsURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Cache-Control", "no-cache");
dos = new DataOutputStream(conn.getOutputStream());
for (File f : files) {
dos.writeBytes(TWO_HYPHENS + BOUNDARY + CRLF);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";" + " filename=\"" + f.getName() + "\"" + CRLF);
dos.writeBytes(CRLF);
fis = new FileInputStream(f);
bytesAvailable = fis.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fis.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fis.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fis.read(buffer, 0, bufferSize);
}
dos.writeBytes(CRLF);
}
// finish delimiter
dos.writeBytes(TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + CRLF);
fis.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (dos != null) try { dos.close(); } catch (IOException ignore) {}
if (fis != null) try { fis.close(); } catch (IOException ignore) {} }
// Response
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = new BufferedInputStream(conn.getInputStream());
reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line).append("\n");
}
reader.close();
return builder.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException ignore) {}
}
if (inputStream != null) {
try { inputStream.close(); } catch (IOException ignore) {}
}
conn.disconnect();
}
return null;
}
///////////////////////////////////////////////////////////////
// Kakao Talk
///////////////////////////////////////////////////////////////
public String talkProfile() {
return request(TALK_PROFILE_PATH);
}
///////////////////////////////////////////////////////////////
// Push Notification
///////////////////////////////////////////////////////////////
public String registerPush(final Map<String, String> params) {
return request(HttpMethodType.POST, PUSH_REGISTER_PATH, mapToParams(params));
}
public String getPushTokens(final Map<String, String> params) {
return request(HttpMethodType.GET, PUSH_TOKENS_PATH, mapToParams(params));
}
public String deregisterPush(final Map<String, String> params) {
return request(HttpMethodType.POST, PUSH_DEREGISTER_PATH, mapToParams(params));
}
public String sendPush(final Map<String, String> params) {
return request(HttpMethodType.POST, PUSH_SEND_PATH, mapToParams(params));
}
public String request(final String apiPath) {
return request(HttpMethodType.GET, apiPath, null);
}
public String request(final HttpMethodType httpMethod, final String apiPath) {
return request(httpMethod, apiPath, null);
}
public String request(HttpMethodType httpMethod, final String apiPath, final String params) {
String requestUrl = API_SERVER_HOST + apiPath;
if (httpMethod == null) {
httpMethod = HttpMethodType.GET;
}
if (params != null && params.length() > 0
&& (httpMethod == HttpMethodType.GET || httpMethod == HttpMethodType.DELETE)) {
requestUrl += params;
}
HttpsURLConnection conn;
OutputStreamWriter writer = null;
BufferedReader reader = null;
InputStreamReader isr = null;
try {
final URL url = new URL(requestUrl);
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod(httpMethod.toString());
if (adminApiPaths.contains(apiPath)) {
conn.setRequestProperty("Authorization", "KakaoAK " + this.adminKey);
} else {
conn.setRequestProperty("Authorization", "Bearer " + this.accessToken);
}
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "utf-8");
if (params != null && params.length() > 0 && httpMethod == HttpMethodType.POST) {
conn.setDoOutput(true);
writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(params);
writer.flush();
}
final int responseCode = conn.getResponseCode();
System.out.println(String.format("\nSending '%s' request to URL : %s", httpMethod, requestUrl));
System.out.println("Response Code : " + responseCode);
if (responseCode == 200)
isr = new InputStreamReader(conn.getInputStream());
else
isr = new InputStreamReader(conn.getErrorStream());
reader = new BufferedReader(isr);
final StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
System.out.println(buffer.toString());
return buffer.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) try { writer.close(); } catch (Exception ignore) { }
if (reader != null) try { reader.close(); } catch (Exception ignore) { }
if (isr != null) try { isr.close(); } catch (Exception ignore) { }
}
return null;
}
public String urlEncodeUTF8(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
public String mapToParams(Map<String, String > map) {
StringBuilder paramBuilder = new StringBuilder();
for (String key : map.keySet()) {
paramBuilder.append(paramBuilder.length() > 0 ? "&" : "");
paramBuilder.append(String.format("%s=%s", urlEncodeUTF8(key),
urlEncodeUTF8(map.get(key).toString())));
}
return paramBuilder.toString();
}
public String mapToJsonStr(Map<String, String > map) {
return JACKSON_OBJECT_MAPPER.writeValueAsString(map);
// return GSON.toJson(map);
}
}
위의 Helper Class에 대한 Test Code
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* SDK를 통해 받은 access token을 지정하시면
* REST API를 테스트해 보실 수 있는 샘플입니다.
* 푸시 알림 관련 API를 테스트하시려면 admin key 지정해야 합니다.
*/
public class Main {
private static KakaoRestApiHelper apiHelper = new KakaoRestApiHelper();
public static void main(String[] args) throws InterruptedException {
new Main().test();
}
/**
* 테스트가 필요한 api 블럭만 주석을 풀고 테스트하세요.
*/
public void test() {
// access token 지정
apiHelper.setAccessToken("[YOUR APP KEY]");
// 푸시 알림이나 유저 아이디 리스트가 필요할 때 설정 합니다.
// (디벨로퍼스 내에 앱설정 메뉴를 가시면 있습니다)
apiHelper.setAdminKey("[YOUR ADMIN KEY]");
testUserManagement();
testKakaoStory();
testKakaoTalk();
testPush();
}
public void testUserManagement() {
Map<String, String> paramMap;
/*
// 앱 사용자 정보 요청 (signup 후에 사용 가능)
apiHelper.me();
*/
// 앱 연결
// apiHelper.signup();
/*
// 앱 연결(파라미터)
paramMap = new HashMap<String, String>();
paramMap.put("properties", "{\"nickname\":\"test\"}");
apiHelper.signup(paramMap);
*/
// 앱 탈퇴
//apiHelper.unlink();
// 앱 로그아웃
//apiHelper.logout();
/*
// 앱 사용자 정보 업데이트
paramMap = new HashMap<String, String>();
paramMap.put("properties", "{\"nickname\":\"test\"}");
apiHelper.updatProfile(paramMap);
*/
// 앱 사용자 리스트 요청
//apiHelper.getUserIds();
/*
// 앱 사용자 리스트 요청 (파라미터)
paramMap = new HashMap<String, String>();
paramMap.put("limit", "100");
paramMap.put("fromId", "1");
paramMap.put("order", "asc");
apiHelper.getUserIds(paramMap);
*/
}
public void testKakaoStory() {
final String TEST_MYSTORY_ID = "[TEST MY STORY ID]";
final String TEST_SCRAP_URL = "https://developers.kakao.com";
// on Linux or Mac
final File TEST_UPLOAD_FILE1 = new File("/xxx/sample1.png");
final File TEST_UPLOAD_FILE2 = new File("/xxx/sample2.png");
// on windows
// final File TEST_UPLOAD_FILE = new File("C:\\~~/sample.png");
Map<String, String> paramMap;
/*
// 스토리 프로파일 요청
apiHelper.storyProfile();
*/
/*
// 스토리 유저인지 확인
apiHelper.isStoryUser();
*/
/*
// 복수개의 내스토리 정보 요청
// https://dev.kakao.com/docs/restapi#복수개의-내스토리-정보-요청
apiHelper.getMyStories();
*/
/*
// 복수개의 내스토리 정보 요청 (특정 아이디 부터)
paramMap = new HashMap<String, String>();
paramMap.put("last_id", TEST_MYSTORY_ID);
apiHelper.getMyStories(paramMap);
*/
/*
// 내스토리 정보 요청
// https://dev.kakao.com/docs/restapi#카카오스토리-내스토리-정보-요청
paramMap = new HashMap<String, String>();
paramMap.put("id", TEST_MYSTORY_ID);
apiHelper.getMyStory(paramMap);
*/
// 내스토리 삭제
// paramMap = new HashMap<String, String>();
// paramMap.put("id", TEST_MYSTORY_ID);
// apiHelper.deleteMyStory(paramMap);
// 스토리 포스팅 공통 파라미터. 필요한 것만 선택하여 사용.
paramMap = new HashMap<String, String>();
paramMap.put("permission", "A"); // A : 전체공개, F: 친구에게만 공개, M: 나만보기
paramMap.put("enable_share", "false"); // 공개 기능 허용 여부
paramMap.put("android_exec_param", "cafe_id=1234"); // 앱 이동시 추가 파라미터
paramMap.put("ios_exec_param", "cafe_id=1234");
paramMap.put("android_market_param", "cafe_id=1234");
paramMap.put("ios_market_param", "cafe_id=1234");
// 글 포스팅일 경우에는 content는 필수지만 링크/사진 포스팅일 때는 옵션.
paramMap.put("content", "더 나은 세상을 꿈꾸고 그것을 현실로 만드는 이를 위하여 카카오에서 앱 개발 플랫폼 서비스를 시작합니다.");
String result;
/*
// 글 포스팅
result = apiHelper.postNote(paramMap);
if (result != null && result.indexOf("code\":-") == -1) {
String postedId = result.split("\"")[3];
System.out.println("postedId:" + postedId);
if (apiHelper.deleteMyStory(postedId).equals(""))
System.out.println("deleted test my story " + postedId);
}
*/
/*
// 사진 포스팅 (최대 10개까지 가능)
String uploadedImageObj = apiHelper.uploadMulti(
new File[]{
TEST_UPLOAD_FILE1,
TEST_UPLOAD_FILE2
});
if (uploadedImageObj != null) {
System.out.println("uploaded file(s) successfully.");
System.out.println(uploadedImageObj);
paramMap.put("image_url_list", uploadedImageObj);
result = apiHelper.postPhoto(paramMap);
if (result != null && result.indexOf("code\":-") == -1) {
String postedId = result.split("\"")[3];
System.out.println("postedId:" + postedId);
if (apiHelper.deleteMyStory(postedId).equals(""))
System.out.println("deleted test my story " + postedId);
}
} else {
System.out.println("failed to upload");
}
*/
/*
// 링크 포스팅
final String linkInfoObj = apiHelper.getLinkInfo(TEST_SCRAP_URL);
if (linkInfoObj != null) {
paramMap.put("link_info", linkInfoObj);
result = apiHelper.postLink(paramMap);
if (result != null && result.indexOf("code\":-") == -1) {
String postedId = result.split("\"")[3];
System.out.println("postedId:" + postedId);
if (apiHelper.deleteMyStory(postedId).equals(""))
System.out.println("deleted test my story " + postedId);
}
}
*/
}
public void testKakaoTalk() {
// 카카오톡 프로필 요청
apiHelper.talkProfile();
}
public void testPush() {
Map<String, String> paramMap;
// 파라미터 설명
// @param uuid 사용자의 고유 ID. 1~(2^63 -1), 숫자가만 가능
// @param push_type gcm or apns
// @param push_token apns(64자) or GCM으로부터 발급받은 push token
// @param uuids 기기의 고유한 ID 리스트 (최대 100개까지 가능)
// 푸시 알림 관련 API를 테스트하시려면 admin key 지정해야 합니다.
/*
// 푸시 등록
paramMap = new HashMap<String, String>();
paramMap.put("uuid", "10000");
paramMap.put("push_type", "gcm");
paramMap.put("push_token", "xxxxxxxxxx");
paramMap.put("device_id", "");
apiHelper.registerPush(paramMap);
*/
/*
// 푸시 토큰 조회
paramMap = new HashMap<String, String>();
paramMap.put("uuid", "10000");
apiHelper.getPushTokens(paramMap);
*/
/*
// 푸시 해제
paramMap = new HashMap<String, String>();
paramMap.put("uuid", "10000");
paramMap.put("push_type", "gcm");
paramMap.put("push_token", "xxxxxxxxxx");
apiHelper.deregisterPush(paramMap);
*/
/*
// 푸시 보내기
paramMap = new HashMap<String, String>();
paramMap.put("uuids", "[\"1\",\"2\", \"3\"]");
apiHelper.sendPush(paramMap);
*/
}
}