HTTPS POST working successfully but variables come up null - php

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"

Related

PHP not receiving POST data from Swift

I'm trying to write to a database and not able to get POST data from Swift into PHP. I've checked everything along the way and the data is present in request.httpBody before sending the request, but I get this error
"SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'order_id' cannot be null"
Also PHP prints an empty array of $request
Any help is appreciated. Racking my brain on this one!
Here's the code
SWIFT:
func saveNewProduct(product: ProductClass) {
//declare parameter as a dictionary which contains string as key and value combination.
let productDict: [String:Any] = ["order_id": product.order_id!,
"product_sku": product.product_sku!,
"product_description": product.product_description!,
"product_base_price": product.product_base_price!,
"product_price": product.product_price!,
"product_min_qty": product.product_min_qty!,
"product_qty": product.product_qty!,
"product_subtotal": product.product_subtotal!,
"product_imageURL": product.product_imageURL!]
let urlString: String = "https://www.mywebsite.com/dbinsertproduct.php"
guard let url = URL(string: urlString) else {
print("Error: cannot create URL")
return
}
//create the session object
let session = URLSession.shared
//create the URLRequest object using the url object
var request = URLRequest(url: url)
//set http method as POST
request.httpMethod = "POST"
do {
request.httpBody = try? JSONSerialization.data(withJSONObject: productDict, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request, completionHandler: {
data,response,error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
// handle json...
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}
PHP:
<?php include("dbclass.php"); ?>
<?php
$postdata = file_get_contents("php://input");
$request = json_decode($postdata, true);
$newProduct = new DBConnector('mysql.mysite.com', 'username', 'password', 'mysiteorders');
$p = $newProduct->dbInsertProduct($request);
error_log($p);
echo ($p);
?>
More PHP:
public function dbInsertProduct($request)
{
try {
$stmt = $this->prepare("INSERT INTO `products` (`order_id`,`product_sku`,`product_description`,`product_base_price`,`product_price`,`product_notes`,`product_min_qty`,`product_qty`,`product_subtotal`,`product_imageURL`) VALUES (:order_id,:product_sku,:product_description,:product_base_price,:product_price,:product_notes,:product_min_qty,:product_qty,:product_subtotal,:product_imageURL);");
$stmt->bindParam(':order_id', $request['order_id']);
$stmt->bindParam(':product_sku', $request['product_sku']);
$stmt->bindParam(':product_description', $request['product_description']);
$stmt->bindParam(':product_base_price', $request['product_base_price']);
$stmt->bindParam(':product_price', $request['product_price']);
$stmt->bindParam(':product_notes', $request['product_notes']);
$stmt->bindParam(':product_min_qty', $request['product_min_qty']);
$stmt->bindParam(':product_qty', $request['product_qty']);
$stmt->bindParam(':product_subtotal', $request['product_subtotal']);
$stmt->bindParam(':product_imageURL', $request['product_imageURL']);
error_log( print_r($request, TRUE) );
$stmt->execute();
} catch(PDOException $e) {
error_log($e->getMessage());
echo json_encode($e->getMessage());
}
}
UPDATE:
The request shows up as GET, not POST (verified with Charles proxy).
As you can see in the code, I'm setting request.httpMethod = "POST". Am I missing something else??
I found that the POST was being changed to GET upon redirect from www.mysite.com to mysite.com. Removing the 'www' did the trick.

Swift save PHP session to stay authenticated

I am building an app, which has login page connected with my AWS server using PHP and MySQL, everything is working fine except that I have no idea how to save the PHP session within the app so the user can stay authenticated.
Part of my PHP code:
<?php
$session_start();
...
...
if($verify){
echo "Verfied";
$_SESSION["Authenticated"] = 1;
} else {
echo "Unverified";
$_SESSION["Authenticated"] = 0;
}
...
...
?>
Part of Swift code:
let url = URL(string: "http://localhost/login.php")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "username=\(username)&password=\(password)"
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)!
print("responseString = \(String(describing: responseString))")
DispatchQueue.main.async() {
if (responseString == "Vaild!") {
self.performSegue(withIdentifier: "MainPageSegue", sender: self)
} else {
self.errorLabel.text = "Invalid username or password."
}
}
}
task.resume()
How can I save the session within my app so the user stay authenticated?

Swift 3 function to POST data and I have an error when I receive JSon answer from my server

I have a function in Swift 3 to POST data to a PHP server. The PHP server send a JSon answer to iOS and I have an error.
This is my function :
func sendRequestPost(urlString: String, dataToPost: String, completion: #escaping (_ dictionary: NSDictionary?, _ error: Error?) -> Void) {
DispatchQueue.global(qos: .background).async {
var request = URLRequest(url: URL(string: urlString)!)
let postString = dataToPost
request.httpMethod = "POST"
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=\(error)")
completion(nil, error)
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // Check for http(s) errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
// make error here and then
completion(nil, error)
return
}
let responseString = String(data: data, encoding: .utf8)
print("responseString : \(responseString)!")
DispatchQueue.main.async {
print("DispatchQueue.main.async")
do {
print("enter do")
let jsonDictionary:NSDictionary = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] as NSDictionary
print("jsonDictionary")
print(jsonDictionary)
completion(jsonDictionary, nil)
} catch {
print("CATCH ERROR !")
completion(nil, error)
}
}
}
task.resume()
}
}
For example I call my function like that :
let url = "https://mywebsite.com/signup/ios/signup.php"
let postData = "username=\(txtUsername.text!)&password=\(txtPassword.text!)&confirmPassword=\(txtConfirmPassword.text!)&email=\(txtEmail.text!)&firstname=\(txtFirstname.text!)&lastname=\(txtLastname.text!)"
sendRequestPost(urlString: url, dataToPost: postData) {
dictionary, error in
print("---directory---")
print(dictionary)
print("---error---")
print(error)
print("==========")
This is what I see in the console :
responseString : "{\"exception\":false,\"success\":false,\"status\":-9,\"message\":\"This username already exist !\",\"confirmMessage\":\"null\",\"html\":\"null\",\"data\":\"boblongueuil\"}"!
DispatchQueue.main.async
---ENTER DO :
CATCH ERROR !
---directory---
nil
---error---
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})
So how can I return the JSon string after call this function to see a registration is OK or registration have a problem (in this case the username already exist in database). I change answer from my PHP server to an array.

