我已根据其他人的堆栈溢出代码完成了大部分工作。见下文。
我目前的问题是,我仍然无法获得授权,我可以清楚地看到原因。 v2 API要求传递X-IBM-Client-Id和X-IBM-Client-Secret以及SOAP安全标头。但是,我不知道如何在使用从中创建的服务时注入它Wsdl文件。
解决问题:
克服命名空间问题(使用消息格式化程序Consume WCF Royal Mail API in c# Console Application)。
解决了绑定配置问题,导致出现两个安全标头。此外,如果要在检索label.Final绑定时没有异常,则必须设置maxReceivedMessageSize:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicBindingTransport" maxReceivedMessageSize="2147483647">
<security mode="Transport">
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://api.royalmail.net/shipping/v2" binding="basicHttpBinding"
bindingConfiguration="basicBindingTransport" contract="RoyalMailApiWsdl.shippingAPIPortType" name="shippingAPIPort" />
</client>
</system.serviceModel>
解决了E0007授权失败问题。
已解决HTTP请求未经授权使用客户端身份验证方案&#39;匿名&#39; (您必须使用上述绑定与安全性&#34; Transport&#34;并将凭据直接注入http帖子标题本身(请参阅下面的答案)。
还有很多其他问题,我现在都记不住了。我希望这篇文章能够帮助其他人。
答案 0 :(得分:1)
要在Shipping API v2中实现双重身份验证,您可以使用此代码(从How to add custom Http Header for C# Web Service Client consuming Axis 1.4 Web service获取的想法)
shippingAPIPortTypeClient client = GetProxy();
<..>
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(@"X-IBM-Client-Id", _credentials.HttpSecurity.ClientId);
httpRequestProperty.Headers.Add(@"X-IBM-Client-Secret", _credentials.HttpSecurity.ClientSecret);
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
createShipmentResponse response = client.createShipment(GetSecurityHeaderType(), request);
return response;
}
private shippingAPIPortTypeClient GetProxy()
{
// binding comes from configuration file
var shippingClient = new shippingAPIPortTypeClient();
shippingClient.ClientCredentials.UserName.UserName = _credentials.SoapSecurity.Username;
shippingClient.ClientCredentials.UserName.Password = _credentials.SoapSecurity.Password;
shippingClient.ClientCredentials.UseIdentityConfiguration = true;
foreach (OperationDescription od in shippingClient.Endpoint.Contract.Operations)
{
od.Behaviors.Add(new RoyalMailIEndpointBehavior());
}
return shippingClient;
}
private SecurityHeaderType GetSecurityHeaderType()
{
SecurityHeaderType securityHeader = new SecurityHeaderType();
DateTime created = DateTime.Now;
string creationDate;
creationDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
string nonce = nonce = (new Random().Next(0, int.MaxValue)).ToString();
byte[] hashedPassword;
hashedPassword = GetSHA1(_credentials.SoapSecurity.Password);
string concatednatedDigestInput = string.Concat(nonce, creationDate, Encoding.Default.GetString(hashedPassword));
byte[] digest;
digest = GetSHA1(concatednatedDigestInput);
string passwordDigest;
passwordDigest = Convert.ToBase64String(digest);
string encodedNonce;
encodedNonce = Convert.ToBase64String(Encoding.Default.GetBytes(nonce));
XmlDocument doc = new XmlDocument();
using (XmlWriter writer = doc.CreateNavigator().AppendChild())
{
writer.WriteStartDocument();
writer.WriteStartElement("Security");
writer.WriteStartElement("UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteElementString("Username", _credentials.SoapSecurity.Username);
writer.WriteElementString("Password", passwordDigest);
writer.WriteElementString("Nonce", encodedNonce);
writer.WriteElementString("Created", creationDate);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
}
doc.DocumentElement.RemoveAllAttributes();
System.Xml.XmlElement[] headers = doc.DocumentElement.ChildNodes.Cast<XmlElement>().ToArray<XmlElement>();
securityHeader.Any = headers;
return securityHeader;
}
除此之外,还可以在此处找到完整的C#Royal Mail Shipping API v2解决方案:https://github.com/povilaspanavas/RoyalMailShippingApiV2
它有三个测试,一个用于创建本地(GB)货件,另一个用于国际,第三个用于检索标签pdf文件。