개발언어/JAVA

Google Calender API 써보기

1동민1 2022. 1. 6. 15:55
반응형

구글 캘린더 api 데이터를 가져오기를 하기위해 열심히 서칭하여 구글 라이브러리를 호출하여 사용하는 샘플들을 사용하였으나, 내 프로젝트에서는 이상하게도 라이브러리를 사용하면 에러만 발생되어 js로 url 호출하는 방식으로 로그인부터 다시 만들게 되었다. OAuth 설정하는 부분은 https://sizin.tistory.com/105 이곳을 참고하면 될것같다.

 

js부분에 아래와 같이 GoogleLogin()이라는 함수를 만들었다.

function GoogleLogin() {
    	var url = "https://accounts.google.com/o/oauth2/auth?" +
		"client_id=12345abcde.apps.googleusercontent.com&" +
		"redirect_uri=http://localhost:8080/redirect.do&" +
		"response_type=code&" +
		"scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.events%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&" +
		"approval_prompt=force&" +
		"access_type=offline";
    	window.open(url, "self");
    }

GoogleLogin() 함수에서 client_id 값에 https://console.cloud.google.com/ 에서 등록된 OAuth 2.0 클라이언트 ID의

클라이언트 ID 값을 복사하여 넣고 redirect_uri는 로그인 된 후 호출하는 페이지로,

아래 캡쳐처럼 OAuth 2.0 클라이언트에서 승인된 리디렉션 URI에 호출할 컨트롤러명을 넣고 저장한다.

구글 Oauth에서 로그인 후 호출할 페이지 설정

CalendarController.java / redirect.do 구현

@RequestMapping(value="/redirect.do", method=RequestMethod.GET, produces=APPLICATION_JSON)
	public @ResponseBody void redirect(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		String code = request.getParameter("code");
		System.out.println("code값 : " + code);
		String query = "code=" + code;
		query += "&client_id=" + "1234abcde.apps.googleusercontent.com";
		query += "&client_secret=" + "시크릿키";
		query += "&redirect_uri=" + "http://localhost:8080/redirect.do";
		query += "&grant_type=authorization_code";
		String tokenJson = postHttpConnection("https://accounts.google.com/o/oauth2/token", query);
		System.out.println("jsondata값 : " + tokenJson.toString());
		
		Gson gson = new Gson();
		Token token = gson.fromJson(tokenJson, Token.class); //vo로 저장
		Map<String, Object> regiToken = new HashMap<String, Object>();
		regiToken.put("acToken", token.getAccess_token());
		regiToken.put("rfToken", token.getRefresh_token());
		calendarService.updateCalToken(setToken);
	}

구글 Oauth 클라이언트 ID와 시크릿키

post 요청 메서드

private String postHttpConnection(String uri, String param) throws ServletException, IOException {
		URL url = new URL(uri);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setRequestMethod("POST");
		conn.setDoOutput(true);
		try (OutputStream stream = conn.getOutputStream()) {
			try (BufferedWriter wd = new BufferedWriter(new OutputStreamWriter(stream))) {
				wd.write(param);
			}
		}
		int responseCode = conn.getResponseCode();
		System.out.println(responseCode);
		String line;
		StringBuffer buffer = new StringBuffer();
		try (InputStream stream = conn.getInputStream()) {
			try (BufferedReader rd = new BufferedReader(new InputStreamReader(stream))) {
				while ((line = rd.readLine()) != null) {
					buffer.append(line);
					buffer.append('\r');
				}
			}
		} catch (Throwable e) {
			//e.printStackTrace();
			return Integer.toString(responseCode);
		}
		return buffer.toString();
	}

Token.java

@Getter
@Setter
@Alias("Token")
public class Token {
	private String access_token;
	private int expires_in;
	private String refresh_token;
	private String scope;
	private String token_type;
	private String id_token;
}

컨트롤러와 토큰vo 추가 후 구글로그인 함수를 호출하게 되면

로그인이 완료 된 후 access_token 값과 refresh_token 값을 map형태로 CalendarService로 DB에 저장하게 된다.

서비스 부분은 mybatis를 사용하여 로컬DB와 연동되게 직접 만들면 된다.

 

