Commit 4d546ae6 by Cam Hayes

Link to QB is now working on the client so dave can connect

parent ab0e2e38
...@@ -34,8 +34,8 @@ object FViewMain: TFViewMain ...@@ -34,8 +34,8 @@ object FViewMain: TFViewMain
Caption = ' User Profile' Caption = ' User Profile'
end end
object wllblLogout: TWebLinkLabel object wllblLogout: TWebLinkLabel
Left = 551 Left = 554
Top = 143 Top = 148
Width = 36 Width = 36
Height = 14 Height = 14
ElementID = 'dropdown.menu.logout' ElementID = 'dropdown.menu.logout'
...@@ -132,6 +132,19 @@ object FViewMain: TFViewMain ...@@ -132,6 +132,19 @@ object FViewMain: TFViewMain
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object lblLinkToQB: TWebLabel
Left = 538
Top = 128
Width = 49
Height = 14
Caption = 'Link to QB'
ElementID = 'dropdown.menu.linktoqb'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = lblLinkToQBClick
end
object WebPanel1: TWebPanel object WebPanel1: TWebPanel
Left = 77 Left = 77
Top = 112 Top = 112
......
...@@ -30,7 +30,10 @@ ...@@ -30,7 +30,10 @@
<a class="dropdown-item" id="dropdown.menu.userprofile" href="#"><i class="fa fa-user fa-fw"></i><span> User Profile</span></a> <a class="dropdown-item" id="dropdown.menu.userprofile" href="#"><i class="fa fa-user fa-fw"></i><span> User Profile</span></a>
</li> </li>
<li> <li>
<a class="dropdown-item" id="dropdown.menu.users" href="#"><i class="fas fa-address-book fa-fw"></i><span> Users</span></abbr></a> <a class="dropdown-item" id="dropdown.menu.users" href="#"><i class="fas fa-address-book fa-fw"></i><span> Users</span></a>
</li>
<li>
<a class="dropdown-item" id="dropdown.menu.linktoqb" href="#"><i class="fas fa-book fa-fw"></i><span> Link to QB</span></a>
</li> </li>
<li> <li>
<hr class="dropdown-divider"> <hr class="dropdown-divider">
......
...@@ -24,6 +24,7 @@ type ...@@ -24,6 +24,7 @@ type
lblorders: TWebLabel; lblorders: TWebLabel;
lblCustomers: TWebLabel; lblCustomers: TWebLabel;
lblVersion: TWebLabel; lblVersion: TWebLabel;
lblLinkToQB: TWebLabel;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure mnuLogoutClick(Sender: TObject); procedure mnuLogoutClick(Sender: TObject);
procedure wllblUserProfileClick(Sender: TObject); procedure wllblUserProfileClick(Sender: TObject);
...@@ -33,8 +34,12 @@ type ...@@ -33,8 +34,12 @@ type
procedure lblUsersClick(Sender: TObject); procedure lblUsersClick(Sender: TObject);
procedure lblordersClick(Sender: TObject); procedure lblordersClick(Sender: TObject);
procedure lblCustomersClick(Sender: TObject); procedure lblCustomersClick(Sender: TObject);
procedure lblLinkToQBClick(Sender: TObject);
private private
const
qbLink = 'https://appcenter.intuit.com/connect/oauth2?client_id=ABYqlDx1EsacZYXvHIJ7RDB7zmnQdwABU3fwQLIZPmBgU0VW1P&response_type=code&scope=com.intuit.quickbooks.accounting&redirect_uri=http://localhost:2004/kgOrders/auth/AuthService/Authorize&state=7';
{ Private declarations } { Private declarations }
private
FUserInfo: string; FUserInfo: string;
FSearchSettings: string; FSearchSettings: string;
FChildForm: TWebForm; FChildForm: TWebForm;
...@@ -97,7 +102,7 @@ begin ...@@ -97,7 +102,7 @@ begin
if (not (JS.toString(AuthService.TokenPayload.Properties['user_access_type']) = 'ADMIN')) then if (not (JS.toString(AuthService.TokenPayload.Properties['user_access_type']) = 'ADMIN')) then
begin begin
lblUsers.enabled := false; lblUsers.enabled := false;
lblLinkToQB.Enabled := false;
lblCustomers.Enabled := false; lblCustomers.Enabled := false;
end; end;
lblAppTitle.Caption := 'Koehler-Gibson Orders'; lblAppTitle.Caption := 'Koehler-Gibson Orders';
...@@ -175,6 +180,15 @@ begin ...@@ -175,6 +180,15 @@ begin
end; end;
procedure TFViewMain.lblLinkToQBClick(Sender: TObject);
var
qbWindow: TJSWindow;
begin
qbWindow := window.open('', '_blank');
if Assigned(qbWindow) then
qbWindow.location.href := qbLink;
end;
procedure TFViewMain.setActive(page: string); procedure TFViewMain.setActive(page: string);
var var
links: TJSNodeList; links: TJSNodeList;
......
...@@ -189,7 +189,6 @@ begin ...@@ -189,7 +189,6 @@ begin
end end
else else
begin begin
FPendingPdfTab := window.open('', '_blank');
if Assigned(FPendingPdfTab) then if Assigned(FPendingPdfTab) then
FPendingPdfTab.document.write( FPendingPdfTab.document.write(
......
...@@ -20,6 +20,7 @@ type ...@@ -20,6 +20,7 @@ type
['{9CFD59B2-A832-4F82-82BB-9A25FC93F305}'] ['{9CFD59B2-A832-4F82-82BB-9A25FC93F305}']
function Login(const user, password: string): string; function Login(const user, password: string): string;
function VerifyVersion(clientVersion: string): TJSONObject; function VerifyVersion(clientVersion: string): TJSONObject;
[HttpGet] function Authorize(code, realmId, state: string): string;
end; end;
implementation implementation
......
...@@ -10,7 +10,8 @@ uses ...@@ -10,7 +10,8 @@ uses
XData.Server.Module, XData.Server.Module,
Auth.Service, Auth.Service,
Auth.Database, Auth.Database,
Uni, Data.DB, System.Hash, System.IniFiles, System.JSON; Uni, Data.DB, System.Hash, System.IniFiles, System.JSON, REST.Client,
REST.Types, Vcl.Forms, System.NetEncoding;
type type
[ServiceImplementation] [ServiceImplementation]
...@@ -22,6 +23,8 @@ type ...@@ -22,6 +23,8 @@ type
public public
function Login(const user, password: string): string; function Login(const user, password: string): string;
function VerifyVersion(ClientVersion: string): TJSONObject; function VerifyVersion(ClientVersion: string): TJSONObject;
function Authorize(code, realmId, state: string): string;
function ExchangeAuthCode(code: string): string;
procedure AfterConstruction; override; procedure AfterConstruction; override;
procedure BeforeDestruction; override; procedure BeforeDestruction; override;
end; end;
...@@ -186,6 +189,110 @@ begin ...@@ -186,6 +189,110 @@ begin
end; end;
end; end;
function TAuthService.Authorize(code, realmId, state: string): string;
var
iniFile: TIniFile;
begin
Logger.Log(3, 'TAuthService.Authorize - begin');
iniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini');
iniFile.WriteString('Quickbooks', 'CompanyID', realmId);
iniFile.Free;
result := ExchangeAuthCode(code);
Logger.Log(3, 'TAuthService.Authorize - end - result: ' + result);
end;
function TAuthService.ExchangeAuthCode(code: string): string;
var
iniFile: TIniFile;
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
Client, Secret, authString, AccessToken, RefreshToken: string;
jsonObj: TJSONObject;
begin
logger.Log(3, 'AuthService.ExchangeAuthCode - start');
iniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini');
restClient := TRESTClient.Create(nil);
restRequest := TRESTRequest.Create(nil);
restResponse := TRESTResponse.Create(nil);
try
try
restRequest.Client := restClient;
restRequest.Response := restResponse;
Client := iniFile.ReadString('Quickbooks', 'ClientID', '');
Secret := iniFile.ReadString('Quickbooks', 'ClientSecret', '');
authString := TNetEncoding.Base64.Encode(Client + ':' + Secret).Replace(#13,'').Replace(#10,'');
restClient.BaseURL := 'https://oauth.platform.intuit.com';
restRequest.Resource := '/oauth2/v1/tokens/bearer';
restRequest.Method := rmPOST;
// Authorization header
param := restRequest.Params.AddItem;
param.Name := 'Authorization';
param.Kind := pkHTTPHEADER;
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Basic ' + authString;
// grant_type
param := restRequest.Params.AddItem;
param.Name := 'grant_type';
param.Kind := pkGETorPOST;
param.Value := 'authorization_code';
// authorization code
param := restRequest.Params.AddItem;
param.Name := 'code';
param.Kind := pkGETorPOST;
param.Value := code;
// redirect URI
param := restRequest.Params.AddItem;
param.Name := 'redirect_uri';
param.Kind := pkGETorPOST;
param.Value := 'http://localhost:2004/kgOrders/auth/AuthService/Authorize';
restRequest.Execute;
logger.Log(5, restResponse.Content);
jsonObj := TJSONObject.ParseJSONValue(restResponse.Content) as TJSONObject;
if Assigned(jsonObj) then
begin
AccessToken := jsonObj.GetValue<string>('access_token');
RefreshToken := jsonObj.GetValue<string>('refresh_token');
logger.Log(3, 'Access Token: ' + AccessToken);
logger.Log(3, 'Refresh Token: ' + RefreshToken);
iniFile.WriteString('Quickbooks', 'AccessToken', AccessToken);
iniFile.WriteString('Quickbooks', 'RefreshToken', RefreshToken);
iniFile.WriteString('Quickbooks', 'LastRefresh', DateTimeToStr(Now));
end;
except
on E: Exception do
begin
result := 'The server has ran into an error please try again later...';
logger.Log(1, 'ExchangeAuthCode Error: ' + E.Message);
end;
end;
result := 'Quickbooks successfully linked!';
finally
restClient.Free;
restRequest.Free;
restResponse.Free;
iniFile.Free;
logger.Log(3, 'AuthService.ExchangeAuthCode - end');
end;
end;
initialization initialization
RegisterServiceType(TAuthService); RegisterServiceType(TAuthService);
end. end.
[Settings] [Settings]
MemoLogLevel=3 MemoLogLevel=3
FileLogLevel=4 FileLogLevel=4
webClientVersion=0.9.12 webClientVersion=0.9.13
LogFileNum=100 LogFileNum=100
[Database] [Database]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment