-
-
Notifications
You must be signed in to change notification settings - Fork 75
Expand file tree
/
Copy pathREADME.md
More file actions
451 lines (329 loc) · 18.4 KB
/
README.md
File metadata and controls
451 lines (329 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# SOAPEngine
  [](http://cocoapods.org/pods/SOAPEngine) []() [](http://cocoapods.org/pods/SOAPEngine) [](http://cocoapods.org/pods/SOAPEngine) [](https://twitter.com/DaniloPriore)
This generic [SOAP](http://www.wikipedia.org/wiki/SOAP) client allows you to access web services using a your [iOS](http://www.wikipedia.org/wiki/IOS) app, [Mac OS X](http://www.wikipedia.org/wiki/OS_X) app and [Apple TV](http://www.apple.com/tv/) app.
With this Framework you can create [iPhone](http://www.wikipedia.org/wiki/IPhone), [iPad](http://www.wikipedia.org/wiki/IPad), [Mac OS X](http://www.wikipedia.org/wiki/OS_X) and [AppleTv](http://www.apple.com/tv/) apps that supports [SOAP](http://www.wikipedia.org/wiki/SOAP) Client Protocol. This framework able executes methods at remote web services with [SOAP](http://www.wikipedia.org/wiki/SOAP) standard protocol.
## Features
* Support both 2001 (v1.1) and 2003 (v1.2) [XML](http://www.wikipedia.org/wiki/XML) schema.
* Support array, array of structs, dictionary and sets.
* Support for user-defined object with serialization of complex data types and array of complex data types, even embedded multilevel structures.
* Supports [ASMX](http://www.wikipedia.org/wiki/ASP.NET#Other_files) Services, [WCF](http://www.wikipedia.org/wiki/Windows_Communication_Foundation) Services ([SVC](http://www.wikipedia.org/wiki/ASP.NET#Other_files)) and now also the [WSDL](http://www.wikipedia.org/wiki/Web_Services_Description_Language) definitions.
* Supports [Basic](http://www.wikipedia.org/wiki/Basic_access_authentication), [Digest](http://www.wikipedia.org/wiki/Digest_access_authentication) and [NTLM](http://www.wikipedia.org/wiki/Integrated_Windows_Authentication) Authentication, [WS-Security](http://www.wikipedia.org/wiki/WS-Security), Client side Certificate and custom security header.
* Supports [iOS](http://www.wikipedia.org/wiki/IOS) Social Account to send [OAuth2.0](http://www.wikipedia.org/wiki/OAuth) token on the request.
* [AES256](http://www.wikipedia.org/wiki/Advanced_Encryption_Standard) or [3DES](http://www.wikipedia.org/wiki/Triple_DES) Encrypt/Decrypt data without [SSL](http://www.wikipedia.org/w/index.php?title=Transport_Layer_Security) security.
* An example of service and how to use it is included in source code.
## Requirements for [iOS](http://www.wikipedia.org/wiki/IOS)
* [iOS](http://www.wikipedia.org/wiki/IOS) 8.0 and later
* [Xcode](http://www.wikipedia.org/wiki/Xcode) 8.0 or later
* Security.framework
* Accounts.framework
* Foundation.framework
* UIKit.framework
* libxml2.dylib
## Requirements for [Mac OS X](http://www.wikipedia.org/wiki/OS_X)
* [OS X](http://www.wikipedia.org/wiki/OS_X) 10.9 and later
* [Xcode](http://www.wikipedia.org/wiki/Xcode) 8.0 or later
* Security.framework
* Accounts.framework
* Foundation.framework
* AppKit.framework
* Cocoa.framework
* libxml2.dylib
## Requirements for [Apple TV](http://www.apple.com/tv/)
* [iOS](http://www.wikipedia.org/wiki/IOS) 9.0 and later
* [Xcode](http://www.wikipedia.org/wiki/Xcode) 8.0 or later
* Security.framework
* Foundation.framework
* UIKit.framework
* libxml2.dylib
## Limitations
* for [WCF](http://www.wikipedia.org/wiki/Windows_Communication_Foundation) services, only supports basic http bindings ([basicHttpBinding](https://msdn.microsoft.com/library/ms731361.aspx)).
* in [Mac OS X](http://www.wikipedia.org/wiki/OS_X) unsupported image objects, instead you can use the [NSData](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/index.html).
## Known issues
- **Swift 4**: the library is currently written in Objective-C and when you import the swift library you will get build errors like this `The use of Swift 3 @objc inference in Swift 4 mode is deprecated`.
For silent this warning is need sets `Swift 3 @objc Inference` to default value in the the Build settings of target. __but It's not all__; the classes used to create requests must be declared with `@objcMembers` and `NSObject`, eg:
``` swift
class MyClass { ... }
let param = MyClass()
// ...
// ...
let soap = SOAPEngine()
soap.setValue(param, forKey: "myKey")
// ...
// ...
```
the declaration of MyClass must become :
``` swift
@objcMembers class MyClass: NSObject { ... }
```
## Security for Xcode 8.x or later
From the new Xcode 8 is required an additional setting for the apps, if this setting does not exist you will see a log message like this:
`App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.`
To resolve this, add few keys in info.plist, the steps are:
1. Open `info.plist` file of your project.
2. Add a Key called `NSAppTransportSecurity` as a Dictionary.
3. Add a Subkey called `NSAllowsArbitraryLoads` as Boolean and set its value to YES as like following image.

ref link: http://stackoverflow.com/a/32631185/4069848
## Migrate from 1.43 to 1.44
This version (1.44) was designed to optimize performance and remove older functionality.
There are no substantial differences but no longer uses delegates with xml in string format, now just uses the format of the data already parsed and converted into a dictionary.
The peculiarity of this version is now works completely in secondary tasks, so all delegates, notifications and closures, now are generated in secondary tasks. If in these delegates are necessary to update the UI, will be necessary to perform the update in a main thread, in this case will be necessary to use `dispatch_async(dispatch_get_main_queue(), ^{...})` for Objective-C language, or `DispatchQueue.main.async {...}` for Swift language.
If no data is retrieved, after a request, an error may be generated with the following message : *"SOAPEngine no valid response, try again with actionNamespaceSlash set to YES or/and responseHeader set to YES"*.
## How to use
with [**Delegates**](https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html) :
``` objective-c
#import "SOAPEngine.h"
// standard soap service (.asmx)
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
soap.delegate = self; // use SOAPEngineDelegate
// each single value
[soap setValue:@"my-value1" forKey:@"Param1"];
[soap setIntegerValue:1234 forKey:@"Param2"];
// service url without ?WSDL, and you can search the soapAction in the WSDL
[soap requestURL:@"http://www.my-web.com/my-service.asmx"
soapAction:@"http://www.my-web.com/My-Method-name"];
#pragma mark - SOAPEngine Delegates
- (void)soapEngine:(SOAPEngine *)soapEngine didFinishLoadingWithDictionary:(NSDictionary *)dict data:(NSData *)data {
// read data from a dataset table
NSArray *list = [dict valueForKeyPath:@"NewDataSet.Table"];
}
```
with [**Block programming**](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html) :
``` objective-c
#import "SOAPEngine.h"
// TODO: your user object
MyClass myObject = [[MyClass alloc] init];
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
soap.version = VERSION_WCF_1_1; // WCF service (.svc)
// service url without ?WSDL, and you can search the soapAction in the WSDL
[soap requestURL:@"http://www.my-web.com/my-service.svc"
soapAction:@"http://www.my-web.com/my-interface/my-method"
value:myObject
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
NSLog(@"%@", dict);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
```
directly from [**WSDL**](http://www.wikipedia.org/wiki/Web_Services_Description_Language) (*not recommended is slow*) :
``` objective-c
#import "SOAPEngine.h"
// TODO: your user object
MyClass myObject = [[MyClass alloc] init];
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
// service url with WSDL, and operation (method name) without tempuri
[soap requestWSDL:@"http://www.my-web.com/my-service.amsx?wsdl"
operation:@"my-method-name"
value:myObject
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
NSLog(@"Result: %@", dict);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
```
with [**Notifications**](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/index.html) :
``` objective-c
#import "SOAPEngine.h"
// TODO: your user object
MyClass myObject = [[MyClass alloc] init];
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
soap.version = VERSION_WCF_1_1; // WCF service (.svc)
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(soapEngineDidFinishLoading:)
name:SOAPEngineDidFinishLoadingNotification
object:nil];
// service url without ?WSDL, and you can search the soapAction in the WSDL
[soap requestURL:@"http://www.my-web.com/my-service.svc"
soapAction:@"http://www.my-web.com/my-interface/my-method"
value:myObject];
#pragma mark - SOAPEngine Notifications
- (void)soapEngineDidFinishLoading:(NSNotification*)notification
{
SOAPEngine *engine = notification.object; // SOAPEngine object
NSDictionary *result = [engine dictionaryValue];
NSLog(@"%@", result);
}
```
[**Synchronous**]() request :
``` objective-c
#import "SOAPEngine.h"
NSError *error = nil;
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.responseHeader = YES; // use only for non standard MS-SOAP service like PHP
NSDictionary *dict = [soap syncRequestURL:@"http://www.my-web.com/my-service.amsx"
soapAction:@"http://tempuri.org/my-method" error:&error];
NSLog(@"error: %@, result: %@", error, dict)
```
[**Swift**](http://www.wikipedia.org/wiki/Swift_programming_language) language :
``` swift
var soap = SOAPEngine()
soap.userAgent = "SOAPEngine"
soap.actionNamespaceSlash = true
soap.version = VERSION_1_1
soap.responseHeader = true // use only for non standard MS-SOAP service
soap.setValue("param-value", forKey: "param-name")
soap.requestURL("http://www.my-web.com/my-service.asmx",
soapAction: "http://www.my-web.com/My-Method-name",
completeWithDictionary: { (statusCode : Int,
dict : [AnyHashable : Any]?) -> Void in
var result:Dictionary = dict! as Dictionary
print(result)
}) { (error : Error?) -> Void in
print(error)
}
```
settings for [**SOAP Authentication**](http://www.whitemesa.com/soapauth.html) :
``` objective-c
#import "SOAPEngine.h"
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
// authorization
soap.authorizationMethod = SOAP_AUTH_BASIC; // basic auth
soap.username = @"my-username";
soap.password = @"my-password";
// TODO: your code here...
```
settings for Social [**OAuth2.0**](http://www.wikipedia.org/wiki/OAuth) token :
``` objective-c
#import "SOAPEngine.h"
#import <Accounts/Accounts.h>
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
// token authorization
soap.authorizationMethod = SOAP_AUTH_SOCIAL;
soap.apiKey = @"1234567890"; // your apikey https://dev.twitter.com/
soap.socialName = ACAccountTypeIdentifierTwitter;
// TODO: your code here...
```
[**Encryption/Decryption**](https://it.wikipedia.org/wiki/Advanced_Encryption_Standard) data without SSL/HTTPS :
``` objective-c
#import "SOAPEngine.h"
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.userAgent = @"SOAPEngine";
soap.encryptionType = SOAP_ENCRYPT_AES256; // or SOAP_ENCRYPT_3DES
soap.encryptionPassword = @"my-password";
// TODO: your code here...
```
Params with [**Attributes**](http://www.w3schools.com/xml/xml_attributes.asp) :
``` objective-c
// book
NSMutableDictionary *book = [NSMutableDictionary dictionaryWithObject:@"Genesis" forKey:@"name"];
// chapter
NSDictionary *attr = @{@"order": @"asc"};
NSDictionary *child = [soap dictionaryForKey:@"chapter" value:@"1" attributes:attr];
[book addEntriesFromDictionary:child]; // add chapter to book
// book attributes
[soap setValue:book forKey:@"Book" attributes:@{@"rack": @"2"}];
```
it builds a request like this:
``` xml
<Book rack="2">
<name>Genesis</name>
<chapter order="asc">1</chapter>
</Book>
```
[**PAYPAL**](http://www.paypal.com) example with certificate :
``` objective-c
SOAPEngine *soap = [[SOAPEngine alloc] init];
// PAYPAL associates a set of API credentials with a specific PayPal account
// you can generate credentials from this https://developer.paypal.com/docs/classic/api/apiCredentials/
// and convert to a p12 from terminal use :
// openssl pkcs12 -export -in cert_key_pem.txt -inkey cert_key_pem.txt -out paypal_cert.p12
soap.authorizationMethod = SOAP_AUTH_PAYPAL;
soap.username = @"support_api1.your-username";
soap.password = @"your-api-password";
soap.clientCerficateName = @"paypal_cert.p12";
soap.clientCertificatePassword = @"certificate-password";
soap.responseHeader = YES;
// use paypal for urn:ebay:api:PayPalAPI namespace
[soap setValue:@"0" forKey:@"paypal:ReturnAllCurrencies"];
// use paypal1 for urn:ebay:apis:eBLBaseComponents namespace
[soap setValue:@"119.0" forKey:@"paypal1:Version"]; // ns:Version in WSDL file
// certificate : https://api.paypal.com/2.0/ sandbox https://api.sandbox.paypal.com/2.0/
// signature : https://api-3t.paypal.com/2.0/ sandbox https://api-3t.sandbox.paypal.com/2.0/
[soap requestURL:@"https://api.paypal.com/2.0/"
soapAction:@"GetBalance" completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
NSLog(@"Result: %@", dict);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
```
[**Magento 2**](http://devdocs.magento.com) login example :
``` objective-c
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.selfSigned = YES; // only for invalid https certificates
soap.responseHeader = YES;
soap.actionNamespaceSlash = NO;
soap.envelope = @"xmlns:urn=\"urn:Magento\"";
[soap setValue:@"your-username" forKey:@"username"];
[soap setValue:@"your-apykey" forKey:@"apiKey"];
[soap requestURL:@"https://your-magentohost/api/v2_soap/"
soapAction:@"urn:Mage_Api_Model_Server_V2_HandlerAction#login"
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict)
{
NSLog(@"Login return: %@", [soap stringValue]);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
```
[**Upload file**]() :
``` objective-c
SOAPEngine *soap = [[SOAPEngine alloc] init];
// read local file
NSData *data = [NSData dataWithContentsOfFile:@"my_video.mp4"];
// send file data
[soap setValue:data forKey:@"video"];
[soap requestURL:@"http://www.my-web.com/my-service.asmx"
soapAction:@"http://www.my-web.com/UploadFile"
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
NSLog(@"Result: %@", dict);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
```
[**Download file**]() :
``` objective-c
SOAPEngine *soap = [[SOAPEngine alloc] init];
// send filename to remote webservice
[soap setValue:"my_video.mp4" forKey:@"filename"];
[soap requestURL:@"http://www.my-web.com/my-service.asmx"
soapAction:@"http://www.my-web.com/DownloadFile"
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
// local writable directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths firstObject] stringByAppendingPathComponent:@"my_video.mp4"];
// the service returns file data in the tag named video
NSData *data = dict[@"video"];
[data writeToFile:@"my_video.mp4" atomically:YES];
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
```
## Optimizations
First of all, if you note a slowdown in the response of the request, try to change the value of the property named `actionNamespaceSlash`.
After, when using the method named `requestWSDL` three steps are performed :
1. retrieve the WSDL with an http request.
2. processing to identify the soapAction.
3. calls the method with an http request.
this is not optimized, very slow, instead you can use the optimization below :
1. retrieving manually the SOAPAction directly from WSDL (once with your favorite browser).
2. use the method named requestURL instead of requestWSDL without WSDL extension.
## Install in your apps
#### With Cocoapods
Read the ["Getting Started" guide](https://github.com/priore/SOAPEngine/wiki/Cocoapods-Installation-guide)
#### Cocoapods and Swift
Read the [Integrating SOAPEngine with a Swift project](https://github.com/priore/SOAPEngine/wiki/Integrating-SOAPEngine-with-a-Swift-project)
#### Standard installation
Read the ["Standard Installation" guide](https://github.com/priore/SOAPEngine/wiki/Standard-Installation)
## Support Development
If this project has been helpful to you, please consider making a small donation. Your support is crucial for funding new features, covering hosting costs, or simply buying me a coffee! Every contribution, big or small, is highly appreciated.
Scan the code below with your cryptocurrency wallet or copy the address.
|Donate with BTC (Bitcoin)
|:------------:|
|
|`BTC Address (SegWit) : bc1q6rjOuuwu9k2fvs5n5elmqy9v4ljazhexejykjm`