I'm trying to create the Google Calendar event with the conference(Google Meet) using Java SDK V3. The event is getting created but the conference details are not being set. Not sure what's missing
Create request:
Calendar service = new Calendar
.Builder(GoogleNetHttpTransport.newTrustedTransport(),
getDefaultInstance(),
new HttpCredentialsAdapter(googleCalendarCredentials()))
.setApplicationName(APPLICATION_NAME)
.build();
Event event = new Event();
event.setStart(new EventDateTime().setDateTime(new DateTime(currentTimeMillis())));
event.setEnd(new EventDateTime().setDateTime(new DateTime(currentTimeMillis() + 10000000)));
ConferenceData conferenceData = new ConferenceData();
conferenceData.setCreateRequest(
new CreateConferenceRequest()
.setConferenceSolutionKey(
new ConferenceSolutionKey()
.setType("hangoutsMeet")));
event.setConferenceData(conferenceData);
service.events().insert("primary", event).execute();
Get Request:
Events events = service.events()
.list("primary")
.execute();
List<Event> items = events.getItems();
if (items.isEmpty()) {
System.out.println("No upcoming events found.");
} else {
System.out.println("Upcoming events");
for (Event eventRs : items) {
System.out.printf("%s\n", eventRs.getConferenceData().getConferenceId());
}
}
Getting eventRs.getConferenceData() as null.
If you check the documentaiton on Event.insert you will see that you need to set the option parameter conferenceDataVersion inorder to enable it to set the conference data.
Version 0 assumes no conference data support and ignores conference data in the event's body. Version 1 enables support for copying of ConferenceData
Related
I have a requirement of creating a google calendar event on a calendar and add other users as attendees to that event. The objective is to send calendar events to the application users without taking their consent ( O-Auth ).
After reading Google's documentation, I found out that I need a service account. So I created a project and a service account from one of the email addresses of our G-Suite, noreply#xxxxx.com and enabled calendar API for the same.
I created and downloaded a key pair ( JSON ) whose content is,
{
"type": "service_account",
"project_id": "*****",
"private_key_id": "bdbbcd**************49f77d599f2",
"private_key": "**"
"client_email": "******#*****.iam.gserviceaccount.com",
"client_id": "11083******576856",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/****dev%40*****kdev.iam.gserviceaccount.com"
}
And as per the documentation, I proceded to write authentication flow code,
public static GoogleCredential doOauth( String credsPath ) throws IOException
{
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(credsPath))
.createScoped(Collections.singleton(CalendarScopes.CALENDAR));
System.out.println(credential);
return credential;
}
The credential object has most of the details from the key file. But, the fields, serviceAccountUser, accessToken, refreshToken, clientAuthentication and requestInitializer have null value. ( I am guessing something wrong here )
Now, using the credentialObject, I continued to write the code as per the documentation to create the event.
GoogleCredential credential = doOauth(CREDENTIALS_FILE_PATH);
Event event = new Event().setSummary("Google I/O 2015").setLocation("800 Howard St., San Francisco, CA 94103")
.setDescription("A chance to hear more about Google's developer products.");
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DateTime startDateTime = new DateTime("2020-12-28T09:00:00-07:00");
EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2020-12-28T17:00:00-07:00");
EventDateTime end = new EventDateTime().setDateTime(endDateTime).setTimeZone("America/Los_Angeles");
event.setEnd(end);
String[] recurrence = new String[] { "RRULE:FREQ=DAILY;COUNT=2" };
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] { new EventAttendee().setEmail("myemailaddress#gmail.com.com") };
event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] {
new EventReminder().setMethod("email").setMinutes(24 * 60),
new EventReminder().setMethod("popup").setMinutes(10), };
Event.Reminders reminders = new Event.Reminders().setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
String calendarId = "primary";
Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("testapp").build();
event = service.events().insert(calendarId, event).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink());
But, this resulted in the error,
{
"code" : 403,
"errors" : [ {
"domain" : "calendar",
"message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.",
"reason" : "forbiddenForServiceAccounts"
} ],
"message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority."
}
After spending time on Domain-Wide Delegation, I understood that this is needed if we have to send the event as other user from our g-suite, which is not needed for my problem. But, to debug, I went ahead and provided Domain-Wide Delegation and re ran the program. The same error came again.
So, I removed the invitees/attendees from the event object and re ran the application. This time the program ran without any error, but the event link generated, on click says, Could not find the requested event.
I do not see any examples of using the service account via java client libraries on the google developer link.
Can you please let me know what is going wrong here and the official/working documentation on how exactly to create a google calendar event from my project add other ( non g suite as well ) users to add as attendees, so that I do not have to get consent from other users to add events to their own calendar?
Thank You.
Fist off I want to say that this is something new, if you are seeing a lot of questions, and tutorials that did not state you needed to do this its because service accounts used to be able to send invites, this is something google locked down about a year ago.
This should work but i have not tested it as i no longer have access to a Gsuite account. You need to have the gsuite admin set up domain wide delegation to anther user. Then the service account needs to impersonate that user so it will appear as that user is the one sending the invites.
The only example I have for how that is added is in .net
.net example
var gsuiteUser = "se#clawskeyboard.com";
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(serviceAccount)
{
User = gsuiteUser,
Scopes = new[] { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels }
}.FromCertificate(certificate);
Java example guess
I am not a java dev but the .net client library and the Java client library are very close in how they were developed. I would guess that you are looking for a method called setServiceAccountUser
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(CalendarScopes.CALENDAR)
.setServiceAccountPrivateKeyFromP12File(credsPath))
.setServiceAccountUser(gsuiteUser)
.build();
OAuth2 for Service Accounts
You should be able to impersonate the account user by setting the delegated variable to the user's email in the GoogleCredential object.
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("credentials.json"))
.createScoped(<SCOPES>)
.createDelegated("user#example.com");
I am looking for a way to get a delta of Appointments. Basically what I want is to react on newly created Appointments.
To get newly created / unread messages there is a SearchFilter in the java ews api that I use. Unfortunately AppointmentSchema does not provide any fitting Enum for the filter.
new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
I get the Appointments like:
CalendarFolder calendarFolder = CalendarFolder.bind(service, WellKnownFolderName.Calendar, new PropertySet());
var result = calendarFolder.findAppointments(cView);
so back to my question. How can I notice if someone invited me to a new Appointment or an email with a new Appointment invitation?
I have already found a solution, luckily. MeetingRequest is the Item I am looking for.
FindItemsResults<Item> result = service.findItems(new FolderId(WellKnownFolderName.Inbox, new Mailbox(getCredentials())), getUnreadEmailFilter(), new ItemView(10));
result.forEach(n -> {
if (n instanceof MeetingRequest) {
System.out.println("New Appointment - MeetingRequest found!");
MeetingRequest req = (MeetingRequest) n;
req.accept(true);
}
}
I'm trying to set up a payment system with paypal for a site where the charging should not happen at payment confirmation time. I understand this is what the "CREATE" action type is for, you make the payment and then you use the execute payment to actually charge the account. Unfortunately, from what I'm seeing in the sandbox, the buyer gets charged immediately, and the execute payment returns a "paykey already used for a payment" error. The IPN notification similarly tells me the payment has already happened.
I'm currently using adaptive payments with 2 receivers. I'm sending the request from Java, using the code pasted below to get the paykey. Then I redirect the user to paypal and the payment is done (and charged).
Am I missing something?
List<PaymentReceiver> receiverList = setReceiversSingleProject(order);
Element root = new Element("PayRequest");
root.addNamespaceDeclaration("ns2", "http://svcs.paypal.com/types/ap");
// requestEnvelope and errorLanguage
Element requestEnvelopeElement = new Element("requestEnvelope");
Element errorLanguageElement = new Element("errorLanguage");
errorLanguageElement.appendChild(errorLanguage);
requestEnvelopeElement.appendChild(errorLanguageElement);
root.appendChild(requestEnvelopeElement);
// cancelUrl
Element cancelUrlElement = new Element("cancelUrl");
cancelUrlElement.appendChild(themeDisplay.getPortalURL()+"/basket");
root.appendChild(cancelUrlElement);
// actionType
Element actionTypeElement = new Element("actionType");
actionTypeElement.appendChild("CREATE");
root.appendChild(actionTypeElement);
// currencyCode
Element currencyCodeElement = new Element("currencyCode");
String projectCurrency = order.getMainProject().getCurrency();
Currency currency = CurrencyLocalServiceUtil.getCurrency(projectCurrency);
currencyCodeElement.appendChild(currency.getPaypalCode());
root.appendChild(currencyCodeElement);
// receiverList
Element receiverListElement = new Element("receiverList");
for (PaymentReceiver receiver : receiverList) {
Element receiverElement = new Element("receiver");
Element amountElement = new Element("amount");
amountElement.appendChild(String.valueOf(receiver.getAmount()));
Element emailElement = new Element("email");
emailElement.appendChild(receiver.getEmail());
Element primaryElement = new Element("primary");
primaryElement.appendChild(receiver.isPrimary()?"true":"false");
receiverElement.appendChild(amountElement);
receiverElement.appendChild(emailElement);
receiverElement.appendChild(primaryElement);
receiverListElement.appendChild(receiverElement);
}
root.appendChild(receiverListElement);
// returnUrl
Element returnUrlElement = new Element("returnUrl");
returnUrlElement.appendChild(returnURL);
root.appendChild(returnUrlElement);
// notifyUrl
Element notifyUrlElement = new Element("ipnNotificationUrl");
notifyUrlElement.appendChild(notifyURL);
root.appendChild(notifyUrlElement);
// Create document object
Document doc = new Document(root);
String result = doc.toXML();
return result;
I'm trying to connect to a calendar using the Java Google Calendar api. The java application uses a service account.
I've the following code:
java.io.File licenseFile = new java.io.File("39790cb51b361f51cab6940d165c6cda4dc60177-privatekey.p12");
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("xxx#developer.gserviceaccount.com")
.setServiceAccountUser(EMAIL_ADRESS)
.setServiceAccountScopes(CalendarScopes.CALENDAR)
.setServiceAccountPrivateKeyFromP12File(licenseFile)
.build();
client = new com.google.api.services.calendar.Calendar.Builder(
HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("Google Calendar Sync").build();
Calendar calendar = client.calendars().get(EMAIL_ADRESS).execute();
On the last line I get an IOException with the message:
ex = (com.google.api.client.auth.oauth2.TokenResponseException)
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad
Request { "error" : "access_denied" }
I dubble checked the values for the GoogleCredential object and they are correct.
I've also added https://www.google.com/calendar/feeds/, http://www.google.com/calendar/feeds/ in my domain console with the application id as client to authorize third party application access
Am I forgetting a step?
The api isn't finished yet. More specifically the service account part.
The calendar owner needs to give permission to the application to read/write the calendar in it's calendar settings. It's found in the sharing settings of the calendar, there you can add e-mail adresses of accounts and give them permission on your calendar.
So in this case I had to add: xxx#developer.gserviceaccount.com to the permission/share list of the calendars the application needed access to.
I also deleted another post that didn't full work because of the issue above. I'll undelete it since it contains some code fragments that may help other people in the future. But beaware of the permission issues and service accounts not supporting Google Calendar
I do:
List find = client.events().list(EMAIL_ADRESS);
DateTime timeMin = new DateTime(DateUtil.stringToDate("01/01/2013"));
DateTime timeMax = new DateTime(DateUtil.stringToDate("01/02/2013"));
find.setTimeMin(timeMin);
find.setTimeMax(timeMax);
try{
Events events = find.execute();
int i =0;
while (true) {
System.out.println("Page: "+(++i)+": "+events.getItems().size());
for (Event event : events.getItems()) {
System.out.println(event.getSummary());
}
String pageToken = events.getNextPageToken();
if (pageToken != null && !pageToken.isEmpty()) {
events = client.events().list(EMAIL_ADRESS).setPageToken(pageToken).execute();
} else {
break;
}
}
}catch(GoogleJsonResponseException e){
System.out.println(e.getMessage());
// e.printStackTrace();
}
I got it to work
I don't know why but I deleted the line
.setServiceAccountUser(EMAIL_ADRESS)
Also I added an extra url in the domain scope:
https://apps-apis.google.com/a/feeds/calendar/resource/#readonly
and deleted a link that wasn't working.
Finally I changed the applicationName in my client declaration to the same name as in the api console
client = new com.google.api.services.calendar.Calendar.Builder(
HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("HolidaySyncs").build();
After these steps it started to work.
Also note for future reference after I did this I had the following error:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "notFound",
"message": "Not Found"
}
],
"code": 404,
"message": "Not Found"
}
}
I solved this by changing for example:
Event result = client.events().insert(<EMAIL ADRESS>, event).execute();
to
Event result = client.events().insert("primary", event).execute();
First I tought there was something wrong with the google servers, but apparently it goes wrong when you try to link to a calendar ID. So linking to "primary" which is the primary calendar of an account works. But according to the documentation it should also work when you refer to a specific calendar ID, where the email address is the primary calendar. Probably a bug?
UPDATE: after these code correction I still had issues. Read the accepted answer for more information.
I have search all over, and I have found bits and pieces on adding events, for .net or php, but not java.
So how do you add events to a google calendar that was created by your program.
Heres what I have
I have is
CalendarEntry calendar, returned from when I created the calendar.
Entry entry, which is a valid event to be inserted in the calendar I created.
CalendarService service, which is a valid calendar service.
So based on the calendar variable, I want to generate a url to insert the event at, by calling
service.insert(url, entry);
I happened to find an answer from here http://www.danwalmsley.com/2008/09/23/free-sms-service-notifications-using-google-calendar/
String postUrlString = calendarEntry.getLink("alternate", "application/atom+xml").getHref();
Seems to work!
From the doc:
URL postURL = new URL("http://www.google.com/calendar/feeds/root#gmail.com/private/full");
CalendarEventEntry myEvent = new CalendarEventEntry();
//Set the title and description
myEvent.setTitle(new PlainTextConstruct("Pi Day Party"));
myEvent.setContent(new PlainTextConstruct("I am throwing a Pi Day Party!"));
//Create DateTime events and create a When object to hold them, then add
//the When event to the event
DateTime startTime = DateTime.parseDateTime("2007-03-14T15:00:00-08:00");
DateTime endTime = DateTime.parseDateTime("2007-03-14T17:00:00-08:00");
When eventTimes = new When();
eventTimes.setStartTime(startTime);
eventTimes.setEndTime(endTime);
myEvent.addTime(eventTimes);
// POST the request and receive the response:
CalendarEventEntry insertedEntry = myService.insert(postURL, myEvent);
And if you already have a CalendarEntry (not tested):
/* CalendarEntry calendar = ...; CalendarEventEntry myEvent = ... */
Service myService = calendar.getService();
myService.insert(new URL(calendar.getEditLink().getHref()), yourEvent)
You can use the Google's Data API for creating events. You can download the java library from here. The Developer's guide can help you get started with using the library.
Here the documentation on creating events: http://code.google.com/apis/calendar/data/2.0/developers_guide_java.html#CreatingEvents