SOAPEngine
这个通用的 SOAP 客户端允许您通过您的 iOS 应用程序,Mac OS X 应用程序和 Apple TV 应用程序来访问网络服务。
使用此框架,您可以创建支持 SOAP 客户端协议的 iPhone,iPad,Mac OS X 和 AppleTv 应用程序。此框架可执行远程 Web 服务的 SOAP 标准协议中的方法。
功能
- 支持 2001 (v1.1) 和 2003 (v1.2) XML 架构。
- 支持数组、结构体数组、字典和集合。
- 支持用户定义的对象,具有复杂数据类型和大复杂类型数组的序列化,甚至支持多层嵌套结构。
- 支持 ASMX 服务、WCF 服务 (SVC) 以及现在还支持 WSDL 定义。
- 支持 Basic、Digest 和 NTLM 身份验证、WS-Security、客户端证书和自定义安全头。
- 支持 iOS 社交账户,以便在请求中发送 OAuth2.0 令牌。
- AES256 或 3DES 加密/解密数据,无需使用 SSL 安全功能。
- 示例服务和如何使用它在源代码中提供。
iOS 的要求
对- iOS 8.0 及更高版本
- Xcode 8.0 及更高版本
- Security.framework
- Accounts.framework
- Foundation.framework
- UIKit.framework
- libxml2.dylib
Mac OS X 的要求
对- OS X 10.9 及更高版本
- Xcode 8.0 及更高版本
- Security.framework
- Accounts.framework
- Foundation.framework
- AppKit.framework
- Cocoa.framework
- libxml2.dylib
Apple TV 的要求
对限制
- 对 WCF 服务,仅支持基本的 http 绑定(basicHttpBinding)。
- 在 Mac OS X 中不支持图像对象,你可以使用 NSData 代替。
已知问题
-
Swift 4:当前库是用 Objective-C 编写的,当你导入 Swift 库时,将会得到如下构建错误("The use of Swift 3 @objc inference in Swift 4 mode is deprecated")。
为了静默处理此警告,需要在目标的构建设置中将
Swift 3 @objc Inference
设置为默认值。但是,这并非全部;用于创建请求的类必须带有@objcMembers
和NSObject
的声明,例如:class MyClass { ... } let param = MyClass() // ... // ... let soap = SOAPEngine() soap.setValue(param, forKey: "myKey") // ... // ...
MyClass 的声明应如下所示:
@objcMembers class MyClass: NSObject { ... }
为 Xcode 8.x 或更高版本的 Xcode 中的安全性
从新的 Xcode 8 开始,对应用程序需要额外的设置,如果该设置不存在,您将看到如下类似的消息
App Transport Security 已阻止不安全的明文 HTTP (http://) 资源加载。可以通过您的应用程序的 Info.plist 文件配置临时异常。
要解决这个问题,请在 info.plist 中添加几个键,步骤如下
- 打开您的项目中的
info.plist
文件。 - 添加一个名为
NSAppTransportSecurity
的字典键。 - 添加一个名为
NSAllowsArbitraryLoads
的布尔值子键,并将其值设置为 YES,如图所示。
参考链接:http://stackoverflow.com/a/32631185/4069848
如何使用
使用 委托
#import <SOAPEngine64/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 didFinishLoading:(NSString *)stringXML {
NSDictionary *result = [soapEngine dictionaryValue];
// read data from a dataset table
NSArray *list = [result valueForKeyPath:@"NewDataSet.Table"];
}
使用 块编程
#import <SOAPEngine64/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);
}];
直接从 WSDL(不推荐,因为速度较慢)
#import <SOAPEngine64/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);
}];
使用 通知
#import <SOAPEngine64/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);
}
同步请求
#import <SOAPEngine64/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 3 语言
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)
}
SOAP 认证的设置
#import <SOAPEngine64/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...
OAuth2.0 令牌的社会设置
#import <SOAPEngine64/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...
没有 SSL/HTTPS 的 加密/解密 数据
#import <SOAPEngine64/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...
带有 属性 的参数
// 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"}];
它将请求构建如下
<Book rack="2">
<name>Genesis</name>
<chapter order="asc">1</chapter>
</Book>
W3Schools 示例
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.actionNamespaceSlash = YES;
// w3schools Celsius to Fahrenheit
[soap setValue:@"30" forKey:@"Celsius"];
[soap requestURL:@"https://w3schools.org.cn/webservices/tempconvert.asmx"
soapAction:@"https://w3schools.org.cn/webservices/CelsiusToFahrenheit"
complete:^(NSInteger statusCode, NSString *stringXML) {
NSLog(@"Result: %f", [soap floatValue]);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
WebServiceX 示例
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.actionNamespaceSlash = NO;
[soap setValue:@"Roma" forKey:@"CityName"];
[soap setValue:@"Italy" forKey:@"CountryName"];
[soap requestURL:@"http://www.webservicex.com/globalweather.asmx"
soapAction:@"http://www.webserviceX.NET/GetWeather"
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
NSLog(@"Result: %@", dict);
} failWithError:^(NSError *error) {
NSLog(@"%@", error);
}];
条形码 与 WebServiceX 示例
SOAPEngine *soap = [[SOAPEngine alloc] init];
soap.actionNamespaceSlash = NO;
NSDictionary *barCodeParam = @{
@"Height" : @(100),
@"Width" : @(150),
@"Angle" : @(0),
@"Ratio" : @(5),
@"Module" : @(0),
@"Left" : @(0),
@"Top" : @(0),
@"CheckSum" : @"true",
@"FontName" : @"Arial",
@"FontSize" : @(20),
@"BarColor" : @"black",
@"BGColor" : @"white",
@"barcodeOption" : @"None",
@"barcodeType" : @"CodeEAN13",
@"checkSumMethod" : @"None",
@"showTextPosition" : @"BottomCenter",
@"BarCodeImageFormat" : @"PNG" };
[soap setValue:barCodeParam forKey:@"BarCodeParam"];
[soap setValue:@"9783161484100" forKey:@"BarCodeText"];
[soap requestURL:@"http://www.webservicex.net/genericbarcode.asmx"
soapAction:@"http://www.webservicex.net/GenerateBarCode"
completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) {
NSString *imgBase64 = [soap stringValue];
NSData *base64 = [[NSData alloc] initWithBase64Encoding:imgBase64];
UIImage *barCodeImage = [[UIImage alloc] initWithData:base64];
} failWithError:^(NSError *error) {
NSLog(@"Error: %@", error);
}];
PAYPAL 示例,带有证书
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 登录示例
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);
}];
上传文件 :
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);
}];
下载文件 :
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);
}];
优化
首先,如果您注意到请求响应减慢,尝试更改名为 actionNamespaceSlash
的属性值。之后,在调用名为 requestWSDL
的方法时,会执行以下三个步骤
- 通过 HTTP 请求检索 WSDL。
- 处理以识别 soapAction。
- 通过 HTTP 请求调用方法。
这并不是优化的,非常慢,相反,您可以使用以下优化
- 手动从 WSDL 中检索 SOAPAction(一次用您喜欢的浏览器)。
- 使用名为 requestURL 的方法,而不是具有 WSDL 扩展的 requestWSDL。
安装到您的应用程序中
使用 Cocoapods
阅读 “入门”指南
Cocoapods 和 Swift
标准安装
阅读 “标准安装”指南
许可证
试用(模拟器) | 单一应用程序 | 企业版(多应用程序) |
---|---|---|
![]() |
![]() |
![]() |