Sample code for 30+ languages & platforms
Swift

QuickBooks - Automatically Refresh Access Token with No User Interaction

See more QuickBooks Examples

Demonstrates how to automaticaly refresh an expired access token and retry the request after a 401 authorization error.

Chilkat Swift Downloads

Swift

func chilkatTest() {
    var success: Bool = false

    // This example assumes the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    // Get our previously obtained OAuth2 access token, which should contain JSON like this:
    // {
    //   "expires_in": 3600,
    //   "x_refresh_token_expires_in": 8726400,
    //   "refresh_token": "L011546037639r ... 3vR2DrbOmg0Sdagw",
    //   "access_token": "eyJlbmMiOiJBMTI4Q0 ... oETJEMbeggg",
    //   "token_type": "bearer"
    // }

    let jsonToken = CkoJsonObject()!
    success = jsonToken.loadFile(path: "qa_data/tokens/qb-access-token.json")

    let rest = CkoRest()!

    // Connect using TLS.
    // A single REST object, once connected, can be used for many Quickbooks REST API calls.
    // The auto-reconnect indicates that if the already-established HTTPS connection is closed,
    // then it will be automatically re-established as needed.
    var bAutoReconnect: Bool = true
    success = rest.connect(hostname: "sandbox-quickbooks.api.intuit.com", port: 443, tls: true, autoReconnect: bAutoReconnect)
    if success == false {
        print("\(rest.lastErrorText!)")
        return
    }

    let sbAuth = CkoStringBuilder()!
    sbAuth.append(value: "Bearer ")
    sbAuth.append(value: jsonToken.string(of: "access_token"))
    rest.authorization = sbAuth.getAsString()

    rest.addHeader(name: "Accept", value: "application/json")
    rest.allowHeaderFolding = false

    // The company ID is 123146096291789
    // The employee ID is 58
    var responseBody: String? = rest.fullRequestNoBody(httpVerb: "GET", uriPath: "/v3/company/123146096291789/employee/58?minorversion=45")
    if rest.lastMethodSuccess == false {
        print("\(rest.lastErrorText!)")
        return
    }

    // If we get a 401 authorization error, then it's likely because the access token expired.
    // We can automatically refresh it without interaction from the user.
    if rest.responseStatusCode.intValue == 401 {

        let oauth2 = CkoOAuth2()!

        oauth2.tokenEndpoint = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"

        // Replace these with actual values.
        oauth2.clientId = "QUICKBOOKS-CLIENT-ID"
        oauth2.clientSecret = "QUICKBOOKS-CLIENT-SECRET"

        // Get the "refresh_token"
        oauth2.refreshToken = jsonToken.string(of: "refresh_token")

        // Send the HTTP POST to refresh the access token..
        success = oauth2.refreshAccessToken()
        if success == false {
            print("\(oauth2.lastErrorText!)")
            return
        }

        print("New access token: \(oauth2.accessToken!)")

        // Update the JSON with the new tokens.
        jsonToken.updateString(jsonPath: "access_token", value: oauth2.accessToken)

        // Save the new JSON access token response to a file.
        // The access + refresh tokens contained in this JSON will be needed for the next refresh.
        let sbJson = CkoStringBuilder()!
        jsonToken.emitCompact = false
        jsonToken.emitSb(sb: sbJson)
        sbJson.writeFile(path: "qa_data/tokens/qb-access-token.json", charset: "utf-8", emitBom: false)

        print("OAuth2 token refreshed!")
        print("New Access Token = \(oauth2.accessToken!)")

        sbAuth.clear()
        sbAuth.append(value: "Bearer ")
        sbAuth.append(value: oauth2.accessToken)
        rest.authorization = sbAuth.getAsString()

        // Now retry the request with the refreshed access token...
        responseBody = rest.fullRequestNoBody(httpVerb: "GET", uriPath: "/v3/company/123146096291789/employee/58?minorversion=45")
        if rest.lastMethodSuccess == false {
            print("\(rest.lastErrorText!)")
            return
        }

    }

    // We should expect a 200 response if successful.
    if rest.responseStatusCode.intValue != 200 {
        print("Request Header: ")
        print("\(rest.lastRequestHeader!)")
        print("----")
        print("Response StatusCode = \(rest.responseStatusCode.intValue)")
        print("Response StatusLine: \(rest.responseStatusText!)")
        print("Response Header:")
        print("\(rest.responseHeader!)")
        print("\(responseBody!)")
        return
    }

    // Load the JSON response into a JSON object for parsing.
    // A sample JSON response is shown below.
    let json = CkoJsonObject()!
    json.load(json: responseBody)

    // These will be used for parsing date/time strings..
    let dtime = CkoDateTime()!
    var bLocalTime: Bool = true

    // Show the JSON.   
    json.emitCompact = false
    print("\(json.emit()!)")

    // Get some information from the JSON..
    print("Name: \(json.string(of: "Employee.DisplayName")!)")
    print("Id: \(json.string(of: "Employee.Id")!)")
    print("City: \(json.string(of: "Employee.PrimaryAddr.City")!)")
    print("PostalCode: \(json.string(of: "Employee.PrimaryAddr.PostalCode")!)")

    // Load the CreateTime into a CkDateTime...
    dtime.set(fromTimestamp: json.string(of: "Employee.MetaData.CreateTime"))
    let dt = CkoDtObj()!
    dtime.toDtObj(bLocal: bLocalTime, dtObj: dt)

    print("\(dt.month.intValue)/\(dt.day.intValue)/\(dt.year.intValue)  \(dt.hour.intValue):\(dt.minute.intValue)")

    print("Success.")

    // Use this online tool to generate parsing code from sample JSON: 
    // Generate Parsing Code from JSON

    // ------------------------------------------------------
    // The JSON response looks like this:

    // {
    //   "Employee": {
    //     "SSN": "XXX-XX-XXXX",
    //     "PrimaryAddr": {
    //       "Id": "116",
    //       "Line1": "45 N. Elm Street",
    //       "City": "Middlefield",
    //       "CountrySubDivisionCode": "CA",
    //       "PostalCode": "93242"
    //     },
    //     "BillableTime": false,
    //     "domain": "QBO",
    //     "sparse": false,
    //     "Id": "98",
    //     "SyncToken": "0",
    //     "MetaData": {
    //       "CreateTime": "2015-07-24T09:34:35-07:00",
    //       "LastUpdatedTime": "2015-07-24T09:34:35-07:00"
    //     },
    //     "GivenName": "Bill",
    //     "FamilyName": "Miller",
    //     "DisplayName": "Bill Miller",
    //     "PrintOnCheckName": "Bill Miller",
    //     "Active": true,
    //     "PrimaryPhone": {
    //       "FreeFormNumber": "234-525-1234"
    //     }
    //   },
    //   "time": "2015-07-24T09:35:54.805-07:00"
    // 

}