Как создать сложную структуру XML в C # - PullRequest
0 голосов
/ 21 ноября 2019

В моем приложении мне нужно работать с API PayGate для обработки онлайн-платежей.

Запросы должны быть в следующем формате:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <SinglePaymentRequest xmlns="http://www.paygate.co.za/PayHOST">
            <CardPaymentRequest>
                <Account>
                    <PayGateId>10011072130</PayGateId>
                    <Password>test</Password>
                </Account>
                <Customer>
                    <Title>Mr</Title>
                    <FirstName>Joe</FirstName>
                    <LastName>Soap</LastName>
                    <Telephone>0861234567</Telephone>
                    <Mobile>0735552233</Mobile>
                    <Email>joe@soap.com</Email>
                </Customer>
                <CardNumber>4000000000000002</CardNumber>
                <CardExpiryDate>122020</CardExpiryDate>
                <CVV>999</CVV>
                <BudgetPeriod>0</BudgetPeriod>
                <Redirect>
                    <NotifyUrl>https://www.mytestsite.com/notify</NotifyUrl>
                    <ReturnUrl>https://www.mytestsite.com/return</ReturnUrl>
                </Redirect>
                <Order>
                    <MerchantOrderId>INV101</MerchantOrderId>
                    <Currency>ZAR</Currency>
                    <Amount>100</Amount>
                </Order>
            </CardPaymentRequest>
        </SinglePaymentRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Я пытаюсь создать этоструктура, использующая классы XElement в C #, но каждый тег, содержащий слова «SOAP-ENV:» перед ними, не анализируется правильно.

Это моя функция:

        private string ParseCardRequestToXml()
        {
            XNamespace soapEnv = "SOAP-ENV";
            XNamespace spReq = "http://www.paygate.co.za/PayHOST";

            //Envelope
            XElement xmlEnvlelope = new XElement(soapEnv + "Envelope", new XAttribute(XNamespace.Xmlns + "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"));

            //Header
            XElement xmlHeader = new XElement(soapEnv + "Header");

            //Body element
            XElement xmlBody = new XElement("Body");

            //SinglePaymentRequest
            XElement xmlSinglePaymentRequest = new XElement(spReq + "SinglePaymentRequest");

            //CardPaymentRequest
            XElement xmlCardPaymentRequest = new XElement("CardPaymentRequest");

            //Account
            XElement xmlAccount = new XElement("Account");

            xmlAccount.Add(new XElement("PayGateId", "10011072130"));
            xmlAccount.Add(new XElement("Password", "test"));

            //Add account to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlAccount);

            //Customer
            XElement xmlCustomer = new XElement("Customer");

            xmlCustomer.Add(new XElement("Title", "Mr"));
            xmlCustomer.Add(new XElement("FirstName", "Joe"));
            xmlCustomer.Add(new XElement("LastName", "Soap"));
            xmlCustomer.Add(new XElement("Telephone", "0861234567"));
            xmlCustomer.Add(new XElement("Mobile", "0735552233"));
            xmlCustomer.Add(new XElement("Email", "joe@soap.com"));

            //Add customer to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlCustomer);

            //Add Card info to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(new XElement("CardNumber", "4000000000000002"));
            xmlCardPaymentRequest.Add(new XElement("CardExpiryDate", "122020"));
            xmlCardPaymentRequest.Add(new XElement("CVV", 999));
            xmlCardPaymentRequest.Add(new XElement("BudgetPeriod", 0));

            //Redirect
            XElement xmlRedirect = new XElement("Redirect");

            xmlRedirect.Add(new XElement("NotifyUrl", "https://www.mytestsite.com/notify"));
            xmlRedirect.Add(new XElement("ReturnUrl", "https://www.mytestsite.com/return"));

            //Add redirect to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlRedirect);

            //Order
            XElement xmlOrder = new XElement("Order");

            xmlOrder.Add(new XElement("MerchantOrderId", "INV101"));
            xmlOrder.Add(new XElement("Currency", "ZAR"));
            xmlOrder.Add(new XElement("Amount", 100));

            //Add order to "CardPaymentRequest" tag
            xmlCardPaymentRequest.Add(xmlOrder);

            xmlSinglePaymentRequest.Add(xmlCardPaymentRequest);

            xmlBody.Add(xmlSinglePaymentRequest);

            xmlEnvlelope.Add(xmlHeader);
            xmlEnvlelope.Add(xmlBody);

            return xmlEnvlelope.ToString();
        }

Ивот результат, который я получаю:

<Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns=\"SOAP-ENV\">
  <Header />
  <Body xmlns=\"\">
    <SinglePaymentRequest xmlns=\"http://www.paygate.co.za/PayHOST\">
      <CardPaymentRequest xmlns=\"\">
        <Account>
          <PayGateId>10011072130</PayGateId>
          <Password>test</Password>
        </Account>
        <Customer>
          <Title></Title>
          <FirstName>Joe</FirstName>
          <LastName>Soap</LastName>
          <Telephone>0861234567</Telephone>
          <Mobile>0735552233</Mobile>
          <Email>joe@soap.com</Email>
        </Customer>
        <CardNumber>4000000000000002</CardNumber>
        <CardExpiryDate>122020</CardExpiryDate>
        <CVV>999</CVV>
        <BudgetPeriod>0</BudgetPeriod>
        <Redirect>
          <NotifyUrl>https://www.mytestsite.com/notify</NotifyUrl>
          <ReturnUrl>https://www.mytestsite.com/return</ReturnUrl>
        </Redirect>
        <Order>
          <MerchantOrderId>INV101</MerchantOrderId>
          <Currency>ZAR</Currency>
          <Amount>100</Amount>
        </Order>
      </CardPaymentRequest>
    </SinglePaymentRequest>
  </Body>
