Programming not sending verification code to given phone number - ios

I am trying to figure out how to send a verification code to a user when signing up to verify their number. I am trying to follow online resources (code below), but it doesn't seem to work. When I put in a phone number as an 'xxxyyyzzzz' or 'xxx-yyy-zzzz' number (with a country code formatted just as the number, no '+') I get an error in my console that the phone number is not properly formatted. I'm not sure if this is the source of my issue, but as of now it seems the most probable. What confuses me about this is that online I am told that either of these formats will work. Any help? Code:
static let path = Bundle.main.path(forResource: "Config", ofType: "plist")
static let config = NSDictionary(contentsOfFile: path!)
private static let baseURLString = config!["serverUrl"] as! String
#IBOutlet var countryCodeField: UITextField! = UITextField()
#IBOutlet var phoneNumberField: UITextField! = UITextField()
#IBAction func sendVerification(_ sender: Any) {
if let phoneNumber = phoneNumberField.text,
let countryCode = countryCodeField.text {
SignUp2ViewController.sendVerificationCode(countryCode, phoneNumber)
}
}
static func sendVerificationCode(_ countryCode: String, _ phoneNumber: String) {
let parameters = [
"via": "sms",
"country_code": countryCode,
"phone_number": phoneNumber
]
let path = "start"
let method = "POST"
let urlPath = "\(baseURLString)/\(path)"
var components = URLComponents(string: urlPath)!
var queryItems = [URLQueryItem]()
for (key, value) in parameters {
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
components.queryItems = queryItems
let url = components.url!
var request = URLRequest(url: url)
request.httpMethod = method
let session: URLSession = {
let config = URLSessionConfiguration.default
return URLSession(configuration: config)
}()
let task = session.dataTask(with: request) {
(data, response, error) in
if let data = data {
do {
let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
print(jsonSerialized!)
} catch let error as NSError {
print(error.localizedDescription)
}
} else if let error = error {
print(error.localizedDescription)
}
}
task.resume()
}

You are calling a POST but passing the values into the URL as if it's a GET. You should use the httpBody for POST.

Related

[Swift]I can't get any JSON data from specific URL

There are two kinds of URLs
http://www.mocky.io/v2/5e91af4b3300008300e9cfd1 (this is which I made)
http://183.111.148.229/mob_json/mob_json.aspx?nm_sp=UP_MOB_CHECK_LOGIN&param=1000|1000|1 (I need to get data from this URL)
Only number1. URL returns JSON data even if they have same structure. I couldn't find way to resolve this problem.
this is my network manager code
import Foundation
class NetworkManager: ObservableObject {
#Published var posts = [Post]()
func fetchData() {
if let url = URL(string: "http://www.mocky.io/v2/5e91af4b3300008300e9cfd1") {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error == nil {
let decoder = JSONDecoder()
if let safeData = data {
do {
let results = try decoder.decode(Results.self, from: safeData)
DispatchQueue.main.async {
self.posts = results.Table
}
} catch {
print(error)
}
}
}
}
task.resume()
}
}
}
and my post data model
import Foundation
struct Results: Decodable {
let Table: [Post]
}
struct Post: Decodable, Identifiable {
var id: String {
return CD_FIRM
}
let CD_FIRM: String
let NM_FIRM: String
let CD_USER: String
let NM_USER: String
}
Can anyone can help me for this problem?
I want to get JSON data from URL number 2.
please help me =)
It looks like the issue with your second url is the pipes | at the end. One way to avoid this issue is to use URLComponents
So insert this at the start of fetchData
var urlComponents = URLComponents()
urlComponents.scheme = "http"
urlComponents.host = "183.111.148.229"
urlComponents.path = "/mob_json/mob_json.aspx"
urlComponents.queryItems = [
URLQueryItem(name: "nm_sp", value: "UP_MOB_CHECK_LOGIN"),
URLQueryItem(name: "param", value: "1000|1000|1")
]
And then get the url from the components
if let url = urlComponents.url {
let session = URLSession(configuration: .default)
//... same as before

How to append Special character in iOS using swift?

I am new to iOS please consider.I want to post some data to server, but I am not able to send Mobile number +91 and bloodGroup A+..it was sending to firebase + is replace with space " " like this ( 91) and (A )
func addEmployees(){
let photoUrl = "https://firebasestorage.googleapis.com/v0/b/pickcel-1241.appspot.com/o/task.careGallery%2FGroup%2018aasa.png?alt=media&token=4e0ac8f6-134a-4807-9fef-f44eabe9f6a8";
let userID = Auth.auth().currentUser!.uid
let mobilenumber = Auth.auth().currentUser?.phoneNumber
var employeeDetails = [String : AnyObject]()
employeeDetails["OID"] = getOID() as AnyObject
employeeDetails["MID"] = userID as AnyObject
employeeDetails["email"] = "ssinth#gmail.com" as AnyObject
employeeDetails["firstName"] = "First Name" as AnyObject
employeeDetails["lastName"] = "last name" as AnyObject
employeeDetails["isManager"] = "true" as AnyObject
employeeDetails["regMedia"] = "mobile" as AnyObject
employeeDetails["shortDestination"] = "btm" as AnyObject
employeeDetails["address"] = "+btm" as AnyObject
employeeDetails["createdDate"] = getdateformat() as AnyObject
employeeDetails["orgName"] = "Test Org" as AnyObject
employeeDetails["photoUrl"] = photoUrl as AnyObject
employeeDetails["officeOpenTime"] = "09:00" as AnyObject
employeeDetails["officeCloseTime"] = "18:00" as AnyObject
employeeDetails["phoneNumber"] = labelmobile.text as AnyObject
employeeDetails["bloodGroup"] = "A+" as AnyObject
employeeDetails["empId"] = "abcd" as AnyObject
let convertedvalue : String = convertToParameters(employeeDetails)
print("convertedvalues : \(convertedvalue)")
let myUrl = URL(string: "https://us-central1-pickceltest.cloudfunctions.net/rebliss/createNewUser");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let postString = convertedvalue;
print("start create employee")
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(String(describing: error))")
return
}
print("start create employee =successfull")
print("response = \(String(describing: response))")
do {
print("start create employee =parsing problems ")
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
// print("resultjson=one : ",self.json)
print("resultjson=two : ",parseJSON)
}
} catch {
print(error)
}
}
task.resume()
}
function convertToParameters
func convertToParameters(_ params: [String: AnyObject?]) -> String {
var paramList: [String] = []
for (key, value) in params {
guard let value = value else {
continue
}
let scapedKey = key
let scapedValue = value
print("employee add status objects = ","\(scapedKey)=\(scapedValue as AnyObject)")
paramList.append("\(scapedKey)=\(scapedValue as AnyObject)")
}
return paramList.joined(separator: "&")
}
Json Error:
resultjson=two : {
error = {
code = "auth/invalid-phone-number";
message = "The phone number must be a non-empty E.164 standard compliant identifier string.";
};
success = 0;
}
Error in firebase console:
Actual issue with you is your parameters not getting properly url encoded.
Temporary Solution for your code:
In your convertToParams method, make following changes:
let scapedKeyEncoded = scapedKey.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed);
let scapedValueEncoded = scapedValue.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed);
paramList.append("\(scapedKeyEncoded)=\(scapedValueEncoded)"
Note: Your scapedValue must be String, so, make employeeDetails as [String:String].
Permanent Solution(Perfect way for encoding query parameters):
For this, you can change your code to something like this:
Remove convertToParameters method
Add following method in place of it
class func getURLRequestWith(urlStr:String, paramsDict:[String:String]?, isParamsAsQuery:Bool, isParamsAsBody:Bool) -> URLRequest? {
guard var components = URLComponents(string: urlStr) else { return nil }
if paramsDict != nil{
components.queryItems = paramsDict!.map({ (key, value) -> URLQueryItem in
return URLQueryItem(name: key, value: value)
})
}
if isParamsAsQuery{
let request = URLRequest(url: components.url!);
return request;
}
if isParamsAsBody{
let url = URL(string: urlStr);
var request = URLRequest(url: url!);
let bodyStr = components.percentEncodedQuery;
if bodyStr != nil{
request.httpBody = bodyStr!.data(using: String.Encoding.utf8);
}
return request;
}
let url = URL(string: urlStr);
let request = URLRequest(url: url!);
return request;
}
Remove below lines from your code:
let convertedvalue : String = convertToParameters(employeeDetails)
print("convertedvalues : \(convertedvalue)")
let myUrl = URL(string: "https://us-central1-pickceltest.cloudfunctions.net/rebliss/createNewUser");
var request = URLRequest(url:myUrl!)
request.httpBody = postString.data(using: String.Encoding.utf8);
Add following code instead of above removed code
let urlStr = "https://us-central1-pickceltest.cloudfunctions.net/rebliss/createNewUser"
var request = getURLRequestWith(urlStr: urlStr, paramsDict: employeeDetails, isParamsAsQuery: false, isParamsAsBody: true)
convert employeeDetails dictionary to type [String:String] instead of [String:AnyObject]
Now, try your code and it will surely work.
Please check if below solution works. Add percent encoding to you url.
// Create NSURL Ibject
let url : NSString = urlWithParams as NSString
let urlStr = url.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)
let searchURL : NSURL = NSURL(string: urlStr! as String)!
// Creaste URL Request
let request = NSMutableURLRequest(url: searchURL as URL, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 120)
// Set request HTTP method to GET. It could be POST as well
request.httpMethod = "POST"

