Jon Cook Jon Cook - 2 months ago 22
HTTP Question

Using Freshdesk API from Swift 2.2

I'm trying to retrieve all tickets from FreshDesk using their API from a Swift 2.2 program (Here's the API)

The following curl works:

curl -v -u myEmail@example.com:myPassword -X GET 'https://mydomain.freshdesk.com/api/v2/tickets'


and I've created this function to retrieve the tickets:

func getAllTickets() {
let username = "myEmail@example.com"
let password = "myPassword"

let loginString = "\(username):\(password)"
let loginData = loginString.data(using: .utf8)
let base64LoginString = loginData?.base64EncodedString(options: [])

if let url = NSURL(string: "https://mydomain.freshdesk.com/api/v2/tickets"){
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "GET"
request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")

let session = URLSession.shared
session.dataTask(with: request as URLRequest, completionHandler: { (returnData, response, error) -> Void in
if let error = error {
// couldn't even make the call - probably no network...
// maybe save it in the DB for next time?
print("Error connecting to Freshdesk API - error is: \(error.localizedDescription)")

if error.localizedDescription == "The Internet connection appears to be offline" {
// TODO - save error up until next time
}
return
}
let strData = NSString(data: returnData!, encoding: String.Encoding.utf8.rawValue)
print("GOT RESULT: \(strData)")
}).resume()
}
}


The output I get is:
GOT RESULT: Optional({"code":"invalid_credentials","message":"You have to be logged in to perform this action."})

But I'm sure the username/password is correct given that the curl works

Answer

OK, I figured it myself, just in case others are trying to do the same... I'm using Alamofire for the networking. It's a slightly old version of Alamofire (3.4.???) because that's what cocoapods thought was the latest for OSX. So, you might need to update the Alamofire calls a bit if using 4.x - shouldn't be hard though

Note that using the Alamofire authentication didn't work for me, which is why I'm building the base64Credentials myself

So here's how to retrieve tickets

func retrieveFreshdeskTickets() {

    let user = "yourFreshDeskEmail@whatever.com"
    let password = "yourFreshDeskPassword"
    let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
    let base64Credentials = credentialData.base64EncodedStringWithOptions([])
    let headers = ["Authorization": "Basic \(base64Credentials)"]

    let freshDeskEndPoint: String = "https://yourDomainName.freshdesk.com/api/v2/tickets"

    Alamofire.request(.GET, freshDeskEndPoint, headers: headers)
        .responseJSON { response in
            guard response.result.error == nil else {
                print("error retrieving freshdesk tickets")
                print(response.result.error!)
                return
            }

            if let value = response.result.value {
                // print the tickets
                print(value)
            }
    }
}

and here's how to post a ticket

func raiseFreshdeskTicket(description: String,
                          subject: String,
                          usersEmail: String,
                          priority: Int,
                          status: Int,
                          ccEmails: [String],
                          type: String ) {

    let user = "yourFreshDeskEmail@whatever.com"
    let password = "yourFreshDeskPassword"
    let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
    let base64Credentials = credentialData.base64EncodedStringWithOptions([])
    let headers = ["Authorization": "Basic \(base64Credentials)"]

    let parameters = [
        "description": description,
        "subject": subject,
        "email": usersEmail,
        "priority": priority ,
        "status": status,
        "cc_emails": ccEmails,
        "type": type
        ] as [String : AnyObject]

    let freshDeskEndPoint: String = "https://yourDomainName.freshdesk.com/api/v2/tickets"

    Alamofire.request(.POST, freshDeskEndPoint, headers: headers, parameters: parameters, encoding: .JSON)
        .responseJSON { response in
            guard response.result.error == nil else {
                print("error calling adding freshdesk ticket")
                print(response.result.error!)
                return
            }
            if let value = response.result.value {
                print(value)
            }
    }

}

And here's an example of calling the post function

let errorDescription = "Log from program - this is what went wrong"
raiseFreshdeskTicket(errorDescription, subject: "Automated Error report from <your program name>", usersEmail: "yourAppUser@zing.com", priority: 1, status: 2, ccEmails: [], type: "Problem")
Comments