How to integrate FitBit Api in IOS app using Swift - ios

First of all I created an account at https://www.fitbit.com
Then I careated an app at https://dev.fitbit.com
then installed OAuthSwift using cocoa pods and implemented this method in my AppDelegate
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
if (url.host == "oauth-callback") {
OAuthSwift.handleOpenURL(url)
}
return true
}
now i want to get the data (Name, Steps taken etc) of user account I created at https://www.fitbit.com
how can I do that ? I searched but was not able to find any tutorial on fitbit integration. And where to use this information in my code?
So please guide me about next step what should I do to get the data.

FitBit work with OAuth 2.0 API which require Client ID and Secret key. You need these client id and secret key to authenticate with OAuth 2.0 API.
There is a blog post related to FitBit integration in iOS with Swift.
Lets checkout and learn "How to implement fitbit in iOS"
https://appengineer.in/2016/04/30/fitbit-aouth-in-ios-app/
ex:
let oauthswift = OAuth2Swift(
consumerKey: fitbit_clientID,
consumerSecret: fitbit_consumer_secret,
authorizeUrl: "https://www.fitbit.com/oauth2/authorize",
accessTokenUrl: "https://api.fitbit.com/oauth2/token",
responseType: "token"
)

Any chance you could do it with basic auth as opposed to OAuth? I had a similar problem trying to POST to MailGun for some automated emails I was implementing in an app.
I was able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "bar#foo.com"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler#<my domain>.com%3E&to=reservations#<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:
https://API:key-<my key>#api.mailgun.net/v3/<my domain>.com/messages?
Hope this helps!

Related

Sending HTTP POST request with Swift to Discord Webhook results in Response Error

I'm trying to create a URL Request in Swift to send an HTTP POST request to a Discord Webhook, and the request completes in a failure defined as 'responseProblem'. I'm not sure where the response problem is originating from.
Discord should technically be able to accept HTTP requests, and a bunch of research into the issue has led me nowhere. I've worked with Discord webhooks before, but I've never played around with this kind of stuff before, so I'm kinda stuck for what I should do now.
import Foundation
enum APIError:Error {
case responseProblem
case decodingProblem
case encodingProblem
}
struct APIRequest {
let resourceURL: URL
init(endpoint: String) {
let resourceString = "<discord-webhook-url-removed-for-privacy>"
guard let resourceURL = URL(string: resourceString) else {fatalError()}
self.resourceURL = resourceURL
}
func save (_ messageToSave:Message, completion: #escaping(Result<Message, APIError>) -> Void ) {
do {
var urlRequest = URLRequest(url: resourceURL)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpBody = try JSONEncoder().encode(messageToSave)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, _ in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, let
jsonData = data else {
completion(.failure(.responseProblem)) // <<< 'responseProblem' is outputted in console as the error
return
}
do {
let messageData = try JSONDecoder().decode(Message.self, from: jsonData)
completion(.success(messageData))
} catch {
completion(.failure(.decodingProblem))
}
}
dataTask.resume()
} catch {
completion(.failure(.encodingProblem))
}
}
}
When I run this Swift program, I expected it to send a request to the Discord Webhook to send a message into it's designated channel. However, the only error outputted into the console is responseProblem. Please let me know if there is anything further I need to add to get the root cause of the problem (I'm still semi-fresh to Swift, and I normally work with JavaScript, so I'm not sure how to properly debug in Swift and Xcode.)
Swift app is built in iOS 12.2 because Xcode doesn't like this stuff in iOS 13
This is a simplified version of how I post to a Discord webhook with Swift. From your post I can't see how you're converting your custom Message struct into a JSON dictionary, but you need at least the key/value pair for "content" to successfully post a Discord Webhook. And of course the posts can be customized in many other ways (with a custom "username" etc.).
var messageString: String = ""
guard let url = URL(string: "your-full-discord-webhook-url") else { return }
let messageJson: [String: Any] = ["content": messageString]
let jsonData = try? JSONSerialization.data(withJSONObject: messageJson)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "content-type")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request)
task.resume()

Oauth1 iOS get data from API

How to get data from API with Oauth1? I just tried like this but it did not work.
import UIKit
import OAuthSwift
class TestLogin: UIViewController {
var oauthswift: OAuthSwift?
final let urlString = "https://conversation.8villages.com/1.0/contents/articles"
override func viewDidLoad() {
super.viewDidLoad()
self.doOAuth()
}
func doOAuth()
{
let oauthswift = OAuth1Swift(
consumerKey: "******",
consumerSecret: "******",
requestTokenUrl: "https://oauth.8villages.com/tokens/request-token",
authorizeUrl: "https://accounts.8villages.com/oauth/request-token",
accessTokenUrl: "https://accounts.8villages.com/oauth/access-token"
)
oauthswift.authorize(
withCallbackURL: URL(string: "https://8villages.com")!,
success: { credential, response, parameters in
print(credential.oauthToken)
print(credential.oauthTokenSecret)
print(parameters["userId"])
},
failure: { error in
print(error.localizedDescription)
}
)
}
func getHandleURL () {
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as? URL)!, completionHandler: { (data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
print(jsonObj!.value(forKey: "data"))
}
}).resume()
}
}
so, how must I do or I need a reference example get data from API with Oauth1? I just don't know how to start to build project with OAuth because I search in google, only tutorial OAuth for login with social media.
In order to send oAuth 1.0 request basically you need to calculate proper query string and body parameter which actually based on your server implementation.
You need to get following query param:
oauth_consumer_key
oauth_nonce
oauth_signature_method
oauth_timestamp
oauth_version
You can check this blog where all the params are explained in very good detail and also the signature process. Also this answer guide you how to create HMAC-SHA1 signature in iOS
In the end of this process you need to create signature based on signature method which your app and server both agreed upon.
Then a sample POST request should look like following: Which is taken from oAuth1 guide
POST /wp-json/wp/v2/posts
Host: example.com
Authorization: OAuth
oauth_consumer_key="key"
oauth_token="token"
oauth_signature_method="HMAC-SHA1"
oauth_timestamp="123456789",
oauth_nonce="nonce",
oauth_signature="..."
{
"title": "Hello World!"
}
Hope it helps.

