Consultar una orden de mantenimiento desde Postman: versión simple con CPI y S/4HANA

Caso SIS-CASE-MIX-002, Variante A. Consulta una orden por header con OData V2, devuelve un JSON de ocho campos y expón el flujo con API Management.

Una aplicación externa necesita consultar una orden de mantenimiento de S/4HANA por su número. Antes de construir validaciones y transformaciones más complejas, conviene comprobar el recorrido completo con una orden conocida.

Este es el caso SIS-CASE-MIX-002, Variante A simple: tres pasos dentro del iFlow, sin Groovy, sin XSD y sin Message Mapping. Primero probamos CPI directamente desde Postman; después agregamos una exposición mínima con API Management.

Tiempo orientativo: 15 minutos para el iFlow y 15 para APIM, si la conectividad, las credenciales y el servicio OData ya están preparados. La preparación del entorno queda fuera de esa estimación.

Descargar colección Postman y environment de la versión simple

En esta guía

Preparar el entorno

Necesitas Cloud Integration habilitado, acceso a un backend S/4HANA con el servicio API_MAINTENANCEORDER y una orden que exista en ese sistema. El número 1000 es un ejemplo del laboratorio: reemplázalo por uno válido en tu entorno.

Revisa estos puntos antes de crear el flujo:

  1. Cloud Connector está conectado a la subcuenta de BTP correspondiente.
  2. El mapping de host virtual apunta a tu backend y el recurso /sap/opu/odata/sap/API_MAINTENANCEORDER permite sus subrutas.
  3. El Location ID del receiver coincide con el configurado en Cloud Connector, si utilizas uno.
  4. El Security Material contiene una credencial Basic del backend con permisos para consultar el servicio. En este artículo usaremos el alias de ejemplo S4H_ODATA_BASIC.
  5. Dispones de credenciales del servicio Process Integration Runtime con el permiso ESBMessaging.send para invocar el iFlow. Son distintas de las credenciales de S/4HANA.

Los hosts y credenciales de esta publicación son placeholders. Configura tus valores localmente en Postman; no los incluyas en un export compartido.

Construir el iFlow

Dentro del paquete ACME_MAINTENANCE_ORDER, crea el Integration Flow Query_MaintenanceOrder_Postman_to_S4HANA como artefacto separado del caso completo.

Postman → HTTPS Sender → CM_SetOrder → RR_GetOrder → CM_BuildResponse → End
                                         │
                                         └→ OData V2 → Cloud Connector → S/4HANA

1. HTTPS Sender y header de entrada

Conecta el participante Sender al Start Event mediante HTTPS:

CampoValor
Address/maint-simple/v1
AuthorizationUser Role
User RoleESBMessaging.send
CSRF ProtectedDesmarcado para esta consulta GET

En Runtime Configuration → Allowed Header(s) del iFlow, agrega orderNumber. Es necesario para que el header que envía Postman esté disponible dentro del flujo.

2. Content Modifier CM_SetOrder

Después del Start, agrega un Content Modifier llamado CM_SetOrder. En Exchange Property configura:

NameSource TypeSource ValueData Type
orderNumberHeaderorderNumberjava.lang.String

Conservamos el número como texto para no perder posibles ceros iniciales. Esta variante presupone un valor válido y conocido; todavía no incorpora validación de entrada.

3. Request Reply y receiver OData V2

Agrega RR_GetOrder y conéctalo al receiver OD_S4H_Simple con el adapter OData V2.

ConnectionConfiguración
Addresshttp://<VIRTUAL_HOST>:<VIRTUAL_PORT>/sap/opu/odata/sap/API_MAINTENANCEORDER
Proxy TypeOn-Premise
Location IDEl de tu Cloud Connector; vacío si no configuraste uno
AuthenticationBasic
Credential NameS4H_ODATA_BASIC
CSRF ProtectedDesmarcado para esta consulta GET

En Processing usa Query(GET), Resource Path MaintenanceOrder, Content Type Atom y deja Custom Query Options vacío. No actives Process in Pages para esta prueba.

En Query Options, coloca exactamente:

$filter=MaintenanceOrder eq '${property.orderNumber}'

El filtro selecciona la orden por su número. Comprueba que el nombre de la property y las comillas estén completos. Por tratarse de un Query, la respuesta sigue siendo una colección aunque solo coincida una orden.

En el primer smoke test omitimos $select. Una vez comprobada la consulta, puedes limitar los campos solicitados a los ocho que utiliza la respuesta. La documentación del receiver OData V2 de SAP detalla la operación y sus Query Options.

4. Content Modifier CM_BuildResponse

