LINUX.ORG.RU

Bitrix веб-сервис

 , , ,


0

1

Доброго дня, встречались тут спецы по битриксу, если токовые имеются, прошу помощи в формировании ответа на соап запрос.

Требуется реализовать веб-сервис внешней аутентификации с помощью соап во внешней системе через сайт на битрексе. У сервиса 3 метода, два из трех реализованы, с одним уже всю голову сломал, ТП битрикса комментариев по модулю веб-сервисов не дает, ссылается на доку, на форуме битриксов тоже тишина, может тут кто поможет.

Необходимо по имени пользователя вернуть массив данных данного пользователя в ответе, загвоздка в том что одино из возвращаемых значений является массивом. В документации по веб-сервисам и примерах кода которые удалось найти в недрах битрикса описано как передать массив во входящем параметре, а мне нужен ответ.

Структура запроса в соапуи выглядит так

<FindConsumer>
          <login>c22314056</login>
      </FindConsumer>

ответа

<pyr:FindConsumerResponse>
         <!--Optional:-->
         <pyr:FindConsumerResult>
            <!--Optional:-->
            <pyr:Address>?</pyr:Address>
            <!--Optional:-->
            <pyr:ContractEndDt>?</pyr:ContractEndDt>
            <!--Optional:-->
            <pyr:ContractNumber>?</pyr:ContractNumber>
            <!--Optional:-->
            <pyr:ContractStartDt>?</pyr:ContractStartDt>
            <!--Optional:-->
            <pyr:Email>?</pyr:Email>
            <!--Optional:-->
            <pyr:INN>?</pyr:INN>
            <!--Optional:-->
            <pyr:Meters>
               <!--Zero or more repetitions:-->
               <pyr:ArrayOfMeterData>
                  <!--Optional:-->
                  <pyr:Model>?</pyr:Model>
                  <!--Optional:-->
                  <pyr:Serial>?</pyr:Serial>
               </pyr:ArrayOfMeterData>
            </pyr:Meters>
            <!--Optional:-->
            <pyr:PersonalAccount>?</pyr:PersonalAccount>
            <!--Optional:-->
            <pyr:Phone>?</pyr:Phone>
         </pyr:FindConsumerResult>
      </pyr:FindConsumerResponse>

Согласно документации классы и структуры описаны таким образом:

$wsdesc->structTypes["CustomConsumerData"] =
		array(
				"Address" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
				"ContractEndDt" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
				"ContractNumber" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
				"ContractStartDt" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
				"Email" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
				"INN" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		        "Meters" => array("varType" => "ArrayOfMeterData", "arrType" => "MeterData", "nillable" => "true"),
				"PersonalAccount" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
				"Phone" => array("varType" => "string", "nillable" => "true", "strict" => "no")
								
		);
		
		$wsdesc->structTypes["ArrayOfMeterData"] =
		array(
		    "MeterData" => array("varType" => "MeterData", "arrType" => "MeterData", "maxOccurs" => "unbounded", "nillable" => "true"),
		);
		
		$wsdesc->structTypes["MeterData"] =
		array(
		    "Model" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		    "Serial" => array("varType" => "string", "nillable" => "true")
		);
		
		$wsdesc->structTypes["NaturalPersonConsumerData"] =
		array(
		    "FirstName" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		    "LastName" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		    "MidleName" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		    "PassportData" => array("varType" => "string", "nillable" => "true", "strict" => "no")
		);
		
		$wsdesc->structTypes["LegalEntityConsumerData"] =
		array(
		    "LegalEntityCaption" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		    "OGRNIP" => array("varType" => "string", "nillable" => "true", "strict" => "no"),
		    "DateEGRIP" => array("varType" => "string", "nillable" => "true", "strict" => "no")
		);
		
		$wsdesc->classes = array(
		    "IExternalAuthProvider" => array(
		        "FindConsumer" => array(
		            "type"		=> "public",
		            "name"		=> "FindConsumer",
		            "input"		=> array(
		                "login" =>array("varType" => "string", "nillable" => "true"),
		            ),
		            "output"	=> array(
		                "FindConsumerResult" => array("varType" => "CustomConsumerData", "nillable" => "true")
		            )
		            
		        ),
		        
		        "ValidatePassword" => array(
		            "type"		=> "public",
		            "name"		=> "ValidatePassword",
		            "input"		=> array(
		                "login" =>array("varType" => "string"),
		                "password" =>array("varType" => "string")
		            ),
		            "output"	=> array(
		                "ValidatePasswordResult" => array("varType" => "bool")
		            )
		        ),
		        
		        "ValidateSession" => array(
		            "type"		=> "public",
		            "name"		=> "ValidateSession",
		            "input"		=> array(
		                "sessionId" =>array("varType" => "string", "nillable" => "true")),
		            "output"	=> array(
		                "ValidateSessionResult" => array("varType" => "string")
		            )
		        )
		    )
		);		

		return $wsdesc;
	}

При вызове метода FindConsumer в соапуи получаю

<soap:Body>
      <soap:Fault>
         <faultcode>Server Error</faultcode>
         <faultstring>Request has not enough params of strict type to be decoded.</faultstring>
      </soap:Fault>
   </soap:Body>

Внутренние тесты битрикса в данном случае игнорируют исключение и возвращают массив значений без meters

Внешняя система при обращении к этому методу выкидывает исключение

System.ServiceModel.Dispatcher.NetDispatcherFaultException: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter PyramidExternalAuth:FindConsumerResult. The InnerException message was 'Error in line 1 position 211. 'EndElement' 'FindConsumerResult' from namespace 'PyramidExternalAuth' is not expected. Expecting element 'Address | ContractEndDt | ContractNumber | ContractStartDt | Email | INN | Meters'.'.  Please see InnerException for more details.
 ---> System.Runtime.Serialization.SerializationException: Error in line 1 position 211. 'EndElement' 'FindConsumerResult' from namespace 'PyramidExternalAuth' is not expected. Expecting element 'Address | ContractEndDt | ContractNumber | ContractStartDt | Email | INN | Meters'.
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.ThrowRequiredMemberMissingException(XmlReaderDelegator xmlReader, Int32 memberIndex, Int32 requiredIndex, XmlDictionaryString[] memberNames)
   at ReadCustomConsumerDataFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
   at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo.ReadObject(XmlDictionaryReader reader, XmlObjectSerializer serializer)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo.ReadObject(XmlDictionaryReader reader)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
   --- End of inner exception stack trace ---
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters)
   at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)
--- End of stack trace from previous location where exception was thrown ---
   at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)
   at generatedProxy_2.FindConsumer(String )
   at CSSecurityManager.Auth.ExternalV2.ExternalAuthProviderClient.Proxy.FindConsumer(String login) in /home/user/p2/Sources/Pyramid/ControlService/CSLinkedAssemblies/CSSecurityManager/Auth/ExternalV2/ExternalAuthProviderClient.cs:line 125
★★★

Последнее исправление: julixs (всего исправлений: 2)