HTTP Post Parameters are passed json encoded to $_POST

I can't figure out how to properly send POST parameters.
My Swift 3:
let parameters = ["name": "thom", "password": "12345"] as Dictionary<String, String>
let url = URL(string: "https://mywebsite.com/test.php")!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
do
{
request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
}
catch let error
{
print(error.localizedDescription)
}
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request as URLRequest, completionHandler:
{
data, response, error in
guard error == nil else
{
print(error as Any)
return
}
guard let data = data else
{
return
}
do
{
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any]
{
print(json)
print(json["post"]!)
}
else
{
print("no json")
}
}
catch let error
{
print(error.localizedDescription)
}
})
task.resume()
My PHP:
<?php
header('Content-Type: application/json');
if(empty($_POST)) echo json_encode(array('post'=>'empty'));
else echo json_encode($_POST+array('post'=>'not_empty'));
exit;
If I set the content-type header (in Swift) to application/json I get:
["post": empty]
empty
If I set it to application/x-www-form-urlencoded I get:
["{\"name\":\"thom\",\"password\":\"12345\"}": , "post": not_empty]
not_empty
How do I send the dictionary to my server as $_POST key/value pairs, not as a json_encoded string?
You want to percent-escape the request into a x-www-form-urlencoded request, like so:
let parameters = ["name": "thom", "password": "12345"]
let url = URL(string: "https://mywebsite.com/test.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.updateHttpBody(with: parameters)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let task = session.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("\(error)")
return
}
// handle response here
}
task.resume()
Where
extension URLRequest {
/// Populate the `httpBody` of `application/x-www-form-urlencoded` request.
///
/// - parameter parameters: A dictionary of keys and values to be added to the request
mutating func updateHttpBody(with parameters: [String : String]) {
let parameterArray = parameters.map { (key, value) -> String in
return "\(key.addingPercentEncodingForQueryValue()!)=\(value.addingPercentEncodingForQueryValue()!)"
}
httpBody = parameterArray.joined(separator: "&").data(using: .utf8)
}
}
extension String {
/// Percent escape value to be added to a HTTP request
///
/// This percent-escapes all characters besides the alphanumeric character set and "-", ".", "_", and "*".
/// This will also replace spaces with the "+" character as outlined in the application/x-www-form-urlencoded spec:
///
/// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
///
/// - returns: Return percent escaped string.
func addingPercentEncodingForQueryValue() -> String? {
let generalDelimitersToEncode = ":#[]#?/"
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return addingPercentEncoding(withAllowedCharacters: allowed)?.replacingOccurrences(of: " ", with: "+")
}
}

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