Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
kgOrders
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Cam Hayes
kgOrders
Commits
4d546ae6
Commit
4d546ae6
authored
Mar 10, 2026
by
Cam Hayes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Link to QB is now working on the client so dave can connect
parent
ab0e2e38
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
144 additions
and
7 deletions
+144
-7
View.Main.dfm
kgOrdersClient/View.Main.dfm
+15
-2
View.Main.html
kgOrdersClient/View.Main.html
+4
-1
View.Main.pas
kgOrdersClient/View.Main.pas
+15
-1
View.Orders.pas
kgOrdersClient/View.Orders.pas
+0
-1
Auth.Service.pas
kgOrdersServer/Source/Auth.Service.pas
+1
-0
Auth.ServiceImpl.pas
kgOrdersServer/Source/Auth.ServiceImpl.pas
+108
-1
kgOrdersServer - Copy.ini
kgOrdersServer/bin/kgOrdersServer - Copy.ini
+1
-1
No files found.
kgOrdersClient/View.Main.dfm
View file @
4d546ae6
...
@@ -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 = 55
1
Left = 55
4
Top = 14
3
Top = 14
8
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
...
...
kgOrdersClient/View.Main.html
View file @
4d546ae6
...
@@ -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"
>
...
...
kgOrdersClient/View.Main.pas
View file @
4d546ae6
...
@@ -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
;
...
...
kgOrdersClient/View.Orders.pas
View file @
4d546ae6
...
@@ -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
(
...
...
kgOrdersServer/Source/Auth.Service.pas
View file @
4d546ae6
...
@@ -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
...
...
kgOrdersServer/Source/Auth.ServiceImpl.pas
View file @
4d546ae6
...
@@ -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
.
kgOrdersServer/bin/kgOrdersServer - Copy.ini
View file @
4d546ae6
[Settings]
[Settings]
MemoLogLevel
=
3
MemoLogLevel
=
3
FileLogLevel
=
4
FileLogLevel
=
4
webClientVersion
=
0.9.1
2
webClientVersion
=
0.9.1
3
LogFileNum
=
100
LogFileNum
=
100
[Database]
[Database]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment