Here is the code where I've sent a SOAP message to my Web Service, with my Integration key, Username and Password. I was able to get the response and parse it all the way down to foundCharacters.
Now I need to store both elements found inside the parsed response, so I can use them later for another request.
I've been searching for tutorials all over, but I cant quiet understand those tutorials, because most of them are about XML files store locally and not from a real WebService.
class LoginCentralViewController: UIViewController, XMLParserDelegate, NSURLConnectionDelegate {
var chaveWS = ChaveWebService().chave()
var mutableData:NSMutableData = NSMutableData()
var currentElement:NSString = ""
@IBAction func btnAcessarACTION(_ sender: Any) {
let soapMessage = "<soapenv:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:log='LoginCentral'><soapenv:Header/><soapenv:Body><log:LoginCentral soapenv:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'><Autenticacao xsi:type='urn:Autenticacao' xmlns:urn='urn:RouterBoxMobile'><ChaveIntegracao xsi:type='xsd:string'>\(chaveWS)</ChaveIntegracao></Autenticacao><DadosLoginCentral xsi:type='urn:DadosLoginCentral' xmlns:urn='urn:RouterBoxMobile'><Usuario xsi:type='xsd:string'>wagner</Usuario><Senha xsi:type='xsd:string'>mudar123</Senha></DadosLoginCentral></log:LoginCentral></soapenv:Body></soapenv:Envelope>"
let urlString = "https://example.com?wsdl"
let url = NSURL (string: urlString)
let theRequest = NSMutableURLRequest(url: url! as URL)
let msgLength = soapMessage.characters.count
theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
theRequest.addValue(String(msgLength), forHTTPHeaderField: "Content-Length")
theRequest.httpMethod = "POST"
theRequest.httpBody = soapMessage.data(using: String.Encoding.utf8, allowLossyConversion: false)
let connection = NSURLConnection(request: theRequest as URLRequest, delegate: self, startImmediately: true)
connection!.start()
if (connection != nil) {
var mutableData : Void = NSMutableData.initialize()
}
print("passou")
}
override func viewDidLoad() {
super.viewDidLoad()
}
func connection(_ connection: NSURLConnection!, didReceiveResponse response: URLResponse!) {
mutableData.length = 0;
print("passou aqui tbm")
}
func connection(_ connection: NSURLConnection!, didReceiveData data: NSData!) {
mutableData.append(data as Data)
}
func connectionDidFinishLoading(_ connection: NSURLConnection!) {
let response = NSString(data: mutableData as Data, encoding: String.Encoding.utf8.rawValue)
let xmlParser = XMLParser(data: mutableData as Data)
xmlParser.delegate = self
xmlParser.parse()
xmlParser.shouldResolveExternalEntities = true
//print(response)
}
//XMLParser
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
currentElement = elementName as NSString
//print(elementName)
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if currentElement == "LoginCentralResponse" {
print(currentElement, string)
}
print(currentElement, string)
}
}
Here is the parsed response that I need to store and reutilize:
ClientCode : 8
Permissions : 70,73,77,75,71,72
I see that you want to store credentials within your app. There is no need to store such file inside XML by writing the file. You can use Keychain
for storing such sensitive data and you can receive anytime you want it back from the Keychain
for further more HTTP requests. It's secure and safe.
Here is the keychain library that I used
https://github.com/marketplacer/keychain-swift
And one another suggestion is you don't need to parse XML so difficult like that,try use this.
https://github.com/drmohundro/SWXMLHash
Your SOAP Web service code seems out of date. It's rare web service that we don't use it most of day and rare documentations. Now, people are turning to REST. And you are using NSURLConnection
which was deprecated in iOS 8. So, let's start using to URLSession
. And I will use Delegate Pattern
here. I have made my answer very simple for you to understand. And you can change anything you want to handle the response.
So, I have two Swift classes. One is ViewController.swift
and another is SOAPService.swift
.
Here is how we gonna handle SOAPService using delegate pattern.
import Foundation
import SWXMLHash
// At here you define your constants at global variables, or you can use structs
public let verify_token = "VerifyToken"
public let WSDL_URL = "https://api.example.com/services?wsdl"
public let BASE_URL = "https://api.example.com/"
public let VERIFY_TOKEN = BASE_URL + "VerifyToken"
// Creating protocol for data transfering
protocol SOAPServiceProtocol{
func didSuccessRequest(results : String, requestName : String)
func didFailRequest(err : String, requestName : String)
}
// I have extended the URLSessionDelegate and URLSessionTaskDelegate for passing TLS, so you might not needed until you handle HTTPS
class SOAPService : NSObject, URLSessionDelegate, URLSessionTaskDelegate{
// Here the initialization of delegate pattern to transfer data between classes
var delegate : SOAPServiceProtocol
init(delegate : SOAPServiceProtocol){
self.delegate=delegate
}
func post(wsdlURL : String, soapAction : String, soapMessage : String, serviceName : String, method : String){
// Here your request configurations
var request = URLRequest(url: URL(string: wsdlURL)!)
let msgLength = String(soapMessage.characters.count)
// Configure your soap message here
let data = soapMessage.data(using: String.Encoding.utf8, allowLossyConversion: false)
// Setting HTTP Header,Body and Method
request.httpMethod = method
request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.addValue(msgLength, forHTTPHeaderField: "Content-Length")
request.addValue(soapAction, forHTTPHeaderField: "SOAPAction")
request.httpBody = data
// URLSession configuration such as TIME OUT,etc
let urlconfig = URLSessionConfiguration.default
urlconfig.timeoutIntervalForRequest = 15
urlconfig.timeoutIntervalForResource = 15
// Initiating URLSession before making a request, I will use default here
var session = URLSession.shared
session = URLSession(configuration: urlconfig, delegate: nil, delegateQueue: nil)
// Start HTTP Request
let task = session.dataTask(with: request) {
data, response, error in
if error != nil {
// If error include,return fail
self.delegate.didFailRequest(err: "Request failed", requestName: serviceName)
return
}
guard let datastring = String(data: data!, encoding:String.Encoding(rawValue: String.Encoding.utf8.rawValue)) else{
return self.delegate.didFailRequest(err: "No Data", requestName: verify_token)
}
let xml = SWXMLHash.parse(datastring)
guard let xmlResult : String = xml["soap:Envelope"]["soap:Body"]["\(serviceName)Response"]["\(serviceName)Result"].element?.text else{
print("XML is NIL")
self.delegate.didFailRequest(err: "XML is NIL", requestName: verify_token)
return
}
// when parsing complete return the parse result
self.delegate.didSuccessRequest(results: xmlResult, requestName: verify_token)
}
task.resume()
}
// Start Writing Your SOAP Services and messages HERE
func doVerify(userName : String, password : String, methodName : String){
let soapMessage = String(format:"<?xml version=\"1.0\" encoding=\"UTF-8\"?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"https://api.example.com/\"><SOAP-ENV:Body><ns1:VerifyToken><ns1:UserName>%@</ns1:UserName><ns1:Password>%@</ns1:Password></ns1:VerifyToken></SOAP-ENV:Body></SOAP-ENV:Envelope>",userName,password)
post(wsdlURL: WSDL_URL, soapAction: VERIFY_TOKEN, soapMessage: soapMessage, serviceName: verify_token, method: "POST")
}
}
So, that is how we gonna handle SOAP web services using URLSession .
So, how do we get the response data from ViewController?
It's easy. We just implement the Protocol methods here.
import UIKit
class ViewController: UIViewController, SOAPServiceProtocol{
var soapService : SOAPService?
override func viewDidLoad() {
super.viewDidLoad()
// You need to initialize the SOAP Service to call SOAP Web Service.
soapService = SOAPService(delegate: self)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func doVerify(sender : AnyObject){
// Here I started HTTP Request
soapService?.doVerify(userName: "Thiha6245", password: "dsadafwa", methodName: verify_token)
}
// Here you implement the results which success
func didSuccessRequest(results : String, requestName: String) {
print("Results : \(results)")
switch requestName {
case verify_token:
// do handling xml parsing from result to model object and get data from model
break
default :
break
}
}
// Here you implement the failure
func didFailRequest(err: String, requestName: String) {
print("Error : \(err)")
switch requestName {
case verify_token:
// do error handling here // Request TIME OUT,Internet connection error or data error,etc
break
default :
break
}
}
}
What is SOAP Message? Like REST,we have to send Parameter to each specific service right?
eg. "www.api.com/services/verifytoken?username=Thiha&password=dwadwdada"
(BASE_URL/SOAPAction?ParamName1=""&ParamName2="")
[GET Request in REST Web Service]
In order to request HTTP in SOAP, you have to write SOAP Message in order to let the SOAP Web Service to understand
<?xml version=\"(Here your SOAP Version)\" encoding=\"UTF-8\"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"(Your API Base URL)/\">
<SOAP-ENV:Body>
<ns1:(SOAPAction)>
<ns1: ParamName1>""</ns1: ParamName1>
<ns1: ParamName2>""</ns1: ParamName2>
</ns1:(SOAPAction)>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I hope it helps you. Since you are beginner at this, I suggest to read the documentations about NSURLSession for further configuration and read how to parse XML using the SWXMLHash that I mentioned. Good Luck!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.