// // EtsyRESTConnectionManager.swift // Vendoo // // Created by Okechi Onyeje on 5/25/16. // Copyright © 2016 Okechi Onyeje. All rights reserved. // //NOT ABLE TO CAPTURE NEEDED DATA FROM RESPONSE IN OAUTH PROCESS FOR ETSY import Foundation import SwiftyJSON import OAuthSwift import Locksmith typealias ServiceResponse = (AnyObject?, NSError?) -> Void class EtsyRESTAPIManager: NSObject { //API Manager class variables //----------------------------------------------// static let sharedInstance = EtsyRESTAPIManager() let baseURL = "https://openapi.etsy.com/v2/private" private var apiKey: String! private var apiSecret: String! private var userEmail:String = (NSUserDefaults.standardUserDefaults().objectForKey("email") as? String)! var isAuthorized: Bool = NSUserDefaults.standardUserDefaults().boolForKey("etsyAuthorized") static var settingsDictionary = Dictionary() //---------------------------------------------// //User specific class variables private var etsyUser: String! private var oauthswift: OAuth1Swift! //private let oauthswift = OAuth1Swift(parameters: ["consumerKey":"snbs78qkfy3yqq6yhe6yv49b","consumerSecret":"4sbva4oqb6", "requestTokenUrl": "https://openapi.etsy.com/v2/oauth/request_token?scope=listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w%20"]) override init(){ if let path = NSBundle.mainBundle().pathForResource("Services", ofType: "plist"), dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] { // use swift dictionary as normal self.apiKey = ((dict["Etsy"] as! Dictionary)["consumerKey"] as! String) self.apiSecret = ((dict["Etsy"] as! Dictionary)["consumerSecret"] as! String) oauthswift = OAuth1Swift(parameters: ["consumerKey":self.apiKey,"consumerSecret":self.apiSecret, "requestTokenUrl" : "https://openapi.etsy.com/v2/oauth/request_token?scope=listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w", "authorizeUrl": "https://www.etsy.com/oauth/signin?", "accessTokenUrl": "https://openapi.etsy.com/v2/oauth/access_token?", "responseType": "token"]) //FIXME: something is wrong when here when logging back in with a diff user if(self.isAuthorized){ let dictionary = Locksmith.loadDataForUserAccount(self.userEmail, inService: "vendoo_oauth_etsy") let oauthDictionary = dictionary?["etsy_oauth"] as? Dictionary print((oauthDictionary?["token"] as? String!)!) self.oauthswift.client.credential.oauth_token = (oauthDictionary?["token"] as? String!)! self.oauthswift.client.credential.oauth_token_secret = (oauthDictionary?["secret"] as? String!)! } /*scope=listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w"*/ if(NSUserDefaults.standardUserDefaults().boolForKey("etsyDefaultsOverriden")) { EtsyRESTAPIManager.settingsDictionary = (NSUserDefaults.standardUserDefaults().objectForKey("etsySettings") as? Dictionary)! } else{ EtsyRESTAPIManager.settingsDictionary = ([ "who_made":"i_did", "is_supply":true, "when_made":"made_to_order" ] as Dictionary) NSUserDefaults.standardUserDefaults().setObject(EtsyRESTAPIManager.settingsDictionary, forKey: "etsySettings") NSUserDefaults.standardUserDefaults().setBool(true, forKey: "etsyDefaultsOverriden") } } } } //Mark: - OAuth Methods extension EtsyRESTAPIManager { //makes application ready for use with users etsy account func authorizeApp(viewcontroller: UIViewController){ var boolResult: Bool! if(!isAuthorized){ oauthswift!.authorize_url_handler = SafariURLHandler(viewController: viewcontroller) /* let authRequest = self.oauthswift.client.makeRequest("https://openapi.etsy.com/v2/oauth/request_token?", method: OAuthSwiftHTTPRequest.Method.GET, parameters: ["scope":"listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w"] , headers: nil) do{ try authRequest?.makeRequest() }catch{ (error) } */ /*["scope":"listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w"]*/ self.oauthswift!.client.get("https://openapi.etsy.com/v2/oauth/request_token?scope=listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w", success: { data, response in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) //print(response.allHeaderFields) //print(dataSting) let json = JSON(data) print(json) print(dataString) self.oauthswift!.authorizeWithCallbackURL( NSURL(string: "vendoo://oauth-callback/etsy")!, success: { credential, response, parameters in print(credential.oauth_token) print(credential.oauth_token_secret) print(response) boolResult = false }, failure: { error in //print(error) dispatch_async(dispatch_get_main_queue(), {() -> Void in print(self.oauthswift!.client.credential.oauth_token) print(self.oauthswift!.client.credential.oauth_token_secret) print(self.oauthswift.client.credential.oauth_verifier) print(self.oauthswift.allowMissingOauthVerifier = true) //save data to keychain self.oauthswift!.client.get("https://openapi.etsy.com/v2/oauth/access_token", parameters: ["oauth_verifier":(self.oauthswift.client.credential.oauth_verifier)], success: { data, response in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) print(response) let json1 = JSON(response) print(json1) //print(response.allHeaderFields) //print(dataSting) let json = JSON(data) print(json) print(dataString!) //parse out token and token secret do { let regex = try NSRegularExpression(pattern: "[oauth_token=|oauth_token_secret=](\\w*)", options: []) let nsString = dataString! as NSString let all = NSRange(location: 0, length: nsString.length) var matches : [String] = [String]() regex.enumerateMatchesInString(nsString as String, options: NSMatchingOptions(rawValue: 0), range: all) { (result : NSTextCheckingResult?, _, _) in if let r = result { let result = nsString.substringWithRange(r.range) as String matches.append(result) } } print(matches) let oauth: Dictionary? = [ "token" : String(matches[1].characters.dropFirst()) , "secret" : String(matches[3].characters.dropFirst()) ] do{ try Locksmith.saveData(["etsy_oauth" : oauth!], forUserAccount: self.userEmail, inService: "vendoo_oauth_etsy") print("account credentials saved") NSUserDefaults.standardUserDefaults().setBool(true, forKey: "etsyAuthorized") self.isAuthorized = true boolResult = true self.oauthswift.client.credential.oauth_token = oauth!["token"]! as! String self.oauthswift.client.credential.oauth_token_secret = oauth!["secret"]! as! String self.oauthswift!.client.get("https://openapi.etsy.com/v2/users/__SELF__", success: { data, response in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) var dict2 = (dict!["results"] as! [[String : AnyObject]]) let json1 = JSON(dataString!) print(json1) print(dataString) boolResult = true print(dict2[0]["login_name"]!) EtsyRESTAPIManager.settingsDictionary["userID"] = dict2[0]["login_name"]! NSUserDefaults.standardUserDefaults().setObject(EtsyRESTAPIManager.settingsDictionary, forKey: "etsySettings") self.sendGETRequest("/shops/__SELF__/payment_templates", onCompletion: { (data, error) -> Void in self.sendGETRequest("/users/__SELF__/shipping/templates", onCompletion: nil) }) } , failure: { error in print(error) boolResult = true } ) } catch{ (error) print(error) //could not save data to keychain print("account credentials could not be saved") boolResult = false } /*let results = regex.matchesInString(dataString! as String, options: [], range: NSMakeRange(0, nsString.length)) print(results.map { nsString.substringWithRange($0.range)})*/ } catch let error as NSError { print("invalid regex: \(error.localizedDescription)") } /* */ }, failure: { error in print(error) }) //return boolResult }) }) //getting error here when trying to retrieve the login url from the response //var dataDictionary = self.convertStringToDictionary(dataString! as String) //print(dataDictionary!["login_url"]) } , failure: { error in print(error) } ) } //once everything is authorized save true value to the authorization boolean /* NSUserDefaults.standardUserDefaults().setBool(true, forKey: "etsyAuthorized") self.isAuthorized = NSUserDefaults.standardUserDefaults().boolForKey("etsyAuthorized") */ } func deAuthorizeApp(viewcontroller: UIViewController){ oauthswift!.authorize_url_handler = SafariURLHandler(viewController: viewcontroller) oauthswift!.client.get("https://openapi.etsy.com/v2/oauth/request_token?scope=listings_w%20listings_r%20listings_d%20transactions_r%20transactions_w", success: { data, response in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) print(dataString!) print(response) //getting error here when trying to retrieve the login url from the response //var dataDictionary = self.convertStringToDictionary(dataString! as String) //print(dataDictionary!["login_url"]) } , failure: { error in print(error) } ) dispatch_async(dispatch_get_main_queue(), {() -> Void in self.oauthswift!.authorizeWithCallbackURL( NSURL(string: "vendoo://oauth-callback/etsy")!, success: { credential, response, parameters in print(credential.oauth_token) print(credential.oauth_token_secret) print(response) //erase all authorization variables do { try Locksmith.deleteDataForUserAccount(self.userEmail, inService: "vendoo_oauth_etsy") self.oauthswift.client.credential.oauth_token = "" self.oauthswift.client.credential.oauth_token_secret = "" NSUserDefaults.standardUserDefaults().setBool(false, forKey: "etsyAuthorized") self.isAuthorized = false print("oauth credentials deleted and app deauthorized from etsy") }catch{ (error) print(error) ("failed to delete credentails and deauthorize app") } }, failure: { error in print(error) dispatch_async(dispatch_get_main_queue(), {() -> Void in //erase all authorization variables do { try Locksmith.deleteDataForUserAccount(self.userEmail, inService: "vendoo_oauth_etsy") self.oauthswift.client.credential.oauth_token = "" self.oauthswift.client.credential.oauth_token_secret = "" NSUserDefaults.standardUserDefaults().setBool(false, forKey: "etsyAuthorized") self.isAuthorized = false print("oauth credentials deleted and app deauthorized from etsy") }catch{ (error) print(error) ("failed to delete credentails and deauthorize app") } }) }) }) } } //MARK: - Request Methods extension EtsyRESTAPIManager { func generateUserRequest(etsyName: String!, etsyOptions: [String]!) -> String { //starting url for user request to api var userRequest: String! if(etsyName == nil || etsyName == ""){ userRequest = (baseURL + "/users/etsystore?") } else{ userRequest = (baseURL + "/users/" + etsyName + "?") } //final api request return userRequest + "api_key=" + self.apiKey } func generateListingRequest(etsyListing: String!){ //starting url for listing request } //sends the pregenerated url as a request to api service func sendGETRequest(request: String, onCompletion: ServiceResponse?) { /* let request = NSMutableURLRequest(URL: NSURL(string: request)!) let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in if let jsonData = data { let json:JSON = JSON(data: jsonData) onCompletion(json, error) } else { onCompletion(nil, error) } }) task.resume()*/ self.oauthswift.client.get(self.baseURL + request, success: { (data, response) -> Void in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) switch (request) { case "/shops/__SELF__/payment_templates" : if ((dict!["results"]!.isKindOfClass(NSNull.classForCoder()))) { //@TODO: Put payment template parameters in function call self.oauthswift.client.post(self.baseURL + "/shops/__SELF__/payment_templates", parameters: [ "shop_id":"__SELF__", ], headers: nil, success: { (data, response) -> Void in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) onCompletion!(nil,nil) }, failure: { (error) -> Void in print(error) } ) } break case "/users/__SELF__/shipping/templates" : var dict2 = (dict!["results"] as! [[String : AnyObject]]) if ((dict!["results"]!.isKindOfClass(NSNull.classForCoder()))) { //@TODO: Put payment template parameters in function call self.oauthswift.client.post(self.baseURL + "/shipping/templates", parameters: [ "title":"vendoo_default", "origin_country_id":209, "primary_cost":2.00, "secondary_cost":1.00 ], headers: nil, success: { (data, response) -> Void in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) }, failure: { (error) -> Void in print(error) } ) }else { EtsyRESTAPIManager.settingsDictionary["shipping_template_id"] = dict2[0]["shipping_template_id"]! NSUserDefaults.standardUserDefaults().setObject(EtsyRESTAPIManager.settingsDictionary, forKey: "etsySettings") } break default: break } }, failure: { (error) -> Void in print(error) } ) } //sends the pregenerated url as a request to api service func sendPOSTRequest(request: String, var body: [String: AnyObject], onCompletion: ServiceResponse?) { /* let request = NSMutableURLRequest(URL: NSURL(string: request)!) // Set the method to POST request.HTTPMethod = "POST" do { // Set the POST body for the request let jsonBody = try NSJSONSerialization.dataWithJSONObject(body, options: .PrettyPrinted) request.HTTPBody = jsonBody let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in if let jsonData = data { let json:JSON = JSON(data: jsonData) onCompletion(json, nil) } else { onCompletion(nil, error) } }) task.resume() } catch { // Create your personal error onCompletion(nil, nil) }*/ if(request.containsString("listings/") && request.containsString("/images")){ let url = NSURL(string: self.baseURL + request)! let requested = NSMutableURLRequest(URL: url) requested.HTTPMethod = "POST" let boundary = "Boundary-\(NSUUID().UUIDString)" /*var headers = oauthswift.client.credential.makeHeaders(url, method: OAuthSwiftHTTPRequest.Method.POST, parameters: ["Content-Type":"multipart/form-dataheader"]) // here with create the authentification headers requested.addValue(self.apiKey, forHTTPHeaderField: "Authorization" ) //define the multipart request type requested.addValue("\((body["image"] as! NSData).length)", forHTTPHeaderField: "Content-Length") requested.addValue("bytes", forHTTPHeaderField: "Content-Transfer-Encoding") requested.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") //requested.addValue(self.apiKey, forHTTPHeaderField: "API-KEY") requested.HTTPBody = self.oauthswift.client.multiPartBodyFromParams(body, boundary: boundary) /*let body1 = NSMutableData() let fname = "main.jpg" let mimetype = "image/jpg" //define the data post parameter body1.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData("Content-Disposition:form-data; name=\"listing_id\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData("\(body["listing_id"] as! Int)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData("Content-Disposition:form-data; name=\"image\"; filename=\"\(fname)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData("Content-Type: \(mimetype)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData((body["image"] as! NSData)) body1.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body1.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) requested.HTTPBody = body1*/ let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(requested) { data, response, error in if nil != error { // something went wrong print(error) onCompletion!(nil,nil) switch (request) { default: break } } else { let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) onCompletion!(nil, nil) switch (request) { default: break } } } task.resume()*/ /* //var headers = oauthswift.client.credential.makeHeaders(url, method: OAuthSwiftHTTPRequest.Method.POST, parameters: ["Content-Type":"multipart/form-dataheader"]) // here with create the authentification headers // here add additional headers "Content-type", etc.. requested.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") requested.addValue("\((body["image"] as! NSData).length)", forHTTPHeaderField: "Content-Length") requested.addValue("bytes", forHTTPHeaderField: "Content-Transfer-Encoding") //requested.addValue("form-data; name='Main Image'; filename='mainImage.jpg'", forHTTPHeaderField: "Content-Disposition") requested.HTTPBody = self.oauthswift.client.multiPartBodyFromParams(body, boundary: "-XXX--") let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(requested) { data, response, error in if nil != error { // something went wrong print(error) onCompletion!(nil,nil) switch (request) { default: break } } else { let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) onCompletion!(nil, nil) switch (request) { default: break } } } task.resume() */ //body["oauth_verifier"] = (self.oauthswift.client.credential.oauth_verifier) //@FIXME: multipart post request is returning with oauth signature invalid for uploading image in etsy self.oauthswift.client.postMultiPartRequest(self.baseURL + request, method: OAuthSwiftHTTPRequest.Method.POST, parameters: body, success: { (data, response) -> Void in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) onCompletion!(nil, nil) switch (request) { default: break } }, failure: { (error) -> Void in print(error) onCompletion!(nil,nil) switch (request) { default: break } } ) }else { self.oauthswift.client.post(self.baseURL + request, parameters: body, headers: nil, success: { (data, response) -> Void in let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) let dict = self.convertStringToDictionary(dataString! as String) print(dict) print(response) switch (request) { case "/shipping/templates": break case "/listings": var dict2 = (dict!["results"] as! [[String : AnyObject]]) print(((dict2[0]["listing_id"])!)) onCompletion!(dict2, nil) break default: break } }, failure: { (error) -> Void in print(error) switch (request) { case "/shipping/templates": break case "/listings": print(error.userInfo["Response-Body"]) if((error.userInfo["Response-Body"]!.isEqualToString("price is below listing fee."))) { //@TODO: add alert to let user know that the price they have given is too low for etsy } break default: break } } ) } } } //MARK: - JSON Methods extension EtsyRESTAPIManager { func convertStringToDictionary(text: String) -> [String:AnyObject]? { if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { do { return try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject] } catch let error as NSError { print(error) } } return nil } }