Web Services SOAP
📋 Visão Geral
Web Services SOAP (Simple Object Access Protocol) permitem integração entre sistemas usando XML e protocolo HTTP/HTTPS.
Características: - ✅ Baseado em XML - ✅ Protocolo SOAP - ✅ WSDL para definição - ✅ Suporte a tipos complexos - ✅ WS-Security para segurança - ⚠️ Mais pesado que REST
🎯 SOAP vs REST
| Aspecto | SOAP | REST |
|---|---|---|
| Protocolo | SOAP (XML) | HTTP |
| Formato | Apenas XML | JSON, XML, etc. |
| Complexidade | Alta | Baixa |
| Performance | Mais lento | Mais rápido |
| Segurança | WS-Security | HTTPS, OAuth |
| Uso SAP | Legacy, ERP | Fiori, S/4HANA |
🛠️ Criar Web Service (Provider)
Transaction SE80
Criar Function Module:
FUNCTION z_ws_get_customer.
*"----------------------------------------------------------------------
*"*"Interface Local:
*" IMPORTING
*" VALUE(IV_KUNNR) TYPE KUNNR
*" EXPORTING
*" VALUE(ES_CUSTOMER) TYPE KNA1
*" VALUE(EV_MESSAGE) TYPE STRING
*" EXCEPTIONS
*" CUSTOMER_NOT_FOUND
*"----------------------------------------------------------------------
SELECT SINGLE * FROM kna1 INTO es_customer
WHERE kunnr = iv_kunnr.
IF sy-subrc = 0.
ev_message = |Cliente { iv_kunnr } encontrado|.
ELSE.
ev_message = |Cliente { iv_kunnr } não existe|.
RAISE customer_not_found.
ENDIF.
ENDFUNCTION.
Atributos da Function: - ☑ Remote-Enabled Module (SE37 → Attributes)
Transaction SE37 - Enterprise Services
Criar Web Service:
- Utilities → More Utilities → Create Web Service
- Service Definition:
Z_CUSTOMER_WS - Endpoint:
Z_CUSTOMER_EP - Profile:
Default - Save & Activate
Transaction SOAMANAGER
Configurar e ativar Web Service:
- SOAMANAGER
- Web Service Configuration
- Search:
Z_CUSTOMER_WS - Create Service
- Binding:
Z_CUSTOMER_BINDING - Configure: HTTPS, autenticação
- Save
URL do WSDL:
https://server:port/sap/bc/srt/wsdl/flv_10002A111AD1/bndg_url/sap/bc/srt/rfc/sap/z_customer_ws/100/z_customer_binding/z_customer_binding
🌐 Consumir Web Service (Consumer)
Transaction SE80
Criar Proxy Local:
- SE80 → Enterprise Services
- Create → Service Consumer
- WSDL: URL ou upload arquivo
- Package: ZPACKAGE
- Prefix: ZCO_
- Generate
Usar Proxy Gerado
*&---------------------------------------------------------------------*
*& Report Z_CONSUME_WEBSERVICE
*&---------------------------------------------------------------------*
REPORT z_consume_webservice.
DATA: lo_proxy TYPE REF TO zco_customer_ws,
ls_input TYPE zco_get_customer_request,
ls_output TYPE zco_get_customer_response.
PARAMETERS: p_kunnr TYPE kunnr DEFAULT '0001000000'.
START-OF-SELECTION.
TRY.
" Criar proxy
CREATE OBJECT lo_proxy
EXPORTING
logical_port_name = 'Z_CUSTOMER_LP'. " SOAMANAGER
" Input
ls_input-iv_kunnr = p_kunnr.
" Chamar Web Service
CALL METHOD lo_proxy->get_customer
EXPORTING
input = ls_input
IMPORTING
output = ls_output.
" Resultado
WRITE: / '═══ RESULTADO ═══', /.
WRITE: / |Cliente: { ls_output-es_customer-kunnr }|.
WRITE: / |Nome: { ls_output-es_customer-name1 }|.
WRITE: / |Cidade: { ls_output-es_customer-ort01 }|.
WRITE: / |Mensagem: { ls_output-ev_message }|, /.
CATCH cx_ai_system_fault INTO DATA(lo_sys_fault).
WRITE: / |Erro de sistema: { lo_sys_fault->get_text( ) }|.
CATCH cx_ai_application_fault INTO DATA(lo_app_fault).
WRITE: / |Erro de aplicação: { lo_app_fault->get_text( ) }|.
CATCH cx_root INTO DATA(lo_ex).
WRITE: / |Erro: { lo_ex->get_text( ) }|.
ENDTRY.
Configurar Logical Port (SOAMANAGER)
- SOAMANAGER
- Single Service Administration
- Search: Proxy name
- Create Logical Port:
Z_CUSTOMER_LP - URL: URL do WSDL remoto
- Authentication: Basic, SSL, etc.
- Save
🔐 Segurança
WS-Security
Username Token:
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>user</wsse:Username>
<wsse:Password Type="PasswordText">pass</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
Configurar em SOAMANAGER: - Authentication: User ID/Password - Transport Level Security: HTTPS
Certificado SSL
STRUST - Trust Manager:
- STRUST
- SSL Client (Anonymous)
- Import Certificate
- Add to Certificate List
SOAMANAGER: - Authentication: SSL Client Certificate - Select Certificate
📊 SOAP Request/Response
Request Example
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:sap-com:document:sap:rfc:functions">
<soapenv:Header/>
<soapenv:Body>
<urn:Z_WS_GET_CUSTOMER>
<IV_KUNNR>0001000000</IV_KUNNR>
</urn:Z_WS_GET_CUSTOMER>
</soapenv:Body>
</soapenv:Envelope>
Response Example
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<n0:Z_WS_GET_CUSTOMER.Response xmlns:n0="urn:sap-com:document:sap:rfc:functions">
<ES_CUSTOMER>
<KUNNR>0001000000</KUNNR>
<NAME1>Cliente Teste</NAME1>
<ORT01>Lisboa</ORT01>
</ES_CUSTOMER>
<EV_MESSAGE>Cliente 0001000000 encontrado</EV_MESSAGE>
</n0:Z_WS_GET_CUSTOMER.Response>
</soapenv:Body>
</soapenv:Envelope>
💡 Exemplo Completo: Integração Externa
Sistema Externo → SAP (Provider)
Function Module:
FUNCTION z_ws_create_sales_order.
*"----------------------------------------------------------------------
*"*"Interface Local:
*" IMPORTING
*" VALUE(IS_HEADER) TYPE BAPISDHD1
*" TABLES
*" IT_ITEMS STRUCTURE BAPISDITM
*" ET_RETURN STRUCTURE BAPIRET2
*" EXPORTING
*" VALUE(EV_ORDER_NUMBER) TYPE VBELN_VA
*"----------------------------------------------------------------------
" Criar ordem via BAPI
CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'
EXPORTING
order_header_in = is_header
IMPORTING
salesdocument = ev_order_number
TABLES
return = et_return
order_items_in = it_items.
" Commit
READ TABLE et_return WITH KEY type = 'E' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING wait = 'X'.
ENDIF.
ENDFUNCTION.
Expor via SOAMANAGER (passos acima).
SAP → Sistema Externo (Consumer)
Consumir Web Service de terceiros:
*&---------------------------------------------------------------------*
*& Report Z_CALL_EXTERNAL_WS
*&---------------------------------------------------------------------*
REPORT z_call_external_ws.
DATA: lo_proxy TYPE REF TO zco_external_service,
ls_request TYPE zco_weather_request,
ls_response TYPE zco_weather_response.
PARAMETERS: p_city TYPE string DEFAULT 'Lisboa'.
START-OF-SELECTION.
TRY.
" Criar proxy (gerado a partir de WSDL externo)
CREATE OBJECT lo_proxy
EXPORTING
logical_port_name = 'Z_WEATHER_LP'.
" Request
ls_request-city = p_city.
" Chamar serviço externo
CALL METHOD lo_proxy->get_weather
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
" Resultado
WRITE: / |Cidade: { p_city }|.
WRITE: / |Temperatura: { ls_response-temperature }°C|.
WRITE: / |Condição: { ls_response-condition }|.
CATCH cx_root INTO DATA(lo_ex).
WRITE: / |Erro: { lo_ex->get_text( ) }|.
ENDTRY.
🔧 Transaction SPROXY
Service Proxy - alternativa a SE80 para criar proxies.
Criar Proxy
- SPROXY
- Outside-In → External WSDL
- Upload WSDL ou URL
- Generate
Vantagens
- ✅ Interface mais moderna
- ✅ Melhor para Enterprise Services
- ✅ Suporte a XSD complexos
🛠️ Monitorização
Transaction SRT_UTIL
Runtime Administration: - Ver logs de execução - Mensagens SOAP - Erros
Transaction SXMB_MONI
Integration Engine Monitoring: - Monitorar mensagens XML - Ver payloads - Reprocessar mensagens
Transaction SICF
HTTP Service Maintenance: - Ativar/desativar serviços - Configurar handlers - Ver estatísticas
⚡ Performance e Boas Práticas
✅ Fazer
" 1. Reutilizar instância do proxy
DATA: go_proxy TYPE REF TO zco_service. " Global
FORM call_service.
IF go_proxy IS NOT BOUND.
CREATE OBJECT go_proxy
EXPORTING logical_port_name = 'LP_NAME'. " ✅ Criar uma vez
ENDIF.
" Usar go_proxy...
ENDFORM.
" 2. Tratar exceções específicas
TRY.
CALL METHOD lo_proxy->method.
CATCH cx_ai_system_fault.
" Erro de comunicação
CATCH cx_ai_application_fault.
" Erro de negócio
CATCH cx_root.
" Outros erros
ENDTRY.
" 3. Timeout adequado
" Configurar em SOAMANAGER → Logical Port → Timeouts
" 4. Comprimir grandes payloads
" SOAMANAGER → Service Definition → Compression
" 5. Usar logical ports (não hardcode URLs)
CREATE OBJECT lo_proxy
EXPORTING logical_port_name = 'Z_LP'. " ✅ SM59
❌ Evitar
" 1. Criar proxy em cada chamada
FORM call_ws.
CREATE OBJECT lo_proxy. " ❌ Repetitivo!
CALL METHOD lo_proxy->method.
ENDFORM.
" 2. Não tratar erros
CALL METHOD lo_proxy->method. " ❌ E se falhar?
" 3. Hardcoded URLs
DATA lv_url TYPE string VALUE 'http://prod.com/ws'. " ❌ Usar LP
" 4. Payloads muito grandes sem compressão
" Configurar compressão em SOAMANAGER
" 5. Sync chamadas para operações longas
CALL METHOD lo_proxy->long_operation. " ❌ Timeout!
" Melhor: usar RFC assíncrono ou job
💡 Exemplo: Integração com Sistema Bancário
Provider (SAP expõe)
Function Module:
FUNCTION z_ws_payment_status.
*"----------------------------------------------------------------------
*"*"Interface Local:
*" IMPORTING
*" VALUE(IV_PAYMENT_ID) TYPE STRING
*" EXPORTING
*" VALUE(EV_STATUS) TYPE STRING
*" VALUE(EV_AMOUNT) TYPE WRBTR
*" VALUE(EV_CURRENCY) TYPE WAERS
*" VALUE(EV_DATE) TYPE DATUM
*"----------------------------------------------------------------------
" Buscar pagamento
SELECT SINGLE
status,
amount,
currency,
payment_date
FROM zpayments
WHERE payment_id = @iv_payment_id
INTO (@ev_status, @ev_amount, @ev_currency, @ev_date).
IF sy-subrc <> 0.
ev_status = 'NOT_FOUND'.
ENDIF.
ENDFUNCTION.
Expor via SOAMANAGER.
Consumer (SAP consome)
Chamar API bancária:
*&---------------------------------------------------------------------*
*& Report Z_BANK_API_CALL
*&---------------------------------------------------------------------*
REPORT z_bank_api_call.
DATA: lo_proxy TYPE REF TO zco_bank_api,
ls_request TYPE zco_transfer_request,
ls_response TYPE zco_transfer_response.
PARAMETERS: p_from TYPE string DEFAULT 'PT50123456789',
p_to TYPE string DEFAULT 'PT50987654321',
p_amnt TYPE p DECIMALS 2 DEFAULT '1000.00'.
START-OF-SELECTION.
TRY.
" Criar proxy para API do banco
CREATE OBJECT lo_proxy
EXPORTING
logical_port_name = 'Z_BANK_LP'.
" Preparar transferência
ls_request-from_account = p_from.
ls_request-to_account = p_to.
ls_request-amount = p_amnt.
ls_request-currency = 'EUR'.
ls_request-description = 'Pagamento SAP'.
" Executar transferência
CALL METHOD lo_proxy->transfer_funds
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
" Resultado
IF ls_response-status = 'SUCCESS'.
WRITE: / '✅ Transferência realizada com sucesso!'.
WRITE: / |ID Transação: { ls_response-transaction_id }|.
WRITE: / |Timestamp: { ls_response-timestamp }|.
ELSE.
WRITE: / '❌ Erro na transferência:'.
WRITE: / |Código: { ls_response-error_code }|.
WRITE: / |Mensagem: { ls_response-error_message }|.
ENDIF.
CATCH cx_ai_system_fault INTO DATA(lo_sys_ex).
WRITE: / |Erro de comunicação: { lo_sys_ex->get_text( ) }|.
CATCH cx_ai_application_fault INTO DATA(lo_app_ex).
WRITE: / |Erro do banco: { lo_app_ex->get_text( ) }|.
CATCH cx_root INTO DATA(lo_ex).
WRITE: / |Erro: { lo_ex->get_text( ) }|.
ENDTRY.
🔧 Troubleshooting
Erro: "Logical Port not found"
Solução: 1. SOAMANAGER 2. Criar Logical Port 3. Configurar URL e autenticação
Erro: "HTTP 500 - Internal Server Error"
Causas: - Erro no código do serviço - Dados inválidos
Solução: - SRT_UTIL → Ver logs - ST22 → Dumps - Debugar function module
Erro: "Connection timeout"
Solução: 1. SOAMANAGER → Logical Port 2. Timeouts tab 3. Aumentar timeout (ex: 60s)
Erro: "Certificate validation failed"
Solução: 1. STRUST 2. Import certificado do servidor 3. Add to Certificate List
🔗 Alternativas Modernas
REST vs SOAP
Preferir REST quando: - ✅ Integração com sistemas modernos - ✅ Aplicações mobile/web - ✅ Performance crítica - ✅ Simplicidade
Usar SOAP quando: - ✅ Sistemas legados - ✅ WS-Security necessário - ✅ Contratos formais (WSDL) - ✅ Transações distribuídas
Migração para OData/REST
" SOAP (antigo)
CALL METHOD lo_proxy->get_customer
EXPORTING input = ls_input
IMPORTING output = ls_output.
" REST (moderno)
DATA(lo_http) = cl_http_client=>create_by_url( 'https://api.com/customers' ).
lo_http->request->set_method( if_http_request=>co_request_method_get ).
lo_http->send( ).
lo_http->receive( ).
DATA(lv_json) = lo_http->response->get_cdata( ).
🔗 Próximos Passos
- OData - Alternativa RESTful moderna
- HTTP Client - Consumir APIs REST
- REST API - Criar APIs REST em ABAP
Tags: #WebServices #SOAP #WSDL #Integrações #SPROXY #SOAMANAGER