Después del Request Reply, agrega CM_BuildResponse. El XML observado a la salida del adapter en este laboratorio tiene una raíz MaintenanceOrder y registros MaintenanceOrderType. Verifica esa estructura en tu propio mensaje antes de reutilizar los XPath.

En Exchange Property, todas las entradas usan Source Type XPath y Data Type java.lang.String:

NameXPath
res_order/MaintenanceOrder/MaintenanceOrderType/MaintenanceOrder
res_type/MaintenanceOrder/MaintenanceOrderType/MaintenanceOrderType
res_desc/MaintenanceOrder/MaintenanceOrderType/MaintenanceOrderDesc
res_priority/MaintenanceOrder/MaintenanceOrderType/MaintPriority
res_plant/MaintenanceOrder/MaintenanceOrderType/MaintenancePlant
res_startDatesubstring(/MaintenanceOrder/MaintenanceOrderType/MaintOrdBasicStartDate,1,10)
res_equipment/MaintenanceOrder/MaintenanceOrderType/Equipment
res_equipmentName/MaintenanceOrder/MaintenanceOrderType/EquipmentName

En Message Header define Content-Type con Source Type Constant y valor application/json. En Message Body selecciona Expression y pega:

{
  "maintenanceOrder": "${property.res_order}",
  "orderType": "${property.res_type}",
  "description": "${property.res_desc}",
  "priority": "${property.res_priority}",
  "plant": "${property.res_plant}",
  "basicStartDate": "${property.res_startDate}",
  "equipment": "${property.res_equipment}",
  "equipmentName": "${property.res_equipmentName}"
}

Este paso ya construye el body JSON: no agregues un XML to JSON Converter después. Si las properties no se resuelven en tu configuración, separa la extracción XPath y la construcción del body en dos Content Modifiers consecutivos.

La interpolación directa no escapa caracteres JSON. Una descripción con comillas, barras invertidas o saltos de línea puede producir JSON inválido. Esta plantilla sirve para datos controlados del laboratorio; para otros datos usa una transformación que serialice y escape los valores correctamente. El orden de las propiedades JSON tampoco debe ser una dependencia del consumidor.

Conecta al End Event, guarda y despliega. Espera el estado Started y copia el endpoint real desde Manage Integration Content.

Probar desde Postman

Importa los dos archivos del paquete descargable. Selecciona el environment Maintenance Order — Simple (template) y configura:

VariableQué colocar
cpiBaseUrlOrigen HTTPS del runtime CPI, sin /http ni barra final
cpiClientIdClient ID del servicio de runtime
cpiClientSecretClient secret, solo en tu entorno local
orderNumberUna orden existente; 1000 es el ejemplo

Ejecuta CPI directo — orden existente:

GET {{cpiBaseUrl}}/http/maint-simple/v1
orderNumber: {{orderNumber}}

La request utiliza Basic Auth con cpiClientId y cpiClientSecret. No tiene body. Para una orden existente, con datos compatibles con la plantilla, esperamos HTTP 200 y este contrato de ocho campos; los valores siguientes son ilustrativos:

{
  "maintenanceOrder": "1000",
  "orderType": "PM01",
  "description": "Mantenimiento preventivo de equipo",
  "priority": "3",
  "plant": "1000",
  "basicStartDate": "2026-09-09",
  "equipment": "10000",
  "equipmentName": "Equipo de prueba"
}

La colección comprueba el estado HTTP, que el body sea JSON, los ocho nombres de campo y que la orden devuelta coincida con la solicitada. Ajusta orderNumber si tu backend exige un formato con ceros iniciales.

No hay un contrato 400/404 en esta versión. Las pruebas sin número o con una orden inexistente se incluyen como diagnóstico, sin afirmar un código que el iFlow todavía no implementa.

Exponer con API Management

Continúa cuando la consulta directa a CPI funcione. La cadena pasa a ser:

Postman -- apikey --> API Proxy -- Basic desde KVM --> CPI --> S/4HANA

1. API Provider y KVM

Crea el provider APIP_CPI_Simple, tipo Cloud Integration, con el host de runtime CPI, puerto 443 y SSL. Usa el host del endpoint que acabas de probar. Un 404 al consultar solo la raíz no demuestra que el endpoint del iFlow falle: prueba su ruta completa.

Crea el Key Value Map cifrado KVM_CPI_Auth, de scope Environment, con las entradas username y password. Guarda allí el client ID y client secret de CPI. El consumidor externo no necesita esas credenciales.

2. API Proxy

CampoValor
Provider SystemAPIP_CPI_Simple
URL del target/http/maint-simple/v1
Nameapi-maint-simple-v1
API Base Path/acme/simple/v1
Service TypeREST

