【问题标题】:Sabre Web Services - Property Description Service Auth Error - ERR.SWS.CLIENT.VALIDATION_FAILEDSabre Web 服务 - 属性描述服务身份验证错误 - ERR.SWS.CLIENT.VALIDATION_FAILED
【发布时间】:2018-07-17 22:54:37
【问题描述】:

我正在尝试使用 C# 调用 HotelPropertyDescriptionLLSRQ Sabre Web 服务。我已经让其他 API 可以使用类似的代码,但我仍然收到相同的客户端验证失败错误,即使在检索到有效的安全令牌之后也是如此。

我想我在代理模型中遗漏了一些小部分,如下所示。

搜索条件对象:

HotelSearchCriteria searchCriteria = new HotelSearchCriteria
            {
                hotelCode = "1191",
                inDate = "8-22",
                outDate = "8-25"
            };

然后是代理类:

public class HotelPropertyDescriptionReq
{
    private HotelPropertyDescriptionService service;
    private HotelPropertyDescriptionRQ req;
    public HotelPropertyDescriptionRS response;
    public string xmlResponse;
    public bool searchPerformed = false;

    public HotelPropertyDescriptionReq()
    {
        //parameterless constructor for serialization
    }

    public HotelPropertyDescriptionReq(SessionToken token, HotelSearchCriteria searchCriteria)
    {
        //argument validation - must have a location of some sort and some dates for search to work. Throw exception here if none found
        if (searchCriteria.hotelCode == null && searchCriteria.cityCode == null)
        {
            //no search can take place if this is null...send back an empty response with searchPerformed == fals
            throw new ArgumentException("Cannot search hotel availability without hotelCode or cityCode");

        }
        else if (searchCriteria.inDate == null || searchCriteria.outDate == null)
        {
            throw new ArgumentException("Cannot serach hotel availability without inDate and outDate");
        }
        //MessageHeader
        MessageHeader mHeader = new MessageHeader();

        PartyId[] pId = { new PartyId() };
        pId[0].Value = "SWS";

        From from = new From();
        from.PartyId = pId;

        To to = new To();
        to.PartyId = pId;

        mHeader.Action = "HotelPropertyDescriptionLLSRQ";
        mHeader.version = "2.3.0";
        mHeader.Service = new Service()
        {
            Value = mHeader.Action
        };
        mHeader.ConversationId = token.conversationID;
        mHeader.CPAId = token.ipcc;
        mHeader.From = from;
        mHeader.To = to;

        mHeader.MessageData = new MessageData()
        {
            Timestamp = DateTime.UtcNow.ToString(),
        };


        //Security
        //Security sec = new Security();
        Security1 sec = new Security1();
        sec.BinarySecurityToken = token.securityToken;


        //Service
        service = new HotelPropertyDescriptionService();
        service.MessageHeaderValue = mHeader;
        //service.SoapVersion = System.Web.Services.Protocols.SoapProtocolVersion.Soap11;
        service.Security = sec;

        //request
        req = new HotelPropertyDescriptionRQ();

        req.AvailRequestSegment = new HotelPropertyDescriptionRQAvailRequestSegment();
        req.AvailRequestSegment.GuestCounts = new HotelPropertyDescriptionRQAvailRequestSegmentGuestCounts();
        req.AvailRequestSegment.GuestCounts.Count = "1";

        req.AvailRequestSegment.HotelSearchCriteria = new HotelPropertyDescriptionRQAvailRequestSegmentHotelSearchCriteria();
        req.AvailRequestSegment.HotelSearchCriteria.Criterion = new HotelPropertyDescriptionRQAvailRequestSegmentHotelSearchCriteriaCriterion();
        req.AvailRequestSegment.HotelSearchCriteria.Criterion.HotelRef = new HotelPropertyDescriptionRQAvailRequestSegmentHotelSearchCriteriaCriterionHotelRef();

        req.AvailRequestSegment.HotelSearchCriteria.Criterion.HotelRef.HotelCode = searchCriteria.hotelCode;

        req.AvailRequestSegment.TimeSpan = new HotelPropertyDescriptionRQAvailRequestSegmentTimeSpan();
        req.AvailRequestSegment.TimeSpan.Start = searchCriteria.inDate;
        req.AvailRequestSegment.TimeSpan.End = searchCriteria.outDate;

        string requestXML = Serializer.toXML(req);
        string headerXML = Serializer.toXML(mHeader);


        //send the request
        try

        {
            response = service.HotelPropertyDescriptionRQ(req);
            searchPerformed = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw;
        }
    }
}

