SOAPEngine 1.43

SOAPEngine 1.43

测试已测试
Lang语言 Obj-CObjective C
许可证 NOASSERTION
发布最后发布2019年4月

Danilo Priore维护。



SOAPEngine

Version Language Platform License codebeat badge Twitter: @DaniloPriore

这个通用的 SOAP 客户端允许您通过您的 iOS 应用程序,Mac OS X 应用程序和 Apple TV 应用程序来访问网络服务。

使用此框架,您可以创建支持 SOAP 客户端协议的 iPhoneiPadMac OS XAppleTv 应用程序。此框架可执行远程 Web 服务的 SOAP 标准协议中的方法。

功能


  • 支持 2001 (v1.1) 和 2003 (v1.2) XML 架构。
  • 支持数组、结构体数组、字典和集合。
  • 支持用户定义的对象,具有复杂数据类型和大复杂类型数组的序列化,甚至支持多层嵌套结构。
  • 支持 ASMX 服务、WCF 服务 (SVC) 以及现在还支持 WSDL 定义。
  • 支持 BasicDigestNTLM 身份验证、WS-Security、客户端证书和自定义安全头。
  • 支持 iOS 社交账户,以便在请求中发送 OAuth2.0 令牌。
  • AES2563DES 加密/解密数据,无需使用 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 的要求


  • iOS 9.0 及更高版本
  • Xcode 8.0 及更高版本
  • Security.framework
  • Foundation.framework
  • UIKit.framework
  • libxml2.dylib

限制


已知问题


  • Swift 4:当前库是用 Objective-C 编写的,当你导入 Swift 库时,将会得到如下构建错误("The use of Swift 3 @objc inference in Swift 4 mode is deprecated")。

    为了静默处理此警告,需要在目标的构建设置中将 Swift 3 @objc Inference 设置为默认值。但是,这并非全部;用于创建请求的类必须带有 @objcMembersNSObject 的声明,例如:

     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 中添加几个键,步骤如下

  1. 打开您的项目中的 info.plist 文件。
  2. 添加一个名为 NSAppTransportSecurity 的字典键。
  3. 添加一个名为 NSAllowsArbitraryLoads 的布尔值子键,并将其值设置为 YES,如图所示。

NSAppTransportSecurity

参考链接: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 的方法时,会执行以下三个步骤

  1. 通过 HTTP 请求检索 WSDL。
  2. 处理以识别 soapAction。
  3. 通过 HTTP 请求调用方法。

这并不是优化的,非常慢,相反,您可以使用以下优化

  1. 手动从 WSDL 中检索 SOAPAction(一次用您喜欢的浏览器)。
  2. 使用名为 requestURL 的方法,而不是具有 WSDL 扩展的 requestWSDL。

安装到您的应用程序中


使用 Cocoapods

阅读 “入门”指南

Cocoapods 和 Swift

阅读 与 Swift 项目集成 SOAPEngine

标准安装

阅读 “标准安装”指南

许可证


试用(模拟器) 单一应用程序 企业版(多应用程序)
TRIAL LICENSE BUY SINGLE LICENSE BUY ENTERPRISE LICENSE

联系人


TWITTER FACEBOOK LINKED-IN