2014年11月5日 星期三

Google Calendar V3

申請google calendar API V3

Google calendar v2版本快要關閉,所以開始研究v3版本,遇到很多困難,希望寫下相關文件有助於相關的朋友解決困難

選擇左方選單 Your First APPàConfigure Your APP





根據以上的做法,需要先至Google Developers Console 先建立project後,再點選APIs & auth建立新的 Client ID, 但是new Client ID的認證方式有以下, 請選擇其中一種



一、單人登入模式


會產生三個碼(ClientID, Client Secret, Redirect URIS) ,根據GOOGLE官方說法,它會採用Oauth2.0二皆段認證方式,原本v2版本需要(gmailAccount, password)即可針對此人的calendar進行CRUD事件控制,然而V3版本的應用程式,要求使用者同意存取權限後,才能進行使用者的Google Calendar CRUD控制。

※程式範例
    UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
               new ClientSecrets
               {
                   //請依照申請的client Ikey填寫
                   ClientId = "xxxxxx-km3rffkv4qaj1ljva3aub8s95mig4ama.apps.googleusercontent.com",                 
                   ClientSecret = "fpJhDvGXxBCfMOdfgtN3Sceg",
               },
               new[] { CalendarService.Scope.Calendar },
               "user",
               CancellationToken.None).Result;
               CalendarService _service = new CalendarService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "API Project"//請依照的創建的ProjectID Name填寫
                });

為了讓通過認證的資料儲存下來,可使用FileDataStore 把資訊儲存本地端電腦,下次不需重新認證,如果有多人帳號,也可使用此方式儲存。

credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                new ClientSecrets
                {
                    ClientId = "xxxxxxxxxxxxxxx.apps.googleusercontent.com",
                    ClientSecret = "xxxxxxxx3mEz81u51Axlp",
                },
               new[] { CalendarService.Scope.Calendar },
               strUser, //gmail 帳號
 CancellationToken.None, new FileDataStore("Calendar.Auth.Store")
).Result;

FileDataStore : 是將認證資料Token Reflash Token資料以JSON格式,儲存電腦中

請參考:


二、domain 認證模式

根據官方的說法,需要在同一domain下,只提供mail帳號,可以直接對此人的calendar 進行CRUD動作而不再取得登入者授權, 所以要開通Service Account

l   先申請公司domain gmail  ex: some@compute.com.tw (PS: 需要向DNS註冊)
l   再到Google Developers Console 新增Service Account 


產生一組金鑰和私鑰和ClientID, ServiceAccount

l   功能表中點選管理員: ps: 需要有管理員的權限才允許登入




l   選擇安全性(Security)à顯示更多àAdvanced Setting


l   右邊選單中àManage API Client access


Client Name: 輸入在Google Developers Console 申請service Account client ID
One or More API Scopes : 輸入 https://www.googleapis.com/auth/calendar (google 稱為API scope)

點選 Authorize 即可加入寫入calendar的權限


 ※程式範例
var certificate = new X509Certificate2(@"Coooper-d3d1343328a5.p12", "notasecret", X509KeyStorageFlags.Exportable); //將私鑰憑證輸入

  ServiceAccountCredential credential = new ServiceAccountCredential(new
   ServiceAccountCredential.Initializer(serviceAccountEmail) //依申請ServiceAccountmail 填入
                {
                    Scopes =
                        new[] { CalendarService.Scope.Calendar },
                    User = strUserGmailAccount
                }.FromCertificate
                (certificate));

                BaseClientService.Initializer initializer = new
                BaseClientService.Initializer();
                initializer.HttpClientInitializer = credential;
                initializer.ApplicationName = "Coooper";
                calservice = new CalendarService(initializer);



