Sample code for 30+ languages & platforms
Lianja

Etsy OAuth1 Authorization

See more Etsy Examples

Demonstrates 3-legged OAuth1 authorization for Etsy.

Chilkat Lianja Downloads

Lianja
llSuccess = .F.

lcConsumerKey = "keystring"
lcConsumerSecret = "shared_secret"

// Specify one or more SPACE separated scopes as query params in the requestTokenUrl
// See https://www.etsy.com/developers/documentation/getting_started/oauth#section_permission_scopes
lcRequestTokenUrl = "https://openapi.etsy.com/v2/oauth/request_token?scope=email_r%20listings_r%20listings_w%20listings_d"
lcAuthorizeUrl = "https://www.etsy.com/oauth/signin"
lcAccessTokenUrl = "https://openapi.etsy.com/v2/oauth/access_token"

// The port number is picked at random. It's some unused port that won't likely conflict with anything else..
lcCallbackUrl = "http://localhost:3017/"
lnCallbackLocalPort = 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
loHttp = createobject("CkHttp")

loHttp.OAuth1 = .T.
loHttp.OAuthConsumerKey = lcConsumerKey
loHttp.OAuthConsumerSecret = lcConsumerSecret
loHttp.OAuthCallback = lcCallbackUrl

loReq = createobject("CkHttpRequest")
loReq.HttpVerb = "POST"
loReq.ContentType = "application/x-www-form-urlencoded"

loResp = createobject("CkHttpResponse")
llSuccess = loHttp.HttpReq(lcRequestTokenUrl,loReq,loResp)
if (llSuccess = .F.) then
    ? loHttp.LastErrorText
    release loHttp
    release loReq
    release loResp
    return
endif

// If successful, the resp.BodyStr contains something like this:  
// login_url=https%3A%2F%2Fwww.etsy.com%2Foauth%2Fsignin%3Foauth_consumer_key%3D9ad9l1omxzbwfr2niq0ce1ly%26oauth_token%3D7116b4d0c72c2736561853d9e50113%26service%3Dv2_prod&oauth_token=7116b4d0c72c2736561853d9e50113&oauth_token_secret=3b7612b5d3&oauth_callback_confirmed=true&oauth_consumer_key=9ad9l1omxzbwfr2niq0ce1ly&oauth_callback=http%3A%2F%2Flocalhost%3A3017%2F
? loResp.BodyStr

// We'll need this for later..
loHashTab = createobject("CkHashtable")
loHashTab.AddQueryParams(loResp.BodyStr)

lcRequestToken = loHashTab.LookupStr("oauth_token")
lcRequestTokenSecret = loHashTab.LookupStr("oauth_token_secret")
loHttp.OAuthTokenSecret = lcRequestTokenSecret

? "oauth_token = " + lcRequestToken
? "oauth_token_secret = " + lcRequestTokenSecret

// ---------------------------------------------------------------------------
// 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.
loSbUrlForBrowser = createobject("CkStringBuilder")
loSbUrlForBrowser.Append(lcAuthorizeUrl)
loSbUrlForBrowser.Append("?")
loSbUrlForBrowser.Append(loResp.BodyStr)
lcUrl = loSbUrlForBrowser.GetAsString()

// When the url is loaded into a browser, the response from Etsy 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.
loListenSock = createobject("CkSocket")

lnBackLog = 5
llSuccess = loListenSock.BindAndListen(lnCallbackLocalPort,lnBackLog)
if (llSuccess = .F.) then
    ? loListenSock.LastErrorText
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    return
endif

// 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.
loSock = createobject("CkSocket")
lnMaxWaitMs = 60000
loTask = loListenSock.AcceptNextAsync(lnMaxWaitMs,loSock)
loTask.Run()

// Launch the system's default browser navigated to the URL.
loOauth2 = createobject("CkOAuth2")
llSuccess = loOauth2.LaunchBrowser(lcUrl)
if (llSuccess = .F.) then
    ? loOauth2.LastErrorText
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    release loSock
    release loOauth2
    return
endif

// Wait for the listenSock's task to complete.
llSuccess = loTask.Wait(lnMaxWaitMs)
if (not llSuccess or (loTask.StatusInt <> 7) or (loTask.TaskSuccess <> .T.)) then
    if (not llSuccess) then
        // The task.LastErrorText applies to the Wait method call.
        ? loTask.LastErrorText
    else
        // The ResultErrorText applies to the underlying task method call (i.e. the AcceptNextConnection)
        ? loTask.Status
        ? loTask.ResultErrorText
    endif

    release loTask
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    release loSock
    release loOauth2
    return
endif

// 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.
loListenSock.Close(10)

