How to Access Magento Rest API in iOS swift 4 - swift

I am write code to post data from Magento REST API for IOS Application put get me error. I try from login and register view controller in the same code get me the same error
The api Magento REST API . I success to get data from api but error to post data in api
self.internetConnectionChecker { (status) in
if status{
KVNProgress.show();
let userLoginApi = "http://3.85.198.62/4apps/rest/V1/integration/customer/token"
let parameters: Parameters = ["username": username, "password": password]
let header : HTTPHeaders = ["Content-Type": "application/json"]
Alamofire.request(userLoginApi, method: .post, parameters: parameters, headers: header).responseObject { (response: DataResponse<User>) in
KVNProgress.dismiss()
print(response.request?.url)
print(response.request?.allHTTPHeaderFields)
let json = try! JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.mutableContainers)
print(json)
DispatchQueue.main.async {
loginCallback(response.result.value!)}
self.maincontroller.SuccessMessage(title: "تسجيل الدخول", successbody: "")
The Output
{
message = "Decoding error: \nUnable to unserialize value. Error: Syntax error\n#0 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Webapi/Rest/Request/Deserializer/Json.php(64): Magento\\Framework\\Serialize\\Serializer\\Json->unserialize('password=Abc%40...')\n#1 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Webapi/Rest/Request.php(141): Magento\\Framework\\Webapi\\Rest\\Request\\Deserializer\\Json->deserialize('password=Abc%40...')\n#2 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Webapi/Rest/Request.php(199): Magento\\Framework\\Webapi\\Rest\\Request->getBodyParams()\n#3 /opt/bitnami/apache2/htdocs/4apps/app/code/Magento/Webapi/Controller/Rest/InputParamsResolver.php(97): Magento\\Framework\\Webapi\\Rest\\Request->getRequestData()\n#4 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(58): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver->resolve()\n#5 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(138): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callParent('resolve', Array)\n#6 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(153): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->Magento\\Framework\\Interception\\{closure}()\n#7 /opt/bitnami/apache2/htdocs/4apps/generated/code/Magento/Webapi/Controller/Rest/InputParamsResolver/Interceptor.php(26): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callPlugins('resolve', Array, Array)\n#8 /opt/bitnami/apache2/htdocs/4apps/app/code/Magento/Webapi/Controller/Rest/SynchronousRequestProcessor.php(85): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->resolve()\n#9 /opt/bitnami/apache2/htdocs/4apps/app/code/Magento/Webapi/Controller/Rest.php(188): Magento\\Webapi\\Controller\\Rest\\SynchronousRequestProcessor->process(Object(Magento\\Framework\\Webapi\\Rest\\Request\\Proxy))\n#10 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(58): Magento\\Webapi\\Controller\\Rest->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#11 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(138): Magento\\Webapi\\Controller\\Rest\\Interceptor->___callParent('dispatch', Array)\n#12 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(153): Magento\\Webapi\\Controller\\Rest\\Interceptor->Magento\\Framework\\Interception\\{closure}(Object(Magento\\Framework\\App\\Request\\Http))\n#13 /opt/bitnami/apache2/htdocs/4apps/generated/code/Magento/Webapi/Controller/Rest/Interceptor.php(26): Magento\\Webapi\\Controller\\Rest\\Interceptor->___callPlugins('dispatch', Array, Array)\n#14 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/App/Http.php(137): Magento\\Webapi\\Controller\\Rest\\Interceptor->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#15 /opt/bitnami/apache2/htdocs/4apps/generated/code/Magento/Framework/App/Http/Interceptor.php(24): Magento\\Framework\\App\\Http->launch()\n#16 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/App/Bootstrap.php(261): Magento\\Framework\\App\\Http\\Interceptor->launch()\n#17 /opt/bitnami/apache2/htdocs/4apps/index.php(39): Magento\\Framework\\App\\Bootstrap->run(Object(Magento\\Framework\\App\\Http\\Interceptor))\n#18 {main}";
trace = "<null>";
}

The error you see has happened on the Magento side Decoding error: \nUnable to unserialize value... It points to the problem unserializing JSON params. So I've tried to play with encoding on the Alamofire request and URLEncoding.queryString works for me. Here is my code
Alamofire.request(userLoginApi, method: .post, parameters: parameters, encoding: URLEncoding.queryString, headers: header).responseData { (response: DataResponse<Data>) in
let json = try! JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.mutableContainers)
print("json", json)
}

Related

Alamofire get method with parameters in the url with header swift

I have a get method with 3 parameters on the base url itself.I have tried the following code, but it is going to failure condition saying either not a valid url or not a valid JSON.
What is the correct way to approach this?
The code i have used is as below:
let header: HTTPHeaders = ["Content-Type":"application/json","x-token":self.token!]
let todosEndpoint: String = "https://reachwebdemo.com/2020/10/listcribdev/api/chatnotification?" + "channel_sid=\(self.channelsid!)&author=\(self.userid!)&message=\(inputMessage)"
if let encoded = todosEndpoint.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),let url = URL(string: encoded)
{
print("notify url is",url)
AF.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: header).responseString { response in
switch response.result {
case .success(let json):
print("Validation Successful for push notification",json)
case let .failure(error):
print("error for push notificaton",error.errorDescription)
}
}
}
You user parameters like url and it's wrong way to make request like this.
You need add parameters on request method like parameters. And yes, you can use parameters on 'GET' requests.
let header: HTTPHeaders = ["Content-Type":"application/json","x-token":self.token!]
let todosEndpoint: String = "https://reachwebdemo.com/2020/10/listcribdev/api/chatnotification"
let params:[String: Any] = ["channel_sid":self.channelsid!, "author":self.userid!, "message": inputMessage]
if let encoded = todosEndpoint.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
let url = URL(string: encoded) {
print("notify url is",url)
AF.request(url, method: .get, parameters: params, encoding: URLEncoding.default, headers: header).responseString { response in
switch response.result {
case .success(let json):
print("Validation Successful for push notification",json)
case let .failure(error):
print("error for push notificaton",error.errorDescription)
}
}
}