How to use access token from response using swift 3

So am making a login application that sends username and password, and the server replies with access token....am trying to save this token for later use but i really cant. here is my code, and the server response incase you need it
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var PhoneNumber: UITextField!
#IBOutlet weak var Password: UITextField!
//***************************************LogIn**********************************************\\
#IBAction func Login(_ sender: UIButton) {
guard let url = URL(string: "https://goollyapp.azurewebsites.net/Token") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
let postString = "username=" + PhoneNumber.text! + "&password="+Password.text!+"&grant_type=password"
print(postString)
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let response = response {
print(response)
}
}
task.resume()
}
}
Where you declare the json variable replace with:
let json = try? JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
Then you can access the token with:
let token = json["access_token"] as! String
(after receiving a successful JSON response)
You can then implement a Singleton as follows:
class Token {
// Can't init a singleton
private init() { }
static let sharedInstance = Token()
var tokenString = ""
}
If you want to save the token in a variable for using it later , try this
(key being the corresponding name of the key in your response object)
let token = httpResponse?.allHeaderFields["SECURITY-TOKEN"] as? String
let task = URLSession.shared.dataTask(with: request) { data, response, error in
let httpResponse = response as? HTTPURLResponse
let token = httpResponse?.allHeaderFields["SECURITY-TOKEN"] as? String
print(token)
}
task.resume()

