translate POST request to API in PHP to Swift - php

Hello I'm trying to translate POST request api code written in php:
<?php
$methodParams = '{
"date_confirmed_from": 1407341754,
"get_unconfirmed_orders": false
}';
$apiParams = [
"method" => "getOrders",
"parameters" => $methodParams
];
$curl = curl_init("https://api.baselinker.com/connector.php");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, ["X-BLToken: xxx"]);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($apiParams));
$response = curl_exec($curl);
To Swift but I don't have idea why it doesn't work:
import UIKit
struct Parameters: Codable {
let date_confirmed_from: Int
let get_unconfirmed_orders: Bool
}
struct BodyData: Codable {
let method: String
let parameters:Parameters
}
let url = URL(string: "https://api.baselinker.com/connector.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.allHTTPHeaderFields = [
"X-BLToken": "xxx"
]
let bodyData = BodyData(method: "getOrders", parameters: Parameters(date_confirmed_from: 1407341754, get_unconfirmed_orders: false))
let encoder = JSONEncoder()
do {
let encodeData = try encoder.encode(bodyData)
request.httpBody = encodeData
let session = URLSession(configuration: .default)
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error)
}
if let data = data {
}
}
task.resume()
}catch {
print(error)
}
When I'm testing my Swift code I'm getting error answer from API can someone help me to find fault in my code?

Does the PHP curl work?
It is not what the baseline documentation is asking for.
The documentation asks for this post data:
array (
'method' => 'getOrders',
'parameters' => '{"date_from": 1407341754}',
)
Your PHP curl request post data:
'array (
'method' => 'getOrders',
'parameters' => '{
"date_confirmed_from": 1407341754,
"get_unconfirmed_orders": false
}',
)'
The documentation asks
parameters = arguments of the requested function in JSON format.
Your parameters are an array, not JSON.

Okay I find out solution for this problem:
import UIKit
let url = URL(string: "https://api.baselinker.com/connector.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/x-www-form-urlencoded",forHTTPHeaderField: "Accept")
request.setValue("xxx",forHTTPHeaderField: "X-BLToken")
let data: Data = "method=getOrders&parameters={\"date_confirmed_from\": 1407341754&\"get_unconfirmed_orders\":false}".data(using: .utf8)!
request.httpBody = data
let session = URLSession(configuration: .default)
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error)
}
if let data = data {
let dataString = String(data: data, encoding: .utf8)
print(dataString!)
}
}
task.resume()
The biggest problem was coding of data. curl in PHP by default sending data as x-www-form-urlencoded

Related

HTTPS POST working successfully but variables come up null

The code I've posted here is a shortened versions with just the essentials to the issue. When put through rigorous error testing, it appears that there are no issues either within the request, within the server, or within the return code, except for the fact that the response from the server says "Function": null instead of "Function": "addUser" as it should. Is there something I'm doing wrong on either end? It just seems to not be recognizing the posted variables, but I've used this code numerous times in other apps and servers and it seems to be failing here for some reason I cannot see. Thank you for any assistance.
Here is my PHP on the server:
<?php
$t = $_POST["function"];
$do = array("Success"=>true, "Function"=> $t);
echo json_encode($do);
?>
Here is the swift I'm using to make the request:
let params = ["function": "addUser"] as [String: AnyObject]?
fetchData("https://pdt.pitchprogress.net/SamplePHP.php", token: nil, parameters: params, method: "POST", onCompletion: { (success, data) -> Void in
if success {
do {
let json = try JSON(data: data!)
if json["Success"].boolValue == true {
print("success!")
print(json.description)
print(json["Function"].stringValue)
}
}
}
})
func fetchData(_ feed:String,token:String? = nil,parameters:[String:AnyObject]? = nil,method:String? = nil, onCompletion:#escaping (_ success:Bool,_ data:Data?)->Void){
DispatchQueue.main.async {
if let unwrapped_url = URL(string: feed){
let request = NSMutableURLRequest(url: unwrapped_url)
if let parm = parameters {
if let data = (try? JSONSerialization.data(withJSONObject: parm, options:[])) as Data? {
request.httpBody = data
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("\(data.count)", forHTTPHeaderField: "Content-Length")
}
}
if let unwrapped_method = method {
request.httpMethod = unwrapped_method
}
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = 15.0
let session = URLSession(configuration: sessionConfiguration)
let taskGetCategories = session.dataTask(with: request as URLRequest, completionHandler: { (responseData, response, error) -> Void in
let statusCode = (response as! HTTPURLResponse?)?.statusCode
//println("Status Code: \(statusCode), error: \(error)")
if error != nil || (statusCode != 200 && statusCode != 201 && statusCode != 202){
onCompletion(false, nil)
} else {
onCompletion(true, responseData)
}
})
taskGetCategories.resume()
}
}
}
This is because you are sending the params as JSON while your API requires params as form data.
This code sends the params as simple form post and this retrieved successful response.
var request = URLRequest(url: URL(string: "http://app123.freeiz.com/Apis/samples/api4.php")!)
request.httpMethod = "POST"
var postString = ""
postString.append("function=value") // replace 'function' with your paramname and 'value' with your value'
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
// check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
if let unWrappedResponseString = responseString{
print(unWrappedResponseString)
}
}
task.resume()
I had once made a small wrapper for sending simple form data, If i find it I will update the answer with that. Till then you can try with this. Let me know how it goes..
Looks like your key is different use "function" instead of using "Function"

