Hello all!
I have this code for access to Bing Translation Api vis SOAP protocol:
sub getLanguagesForTranslate {
my ($self) = @_;
my $token = $self->getAccessToken();
my $soap = SOAP::Lite->proxy('http://api.microsofttranslator.com/V
+2/Soap.svc');
$soap->transport->http_request->header('Authorization' => $token);
my $answer = $soap->GetLanguagesForTranslate("appId" => "");
return $answer->result;
}
My problem is in SOAP contract mismatch. My debug messages from SOAP is:
SOAP::Transport::HTTP::Client::send_receive: POST http://api.microsoft
+translator.com/V2/Soap.svc HTTP/1.1
Accept: text/xml
Accept: multipart/*
Accept: application/soap
Authorization: Bearer http%253a%252f%252fschemas.xmlsoap.org%252fws%25
+2f2005%252f05%252fidentity%252fclaims%252fnameidentifier%3DBingTransl
+ationTest%26http%253a%252f%252fschemas.microsoft.com%252faccesscontro
+lservice%252f2010%252f07%252fclaims%252fidentityprovider%3Dhttps%253a
+%252f%252fdatamarket.accesscontrol.windows.net%252f%26Audience%3Dhttp
+%253a%252f%252fapi.microsofttranslator.com%26ExpiresOn%3D1359323697%2
+6Issuer%3Dhttps%253a%252f%252fdatamarket.accesscontrol.windows.net%25
+2f%26HMACSHA256%3Dd4RTa2yAxgndSazm3Ikg0H%252bs3k24wua4rXqZvrUP90Y%253
+d
Content-Length: 505
Content-Type: text/xml; charset=utf-8
SOAPAction: "#GetLanguagesForTranslate"
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi="http:/
+/www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xm
+lsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema
+" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmln
+s:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetLan
+guagesForTranslate><c-gensym3 xsi:type="xsd:string">appId</c-gensym3>
+<c-gensym5 xsi:type="xsd:string" /></GetLanguagesForTranslate></soap:
+Body></soap:Envelope>
SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Internal Ser
+ver Error
Date: Sun, 27 Jan 2013 21:44:55 GMT
Content-Length: 723
Content-Type: text/xml; charset=utf-8
Client-Date: Sun, 27 Jan 2013 21:44:56 GMT
Client-Peer: 131.253.14.99:80
Client-Response-Num: 1
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Bod
+y><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/0
+5/addressing/none">a:ActionNotSupported</faultcode><faultstring xml:l
+ang="en-US">The message with Action '#GetLanguagesForTranslate' canno
+t be processed at the receiver, due to a ContractFilter mismatch at t
+he EndpointDispatcher. This may be because of either a contract misma
+tch (mismatched Actions between sender and receiver) or a binding/sec
+urity mismatch between the sender and the receiver. Check that sende
+r and receiver have the same contract and the same binding (including
+ security requirements, e.g. Message, Transport, None).</faultstring>
+</s:Fault></s:Body></s:Envelope>
I think that problem in authentication. The fact is that you must first obtain the token from Microsoft OAuth server, and put it into the Http request header (you will can read about it from, for example, GetLanguagesForTranslate Method). You can see this in the "Authorization" row from my debug info. This token getting from getAccessToken method in my code, and i don't have warning about this method. I had tested it earler.
I think, that problem in authentication because if i don't put token into Http request, i will have the same error.
This is my first expirience with SOAP and please tell me when i could make mistake!
Thanks for you attention!
UPDATE
I just tried to run PHP example from microsoft sample and made output SOAP request. It is very intresting and you can see this:
POST /V2/soap.svc HTTP/1.1
Host: api.microsofttranslator.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.4.10
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f0
+5%2fidentity%2fclaims%2fnameidentifier=BingTranslationTest&http%3a%2f
+%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%
+2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net
+%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=13593
+95243&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HM
+ACSHA256=a7cPdve2lE7kF5n3ZMMY8byf3p5SIMfrFpJpZird2Vw%3d Content-Type:
+ text/xml; charset=utf-8
SOAPAction: "http://api.microsofttranslator.com/V2/LanguageService/Get
+LanguagesForTranslate"
Content-Length: 1462
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f0
+5%2fidentity%2fclaims%2fnameidentifier=BingTranslationTest&http%3a%2f
+%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%
+2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net
+%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=13593
+95243&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HM
+ACSHA256=a7cPdve2lE7kF5n3ZMMY8byf3p5SIMfrFpJpZird2Vw%3d
You can see that "Authorization" field in HTTP request have duplicate! But, you can see also that "SOAPAction" field have value is "http://api.microsofttranslator.com/V2/LanguageService/GetLanguagesForTranslate".
In my request from SOAP::Lite i had "SOAPAction" called as "#GetLanguagesForTranslate". And now i have a question - how i can change SOAPAction field in my SOAP::Lite request?
UPDATE 2. Solution
After i traced C# sample and when i saw SOAP request i had found a solution. Say the truth i had not made the SOAP::Lite request is equal as C# SOAP request because i had couldn't change http header fully. But it work!
My code now is:
use SOAP::Lite;
$SOAP::Constants::DO_NOT_USE_CHARSET = 0;
$SOAP::Constants::PREFIX_ENV= "s";
$SOAP::Constants::DEFAULT_XML_SCHEMA = undef;
#Other code
sub getLanguagesForTranslate {
my ($self) = @_;
my $token = $self->getAccessToken();
my $soap = SOAP::Lite->proxy('http://api.microsofttranslator.com/V
+2/Soap.svc')
->on_action(sub {return
+ '"http://api.microsofttranslator.com/V2/LanguageService/Ge
+tLanguagesForTranslate"'})
->readable(1)
->encodingStyle("")
->encoding(undef);
$soap->transport->http_request->header("Authorization" => $token);
my $method = SOAP::Data->name('GetLanguagesForTranslate')->attr({x
+mlns => 'http://api.microsofttranslator.com/V2'});
my @params = ( SOAP::Data->name("appId")->type("string")->value(""
+)->type(""));
my $answer = $soap->call($method => @params);
return $answer->result->{string};
}
</p>
This page very helped me: How to Call a .NET-based Web Service Using the SOAP::Lite Perl Library.