</Envelope>

Я использовал класс XNamespace в соответствии с этим руководством от Microsoft, но, похоже, я что-то пропустил. Редактировать: В примере make переменная XNamespace aw, но в моем случае я не могу создать такую ​​переменную, потому что "-" не разрешено использовать в именовании ...

Редактировать 2: Хорошо, поэтому я пошел и попробовалдля построения запроса с использованием StringBuilder.

Это функция:

        private string GetDemoCardRequestXML()
        {
            StringBuilder builder = new StringBuilder();

            builder.Append("<SOAP-ENV:Envelope xmlns:SOAP-ENV=").Append('"').Append("http://schemas.xmlsoap.org/soap/envelope/").Append('"').Append(">");
            builder.Append("<SOAP-ENV:Header/>");
            builder.Append("<SOAP-ENV:Body>");
            builder.Append("<SinglePaymentRequest xmlns=").Append('"').Append("http://www.paygate.co.za/PayHOST").Append('"').Append(">");
            builder.Append("<CardPaymentRequest>");
            builder.Append("<Account>");
            builder.Append("<PayGateId>").Append("10011072130").Append("</PayGateId>");
            builder.Append("<Password>").Append("test").Append("</Password>");
            builder.Append("</Account>");
            builder.Append("<Customer>");
            builder.Append("<Title>").Append("Mr").Append("</Title>");
            builder.Append("<FirstName>").Append("Joe").Append("</FirstName>");
            builder.Append("<LastName>").Append("Soap").Append("</LastName>");
            builder.Append("<Telephone>").Append("0861234567").Append("</Telephone>");
            builder.Append("<Mobile>").Append("0735552233").Append("</Mobile>");
            builder.Append("<Email>").Append("joe@soap.com").Append("</Email>");
            builder.Append("</Customer>");
            builder.Append("<CardNumber>").Append("4000000000000002").Append("</CardNumber>");
            builder.Append("<CardExpiryDate>").Append("122020").Append("</CardExpiryDate>");
            builder.Append("<CVV>").Append("999").Append("</CVV>");
            builder.Append("<BudgetPeriod>").Append("0").Append("</BudgetPeriod>");
            builder.Append("<Redirect>");
            builder.Append("<NotifyUrl>").Append("https://www.mytestsite.com/notify").Append("</NotifyUrl>");
            builder.Append("<ReturnUrl>").Append("https://www.mytestsite.com/return").Append("</ReturnUrl>");
            builder.Append("</Redirect>");
            builder.Append("<Order>");
            builder.Append("<MerchantOrderId>").Append("INV101").Append("</MerchantOrderId>");
            builder.Append("<Currency>").Append("ZAR").Append("</Currency>");
            builder.Append("<Amount>").Append("100").Append("</Amount>");
            builder.Append("</Order>");
            builder.Append("</CardPaymentRequest>");
            builder.Append("</SinglePaymentRequest>");
            builder.Append("</SOAP-ENV:Body>");
            builder.Append("</SOAP-ENV:Envelope>");

            return builder.ToString();
        }

Результат:

<SOAP-ENV:Envelope
    xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <SinglePaymentRequest
            xmlns=\"http://www.paygate.co.za/PayHOST\">
            <CardPaymentRequest>
                <Account>
                    <PayGateId>10011072130</PayGateId>
                    <Password>test</Password>
                </Account>
                <Customer>
                    <Title>Mr</Title>
                    <FirstName>Joe</FirstName>
                    <LastName>Soap</LastName>
                    <Telephone>0861234567</Telephone>
                    <Mobile>0735552233</Mobile>
                    <Email>joe@soap.com</Email>
                </Customer>
                <CardNumber>4000000000000002</CardNumber>
                <CardExpiryDate>122020</CardExpiryDate>
                <CVV>999</CVV>
                <BudgetPeriod>0</BudgetPeriod>
                <Redirect>
                    <NotifyUrl>https://www.mytestsite.com/notify</NotifyUrl>
                    <ReturnUrl>https://www.mytestsite.com/return</ReturnUrl>
                </Redirect>
                <Order>
                    <MerchantOrderId>INV101</MerchantOrderId>
                    <Currency>ZAR</Currency>
                    <Amount>100</Amount>
                </Order>
            </CardPaymentRequest>
        </SinglePaymentRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Теперь запрос выглядит лучше, но с экранирующими символами "\msgstr "в области URL xmlns помешает ему быть действительным XML. Любая идея, как я могу удалить их?

Ответы [ 2 ]

0 голосов
/ 27 ноября 2019

Как я уже писал в своем первом комментарии, вам нужно добавить пространства имен soapEnv в "Body" и spReq для всех элементов, начиная с "CardPaymentRequest"

, он будет генерировать XML как

<Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns="SOAP-ENV">
  <Header />
  <Body>
    <SinglePaymentRequest xmlns="http://www.paygate.co.za/PayHOST">
      <CardPaymentRequest>
       ...
      </CardPaymentRequest>
    </SinglePaymentRequest>
  </Body>
</Envelope>

К сожалению, я ошибся, и это формально не тот же xml и не пройдет проверку по той же схеме.

Чтобы получить xat excat, нужно изменитьsoapEnv до http://schemas.xmlsoap.org/soap/envelope/

0 голосов
/ 21 ноября 2019

Вы должны использовать soapEnv.NamespaceName, чтобы добавить префикс к XmlElement

...