【问题标题】:Royal Mail Shipping API v2 SOAP authentication C#Royal Mail Shipping API v2 SOAP 身份验证 C#
【发布时间】:2016-08-11 12:14:47
【问题描述】:

我已经根据其他人的堆栈溢出代码完成了大部分工作。见下文。

我目前的问题是我仍然遇到授权失败,我可以清楚地看到原因。 v2 API 需要传递 X-IBM-Client-Id 和 X-IBM-Client-Secret 以及 SOAP 安全标头。 但是,我不知道在使用从 Wsdl 文件创建的服务时如何注入它.

已解决的问题:

克服命名空间问题(使用消息格式化程序Consume WCF Royal Mail API in c# Console Application)。

解决了导致两个安全标头的绑定配置问题。此外,如果您希望在检索标签时不出现异常,则必须设置 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 请求未通过客户端身份验证方案“匿名”进行授权(您必须将上述绑定与安全“传输”一起使用,并将凭据直接注入 http post 标头本身(请参阅下面的答案)。

还有很多其他的问题,我现在不记得了。我希望这篇文章对其他人有所帮助。

【问题讨论】:

    标签: c# soap wsdl


    【解决方案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 文件。

    【讨论】:

    • 我刚刚在 github 上查看了您的解决方案。看起来它没有一个“工作”项目。那是对的吗?我是否认为要使用它我需要创建一个新项目,然后从中调用 RoyalMailApiCredentials 和 RoyalMailApiClient 类?谢谢。
    • @jimmy 我不确定您所说的“工作项目”是什么意思。这是在您的软件中使用的库。但是,正如文档所述,只需转到测试项目,输入您的凭据,您就可以测试创建货件和打印标签。
    • 感谢您的回答,我确实尝试按照文档进行操作,但出现错误。 “无法直接启动具有类库输出类型的项目”。我所说的工作项目是一个简单的可执行项目,因此代码可以运行。从文档来看,它听起来应该是“开箱即用”,所以我主要想确保我没有弄乱我的代码版本
    • 好吧,你只需要执行测试。有两个项目,第二个是测试。执行它们与运行 exe 相同。它将运行代码,并调用 Royal Mail Api。打开测试,右键单击并单击“运行测试”。如果你使用 Visual Studio,就这么简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    • 2022-12-10
    • 2020-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多