refresh_token은 access_token 값이 만료된 경우 access_token을 다시 구글쪽에 요청하여 받아오는 역할을 한다.

 

refresh_token으로 access_token을 재요청하여 DB에 저장하는 소스

String query = "client_id=" + "1245abcdef.apps.googleusercontent.com";
	query += "&client_secret=" + "시크릿 키값";
	query += "&refresh_token=" + "DB에 저장된 리플레시 토큰값";
	query += "&grant_type=" + "refresh_token";
String tokenJson = postHttpConnection("https://oauth2.googleapis.com/token", query);
Gson gson = new Gson();
Token token = gson.fromJson(tokenJson, Token.class);
Map<String, Object> updateToken = new HashMap<String, Object>();
updateToken.put("acToken", token.getAccess_token());
calendarService.updateCalToken(updateToken);

구글 캘린더에서 일정을 가져오기 전에 먼저 어떤 캘린더에서 가져와야 하므로

캘린더 목록을 호출하여 선택 하는 과정을 거쳐야 한다. 

 

DB에서 가져온 엑세스 토큰으로 GET요청을 하는 과정

String ac_Token = calendarService.getCalToken();
String returnJson = getHttpConnection("https://www.googleapis.com/calendar/v3/users/me/calendarList?access_token=" + ac_Token);
if(returnJson.equals("401") || returnJson.equals("404")){ //토큰 만료시 에러 발생
	throw new NullPointerException();
}

JSONObject jObject;
jObject = new JSONObject(returnJson);
Map<String, Object> addData;
List<Object> addDataList = new ArrayList<Object>();
JSONArray jArray = jObject.getJSONArray("items");
for(int i = 0; i < jArray.length();i++){
	addData = new HashMap<String, Object>();
	jObject = jArray.getJSONObject(i);
	addData.put("id", jObject.getString("id"));
	addData.put("summary", jObject.getString("summary"));
	addDataList.add(addData);
}
result.put("list", addDataList);

필자는 json파싱된 캘린더의 고유 id값과 제목을 리스트에 담아서 프론트쪽에 리턴하여 사용하였다.

id값과 제목을 콤보박스로 선택하여 값을 넘기는 js는 생략하겠다. 

 

토큰을 받아서 GET요청을 하는 메서드

private String getHttpConnection(String uri, String token) throws ServletException, IOException {
		URL url = new URL(uri);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setRequestProperty("Authorization", "Bearer " + token);
		conn.setRequestProperty("Accept", "application/json");	 
		int responseCode = conn.getResponseCode();
		String line;
		StringBuffer buffer = new StringBuffer();
		try (InputStream stream = conn.getInputStream()) {
			try (BufferedReader rd = new BufferedReader(new InputStreamReader(stream, "UTF-8"))) {
				while ((line = rd.readLine()) != null) {
					buffer.append(line);
					buffer.append('\r');
				}
			}
		} catch (Throwable e) {
			//e.printStackTrace();
			return Integer.toString(responseCode);
		}
		return buffer.toString();
	}

HttpsURLConnection의 setRequestProperty() 함수로 헤더에 베어러 토큰값을 넣어주는게 핵심이다.

 

콤보박스에 캘린더 목록들을 넣는 js

var selectBox = $("select[name='calendarList']");
    	$.ajax({
            type: "POST",
            url: "/GetCalendarList.do",
    		async : false,
    		contentType : false,
    		processData : false, 
    		dataType : "json",
            success: function (res) {
            	console.log("return map data = " + JSON.stringify(res.list));
            	$.each(res.list, function(idx, val) {
    	        selectBox.append("<option value=" + val.id + ">" + val.summary + "</option>");
    	        //console.log("id값 : " + val.id + "/ 캘린더 이름 : " + val.summary);
    	        });
             }
        });

js까지 만들어서 호출하게 되면 화면단의 calendarList라는 콤보박스에 캘린더 목록들이 들어가는걸 확인할 수 있다.

 

이제 동작안하는 구글 라이브러리 없이 캘린더 id값으로 캘린더에 일정 내보내기, 가져오기 등을 사용할 수 있게 되었다.

반응형