Azure API管理SOAP到REST

问题描述

我们正在从旧的SOAP Web服务调用转移到让客户调用新的Azure Functions / REST API调用

我们希望能够使用Azure API管理为我们的客户将OLD SOAP消息转换为REST调用,这样他们就不必重写自己的资料,就可以继续使用SOAP消息。

我几乎没有找到关于如何进行此工作的文档。我尝试使用旧SOAP服务中的WSDL来摆弄它,然后将其指向Azure API,但是除了错误我什么都没有。

我看不到任何获取详细信息的方法

我知道我需要使用Liquid Templates来转换SOAP消息,该消息具有大约10个属性,并且是将数据数组转换为JSON的方法,但是运气很好。

有人有什么资源可以使它正常工作吗?

添加以下示例数据。

这就是我们所说的传统SOAP消息。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ad="http://ad-c.com/">
    <soapenv:Header/>
    <soapenv:Body>
        <ad:ImportItemmovement>
            <ad:authenticationToken>0badec32-81f7-4f88-813f-2dbfb62b4484</ad:authenticationToken>
            <ad:movementArray>
                <ad:WSItemmovementInfo>
                    <ad:OrgUnitNum>52</ad:OrgUnitNum>
                    <ad:MovementDateTime>2020-10-06T09:55:50</ad:MovementDateTime>
                    <ad:RetailSold>5.99</ad:RetailSold>
                    <ad:QtySold>300</ad:QtySold>
                    <ad:ItemNum>123456789</ad:ItemNum>
                    <ad:UpcNum>00021234500000</ad:UpcNum>
                </ad:WSItemmovementInfo>
                <ad:WSItemmovementInfo>
                    <ad:OrgUnitNum>54</ad:OrgUnitNum>
                    <ad:MovementDateTime>2020-10-06T09:55:50</ad:MovementDateTime>
                    <ad:RetailSold>5.99</ad:RetailSold>
                    <ad:QtySold>300</ad:QtySold>
                    <ad:ItemNum>123456789</ad:ItemNum>
                    <ad:UpcNum>00021234500000</ad:UpcNum>
                </ad:WSItemmovementInfo>
            </ad:movementArray>
        </ad:ImportItemmovement>
    </soapenv:Body>
</soapenv:Envelope>

在@DSpirit的帮助下,这是当前政策

    <policies>
    <inbound>
        <base />
        <find-and-replace from="ad:" to="" />
        <find-and-replace from="soapenv:" to="" />
        <xml-to-json kind="direct" apply="always" consider-accept-header="true" />
        <trace source="inbound">@(context.Request.Body.As<string>(true))</trace>
            <set-body>@{
                 var body = JObject.Parse(context.Request.Body.As<string>());
                 return body["Envelope"]["Body"]["ImportItemmovement"]["movementArray"]["WSItemmovementInfo"]?.ToString();
                 }</set-body>
                <set-body template="liquid">
                [
                 {% JSONArrayFor item in body %}
                 {
                 "StoreNumber": {{ item.OrgUnitNum }},"BarcodeNumber": "{{ item.UpcNum }}",{% if item.WgtSold %}
                 "Type": "W","QuantitySold": {{ item.WgtSold }},{% endif %}
                 {% if item.QtySold %} 
                 "Type": "Q","QuantitySold": {{ item.QtySold }},{% endif %}
                 "TotalRetail": {{ item.RetailSold }},{% if item.onPromotion %}
                 "PromotionType": {{ item.onPromotion }},{% else %}
                 "PromotionType": 0,{% endif %}
                 "SerialNumber": "{{ item.labelSerialNum }}","MovementDateTime": "{{ item.MovementDateTime }}"
                 }
                 {% endJSONArrayFor %}
                 ]
            </set-body>
        <!-- Here you should forward the request to the function backend instead of returning it -->
        <set-backend-service base-url="https://proxy.freshiq.com/prod/inventory/" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