Alamofire syntax for ecobee request

I'm trying to find the correct syntax for calling ecobee's API from Swift 4 using Alamofire.
Their cURL example:
curl -H "Content-Type: text/json" -H "Authorization: Bearer ACCESS_TOKEN" 'https://api.ecobee.com/1/thermostat?format=json&body=\{"selection":\{"selectionType":"registered","selectionMatch":"","includeRuntime":true\}\}'
The closest I've been to a solution is this
func doRequest() {
guard let url = URL(string: "https://api.ecobee.com/1/thermostat?format=json") else { return }
let parameters: Parameters = [
"selection": [
"selectionType": "registered",
"selectionMatch": ""
]
]
let headers: HTTPHeaders = [
"Content-Type": "text/json",
"Authorization": "Bearer \(core.accessToken)"
]
let req = AF.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
print("Error:", response.error?.localizedDescription ?? "no error")
print("Data:", String(data: response.data!, encoding: .utf8)!)
}
debugPrint(req)
}
When I run this, the call ultimately fails with status code 408, a server timeout.
When I change the HTTP method to use .post, the call completes, but the response is an internal status 3 with message "Update failed due to a communication error."
Can anyone help me figure out what I'm doing wrong before I waste another day trying to hack my way through it?
Ecobee's request format is a bit bizarre, as it uses form encoded parameters, but one of the values is a JSON encoded body. You'll have to do a little bit of prep work, as Alamofire doesn't naturally support something like this. This is just sample code, you'll need to do the work to make it safer.
First, encode the JSON parameters and get the String value:
let jsonParameters = ["selection": ["selectionType": "registered", "selectionMatch": ""]]
let jsonData = try! JSONEncoder().encode(jsonParameters)
let jsonString = String(decoding: jsonData, as: UTF8.self)
Then, create the actual parameters and headers values:
let parameters = ["format": "json", "body": jsonString]
let token = "token"
let headers: HTTPHeaders = [.authorization(bearerToken: token), .contentType("text/json")]
let url = URL(string: "https://api.ecobee.com/1/thermostat")!
And make the request:
AF.request(url, parameters: parameters, headers: headers).responseJSON { response in ... }

Swift Alamofire "The request timed out" in one of every two requests