Posting to a secure API with swift

I'm trying to post to an API secured with a key (MailGun) with swift but it appears that my key is never utilized as I receive a Forbidden 401 error (Unauthorized - No valid API key provided) according to https://documentation.mailgun.com/api-intro.html#errors
I've verified the URL and key are correct by posting using curl, but I am unable to figure out why my key is not used here. I'm hoping someone can point in the right direction as to why this isn't authenticating correctly
My code is as such but I have replaced all the personal info with <>:
// Email the FBO with desired information
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.mailgun.net/v3/<My Domain>/messages")!)
request.HTTPMethod = "POST"
let data = "from: Excited User <scheduler#<mg.mydomain.com>>&to: [bar#example.com,<my email>]&subject:Hello&text:Testinggsome Mailgun awesomness!"
request.HTTPBody = data.dataUsingEncoding(NSASCIIStringEncoding)
request.setValue("key-<my key>", forHTTPHeaderField: "api")
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
Update:
Banged away at it for a few hours and I still can't get my head around it. Maybe I'm not exactly sure what you mean? I can successfully get a response with curl by using:
curl -s --user 'api:key-<my personal key>' https://api.mailgun.net/v3/mg.<my domain>.com/messages -F from='Reservation Scheduler <scheduler#mg.<my domain>.com>' -F to=reservations#<my domain>.com -F subject='Curl Test' -F text='Test from terminal'
I tried inputting it explicitly like so:
request.setValue("api", forHTTPHeaderField: "username")
request.setValue("key-<my key>", forHTTPHeaderField: "password")
It looks to me like the basic auth credentials are never sent? How can I be sure that the fields are "user" and "password"?
After verifying my header appeared to be missing the authentication section of the header I was able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "bar#foo.com"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler#<my domain>.com%3E&to=reservations#<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:
https://API:key-<my key>#api.mailgun.net/v3/<my domain>.com/messages?
Hope this offers a solution to anyone else having issues with MailGun and wanting to avoid a 3rd party solution!

Google API Key issues with Google Places

I'm working on an app where I need to query places from the google places API and save the nearest place to the user's google account (they sign into the app through GIDSignIN). The Places API is activated in the console and they key is correct, however, the URL might be problematic and I keep getting this error...
Optional(["error_message": This IP, site or mobile application is not
authorized to use this API key. Request received from IP address
2607:f598:b349:fd01:94f8:7386:d82c:1b29, with empty referer,
"results": ( ), "status": REQUEST_DENIED, "html_attributions": ( )])
The method that is called to query the API, the current lat and on long come from the location manager (working fine)
func saveCurrentLocation() {
//API CALL
let latString = String(currentLat)
let longString = String(currentLong)
let apiString = NSString(format: "https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=500&types=food&sensor=true&key=AIzaSyDH0jNx1WJw0pkCzbc0xaHumDoDAYYWvtk", latString, longString)
let url = NSURL(string: apiString as String)
let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithURL(url!) { (data, response, error) -> Void in
if let urlContent = data {
do {
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.AllowFragments) as? [String:AnyObject]
print(jsonDictionary)
}
catch {
print("JSON error")
}
}
}
dataTask.resume()
}
Anyone able to help? Thanks!
This type of error usually comes when you not enable your Api on Google console. So please make your Api enable on Console.

Can any one tell me why i am getting Bad authentication error while executing this code(Swift)?

I am using Fabric SDK to add the twitter login button in my app.......
i add the authentication header in my URL but still it is showing Bad authentication error while executing.
Suggest me how to add Header in the URL in Swift.
let twitter = Twitter.sharedInstance()
let oauthSigning = TWTROAuthSigning(authConfig:twitter.authConfig, authSession:twitter.session())
let authHeaders = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.twitter.com/1.1/search/tweets.json?q=Himan_dhawan")!)
request.allHTTPHeaderFields = authHeaders
println(request)
var session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if((error) != nil) {
println(error.localizedDescription)
}
var strData = NSString(data: data, encoding: NSASCIIStringEncoding)
println(strData)
})
task.resume()
It's to do with the way that you're setting the headers on the request.
The Fabric doc's don't quite give you the full picture about creating the OAuth signing headers when wanting to use your own NSMutableURLRequest.
let authHeaders = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
The return [NSObject : AnyObject]! dictionary gives you the values you need for the request. However, what it provides for the headers are different to what needs to be sent with the NSMutableURLRequest.
This is how you should be setting the headers for this request:
let twitter = Twitter.sharedInstance()
let oauthSigning = TWTROAuthSigning(authConfig:twitter.authConfig, authSession:twitter.session())
let authHeaders = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
let mutableUrlWithUsableUrlAddress = NSMutableURLRequest(URL: usableUrlForRequest)
mutableUrlWithUsableUrlAddress.addValue(authHeaders[TWTROAuthEchoAuthorizationHeaderKey] as? String, forHTTPHeaderField: "Authorization")
This sets the required Authorisation Key as a value for the "Authorization" header on the request, opposed to when you pass in the authHeaders dictionary, it gets set for "X-Verify-Credentials-Authorization".
The Fabric doc's do go into this, but it's slightly more tucked away than it should be.

Resources