swift PUT API from json object

I am trying to make an api call I build the json object. But the data is not being passed I believe it is the formatting of the data when passed the service only has examples in php which i have posted below
API Docs: http://middleware.idxbroker.com/docs/api/methods/index.html#api-Leads-putLead
php call
// PUT lead in to IDX Broker
$url = 'https://api.idxbroker.com/leads/lead';
$data = array(
'firstName'=>$firstname,
'lastName'=>$lastname,
'email'=>$email
);
$data = http_build_query($data); // encode and & delineate
$method = 'PUT';
Swift Code to build json object
/// Create lead from text fields
let jsonObject: [String: String] = [
"firstName": (firstName.text! as String),
"lastNmae": lastName.text!,
"email": Email.text!,
"phoneNumber": phoneNumber.text!,
"city": (city.text as AnyObject) as! String,
"recieveUpdates": (switchIsChanged(recieveUpdates: recieveUpdates) as AnyObject) as! String
]
The API Call
class func putLead(lead: AnyObject){
let urlString = "https://api.idxbroker.com/leads/lead"
let url = NSURL(string: urlString)
print(lead)
var downloadTask = URLRequest(url: (url as URL?)!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 20)
/******************** Add Headers required for API CALL *************************************/
downloadTask.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
downloadTask.setValue(APICalls.getAccessKey(), forHTTPHeaderField: "accesskey")
downloadTask.setValue("json", forHTTPHeaderField: "outputtype")
downloadTask.httpMethod = "PUT"
downloadTask.httpBody = (lead as? Data)
/******************** End Headers required for API CALL *************************************/
URLSession.shared.dataTask(with: downloadTask, completionHandler: {(data, response, error) -> Void in
/// Status Returned from API CALL
if let httpResponse = response as? HTTPURLResponse {
print("statusCode: \(httpResponse.statusCode)")
}
let jsonData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print(jsonData ?? "No Return")
}).resume()
/******** End URL Session **********/
}
Working Version
let newLead = "firstName=\(firstName.text!)&lastName=\(lastName.text!)&email=\(Email.text!)&phoneNumber=\(phoneNumber.text!)&city=\(String(describing: city.text))&recieveUpdates=\((switchIsChanged(recieveUpdates: recieveUpdates) as AnyObject) as! String)"
let newData = newLead.data(using: String.Encoding.utf8)
/// API Call with passing json String
APICalls.putLead(lead: newData!)
I was able to get it working by making the following changes to your putLead() function:
class func putLead(lead: [String:String]){
let urlString = "https://api.idxbroker.com/leads/lead"
let url = NSURL(string: urlString)
var httpBodyString = ""
for (key,value) in lead{
let currentKey = key.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
let currentValue = value.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
httpBodyString += "\(currentKey!)=\(currentValue!)&"
}
var downloadTask = URLRequest(url: (url as URL?)!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 20)
/******************** Add Headers required for API CALL *************************************/
downloadTask.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
downloadTask.setValue(<API_KEY_HERE>, forHTTPHeaderField: "accesskey")
downloadTask.httpMethod = "PUT"
downloadTask.httpBody = httpBodyString.data(using: String.Encoding.utf8)
/******************** End Headers required for API CALL *************************************/
URLSession.shared.dataTask(with: downloadTask, completionHandler: {(data, response, error) -> Void in
/// Status Returned from API CALL
if let httpResponse = response as? HTTPURLResponse {
print("statusCode: \(httpResponse.statusCode)")
}
let jsonData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print(jsonData ?? "No Return")
}).resume()
/******** End URL Session **********/
}

