Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(SQL Server) Xero OAuth1 Authorization (3-legged)Demonstrates 3-legged OAuth1 authorization for Xero
-- Important: See this note about string length limitations for strings returned by sp_OAMethod calls. -- CREATE PROCEDURE ChilkatSample AS BEGIN DECLARE @hr int DECLARE @iTmp0 int DECLARE @iTmp1 int -- Important: Do not use nvarchar(max). See the warning about using nvarchar(max). DECLARE @sTmp0 nvarchar(4000) DECLARE @consumerKey nvarchar(4000) SELECT @consumerKey = 'XERO_CONSUMER_KEY' DECLARE @consumerSecret nvarchar(4000) SELECT @consumerSecret = 'XERO_CONSUMER_SECRET' DECLARE @requestTokenUrl nvarchar(4000) SELECT @requestTokenUrl = 'https://api.xero.com/oauth/RequestToken' DECLARE @authorizeUrl nvarchar(4000) SELECT @authorizeUrl = 'https://api.xero.com/oauth/Authorize' DECLARE @accessTokenUrl nvarchar(4000) SELECT @accessTokenUrl = 'https://api.xero.com/oauth/AccessToken' -- The port number is picked at random. It's some unused port that won't likely conflict with anything else.. DECLARE @callbackUrl nvarchar(4000) SELECT @callbackUrl = 'http://localhost:3017/' DECLARE @callbackLocalPort int SELECT @callbackLocalPort = 3017 -- The 1st step in 3-legged OAuth1.0a is to send a POST to the request token URL to obtain an OAuth Request Token DECLARE @http int -- Use "Chilkat_9_5_0.Http" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.Http', @http OUT IF @hr <> 0 BEGIN PRINT 'Failed to create ActiveX component' RETURN END DECLARE @success int EXEC sp_OASetProperty @http, 'OAuth1', 1 EXEC sp_OASetProperty @http, 'OAuthConsumerKey', @consumerKey EXEC sp_OASetProperty @http, 'OAuthConsumerSecret', @consumerSecret EXEC sp_OASetProperty @http, 'OAuthCallback', @callbackUrl DECLARE @req int -- Use "Chilkat_9_5_0.HttpRequest" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.HttpRequest', @req OUT DECLARE @resp int EXEC sp_OAMethod @http, 'PostUrlEncoded', @resp OUT, @requestTokenUrl, @req EXEC sp_OAGetProperty @http, 'LastMethodSuccess', @iTmp0 OUT IF @iTmp0 <> 1 BEGIN EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT PRINT @sTmp0 EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req RETURN END -- If successful, the resp.BodyStr contains something like this: -- oauth_token=-Wa_KwAAAAAAxfEPAAABV8Qar4Q&oauth_token_secret=OfHY4tZBX2HK4f7yIw76WYdvnl99MVGB&oauth_callback_confirmed=true EXEC sp_OAGetProperty @resp, 'BodyStr', @sTmp0 OUT PRINT @sTmp0 DECLARE @hashTab int -- Use "Chilkat_9_5_0.Hashtable" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.Hashtable', @hashTab OUT EXEC sp_OAGetProperty @resp, 'BodyStr', @sTmp0 OUT EXEC sp_OAMethod @hashTab, 'AddQueryParams', @success OUT, @sTmp0 DECLARE @requestToken nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @requestToken OUT, 'oauth_token' DECLARE @requestTokenSecret nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @requestTokenSecret OUT, 'oauth_token_secret' EXEC sp_OASetProperty @http, 'OAuthTokenSecret', @requestTokenSecret EXEC @hr = sp_OADestroy @resp PRINT 'oauth_token = ' + @requestToken PRINT 'oauth_token_secret = ' + @requestTokenSecret -- --------------------------------------------------------------------------- -- The next step is to form a URL to send to the authorizeUrl -- This is an HTTP GET that we load into a popup browser. DECLARE @sbUrlForBrowser int -- Use "Chilkat_9_5_0.StringBuilder" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbUrlForBrowser OUT EXEC sp_OAMethod @sbUrlForBrowser, 'Append', @success OUT, @authorizeUrl EXEC sp_OAMethod @sbUrlForBrowser, 'Append', @success OUT, '?oauth_token=' EXEC sp_OAMethod @sbUrlForBrowser, 'Append', @success OUT, @requestToken DECLARE @urlForBrowser nvarchar(4000) EXEC sp_OAMethod @sbUrlForBrowser, 'GetAsString', @urlForBrowser OUT -- When the urlForBrowser is loaded into a browser, the response from Xero will redirect back to localhost:3017 -- We'll need to start a socket that is listening on port 3017 for the callback from the browser. DECLARE @listenSock int -- Use "Chilkat_9_5_0.Socket" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.Socket', @listenSock OUT DECLARE @backLog int SELECT @backLog = 5 EXEC sp_OAMethod @listenSock, 'BindAndListen', @success OUT, @callbackLocalPort, @backLog IF @success <> 1 BEGIN EXEC sp_OAGetProperty @listenSock, 'LastErrorText', @sTmp0 OUT PRINT @sTmp0 EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock RETURN END -- Wait for the browser's connection in a background thread. -- (We'll send load the URL into the browser following this..) -- Wait a max of 60 seconds before giving up. DECLARE @maxWaitMs int SELECT @maxWaitMs = 60000 DECLARE @task int EXEC sp_OAMethod @listenSock, 'AcceptNextConnectionAsync', @task OUT, @maxWaitMs EXEC sp_OAMethod @task, 'Run', @success OUT -- At this point, your application should load the URL in a browser. -- For example, -- in C#: System.Diagnostics.Process.Start(urlForBrowser); -- in Java: Desktop.getDesktop().browse(new URI(urlForBrowser)); -- in VBScript: Set wsh=WScript.CreateObject("WScript.Shell") -- wsh.Run urlForBrowser -- in Xojo: ShowURL(url) (see http://docs.xojo.com/index.php/ShowURL) -- in Dataflex: Runprogram Background "c:\Program Files\Internet Explorer\iexplore.exe" sUrl -- The Xero account owner would interactively accept or deny the authorization request. -- Add the code to load the url in a web browser here... -- Add the code to load the url in a web browser here... -- Add the code to load the url in a web browser here... -- System.Diagnostics.Process.Start(urlForBrowser); -- Wait for the listenSock's task to complete. EXEC sp_OAMethod @task, 'Wait', @success OUT, @maxWaitMs EXEC sp_OAGetProperty @task, 'StatusInt', @iTmp0 OUT EXEC sp_OAGetProperty @task, 'TaskSuccess', @iTmp1 OUT IF Not @success or (@iTmp0 <> 7) or (@iTmp1 <> 1) BEGIN IF Not @success BEGIN -- The task.LastErrorText applies to the Wait method call. EXEC sp_OAGetProperty @task, 'LastErrorText', @sTmp0 OUT PRINT @sTmp0 END ELSE BEGIN -- The ResultErrorText applies to the underlying task method call (i.e. the AcceptNextConnection) EXEC sp_OAGetProperty @task, 'Status', @sTmp0 OUT PRINT @sTmp0 EXEC sp_OAGetProperty @task, 'ResultErrorText', @sTmp0 OUT PRINT @sTmp0 END EXEC @hr = sp_OADestroy @task EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock RETURN END -- If we get to this point, the connection from the browser arrived and was accepted. -- We no longer need the listen socket... -- Stop listening on port 3017. EXEC sp_OAMethod @listenSock, 'Close', @success OUT, 10 -- First get the connected socket. DECLARE @sock int -- Use "Chilkat_9_5_0.Socket" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.Socket', @sock OUT EXEC sp_OAMethod @sock, 'LoadTaskResult', @success OUT, @task EXEC @hr = sp_OADestroy @task -- Read the start line of the request.. DECLARE @startLine nvarchar(4000) EXEC sp_OAMethod @sock, 'ReceiveUntilMatch', @startLine OUT, CHAR(13) + CHAR(10) EXEC sp_OAGetProperty @sock, 'LastMethodSuccess', @iTmp0 OUT IF @iTmp0 <> 1 BEGIN EXEC sp_OAGetProperty @sock, 'LastErrorText', @sTmp0 OUT PRINT @sTmp0 EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock EXEC @hr = sp_OADestroy @sock RETURN END -- Read the request header. DECLARE @requestHeader nvarchar(4000) EXEC sp_OAMethod @sock, 'ReceiveUntilMatch', @requestHeader OUT, CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) EXEC sp_OAGetProperty @sock, 'LastMethodSuccess', @iTmp0 OUT IF @iTmp0 <> 1 BEGIN EXEC sp_OAGetProperty @sock, 'LastErrorText', @sTmp0 OUT PRINT @sTmp0 EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock EXEC @hr = sp_OADestroy @sock RETURN END -- The browser SHOULD be sending us a GET request, and therefore there is no body to the request. -- Once the request header is received, we have all of it. -- We can now send our HTTP response. DECLARE @sbResponseHtml int -- Use "Chilkat_9_5_0.StringBuilder" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbResponseHtml OUT EXEC sp_OAMethod @sbResponseHtml, 'Append', @success OUT, '<html><body><p>Chilkat thanks you!</b></body</html>' DECLARE @sbResponse int -- Use "Chilkat_9_5_0.StringBuilder" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbResponse OUT EXEC sp_OAMethod @sbResponse, 'Append', @success OUT, 'HTTP/1.1 200 OK' + CHAR(13) + CHAR(10) EXEC sp_OAMethod @sbResponse, 'Append', @success OUT, 'Content-Length: ' EXEC sp_OAGetProperty @sbResponseHtml, 'Length', @iTmp0 OUT EXEC sp_OAMethod @sbResponse, 'AppendInt', @success OUT, @iTmp0 EXEC sp_OAMethod @sbResponse, 'Append', @success OUT, CHAR(13) + CHAR(10) EXEC sp_OAMethod @sbResponse, 'Append', @success OUT, 'Content-Type: text/html' + CHAR(13) + CHAR(10) EXEC sp_OAMethod @sbResponse, 'Append', @success OUT, CHAR(13) + CHAR(10) EXEC sp_OAMethod @sbResponse, 'AppendSb', @success OUT, @sbResponseHtml EXEC sp_OAMethod @sbResponse, 'GetAsString', @sTmp0 OUT EXEC sp_OAMethod @sock, 'SendString', @success OUT, @sTmp0 EXEC sp_OAMethod @sock, 'Close', @success OUT, 50 -- The information we need is in the startLine. -- For example, the startLine will look something like this: -- GET /?oauth_token=abcdRQAAZZAAxfBBAAABVabcd_k&oauth_verifier=9rdOq5abcdCe6cn8M3jabcdj3Eabcd&org=mUkIZabcdKEababcd189t0 HTTP/1.1 DECLARE @sbStartLine int -- Use "Chilkat_9_5_0.StringBuilder" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbStartLine OUT EXEC sp_OAMethod @sbStartLine, 'Append', @success OUT, @startLine DECLARE @numReplacements int EXEC sp_OAMethod @sbStartLine, 'Replace', @numReplacements OUT, 'GET /?', '' EXEC sp_OAMethod @sbStartLine, 'Replace', @numReplacements OUT, ' HTTP/1.1', '' EXEC sp_OAMethod @sbStartLine, 'Trim', @success OUT -- oauth_token=abcdRQAAZZAAxfBBAAABVabcd_k&oauth_verifier=9rdOq5abcdCe6cn8M3jabcdj3Eabcd&org=mUkIZabcdKEababcd189t0 EXEC sp_OAMethod @sbStartLine, 'GetAsString', @sTmp0 OUT PRINT 'startline: ' + @sTmp0 EXEC sp_OAMethod @hashTab, 'Clear', NULL EXEC sp_OAMethod @sbStartLine, 'GetAsString', @sTmp0 OUT EXEC sp_OAMethod @hashTab, 'AddQueryParams', @success OUT, @sTmp0 EXEC sp_OAMethod @hashTab, 'LookupStr', @requestToken OUT, 'oauth_token' DECLARE @authVerifier nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @authVerifier OUT, 'oauth_verifier' -- ------------------------------------------------------------------------------ -- Finally , we must exchange the OAuth Request Token for an OAuth Access Token. EXEC sp_OASetProperty @http, 'OAuthToken', @requestToken EXEC sp_OASetProperty @http, 'OAuthVerifier', @authVerifier EXEC sp_OAMethod @http, 'PostUrlEncoded', @resp OUT, @accessTokenUrl, @req EXEC sp_OAGetProperty @http, 'LastMethodSuccess', @iTmp0 OUT IF @iTmp0 <> 1 BEGIN EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT PRINT @sTmp0 EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock EXEC @hr = sp_OADestroy @sock EXEC @hr = sp_OADestroy @sbResponseHtml EXEC @hr = sp_OADestroy @sbResponse EXEC @hr = sp_OADestroy @sbStartLine RETURN END -- Make sure a successful response was received. EXEC sp_OAGetProperty @resp, 'StatusCode', @iTmp0 OUT IF @iTmp0 <> 200 BEGIN EXEC sp_OAGetProperty @resp, 'StatusLine', @sTmp0 OUT PRINT @sTmp0 EXEC sp_OAGetProperty @resp, 'Header', @sTmp0 OUT PRINT @sTmp0 EXEC sp_OAGetProperty @resp, 'BodyStr', @sTmp0 OUT PRINT @sTmp0 EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock EXEC @hr = sp_OADestroy @sock EXEC @hr = sp_OADestroy @sbResponseHtml EXEC @hr = sp_OADestroy @sbResponse EXEC @hr = sp_OADestroy @sbStartLine RETURN END -- If successful, the resp.BodyStr contains something like this: -- oauth_token=85123455-fF41296Bi3daM8eCo9Y5vZabcdxXpRv864plYPOjr&oauth_token_secret=afiYJOgabcdSfGae7BDvJVVTwys8fUGpra5guZxbmFBZo&oauth_expires_in=1800&xero_org_muid=abcdecNhPKabcdNjz189t0 EXEC sp_OAGetProperty @resp, 'BodyStr', @sTmp0 OUT PRINT @sTmp0 EXEC sp_OAMethod @hashTab, 'Clear', NULL EXEC sp_OAGetProperty @resp, 'BodyStr', @sTmp0 OUT EXEC sp_OAMethod @hashTab, 'AddQueryParams', @success OUT, @sTmp0 DECLARE @accessToken nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @accessToken OUT, 'oauth_token' DECLARE @accessTokenSecret nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @accessTokenSecret OUT, 'oauth_token_secret' DECLARE @orgMuid nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @orgMuid OUT, 'xero_org_muid' DECLARE @expiresIn nvarchar(4000) EXEC sp_OAMethod @hashTab, 'LookupStr', @expiresIn OUT, 'oauth_expires_in' EXEC @hr = sp_OADestroy @resp -- The access token + secret is what should be saved and used for -- subsequent REST API calls. PRINT 'Access Token = ' + @accessToken PRINT 'Access Token Secret = ' + @accessTokenSecret PRINT 'xero_org_muid = ' + @orgMuid PRINT 'oauth_expires_in = ' + @expiresIn -- Save this access token for future calls. -- Just in case we need xero_org_muid and oauth_expires_in, save those also.. DECLARE @json int -- Use "Chilkat_9_5_0.JsonObject" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @json OUT EXEC sp_OAMethod @json, 'AppendString', @success OUT, 'oauth_token', @accessToken EXEC sp_OAMethod @json, 'AppendString', @success OUT, 'oauth_token_secret', @accessTokenSecret EXEC sp_OAMethod @json, 'AppendString', @success OUT, 'xero_org_muid', @orgMuid EXEC sp_OAMethod @json, 'AppendString', @success OUT, 'oauth_expires_in', @expiresIn DECLARE @fac int -- Use "Chilkat_9_5_0.FileAccess" for versions of Chilkat < 10.0.0 EXEC @hr = sp_OACreate 'Chilkat.FileAccess', @fac OUT EXEC sp_OAMethod @json, 'Emit', @sTmp0 OUT EXEC sp_OAMethod @fac, 'WriteEntireTextFile', @success OUT, 'qa_data/tokens/xero.json', @sTmp0, 'utf-8', 0 PRINT 'Success.' EXEC @hr = sp_OADestroy @http EXEC @hr = sp_OADestroy @req EXEC @hr = sp_OADestroy @hashTab EXEC @hr = sp_OADestroy @sbUrlForBrowser EXEC @hr = sp_OADestroy @listenSock EXEC @hr = sp_OADestroy @sock EXEC @hr = sp_OADestroy @sbResponseHtml EXEC @hr = sp_OADestroy @sbResponse EXEC @hr = sp_OADestroy @sbStartLine EXEC @hr = sp_OADestroy @json EXEC @hr = sp_OADestroy @fac END GO |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.