Mantén la Route Rule hacia el TargetEndpoint y comprueba que se reenvíe el header orderNumber.

3. Tres policies mínimas

En ProxyEndpoint → PreFlow → Request, agrega PL_VerifyApiKey:

<VerifyAPIKey xmlns="http://www.sap.com/apimgmt"
              async="false" continueOnError="false" enabled="true">
  <APIKey ref="request.header.apikey"/>
</VerifyAPIKey>

En TargetEndpoint → PreFlow → Request, agrega primero la lectura del KVM:

<KeyValueMapOperations xmlns="http://www.sap.com/apimgmt"
    mapIdentifier="KVM_CPI_Auth" async="false" continueOnError="false" enabled="true">
  <Get assignTo="private.cpiUser" index="1">
    <Key><Parameter>username</Parameter></Key>
  </Get>
  <Get assignTo="private.cpiPassword" index="1">
    <Key><Parameter>password</Parameter></Key>
  </Get>
  <Scope>environment</Scope>
</KeyValueMapOperations>

Después, agrega la policy de Basic Authentication:

<BasicAuthentication xmlns="http://www.sap.com/apimgmt"
    async="false" continueOnError="false" enabled="true">
  <Operation>Encode</Operation>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <User ref="private.cpiUser"/>
  <Password ref="private.cpiPassword"/>
  <AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>

Conserva el namespace SAP de estos ejemplos y haz coincidir exactamente el nombre del KVM y sus entradas. Guarda y despliega el proxy.

4. API Product y aplicación

Crea el producto PRD_Acme_Simple, asocia api-maint-simple-v1 y publícalo. En Developer Hub crea la aplicación APP_Demo_Simple, suscríbela al producto y obtiene su Application Key.

En el laboratorio, el mensaje Unable to publish Product se resolvió activando Developer Hub. Si aparece en otro entorno, comprueba primero esa capability y los detalles del error; no es una causa universal.

5. Prueba final

Configura apimBaseUrl con el origen HTTPS de tu API proxy y apiKey con la Application Key local. Ejecuta APIM — orden existente:

GET {{apimBaseUrl}}/acme/simple/v1
apikey: {{apiKey}}
orderNumber: {{orderNumber}}

Esta request usa No Auth en Postman. La autenticación hacia CPI la construye APIM. Debes recibir el mismo contrato de ocho campos que en la prueba directa.

Ejecuta también APIM — sin API key. Con la policy del ejemplo se espera 401; SAP documenta ese estado para la clave que no puede resolverse en Verify API Key.

Diagnosticar errores

SíntomaQué revisar
404 HTML al llamar a CPIEstado Started y ruta /http/maint-simple/v1
401 al llamar a CPICredencial del runtime y permiso ESBMessaging.send
Número vacío en el flujoorderNumber en Allowed Headers y Source Type Header
La consulta devuelve varias órdenesValor enviado y Query Options completos; inspecciona la consulta real
Error de conexión al backendEstado del Cloud Connector, mapping, Location ID y recurso permitido
JSON vacío o campos vacíosExistencia de la orden y estructura XML que reciben los XPath
JSON inválidoCaracteres sin escapar en los valores interpolados
401 por APIM con una key válidaKVM, orden de policies y credenciales hacia CPI; identifica qué capa rechaza la llamada
500 con MPL IDBusca ese identificador en Monitor Message Processing y revisa Error Details

Si necesitas Trace, actívalo temporalmente para una prueba controlada y revisa properties y payload después de RR_GetOrder. Evita compartir capturas con Authorization, API keys o credenciales visibles.

Límites y siguiente paso

El objetivo de la Variante A es comprobar conectividad y entender cada salto. No valida el número antes de interpolarlo en el filtro OData, no distingue una orden inexistente mediante un 404 propio y no normaliza errores del backend. La respuesta manual tiene la limitación de escape JSON descrita arriba.

Para evolucionar el caso, agrega validación y tratamiento seguro del número, detección de resultado vacío, serialización JSON, Exception Subprocess, parámetros externalizados y un contrato de errores. En APIM faltan límites de tráfico, eliminación del header apikey antes de enviarlo al target y Fault Rules.

Puedes continuar con el caso de API gobernada con CPI y API Management para estudiar esas policies, o revisar más recursos descargables.

Adaptado de la guía local «implementation-guide-variante-A-simple.md» del caso SIS-CASE-MIX-002. Esta publicación no incluye credenciales, hosts privados ni capturas del tenant. Las verificaciones sobre tu backend se realizan al ejecutar la colección en tu entorno.