Parsing integer from Swift to SQL with JSON

I'm developing an app in Swift 3 where I need to pass an integer value from the app to an online SQL server.
My Swift code is as following:
func saveData(data: Int) {
// prepare json data
let json: [String: Any] = ["matchScore": ["\(data)"]]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// create post request
let url = URL(string: "http://mywebpage.com/swift/addToSQL.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
}
And the part of the PHP file where I'm supposed to get the JSON data:
$jsonData = file_get_contents("php://input");
$json = json_decode($jsonData, true);
$matchScore = $json['matchScore'][1];
However, the database is not getting anything. I found out that if I set $matchScore = 42 (example) it works and posts to SQL database, so it has to be the parsing that's the issue.
What am I missing out here?
Thanks.

POST json object in a form variable on a sever

hello I am working on IOS SWIFT 2. I NEED to send the json object in a variable so that I can access the json object like that
$json = $_POST['json'];
$data = json_decode($json, TRUE);
$email = $data['email'];
$user_password = $data['password'];
right now the data is posting on server like this
{
"email" : "email",
"password" : "password"
}
This is the code I am using
func post() {
let url:String = "http://example.com/test.php"
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
let params = ["email":"email", "password":"password"] as Dictionary<String, String>
//let request = NSMutableURLRequest(URL:url)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
do {
let data = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)!
print("dataString is \(dataString)")
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
} catch {
//handle error. Probably return or mark function as throws
print(error)
return
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// handle error
guard error == nil else { return }
print("Response: \(response)")
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)")
let json: NSDictionary?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
} catch let dataError {
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
print(dataError)
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: '\(jsonStr)'")
// return or throw?
return
}
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
let success = parseJSON["success"] as? Int
print("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: \(jsonStr)")
}
})
task.resume()
}
I want to pass the json above in a form variable called 'json'.
I would highly recommend using a Library, such as Alamofire to handle this.
Doing it yourself is tedious.
Once added to your Swift Project, you can send JSON parameters really, really elegantly:
Example from the Github page:
let parameters = [
"foo": [1,2,3],
"bar": [
"baz": "qux"
]
]
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters, encoding: .JSON)
Then you can use your existing PHP code to process your JSON.
Edit:
Also handling JSON is really elegant too:
Alamofire.request(.POST, url, etc).responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}

Empty array when making a HTTP Post Request to PHP from Swift App

Hi I am trying to connect my iOS app to my PHP API.
I am sending JSON POST to my PHP API but I am getting an empty array as Output.
My Swift Code
#IBAction func JSONButtonAction(sender: AnyObject) {
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration)
var usr = "dsdd"
var pwdCode = "dsds"
var image : UIImage = clickedPhotoView.image!
var imageData = UIImagePNGRepresentation(image)
let base64String = imageData.base64EncodedStringWithOptions(.allZeros)
let params:[String: AnyObject] = [
"email" : usr,
"image" : base64String ]
let url = NSURL(string:"http://localhost/app/")
let request = NSMutableURLRequest(URL: url!)
let boundaryConstant = "Boundary-7MA4YWxkTLLu0UIW"; // This should be auto-generated.
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, error: &err)
let task = session.dataTaskWithRequest(request) {
data, response, error in
// println("response = \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("\(responseString)")
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode != 200 {
println("response was not 200: \(response)")
return
}
}
if (error != nil) {
println("error submitting request: \(error)")
return
}
// handle the data of the successful response here
var result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as? NSDictionary
//println(result)
}
task.resume()
}
PHP Code
print_r($_POST);
Output is
array(
)
But when I use
$data = json_decode(file_get_contents('php://input'), true);
It works fine
I dont know why $_POST is not working.
If your intent is actually to send a string, then you should change the content-type:
request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
Tested your exact code with this modification on my tests server:
Otherwise, check #kekub's comment.

Categories