From 17320e714b2feceee31655a17d272fa2016e1302 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Tue, 1 Oct 2019 20:32:14 +0000 Subject: [PATCH] --- source/Plugins/AyaNova.Plugin.QBOI/Util.cs | 240 +++++++++++++-------- 1 file changed, 155 insertions(+), 85 deletions(-) diff --git a/source/Plugins/AyaNova.Plugin.QBOI/Util.cs b/source/Plugins/AyaNova.Plugin.QBOI/Util.cs index 89c3b5c..2b7dc3b 100644 --- a/source/Plugins/AyaNova.Plugin.QBOI/Util.cs +++ b/source/Plugins/AyaNova.Plugin.QBOI/Util.cs @@ -128,14 +128,14 @@ namespace AyaNova.PlugIn.QBOI public static Dictionary QCompOtherPrefs = new Dictionary(); //whether the QB company supports inventory or not //In testing AU, CA, UK and US all support inventory if OfferingSku is "Quickbooks online plus" and not if any other value - // public static bool QBSupportsInventory = false; + // public static bool QBSupportsInventory = false; public static string QOfferingSku = ""; //case 1062 public static bool bMainWindowOpen = false; - + /// /// The official and unchanging integration ID for /// QBOI @@ -294,6 +294,12 @@ namespace AyaNova.PlugIn.QBOI const string KAT = "xZ\v\nQ\a(\fN\nX\0\a}\vO[\vZTV_\fWQ,\vV\v-"; const string KOACS = "Y?,V\f1^\0\r+\v!<0-1$\n7-9\fV\0?%#3"; + const string Q2_CLIENT_ID = "ABj70Wv5gDauFd9KgKFwuvpQjfzTwEgodEG8tnBbS8mSQhNrZJ"; + const string Q2_CLIENT_SECRET = "XUmJyvEcEuwQuyhARUAm0a8G3gzbEAeMiATCLyFZ"; + const string Q2_REDIRECT_URL = "https://qboauth.ayanova.com/redirect"; + const string Q2_ENVIRONMENT = "Sandbox"; + + //simple xor encryption private static string Ec(string text, string key) @@ -307,99 +313,163 @@ namespace AyaNova.PlugIn.QBOI } + //OAUTH 1.x code, unchanged. + + // static ServiceContext SC = null; + // static DesktopIppOAuth.OAuthConnector CN; + // //case 3671 + // //Modify the below code to instead work with a static tokens obtained from qBridge (just for initial testing) + ////then test that all ops work witha fresh company connection + // static public void StartAuthorization() + // { + // //case 3669 + // //https://help.developer.intuit.com/s/question/0D50f00005gFeqpCAC/how-do-i-suddenly-get-there-was-an-error-while-communicating-with-the-ids-server + // System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //Add this just to be sure to use TLS1.2 + + // //#if(DEBUG) + // // string KEY_APP_TOKEN_ENCRYPTED = Ec(KEY_APP_TOKEN, "Invoice"); + // // string KEY_O_AUTH_CONSUMER_ENCRYPTED = Ec(KEY_O_AUTH_CONSUMER, "Invoice"); + // // string KEY_O_AUTH_CONSUMER_SECRET_ENCRYPTED = Ec(KEY_O_AUTH_CONSUMER_SECRET, "Invoice"); + // //#endif + // SC = null; + // CN = new OAuthConnector(); + // CN.IppOAuthResultEvent += _authResultEvent; + // //CN.Connect(KEY_O_AUTH_CONSUMER, KEY_O_AUTH_CONSUMER_SECRET, "http://www.ayanova.com"); + // CN.Connect(Ec(KOAC, "Invoice"), Ec(KOACS, "Invoice"), "http://www.ayanova.com"); + + + // } + + static ServiceContext SC = null; - static DesktopIppOAuth.OAuthConnector CN; + //static DesktopIppOAuth.OAuthConnector CN; //case 3671 //Modify the below code to instead work with a static tokens obtained from qBridge (just for initial testing) - //then test that all ops work witha fresh company connection + //then test that all ops work witha fresh company connection static public void StartAuthorization() { + + Intuit.Ipp.OAuth2PlatformClient.OAuth2Client oac = new OAuth2Client(Q2_CLIENT_ID,Q2_CLIENT_SECRET,Q2_REDIRECT_URL, Q2_ENVIRONMENT); + //case 3669 //https://help.developer.intuit.com/s/question/0D50f00005gFeqpCAC/how-do-i-suddenly-get-there-was-an-error-while-communicating-with-the-ids-server System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //Add this just to be sure to use TLS1.2 - //#if(DEBUG) - // string KEY_APP_TOKEN_ENCRYPTED = Ec(KEY_APP_TOKEN, "Invoice"); - // string KEY_O_AUTH_CONSUMER_ENCRYPTED = Ec(KEY_O_AUTH_CONSUMER, "Invoice"); - // string KEY_O_AUTH_CONSUMER_SECRET_ENCRYPTED = Ec(KEY_O_AUTH_CONSUMER_SECRET, "Invoice"); - //#endif - SC = null; - CN = new OAuthConnector(); - CN.IppOAuthResultEvent += _authResultEvent; - //CN.Connect(KEY_O_AUTH_CONSUMER, KEY_O_AUTH_CONSUMER_SECRET, "http://www.ayanova.com"); - CN.Connect(Ec(KOAC, "Invoice"), Ec(KOACS, "Invoice"), "http://www.ayanova.com"); + string ACCESS_TOKEN = ""; + string REFRESH_TOKEN = ""; + string REALM_ID = ""; - - } + Intuit.Ipp.Security.OAuth2RequestValidator validator = new Intuit.Ipp.Security.OAuth2RequestValidator(ACCESS_TOKEN); + SC = new Intuit.Ipp.Core.ServiceContext(REALM_ID, Intuit.Ipp.Core.IntuitServicesType.QBO, validator); + SC.IppConfiguration.Logger.RequestLog.EnableRequestResponseLogging = true; + SC.IppConfiguration.Logger.RequestLog.ServiceRequestLoggingLocation = "c:\\temp\\qblogs\\"; - /// - /// Process auth event - /// - /// - /// - /// - /// - static void _authResultEvent( - string accessToken, - string accessTokenSecret, - string realmId, - string dataSource) - { - //Intuit.Ipp.Security.OAuthRequestValidator oauthValidator = - // new Intuit.Ipp.Security.OAuthRequestValidator( - // accessToken, - // accessTokenSecret, - // KEY_O_AUTH_CONSUMER, - // KEY_O_AUTH_CONSUMER_SECRET); + - Intuit.Ipp.Security.OAuthRequestValidator oauthValidator = - new Intuit.Ipp.Security.OAuthRequestValidator( - accessToken, - accessTokenSecret, - Ec(KOAC, "Invoice"), - Ec(KOACS, "Invoice")); + //' Common setting for both ServiceContexts: - SC = new ServiceContext(accessToken, realmId, IntuitServicesType.QBO, oauthValidator); + SC.IppConfiguration.MinorVersion.Qbo = "23"; - //TODO: set up a proper retry policy look into it - //https://developer.intuit.com/docs/0100_quickbooks_online/0400_tools/0005_sdks/0010.net_tools/0050_retries + SC.IppConfiguration.BaseUrl.Qbo = "https://sandbox-quickbooks.api.intuit.com/"; - //FOr now retry every 10 seconds for 3 times for total of a 30 seconds. -#if(!DEBUG) - //Can't do this because I lose the exception and the end user never sees it. - // SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Retry.IntuitRetryPolicy(3, new TimeSpan(0, 0, 10)); -#endif + //' Serialization Format Json or xml -#if(DEBUG) + SC.IppConfiguration.Message.Request.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json; - //DANGER DANGER!!! If a retry is specified then the only exception error seen during dev is BadRequest - //and not the actual error. - //Have a case on the go about it: - //https://help.developer.intuit.com/s/case/5000f00001Bu1umAAB + SC.IppConfiguration.Message.Response.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json; - //SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Retry.IntuitRetryPolicy(3, new TimeSpan(0, 0, 10)); - //SC.IppConfiguration.Logger.RequestLog.EnableRequestResponseLogging = true; - //SC.IppConfiguration.Logger.RequestLog.ServiceRequestLoggingLocation = @"C:\temp\QBOLOGS"; -#endif + - //Notify that we are authenticated - _AuthenticationCompleted = true; - //todo what happens if we don't login?? +//' Compression Format can be GZip or Deflate: - //test case 3515 - //System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //Add this just to be sure to use TLS1.2 + SC.IppConfiguration.Message.Request.CompressionFormat = Intuit.Ipp.Core.Configuration.CompressionFormat.GZip; - + SC.IppConfiguration.Message.Response.CompressionFormat = Intuit.Ipp.Core.Configuration.CompressionFormat.GZip; - //var result = string.Empty; - //using (var webClient = new System.Net.WebClient()) - //{ - // result = webClient.DownloadString("https://tlstest.intuit.com"); - //} + //' Retry 5 times at an interval of 1 Second if service fails. Note that RetryPolicy moved from Intuit.Ipp.Retry to Intuit.Ipp.Core. + +TimeSpan retryInterval = new TimeSpan(0, 0, 0, 1); + +SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Core.IntuitRetryPolicy(5, retryInterval); + + //' For data updates, create DataService: + + Intuit.Ipp.DataService.DataService loDataService = new Intuit.Ipp.DataService.DataService(SC); + _AuthenticationCompleted=true; } + + // + + + // /// + // /// Process auth event + // /// + // /// + // /// + // /// + // /// + // static void _authResultEvent( + // string accessToken, + // string accessTokenSecret, + // string realmId, + // string dataSource) + // { + // //Intuit.Ipp.Security.OAuthRequestValidator oauthValidator = + // // new Intuit.Ipp.Security.OAuthRequestValidator( + // // accessToken, + // // accessTokenSecret, + // // KEY_O_AUTH_CONSUMER, + // // KEY_O_AUTH_CONSUMER_SECRET); + + // Intuit.Ipp.Security.OAuthRequestValidator oauthValidator = + // new Intuit.Ipp.Security.OAuthRequestValidator( + // accessToken, + // accessTokenSecret, + // Ec(KOAC, "Invoice"), + // Ec(KOACS, "Invoice")); + + // SC = new ServiceContext(accessToken, realmId, IntuitServicesType.QBO, oauthValidator); + + // //TODO: set up a proper retry policy look into it + // //https://developer.intuit.com/docs/0100_quickbooks_online/0400_tools/0005_sdks/0010.net_tools/0050_retries + + // //FOr now retry every 10 seconds for 3 times for total of a 30 seconds. + //#if(!DEBUG) + // //Can't do this because I lose the exception and the end user never sees it. + // // SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Retry.IntuitRetryPolicy(3, new TimeSpan(0, 0, 10)); + //#endif + + //#if(DEBUG) + + // //DANGER DANGER!!! If a retry is specified then the only exception error seen during dev is BadRequest + // //and not the actual error. + // //Have a case on the go about it: + // //https://help.developer.intuit.com/s/case/5000f00001Bu1umAAB + + // //SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Retry.IntuitRetryPolicy(3, new TimeSpan(0, 0, 10)); + // //SC.IppConfiguration.Logger.RequestLog.EnableRequestResponseLogging = true; + // //SC.IppConfiguration.Logger.RequestLog.ServiceRequestLoggingLocation = @"C:\temp\QBOLOGS"; + //#endif + + // //Notify that we are authenticated + // _AuthenticationCompleted = true; + // //todo what happens if we don't login?? + + // //test case 3515 + // //System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //Add this just to be sure to use TLS1.2 + + + + // //var result = string.Empty; + // //using (var webClient = new System.Net.WebClient()) + // //{ + // // result = webClient.DownloadString("https://tlstest.intuit.com"); + // //} + + // } #endregion authentication #region Pre flight check @@ -748,13 +818,13 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 //case 3520 if (QCompOtherPrefs.ContainsKey(i.Name)) { - dupeKeyFoundInCompanyInfo = true; + dupeKeyFoundInCompanyInfo = true; } else { QCompOtherPrefs.Add(i.Name, i.Value); } - + //get the exact type of QB Online if (i.Name == "OfferingSku") { @@ -780,7 +850,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 //this is current as of 7/27/2017 // wrong wrong wrong apparently, need to use preferences.ProductAndServicesPrefs.QuantityOnHand is true instead - // QBSupportsInventory = (QOfferingSku == "QuickBooks Online Plus" || QOfferingSku == "QuickBooks Online"); + // QBSupportsInventory = (QOfferingSku == "QuickBooks Online Plus" || QOfferingSku == "QuickBooks Online"); QCountry = comp[0].Country;//In testing it was CA for canada and US for US, GB for UK, AU for australia @@ -794,7 +864,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 { IntegrationLog.Log(QBID, "PFC: Failed with exception:" + CrackException(ex)); //clean connection - CN.Clean(); + //CN.Clean();//removed as part of oauth2 switch throw; } } @@ -1270,7 +1340,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 #endregion - + #region ToBePrinted //No validation possible //so prompt only if not setup yet @@ -1343,7 +1413,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 TBEMOK: #endregion - + #region SetMemoField //No validation possible //so prompt only if not setup yet @@ -1387,7 +1457,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 SETMEMOOK: #endregion - + #region SetAutoCloseField Case 7 //No validation possible //so prompt only if not setup yet @@ -2043,7 +2113,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 sTaxCode }); } - + @@ -2536,7 +2606,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 // } //} - + ///// ///// Populate the cached qb data ///// @@ -3302,7 +3372,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 #region Export to QB - + //this code is called from AyaNova via plugin command menu on selected clients public static void ImportAyaClient(List objectIDList) { @@ -3311,7 +3381,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 //WARNING: BEFORE MAKING CHANGES HERE SEE //MAP.CS line 1606 same code //AND QBOI.CS single client command code line 378 - + //Only USA uses one tax code for the whole customer //other regions are taxed by item and set with items if (Util.QUSA) @@ -4460,7 +4530,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 //Example of how to make an invoice using .net api //https://gist.github.com/IntuitDeveloperRelations/6500373 - + if (alWorkorders.Count == 0) return; try @@ -4661,7 +4731,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 #region Part charges //case 3296 - PartDisplayFormats defaultPartDisplayFormat = AyaBizUtils.GlobalSettings.DefaultPartDisplayFormat; + PartDisplayFormats defaultPartDisplayFormat = AyaBizUtils.GlobalSettings.DefaultPartDisplayFormat; foreach (WorkorderItem it in w.WorkorderItems) { @@ -5174,7 +5244,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 //Get item from cache - DataRow drItemCacheData = _dtQBItems.Rows.Find(QBListID); + DataRow drItemCacheData = _dtQBItems.Rows.Find(QBListID); //case 3296 //Line item DESCRIPTION @@ -5186,7 +5256,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 { line.Description = OverrideDescriptionText; } - + //TAXES @@ -5237,7 +5307,7 @@ KEY: AssignedTime, VALUE: 12/08/2017 18:52:04 }; lineList.Add(line); - + //QBO MAY BE RELEVANT: For Invoice objects in global locales: when updating Amount, remove the TxnTaxDetail element in the object before submitting it in the update request payload. }