release loTask

// Read the start line of the request..
lcStartLine = loSock.ReceiveUntilMatch(Chr(13) + Chr(10))
if (loSock.LastMethodSuccess = .F.) then
    ? loSock.LastErrorText
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    release loSock
    release loOauth2
    return
endif

// Read the request header.
lcRequestHeader = loSock.ReceiveUntilMatch(Chr(13) + Chr(10) + Chr(13) + Chr(10))
if (loSock.LastMethodSuccess = .F.) then
    ? loSock.LastErrorText
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    release loSock
    release loOauth2
    return
endif

// 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.
loSbResponseHtml = createobject("CkStringBuilder")
loSbResponseHtml.Append("<html><body><p>Chilkat thanks you!</b></body</html>")

loSbResponse = createobject("CkStringBuilder")
loSbResponse.Append("HTTP/1.1 200 OK" + Chr(13) + Chr(10))
loSbResponse.Append("Content-Length: ")
loSbResponse.AppendInt(loSbResponseHtml.Length)
loSbResponse.Append(Chr(13) + Chr(10))
loSbResponse.Append("Content-Type: text/html" + Chr(13) + Chr(10))
loSbResponse.Append(Chr(13) + Chr(10))
loSbResponse.AppendSb(loSbResponseHtml)

loSock.SendString(loSbResponse.GetAsString())
loSock.Close(50)

// The information we need is in the startLine.
// For example, the startLine will look like this:
//  GET /?oauth_token=a3bc8bec84acc31418b68a532e9511&oauth_verifier=b5558d37 HTTP/1.1
loSbStartLine = createobject("CkStringBuilder")
loSbStartLine.Append(lcStartLine)
lnNumReplacements = loSbStartLine.Replace("GET /?","")
lnNumReplacements = loSbStartLine.Replace(" HTTP/1.1","")
loSbStartLine.Trim()

// oauth_token=a3bc8bec84acc31418b68a532e9511&oauth_verifier=b5558d37
? "startline: " + loSbStartLine.GetAsString()

loHashTab.Clear()
loHashTab.AddQueryParams(loSbStartLine.GetAsString())

lcRequestToken = loHashTab.LookupStr("oauth_token")
lcAuthVerifier = loHashTab.LookupStr("oauth_verifier")

// ------------------------------------------------------------------------------
// Finally , we must exchange the OAuth Request Token for an OAuth Access Token.

loHttp.OAuthToken = lcRequestToken
loHttp.OAuthVerifier = lcAuthVerifier

loReq.HttpVerb = "POST"
loReq.ContentType = "application/x-www-form-urlencoded"

llSuccess = loHttp.HttpReq(lcAccessTokenUrl,loReq,loResp)
if (llSuccess = .F.) then
    ? loHttp.LastErrorText
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    release loSock
    release loOauth2
    release loSbResponseHtml
    release loSbResponse
    release loSbStartLine
    return
endif

// Make sure a successful response was received.
if (loResp.StatusCode <> 200) then
    ? loResp.StatusLine
    ? loResp.Header
    ? loResp.BodyStr
    release loHttp
    release loReq
    release loResp
    release loHashTab
    release loSbUrlForBrowser
    release loListenSock
    release loSock
    release loOauth2
    release loSbResponseHtml
    release loSbResponse
    release loSbStartLine
    return
endif

// If successful, the resp.BodyStr contains something like this:
// oauth_token=7898d7ba280dc791586dcfd26b37a9&oauth_token_secret=f2a7c267aa
? loResp.BodyStr

loHashTab.Clear()
loHashTab.AddQueryParams(loResp.BodyStr)

lcAccessToken = loHashTab.LookupStr("oauth_token")
lcAccessTokenSecret = loHashTab.LookupStr("oauth_token_secret")

// The access token + secret is what should be saved and used for
// subsequent REST API calls.
? "Access Token = " + lcAccessToken
? "Access Token Secret = " + lcAccessTokenSecret

// Save this access token for future calls.
// Just in case we need user_id and screen_name, save those also..
loJson = createobject("CkJsonObject")
loJson.AppendString("oauth_token",lcAccessToken)
loJson.AppendString("oauth_token_secret",lcAccessTokenSecret)

loFac = createobject("CkFileAccess")
loFac.WriteEntireTextFile("qa_data/tokens/etsy.json",loJson.Emit(),"utf-8",.F.)

? "Success."


release loHttp
release loReq
release loResp
release loHashTab
release loSbUrlForBrowser
release loListenSock
release loSock
release loOauth2
release loSbResponseHtml
release loSbResponse
release loSbStartLine
release loJson
release loFac