【问题讨论】:

  • 能否请您发布生成的肥皂请求?从那里调试更有意义。
  • 我使用 Pastebin 将 XML 放到网上,因为它不适合 cmets - 如果这不是提供它的最有用的方式,请告诉我。感谢您的输入! pastebin.com/9TPZXaWg
  • 我不知道你的请求中的“-”是从哪里来的,但他们一定要去。整体看起来有点畸形。将添加一个工作请求。

标签: c# .net web-services soap-client sabre


【解决方案1】:

这是一个工作请求 - 您的有效负载与您创建的负载看起来有点不同。试着复制一下 - 需要设置 PCC 和安全凭证:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/1999/XMLSchema">
    <SOAP-ENV:Header>
        <eb:MessageHeader SOAP-ENV:mustUnderstand="1" eb:version="2.0">
            <eb:From>
                <eb:PartyId type="urn:x12.org:IO5:01">1212</eb:PartyId>
            </eb:From>
            <eb:To>
                <eb:PartyId type="urn:x12.org:IO5:01">2323</eb:PartyId>
            </eb:To>
            <eb:CPAId>YOURPCCHERE</eb:CPAId>
            <eb:ConversationId>XXX-dd74-4500-99d6-1e746b8876cc1507217090989</eb:ConversationId>
            <eb:Service eb:type="OTA">HotelPropertyDescriptionLLSRQ</eb:Service>
            <eb:Action>HotelPropertyDescriptionLLSRQ</eb:Action>
            <eb:MessageData>
                <eb:MessageId>1001</eb:MessageId>
                <eb:Timestamp>2016-06-07T10:00:01</eb:Timestamp>
                <eb:TimeToLive>2017-06-06T23:59:59</eb:TimeToLive>
            </eb:MessageData>
        </eb:MessageHeader>
        <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext" xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/12/utility">
            <wsse:BinarySecurityToken EncodingType="wsse:Base64Binary" valueType="String">YOURSECRETHERE</wsse:BinarySecurityToken>
        </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <HotelPropertyDescriptionRQ xmlns="http://webservices.sabre.com/sabreXML/2011/10" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ReturnHostCommand="false" TimeStamp="2015-11-30T12:00:00-06:10" Version="2.3.0">
            <AvailRequestSegment>
             <GuestCounts Count="1"/>
                <HotelSearchCriteria>
                    <Criterion>
                        <HotelRef HotelCode="0022426" UnitOfMeasure="KM"/>
                    </Criterion>
                </HotelSearchCriteria>
                <POS>
                    <Source>
                        <CompanyName Division="BER"/>
                    </Source>
                </POS>
                <TimeSpan End="04-24" Start="04-22" />
            </AvailRequestSegment>
        </HotelPropertyDescriptionRQ>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

【讨论】:

  • 这很好 - 感谢您的回复。我认为破折号是我从 VS 复制/粘贴方式的产物。我修改了一些请求并将元素添加到请求的 POS 级别,现在似乎正在返回结果。该文档确实将 POS 和 Source 列为强制,但我完全不知道 CompanyName 和 Division 成员指的是什么,因为我不知道等效的 Sabre 主机命令。 Sabre 示例有效负载在请求中不包含任何 POS 级别信息,这让我非常困惑。
  • 是的,Sabre 文档不是那么好 - 对于部门,您应该使用“代理”/票务合作伙伴的城市代码,在我们柏林的案例 BER 中
  • 感谢您提供的信息。这些节点被列为强制性节点,但他们在当前文档中列出的示例有效负载都没有包含它 (webservices.sabre.com/drc/servicedoc/…)。确实令人沮丧。
  • 欢迎使用 sabre webservices 进行开发/集成任何 GDS ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 2023-03-08
  • 2013-06-22
相关资源
最近更新 更多