PHP POST + iOS Swift error - php

I'm having trouble with my App, what I am trying to do is send some information from my textfields through a "NSMutableURLRequest" URL to a PHP file I have.
The error says there are undefined indexes for each of my vars.
This is the first time I do this kind of exercises so I don't know if the error is in my PHP code or in the Swift Function.
Below is my swift function.
#IBAction func enviarInfo(_ sender: Any) {
let request = NSMutableURLRequest(url: NSURL(string: "http://www.mydomain/index.php")! as URL)
request.httpMethod = "POST"
//The String with the vars that will be sent to the $_POST["var"]
let postString = "nombre = \(nombreText.text!) &aPaterno = \(apaternoText.text!) &aMaterno = \(amaternoText.text!) &genero = \(genero.text!) &email = \(emailText.text!) &telefono = \(telefonoText.text!)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(String(describing: error))")
return
}
print("response = \(String(describing: response))")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(String(describing: responseString))")
}
task.resume()
}
The PHP code looks like this
$nombre = $_POST["nombre"];
//All the $vars look like this.
echo $nombre;
I would appreciate your help :)

You need to remove the spaces from your postString.
Change:
let postString = "nombre = \(nombreText.text!) &aPaterno = ..."
to
let postString = "nombre=\(nombreText.text!)&aPaterno=..." ...and so on
When sending data like that, those extra spaces matters when the string get's parsed.

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"

Post variable undefined in Braintree transaction

I am setting up payment processing for my OSX desktop app in swift. Since there is no SDK for OSX, I am using a Web View via the PHP SDK for Braintree. I want to pass some POST data so that the price of a product is coming dynamically from my App, but it seems to not be recognized and is underfined according to PHP errors.
I know how to send POST variable to a PHP script and have done it many times, but I have a feeling something might not be right with my swift code. My PHP error is: "Notice: Undefined variable: price"
PayPal.swift
import Cocoa
import WebKit
class PayPal: NSViewController {
#IBOutlet weak var paypalWebView: WebView?
override func viewWillAppear() {
self.view.window!.title = "Payment"
}
override func viewDidLoad() {
super.viewDidLoad()
setupPP()
}
func setupPP(){
let request: NSURL = NSURL(string: "http://")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: request as URL)
urlRequest.httpMethod = "POST"
let postString = "price=45"
urlRequest.httpBody = postString.data(using: String.Encoding.utf8);
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) {
(data, response, error) -> Void in
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data!, encoding: .utf8)
print("responseString = \(responseString)")
}
task.resume()
let requesting = NSURLRequest(url: request as URL)
DispatchQueue.main.async(){
self.paypalWebView?.mainFrame.load(requesting as URLRequest)
}
}
}
Braintree PHP Script
if(isset($_POST["price"])){
$price = $_POST["price"];
}
<?php $tr_data = Braintree_TransparentRedirect::transactionData(
array('redirectUrl' => "http://" ,
'transaction' => array('amount' => $price, 'type' => 'sale'))) ?>
Also the Paypal View that is essentially a web view is being activated when a user clicks on a button via a segue. I don't know if that would have anything to do with it or not?
I ended up getting it to work!
Paypal.swift
import Cocoa
import WebKit
class PayPal: NSViewController {
#IBOutlet weak var paypalWebView: WebView?
override func viewWillAppear() {
self.view.window!.title = "Payment"
}
override func viewDidLoad() {
super.viewDidLoad()
setupPP()
}
func setupPP(){
let request: NSURL = NSURL(string: "http://")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: request as URL)
urlRequest.httpMethod = "POST"
let postString = "amount=29.95"
urlRequest.httpBody = postString.data(using: String.Encoding.utf8);
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) {
(data, response, error) -> Void in
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data!, encoding: .utf8)
print("responseString = \(responseString)")
}
paypalWebView?.mainFrame.load(urlRequest as URLRequest)
task.resume()
}
}
PHP Script
<?php
if (isset ($_POST['amount'])) {
$amount = $_POST['amount'];
}
$tr_data = Braintree_TransparentRedirect::transactionData(
array('redirectUrl' => "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH),
'transaction' => array('amount' => $amount, 'type' => 'sale')))
?>

Swift 3 problems Parsing json response

I am new on Swift but I was follwoing some examples like how to make a login app sending username and password fields to a php file and getting the json response back.
When I print my responseString I get:
[{"userid":1,"username":"rodrigo","password":"minhoca","groupname":"couple"}]
But when I try to parse the json I never can set the username variable because never gets into that part of the code, I just get "here"
Thanks for the help
func sendLoginInfo(username: String, password: String) -> String{
if let url = URL(string: "myphpurl"){
let request = NSMutableURLRequest(url:url)
request.httpMethod = "POST";// Compose a query string
let postString = "?username=\(myUsername)&password=\(myPassword)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
if error != nil{
print("1\(error)")
}
else{
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response string = \(responseString!)")
}
do {
if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
// Print out dictionary
print(convertedJsonIntoDict)
// Get value by key
let firstNameValue = convertedJsonIntoDict["username"] as? String
print("here = \(firstNameValue!)")
}
else{
print("here")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
task.resume()
}
return ""
}
Change the NSDictionary to NSArray in your code because you are getting an array and trying to convert to dictonary:
if let convertedJson = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray
get the object at index 0 which will give you dictonary & then you can get username
So the Final code will be:
func sendLoginInfo(username: String, password: String) -> String{
if let url = URL(string: "myphpurl"){
let request = NSMutableURLRequest(url:url)
request.httpMethod = "POST";// Compose a query string
let postString = "?username=\(myUsername)&password=\(myPassword)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
if error != nil{
print("1\(error)")
}
else{
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response string = \(responseString!)")
}
do {
if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray {
// Print out dictionary
print(convertedJsonIntoDict)
// Get value by key
let firstNameValue = (convertedJsonIntoDict[0] as! NSDictionary)["username"] as? String
print("here = \(firstNameValue!)")
}
else{
print("here")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
task.resume()
}
return ""
}

Post request always wrapped by optional text

I have a very similar problem like in Why the http post request body always wrapped by Optional text in the Swift app
but I can´t apply the solution from this thread to my code, because I don´t have a request.setValue.
Does anyone know what I need to do to get rid of the Optional?
My Code:
#IBAction func LoginButtonTapped(sender: UIButton) {
let username = UsernameTextField.text
let password = PasswordTextField.text
if(username!.isEmpty || password!.isEmpty) {return; }
let request = NSMutableURLRequest (URL: NSURL(string: "http://myip/loginregister.php")!)
request.HTTPMethod = "POST"
let postString = "username=\(username)&password=\(password)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else {
// check for fundamental networking error
print("error=\(error)")
return
}
let data = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
let success = json["success"] as? Int // Okay, the `json` is here, let's get the value for 'success' out of it
print("Success: \(success)")
} else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding) // No error thrown, but not NSDictionary
print("Error could not parse JSON: \(jsonStr)")
}
} catch let parseError {
print(parseError) // Log the error thrown by `JSONObjectWithData`
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: '\(jsonStr)'")
}
}
task.resume()
You must unwrapping the value when get text from UITextField first, because the text property of UITextField allow nil
let username = UsernameTextField.text!
let password = PasswordTextField.text!
Explain more
When you unwrap the text of the UITextField, the username and password will be not nil variable.
The code compare empty should be:
if(username.isEmpty || password.isEmpty) {return }
If you does not unwrap, when you use this "\(username)", your are try to convert a nilable object to string, so the string result will be appended with a "Optional" text.
To Solve problem with Content-Type for request
Paste this line to your code. I don't believe that you do not have setValue method.
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")

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