How to work with nonjson data in swift3.0

I am facing some issue with non json data from the backed in swft3.0.
This is the Api I am using http://api.geonames.org/export/geonamesData.js?username=orakzai.
And the response is:
var geonamesPostalCodeCountries = ["AD","AR","AS","AT","AU","AX","BD","BE","BG","BR","BY","CA","CH","CO","CR","CZ","DE","DK","DO","DZ","ES","FI","FO","FR","GB","GF","GG","GL","GP","GT","GU","HR","HU","IE","IN","IS","IT","JE","JP","LI","LK","LT","LU","MC","MD","MK","MP","MQ","MT","MX","MY","NC","NL","NO","NZ","PH","PK","PL","PM","PR","PT","RE","RO","RU","SE","SI","SK","SM","TH","TR","US","VA","VI","WF","YT","ZA","GR"];
var geonamesUserIpCountryCode='null';
Please find the below code.
callApi(apiName: "http://api.geonames.org/export/geonamesData.js?username=orakzai")
func callApi(apiName :String) {
let reachability = Reachability()
if !(reachability?.isReachable)! {
showAlertView(message: " We are unable to reach servers. Please check your network/internet connection.")
} else {
let url = URL(string: "\(apiName)")
let session = URLSession.shared // or let session = URLSession(configuration: URLSessionConfiguration.default)
if let usableUrl = url {
let task = session.dataTask(with: usableUrl, completionHandler: { (data, response, error) in
print(response)
if let data = data {
if let stringData = String(data: data, encoding: String.Encoding.utf8) {
self.dataArray.append(stringData)
print(self.dataArray)
}
}
})
task.resume()
}
}
When I use this code I am getting below response
["var geonamesPostalCodeCountries = [\"AD\",\"AR\",\"AS\",\"AT\",\"AU\",\"AX\",\"BD\",\"BE\",\"BG\",\"BR\",\"BY\",\"CA\",\"CH\",\"CO\",\"CR\",\"CZ\",\"DE\",\"DK\",\"DO\",\"DZ\",\"ES\",\"FI\",\"FO\",\"FR\",\"GB\",\"GF\",\"GG\",\"GL\",\"GP\",\"GT\",\"GU\",\"HR\",\"HU\",\"IE\",\"IN\",\"IS\",\"IT\",\"JE\",\"JP\",\"LI\",\"LK\",\"LT\",\"LU\",\"MC\",\"MD\",\"MK\",\"MP\",\"MQ\",\"MT\",\"MX\",\"MY\",\"NC\",\"NL\",\"NO\",\"NZ\",\"PH\",\"PK\",\"PL\",\"PM\",\"PR\",\"PT\",\"RE\",\"RO\",\"RU\",\"SE\",\"SI\",\"SK\",\"SM\",\"TH\",\"TR\",\"US\",\"VA\",\"VI\",\"WF\",\"YT\",\"ZA\",\"GR\"];\nvar geonamesUserIpCountryCode=\'null\';\n"]
I want to var geonamesPostalCodeCountrie to tableview.
Assume you have the following string variable:
let response = "var geonamesPostalCodeCountries = [\"AD\",\"AR\",\"AS\",\"AT\",\"AU\",\"AX\",\"BD\",\"BE\",\"BG\",\"BR\",\"BY\",\"CA\",\"CH\",\"CO\",\"CR\",\"CZ\",\"DE\",\"DK\",\"DO\",\"DZ\",\"ES\",\"FI\",\"FO\",\"FR\",\"GB\",\"GF\",\"GG\",\"GL\",\"GP\",\"GT\",\"GU\",\"HR\",\"HU\",\"IE\",\"IN\",\"IS\",\"IT\",\"JE\",\"JP\",\"LI\",\"LK\",\"LT\",\"LU\",\"MC\",\"MD\",\"MK\",\"MP\",\"MQ\",\"MT\",\"MX\",\"MY\",\"NC\",\"NL\",\"NO\",\"NZ\",\"PH\",\"PK\",\"PL\",\"PM\",\"PR\",\"PT\",\"RE\",\"RO\",\"RU\",\"SE\",\"SI\",\"SK\",\"SM\",\"TH\",\"TR\",\"US\",\"VA\",\"VI\",\"WF\",\"YT\",\"ZA\",\"GR\"];\nvar geonamesUserIpCountryCode=\'null\';\n"
Since in Swift you cannot simply evaluate the response string like in JavaScript, using eval(response); (which would have created dynamic variables matching the ones declared in the string), how about this:
let vars = response.components(separatedBy: "\n")
var geonamesPostalCodeCountriesStr = vars[0].components(separatedBy: "=")[1].trimmingCharacters(in: CharacterSet(charactersIn: " [];")).replacingOccurrences(of: "\"", with: "")
var geonamesPostalCodeCountries: [String] = geonamesPostalCodeCountriesStr.components(separatedBy: ",")
var geonamesUserIpCountryCodeStr = vars[1].components(separatedBy: "=")[1].trimmingCharacters(in: CharacterSet(charactersIn: " [];")).replacingOccurrences(of: "\'", with: "")
var geonamesUserIpCountryCode: String? = (geonamesUserIpCountryCodeStr == "null") ? nil : geonamesUserIpCountryCodeStr

How to escape the HTTP params in Swift

I'm trying to make a post to an HTTP server
By the way this is my code:
func sendPostToUrl(url:String, withParams params: [String: String?] ) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
var bodyData = ""
for (key,value) in params{
if (value==nil){ continue }
let scapedKey = key.stringByAddingPercentEncodingWithAllowedCharacters(
.URLHostAllowedCharacterSet())!
let scapedValue = value!.stringByAddingPercentEncodingWithAllowedCharacters(
.URLHostAllowedCharacterSet())!
bodyData += "\(scapedKey)=\(scapedValue)&"
}
request.HTTPBody = bodyData.dataUsingEncoding
(NSUTF8StringEncoding, allowLossyConversion: true)
var task = session.dataTaskWithRequest(request,
completionHandler: {data, response, error -> Void in
println("Response: \(response)")
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Data: \(dataString)")
})
task.resume()
}
It works but is not perfect. If I call the function this way:
client.sendPostToUrl("http://novagecko.com/tests/test.php",
withParams: ["hello":"world","inject":"param1=value1&param2=value2"]);
The server detects 3 post fields (with keys hello,inject and param2) instead of 2.
How can I escape the key and values?
Is there something more I could do for improving the method?
If you can target iOS 8 (thanks #Rob), use NSURLComponents to escape your parameters instead:
import Foundation
func encodeParameters(#params: [String: String]) -> String {
var queryItems = map(params) { NSURLQueryItem(name:$0, value:$1)}
var components = NSURLComponents()
components.queryItems = queryItems
return components.percentEncodedQuery ?? ""
}
Now encodeParameters(params:["hello":"world","inject":"param1=value1&param2=value2"]) returns hello=world&inject=param1%3Dvalue1%26param2%3Dvalue2 as you would expect.
Otherwise, the best way to create the character set that will let you escape your values properly is this:
var safeCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy()
safeCharacterSet.removeCharactersInString("&=")
and see #rintaro's answer to use filter/map properly to perform the encoding in a nice way.
It seems, NSCharacterSet doesn't have relevant set for that.
So, add this
extension NSCharacterSet {
class func URLUnreservedCharacterSet() -> NSCharacterSet {
return self(charactersInString: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~")
}
}
Then
var bodyData = ""
var safeCharacterSet = NSCharacterSet.URLUnreservedCharacterSet()
for (key,value) in params{
if (value==nil){ continue }
let scapedKey = key.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)!
let scapedValue = value!.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)!
bodyData += "\(scapedKey)=\(scapedValue)&"
}
As following #Rob's advice in comment, here is a map and join example:
let params:[String:String?] = ["fubar":nil, "hello":"world", "inject":"param1=value1&param2=value2"]
let safeCharacterSet = NSCharacterSet.URLUnreservedCharacterSet()
let pairs = filter(params, {$1 != nil}).map { (key, value) -> String in
let _key = key.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)!
let _val = value!.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)!
return _key + "=" + _val
}
let bodyData = "&".join(pairs)
This is better because there is no trailing & in the result.

Resources