我正在尝试连接到 Google 日历 API。我已按照 Google calendar quick start for Java
中的步骤操作 <块引用>{ "error" : "invalid_grant", "error_description" : "错误请求" }
你能建议如何调试吗?不幸的是,错误消息没有帮助,我已经尝试了我能找到的关于堆栈溢出或其他地方的这个特定错误的一切
每次我为不同的凭据获得相同的访问令牌时:
<块引用>访问令牌:{user=Class{accessToken=null, refreshToken="" expireTimeMilliseconds=null}}
代码:
public class CalendarServiceImpl implements CalendarService {
public static final String APPLICATION_NAME = "GoogleCalenderApi";
public static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
public static final String TOKENS_DIRECTORY_PATH = "/data.json";
public static final List<String> SCOPES = Collections.singletonList(CalendarScopes.CALENDAR);
public static final String CREDENTIALS_FILE_PATH = "/data.json";
public Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT, HttpServletRequest request)
throws IOException {
InputStream in = CalendarServiceImpl.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
log.info("Resource not found: " + CREDENTIALS_FILE_PATH);
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
System.out.println("Access token: " + flow.getCredentialDataStore());
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(80)
.build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
}
public void createCalendarEvent(String candidateMailId, String companyEmailId, DateTime fromTime, DateTime toTime,
String summary, String description, HttpServletRequest request)
throws GeneralSecurityException, IOException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Event event = new Event().setSummary(summary).setLocation("Test").setDescription(description);
EventDateTime start = new EventDateTime().setDateTime(fromTime).setTimeZone("Asia/Kolkata");
event.setStart(start);
EventDateTime end = new EventDateTime().setDateTime(toTime).setTimeZone("Asia/Kolkata");
event.setEnd(end);
String[] recurrence = new String[] { "RRULE:FREQ=DAILY" };
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] { new EventAttendee().setEmail(candidateMailId),
new EventAttendee().setEmail(companyEmailId) };
event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] { new EventReminder().setMethod("email").setMinutes(10),
new EventReminder().setMethod("popup").setMinutes(10), };
Event.Reminders reminders = new Event.Reminders().setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
// Build service account credential.
Credential credential = getCredentials(HTTP_TRANSPORT, request);
log.info("got credential:" + event);
Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
String calendarId = "primary";
try {
System.out.printf("Event started" + event);
event = service.events().insert(calendarId, event).setSendUpdates("all").execute();
} catch (IOException e) {
log.info("event IOException:" + e);
e.getMessage();
}
log.info("Event created:" + event.getHtmlLink());
}
}
答案 0 :(得分:0)
您似乎正在使用 AuthorizationCodeInstalledApp,因为它的统计数据是针对已安装的应用程序。对于 Web 应用程序,您需要使用 AuthorizationCodeFlow。
官方示例可以在这里找到 Web server application
public class CalendarServletSample extends AbstractAuthorizationCodeServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// do stuff
}
@Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
GenericUrl url = new GenericUrl(req.getRequestURL().toString());
url.setRawPath("/oauth2callback");
return url.build();
}
@Override
protected AuthorizationCodeFlow initializeFlow() throws IOException {
return new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(), JacksonFactory.getDefaultInstance(),
"[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
DATA_STORE_FACTORY).setAccessType("offline").build();
}
@Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
}
}
public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {
@Override
protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
throws ServletException, IOException {
resp.sendRedirect("/");
}
@Override
protected void onError(
HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
throws ServletException, IOException {
// handle error
}
@Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
GenericUrl url = new GenericUrl(req.getRequestURL().toString());
url.setRawPath("/oauth2callback");
return url.build();
}
@Override
protected AuthorizationCodeFlow initializeFlow() throws IOException {
return new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(), JacksonFactory.getDefaultInstance()
"[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
DATA_STORE_FACTORY).setAccessType("offline").build();
}
@Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
}
}
AuthorizationCodeFlow 在运行代码的机器上打开同意浏览器窗口。当您将某些内容作为网站运行时,它需要在客户端计算机上打开,以便用户可以看到。