In every one of my two calls to loadHeader with the same URL, I get "The request timed out" error. In first try, the function works and I manage to get and parse the response. In second, I get time out. In third it works and in forth time out again. Is it about my code or about server? I tried waiting before trying again as it might be some security protocol of server but it didn't change anything.
Here is error code:
FAILURE: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
And here is my code:
func loadHeader(url: String){
let parameters = ["foo": "bar"]
Alamofire.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default)
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON {
response in
let json=response.data
self.jsonToObjectHeader(json: json!)
}
}
func jsonToObjectHeader(json:Data){
do{
databases = try JSONDecoder().decode(responseHeader.self,from: json)
if databases.ordersHeader.count == 0 {
let alert = UIAlertView(title: "empty",message: "empty",delegate: nil,cancelButtonTitle: "OK")
alert.show()
}
else {
for i in 0...databases.ordersHeader.count-1 {
myArray2.append(databases.ordersHeader[i].productName!)
}
}
DispatchQueue.main.async {
self.myTableView.reloadData()
self.myTableView.tableFooterView = UIView()
}
//print(databases.ordersHeader[0].companyAddress)
}catch let jsonErr {
print(jsonErr)
}
}
I've added
let parameters = ["foo": "bar"]
thinking I've to give parameters as it is in the function. Just updated
Alamofire.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default)
to
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default)
and it solved the issue. Posting this in case of someone experiences something similar.

Can't make post request using params as dictionary with Swift 4 & Alamofire

I'm trying to learn to call API with/without library. But the problem here confuses me.
I have params like this:
let parameters: [String:String] =
["key":"MY_KEY" ,
"q":sourceText,
"source": sourceLanguage),
"target": target)]
let headers: HTTPHeaders = [ "Content-type": "application/json"]
I make a post call like this:
Alamofire.request(urlString, method: HTTPMethod.post, parameters: parameters, headers: headers)
.responseJSON{ response in
guard response.result.error == nil else {
print("error calling POST on /todos/1")
print(response.result.error!)
return
}
// make sure we got some JSON since that's what we expect
guard let json = response.result.value as? [String: Any] else {
print("didn't get todo object as JSON from API")
print("Error: \(response.result.error)")
return
}
By this I get an error 403, saying that I do not have a valid API key (I tested the key with postman, and it is okay).
After many efforts, I have to change the code like this
let stringparams = "key=MY_KEY&q=\(sourceText)&source=\(sourceLanguage)&target=\(target)"
request.httpBody = stringparams.data(using: String.Encoding.utf8)
and using this: Alamofire.request(request)
it works!
I'm using Google Cloud Translation api. And the web use a REST api as said here: https://cloud.google.com/translate/docs/reference/translate
So why can't I use params as dictionary, but using the string (like formdata) will work here?
My guess is Alamofire didn't make the right BODY for the request from the parameters because other arguments is okay. But I don't know why.
And I think Google should accept a json params as they mentioned, in stead of using form data? I did try the original method, but it didn't work with JSON.
From what actually works for you it looks like you need to encode the parameters in the same style as a query. Try this:
struct ParameterQueryEncoding: ParameterEncoding {
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var request = try urlRequest.asURLRequest()
request.httpBody = parameters?
.map { "\($0)=\($1)" }
.joined(separator: "&")
.data(using: .utf8)
return request
}
}
You should then be able to perform the original call that you had before:
Alamofire.request(urlString,
method: HTTPMethod.post,
parameters: parameters,
encoding: ParameterQueryEncoding(),
headers: headers)
.responseJSON { response in
...
}
Try by using JSON encoding. Make sure you have removed ) from dictionary.
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)

Issue with Alamofire Request

I am trying to use Alamofire to make a web request. It had been working absolutely fine, but after doing a recent pod update it has stopped.
My syntax is:
var params = [String : Any]()
if (data != nil) {
params = try! JSONSerialization.jsonObject(with: data!, options: []) as! [String : Any]
}
let _ = Alamofire.request( "http://example.com" , method: Method, parameters: params?, encoding: .queryString, headers: [:]).response{ (request, response, data, error) in
}
the error looks is "Extra argument 'method' in call" and I don't seem to be able to get rid of it. My parameters of the request to Alamofire.request seem ok to me, but clearly I am missing something.
You're not passing anything to the method parameter. I don't know what you're trying to provide in the encoding parameter either but that went through some changes in Alamofire 4.0. For example and for simplicity's sake, this compiles:
let _ = Alamofire.request( "http://example.com" , method: HTTPMethod.get, parameters: nil, encoding: JSONEncoding.default, headers: nil)