※程式範例
   
   public class googleCalendarTaken :IgoogleCalendarHelp
    {
        public CalendarService _service;       
        public googleCalendarTaken(string strGmailAccount)
        {
            startBuild(strGmailAccount);
        }

        public void startBuild(string strUser)
        {         
            UserCredential credential;
            try
            {
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                new ClientSecrets
                {
                    ClientId = "xxxxx",
                    ClientSecret = "xxxx",
                },
               new[] { CalendarService.Scope.Calendar },
               strUser, CancellationToken.None, new FileDataStore("Calendar.Auth.Store")).Result;
                BaseClientService.Initializer initializer = new BaseClientService.Initializer();
                initializer.HttpClientInitializer = credential;
                initializer.ApplicationName = "Cooper"; //申請API Project Name                  
                _service = new CalendarService(initializer);
            }
            catch (Exception ex)
            {              
                var st = new StackTrace(ex, true);
                var frame = st.GetFrame(0);
                var line = frame.GetFileLineNumber();
                throw new Exception("startBuild 失敗"+line.ToString() +"行號 " + ex.Message+"行數:"+ strTestLine);
            }
        }

        public bool addEvent(viewCalendar viewCalendarObj)
        {
            try
            {            
                Event eventGoogle = new Event()
                {
                    Kind = "calendar#event",
                    Id = viewCalendarObj.strEventID,
                    Summary = viewCalendarObj.strSummary,
                    Location = viewCalendarObj.strLocation,
                    Description = viewCalendarObj.strDesc,                   
                    Start = new EventDateTime()
                    {
                        DateTime = viewCalendarObj.timeStart,
                    },

                    End = new EventDateTime()
                    {
                        DateTime = viewCalendarObj.timeEnd,
                    },                  
                };

                _service.Events.Insert(eventGoogle, "primary").Execute(); 
                Event googleEventObj = getEvent(viewCalendarObj.strEventID);               
                if (googleEventObj != null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("addEvent  新增事件失敗:" + ex.Message);
            }
        }

        /// <summary>
        /// 刪除google 行事曆事件
        /// </summary>
        /// <param name="strCalendarID">google 行事曆的名稱</param>
        /// <param name="strEventID">google calendar's id</param>
        public bool deleteEvent(string strEventID)
        {
            try
            {
                _service.Events.Delete("primary", strEventID).Execute();
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception("deleteEvent 刪除失敗" + ex.Message);
            }
        }

        /// <summary>
        /// 更新行事曆
        /// </summary>
        /// <param name="strEventID"></param>
        /// <param name="viewCalendarObj"></param>
        /// <returns></returns>
        public bool updateEvent(viewCalendar viewCalendarObj)
        {
            try
            {           
                // First retrieve the event from the API.
                Event googleEventObj = _service.Events.Get("primary", viewCalendarObj.strEventID).Execute();

                if (!string.IsNullOrEmpty(viewCalendarObj.strSummary))
                    googleEventObj.Summary = viewCalendarObj.strSummary;

                if (!string.IsNullOrEmpty(viewCalendarObj.strLocation))
                    googleEventObj.Location = viewCalendarObj.strLocation;

                if (!string.IsNullOrEmpty(viewCalendarObj.strDesc))
                    googleEventObj.Description = viewCalendarObj.strDesc;

                if (viewCalendarObj.timeStart != null)
                {
                    googleEventObj.Start = new EventDateTime()
                    {
                        DateTime = viewCalendarObj.timeStart
                    };
                }

                if (viewCalendarObj.timeEnd != null)
                {
                    googleEventObj.End = new EventDateTime()
                    {
                        DateTime = viewCalendarObj.timeEnd
                    };
                }

                googleEventObj.Status = "confirmed"; //即使已刪除,也會回復原本狀態               
                Event updatedEvent = _service.Events.Update(googleEventObj, "primary", googleEventObj.Id).Execute();

                //比對所有資料是否一致,才代表更改成功
                Event confirmEventObj = getEvent(viewCalendarObj.strEventID);
                if ((confirmEventObj.Start.DateTime == googleEventObj.Start.DateTime)
                    && (confirmEventObj.End.DateTime == googleEventObj.End.DateTime)
                    && (confirmEventObj.Summary == googleEventObj.Summary)
                    && (confirmEventObj.Location == googleEventObj.Location)
                    && (confirmEventObj.Description == googleEventObj.Description) )
                {
                    return true;
                }else
                {
                    return false;
                }               
            }
            catch (Exception ex)
            {
                throw new Exception("updateEvent: 更新失敗 " + ex.Message);
            }
        }
        public Event getEvent(string strEventID)
        {
            try
            {
                 Event eventObj= _service.Events.Get("primary", strEventID).Execute();
                 return eventObj;
            }
            catch (Exception ex)
            {
                return null;
            }
        }




















2 則留言:

  1. viewCalendar 是自已建立的物件,屬性型態也都自訂的

    回覆刪除
  2. 您好,我建立了一組service account要來顯示同網域下使用者的日曆,請問現在還是得再透過G-Suite管理API Access才行嗎?不能直接用service account透過憑證存取使用者的日曆?

    回覆刪除