This commit is contained in:
@@ -309,7 +309,7 @@ namespace AyaNova.PlugIn.QBOI
|
|||||||
public static string REALM_ID { get; set; }
|
public static string REALM_ID { get; set; }
|
||||||
public static DateTime TOKEN_BIRTHDAY { get; set; }
|
public static DateTime TOKEN_BIRTHDAY { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//simple xor encryption
|
//simple xor encryption
|
||||||
private static string Ec(string text, string key)
|
private static string Ec(string text, string key)
|
||||||
@@ -378,23 +378,21 @@ namespace AyaNova.PlugIn.QBOI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void RefreshTokens()
|
public static void RefreshTokens()
|
||||||
{
|
{
|
||||||
DateTime dtExpireAfter=DateTime.Now.AddMinutes( Q2_TOKEN_LIFESPAN_MINUTES);
|
TimeSpan age = DateTime.Now.Subtract(TOKEN_BIRTHDAY);
|
||||||
|
if (age.TotalMinutes < Q2_TOKEN_LIFESPAN_MINUTES)
|
||||||
if (TOKEN_BIRTHDAY < dtExpireAfter)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//refresh token here
|
//refresh token here
|
||||||
|
var v = oac.RefreshTokenAsync(REFRESH_TOKEN).Result;
|
||||||
|
TOKEN_BIRTHDAY = DateTime.Now;
|
||||||
|
ACCESS_TOKEN = v.AccessToken;
|
||||||
|
REFRESH_TOKEN = v.RefreshToken;
|
||||||
|
|
||||||
var v= oac.RefreshTokenAsync(REFRESH_TOKEN).Result;
|
|
||||||
TOKEN_BIRTHDAY = DateTime.Now;
|
|
||||||
ACCESS_TOKEN = v.AccessToken;
|
|
||||||
REFRESH_TOKEN = v.RefreshToken;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ServiceContext SC = null;
|
static ServiceContext SC = null;
|
||||||
@@ -409,11 +407,11 @@ namespace AyaNova.PlugIn.QBOI
|
|||||||
//shell out to browser for user to login to QB
|
//shell out to browser for user to login to QB
|
||||||
System.Diagnostics.Process.Start("https://qboauth.ayanova.com/start/" + QBOI2_SESSION_TOKEN);
|
System.Diagnostics.Process.Start("https://qboauth.ayanova.com/start/" + QBOI2_SESSION_TOKEN);
|
||||||
|
|
||||||
|
|
||||||
//Open dialog that polls for token repeatedly, there is a delay built into the server
|
//Open dialog that polls for token repeatedly, there is a delay built into the server
|
||||||
//so no need to delay here, just keep attempting to fetch over and over or until cancel
|
//so no need to delay here, just keep attempting to fetch over and over or until cancel
|
||||||
GetToken gt = new GetToken(QBOI2_SESSION_TOKEN);
|
GetToken gt = new GetToken(QBOI2_SESSION_TOKEN);
|
||||||
DialogResult tokenResult=gt.ShowDialog();
|
DialogResult tokenResult = gt.ShowDialog();
|
||||||
if (tokenResult == DialogResult.Cancel)
|
if (tokenResult == DialogResult.Cancel)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(gt.LastError))
|
if (!string.IsNullOrEmpty(gt.LastError))
|
||||||
@@ -427,30 +425,28 @@ namespace AyaNova.PlugIn.QBOI
|
|||||||
if (string.IsNullOrEmpty(gt.FetchedToken))
|
if (string.IsNullOrEmpty(gt.FetchedToken))
|
||||||
{
|
{
|
||||||
|
|
||||||
IntegrationLog.Log(QBID, "PFC: QuickBooks online retrieved token is empty! Unable to proceed.");
|
IntegrationLog.Log(QBID, "PFC: QuickBooks online retrieved token is empty! Unable to proceed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//parse the token and store the values in the session variables
|
//parse the token and store the values in the session variables
|
||||||
JObject j=JObject.Parse(gt.FetchedToken);
|
JObject j = JObject.Parse(gt.FetchedToken);
|
||||||
/* example return value
|
/* example return value
|
||||||
{
|
{
|
||||||
"realmId": "193514527954149",
|
"realmId": "193514527954149",
|
||||||
"access_token": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiZGlyIn0..f_bBkYjAwaN2H9cVLHDDog.XNz0F7PN96vJhpdn6y-yVv85sqBGI0QQYucLQ4NjzKfk3eKmTh0es8hJofZufequZu1dqy1q8wIuJ3kGABsKqL6yUy3kDg9jrED-bgqMaDHAbafLdaMuzVmzwF2pnR1M61ey5rxfio2Nr54q9_HhRJpealHyiM4hDXhA87FVbMP1pqH43HB5dt6WIu4EFnNX-HSWEZCa-LeYTn39bGpCdxA89WQyi4B_fnVvF1YhbzWe3GINZV3bHrVlD9flslBuym_HHNISapSK9AKwx71upAgRhxGf9Q5aBvb3w5-HCQYTbZZv2oooTApFP6SnrxhEC7d11h2e2_cDlCvvxeGaK5ZqmeOzwZKY72Fmum50UB61ChoLEFl_odW2e8GZY_f7EavufVklj9yWu-zuFeExSwHEP-QCbFZ10EvP5BIxB0os2vRXfS906zVpFJACuAaoVrfpIlRa0QIPMpwLuN50lONPMV1xBRGuodqs7R550Pm-5Bff6-Im-ialg9sLkETSsE9ICsJ7z4p2wQ1Z9b_Cdz6fbOUSotv8uwK2ke4mKTRKejbl6UfDG8DNoeCGMcaF7VDLd_8X8UdMU2gYH6Y9EEOFbX6MOpmUUIsyd-0WLZjDTya6bbLONsrpZmZXXX12n5pDykXxachl6I6XR0vuhGnF6Z_CSvOjYWrArQ8IY8SF9oobgFWi0wy_izurVq5R.ltpcEsh0zXmOBmRTggommQ",
|
"access_token": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiZGlyIn0..f_bBkYjAwaN2H9cVLHDDog.XNz0F7PN96vJhpdn6y-yVv85sqBGI0QQYucLQ4NjzKfk3eKmTh0es8hJofZufequZu1dqy1q8wIuJ3kGABsKqL6yUy3kDg9jrED-bgqMaDHAbafLdaMuzVmzwF2pnR1M61ey5rxfio2Nr54q9_HhRJpealHyiM4hDXhA87FVbMP1pqH43HB5dt6WIu4EFnNX-HSWEZCa-LeYTn39bGpCdxA89WQyi4B_fnVvF1YhbzWe3GINZV3bHrVlD9flslBuym_HHNISapSK9AKwx71upAgRhxGf9Q5aBvb3w5-HCQYTbZZv2oooTApFP6SnrxhEC7d11h2e2_cDlCvvxeGaK5ZqmeOzwZKY72Fmum50UB61ChoLEFl_odW2e8GZY_f7EavufVklj9yWu-zuFeExSwHEP-QCbFZ10EvP5BIxB0os2vRXfS906zVpFJACuAaoVrfpIlRa0QIPMpwLuN50lONPMV1xBRGuodqs7R550Pm-5Bff6-Im-ialg9sLkETSsE9ICsJ7z4p2wQ1Z9b_Cdz6fbOUSotv8uwK2ke4mKTRKejbl6UfDG8DNoeCGMcaF7VDLd_8X8UdMU2gYH6Y9EEOFbX6MOpmUUIsyd-0WLZjDTya6bbLONsrpZmZXXX12n5pDykXxachl6I6XR0vuhGnF6Z_CSvOjYWrArQ8IY8SF9oobgFWi0wy_izurVq5R.ltpcEsh0zXmOBmRTggommQ",
|
||||||
"refresh_token": "AB11578778808Neoah1qLV0tgnNrnr4T9mJkIlTY5nZdOieQdo",
|
"refresh_token": "AB11578778808Neoah1qLV0tgnNrnr4T9mJkIlTY5nZdOieQdo",
|
||||||
"tokenBirthday": "2019-10-02T14:40:08.4855781-07:00"
|
"tokenBirthday": "2019-10-02T14:40:08.4855781-07:00"
|
||||||
}
|
}
|
||||||
* */
|
* */
|
||||||
|
|
||||||
ACCESS_TOKEN = j["access_token"].Value<string>();
|
ACCESS_TOKEN = j["access_token"].Value<string>();
|
||||||
REFRESH_TOKEN = j["refresh_token"].Value<string>();
|
REFRESH_TOKEN = j["refresh_token"].Value<string>();
|
||||||
REALM_ID = j["realmId"].Value<string>();
|
REALM_ID = j["realmId"].Value<string>();
|
||||||
///***************************************** TESTING FIX THIS LATER ***********************
|
//start the clock on the tokens
|
||||||
TOKEN_BIRTHDAY = DateTime.Now.AddMinutes(-90);//TESTING TESTING TESTING
|
TOKEN_BIRTHDAY = DateTime.Now;
|
||||||
|
|
||||||
//NOTE: this app will handle refreshing the token in-session as apparently that's possible from here, maybe should test that or could simply just refresh via our server
|
|
||||||
|
|
||||||
oac = new OAuth2Client(Q2_CLIENT_ID, Q2_CLIENT_SECRET, Q2_REDIRECT_URL, Q2_ENVIRONMENT);
|
oac = new OAuth2Client(Q2_CLIENT_ID, Q2_CLIENT_SECRET, Q2_REDIRECT_URL, Q2_ENVIRONMENT);
|
||||||
|
|
||||||
@@ -458,47 +454,35 @@ namespace AyaNova.PlugIn.QBOI
|
|||||||
//https://help.developer.intuit.com/s/question/0D50f00005gFeqpCAC/how-do-i-suddenly-get-there-was-an-error-while-communicating-with-the-ids-server
|
//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
|
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //Add this just to be sure to use TLS1.2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Intuit.Ipp.Security.OAuth2RequestValidator validator = new Intuit.Ipp.Security.OAuth2RequestValidator(ACCESS_TOKEN);
|
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 = new Intuit.Ipp.Core.ServiceContext(REALM_ID, Intuit.Ipp.Core.IntuitServicesType.QBO, validator);
|
||||||
|
|
||||||
SC.IppConfiguration.Logger.RequestLog.EnableRequestResponseLogging = true;
|
//SC.IppConfiguration.Logger.RequestLog.EnableRequestResponseLogging = true;
|
||||||
|
// SC.IppConfiguration.Logger.RequestLog.ServiceRequestLoggingLocation = "c:\\temp\\qblogs\\";
|
||||||
SC.IppConfiguration.Logger.RequestLog.ServiceRequestLoggingLocation = "c:\\temp\\qblogs\\";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//' Common setting for both ServiceContexts:
|
//' Common setting for both ServiceContexts:
|
||||||
|
|
||||||
SC.IppConfiguration.MinorVersion.Qbo = "23";
|
SC.IppConfiguration.MinorVersion.Qbo = "23";
|
||||||
|
TODO: variableize this: SC.IppConfiguration.BaseUrl.Qbo = "https://sandbox-quickbooks.api.intuit.com/";
|
||||||
SC.IppConfiguration.BaseUrl.Qbo = "https://sandbox-quickbooks.api.intuit.com/";
|
|
||||||
|
|
||||||
//' Serialization Format Json or xml
|
//' Serialization Format Json or xml
|
||||||
|
|
||||||
SC.IppConfiguration.Message.Request.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json;
|
SC.IppConfiguration.Message.Request.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json;
|
||||||
|
|
||||||
SC.IppConfiguration.Message.Response.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json;
|
SC.IppConfiguration.Message.Response.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//' Compression Format can be GZip or Deflate:
|
//' Compression Format can be GZip or Deflate:
|
||||||
|
|
||||||
SC.IppConfiguration.Message.Request.CompressionFormat = Intuit.Ipp.Core.Configuration.CompressionFormat.GZip;
|
SC.IppConfiguration.Message.Request.CompressionFormat = Intuit.Ipp.Core.Configuration.CompressionFormat.GZip;
|
||||||
|
|
||||||
SC.IppConfiguration.Message.Response.CompressionFormat = Intuit.Ipp.Core.Configuration.CompressionFormat.GZip;
|
SC.IppConfiguration.Message.Response.CompressionFormat = Intuit.Ipp.Core.Configuration.CompressionFormat.GZip;
|
||||||
|
|
||||||
//' Retry 5 times at an interval of 1 Second if service fails. Note that RetryPolicy moved from Intuit.Ipp.Retry to Intuit.Ipp.Core.
|
//' 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);
|
TimeSpan retryInterval = new TimeSpan(0, 0, 0, 1);
|
||||||
|
|
||||||
SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Core.IntuitRetryPolicy(5, retryInterval);
|
SC.IppConfiguration.RetryPolicy = new Intuit.Ipp.Core.IntuitRetryPolicy(5, retryInterval);
|
||||||
|
|
||||||
//' For data updates, create DataService:
|
//' For data updates, create DataService:
|
||||||
|
// Intuit.Ipp.DataService.DataService loDataService = new Intuit.Ipp.DataService.DataService(SC);
|
||||||
|
|
||||||
Intuit.Ipp.DataService.DataService loDataService = new Intuit.Ipp.DataService.DataService(SC);
|
|
||||||
|
|
||||||
_AuthenticationCompleted = true;
|
_AuthenticationCompleted = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -598,6 +582,7 @@ namespace AyaNova.PlugIn.QBOI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
todo: call this from all over the place (i.e. before every api call) //and remove logging
|
||||||
RefreshTokens();
|
RefreshTokens();
|
||||||
|
|
||||||
IntegrationLog.Log(QBID, "PFC: Authentication completed, validating company data");
|
IntegrationLog.Log(QBID, "PFC: Authentication completed, validating company data");
|
||||||
|
|||||||
Reference in New Issue
Block a user