这是Azure REST API的期望。

  [{
      "StoreNumber": 0,"BarcodeNumber": "string","Type": "string","QuantitySold": 0.5229864343061676,"TotalRetail": 0.2568850594082819,"PromotionType": 0,"SerialNumber": "string","MovementDateTime": "string"
  },{
      "StoreNumber": 0,"MovementDateTime": "string"
  }]

从SOAP XML到REST JSON的映射为:

OrgUnitNum = StoreNumber
UpcNum = BarcodeNumber
If WgtSold exits Then Type = "W"
If QtySold exist then Type = "Q"
WgtSold if exists or QtySold if exists = QuantitySold
RetailSold = TotalRetail 
onPromotion = PromotionType 
labelSerialNum = SerialNumber
MovementDateTime = MovementDateTime

使用上述方法似乎确实可以工作,但有一个例外,即在第2个记录的第一个记录中生成的JSON具有SOAP字段的名称,而不是JSON的名称,但是“ FOR”循环中的第二个记录是正确的。我不确定是什么原因造成的。

解决方法

我已经对一个策略进行了剪贴,该策略返回了我猜想的期望输出。

<policies>
    <inbound>
        <base />
        <find-and-replace from="ad:" to="" />
        <find-and-replace from="soapenv:" to="" />
        <xml-to-json kind="direct" apply="always" consider-accept-header="true" />
        <trace source="inbound">@(context.Request.Body.As<string>(true))</trace>
        <set-body>@{
                var body = JObject.Parse(context.Request.Body.As<string>());
                return body["Envelope"]["Body"]["ImportItemMovement"]["movementArray"]["WSItemMovementInfo"]?.ToString();
            }</set-body>
        <set-body template="liquid">
            {
                "StoreNumber": {{ body.OrgUnitNum }},"BarcodeNumber": "{{ body.UpcNum  }}",{% if body.WgtSold %}
                "Type": "W","QuantitySold": {{ body.WgtSold }},{% endif %}
                {% if body.QtySold  %}                
                "Type": "Q","QuantitySold": {{ body.QtySold }},{% endif %}
                "TotalRetail": {{ body.RetailSold }},"PromotionType": {{ body.onPromotion }},"SerialNumber": "{{ body.labelSerialNum }}","MovementDateTime": "{{ body.MovementDateTime }}"
            }</set-body>
        <!-- Here you should forward the request to the function backend instead of returning it -->
        <return-response>
            <set-status code="200" reason="Ok" />
            <set-header name="Content-Type" exists-action="override">
                <value>application/json</value>
            </set-header>
            <set-body template="none">@(context.Request.Body.As<string>())</set-body>
        </return-response>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

对于此输入:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ad="http://company.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <ad:ImportItemMovement>
         <ad:authenticationToken>0badec32-81f7-4f88-813f-8hgty27b4484</ad:authenticationToken>
         <ad:movementArray>
            <!--Zero or more repetitions:-->
            <ad:WSItemMovementInfo>
               <ad:OrgUnitNum>52</ad:OrgUnitNum>
               <ad:MovementDateTime>2020-10-01T09:55:50</ad:MovementDateTime>
               <ad:RetailSold>5.99</ad:RetailSold>
               <ad:WgtSold>6</ad:WgtSold>
               <ad:ItemNum>123456789</ad:ItemNum>
               <ad:UpcNum>00021234500000</ad:UpcNum>
               <ad:onPromotion>0</ad:onPromotion>
               <ad:labelSerialNum>0123456</ad:labelSerialNum>
            </ad:WSItemMovementInfo>
         </ad:movementArray>
      </ad:ImportItemMovement>
   </soapenv:Body>
</soapenv:Envelope>

此政策返回:

{
    "StoreNumber": 52,"BarcodeNumber": "00021234500000","Type": "W","QuantitySold": 6,"TotalRetail": 5.99,"PromotionType": 0,"SerialNumber": "0123456","MovementDateTime": "10/1/2020 9:55:50 AM"
}