Currently Being Moderated

Conectando o SAP com uma aplicação PHP usando Webservices (WSDL) e SOAP

Nesse documento tem como objetivo explicar, de forma simples e objetiva, como realizar de forma simples uma conexão usando RFCs/Webservices (WSDL) com uma aplicação PHP, utilizando a classe SoapClient. A motivação para criar esse documento em português vem da falta de artigos desse tipo na nossa língua.

 

O documento será dividido em duas partes:

  1. Configurar o lado SAP, criandos as RFCs e gerando os Webservices.
  2. Criar os arquivos PHP para consumir os Webservices.

 

Iremos utilizar como exemplo uma situação em que uma aplicação PHP tem as seguintes necessidades de integração com o SAP:

  • Acessar os dados básicos de um usuário do SAP, como nome, validade, endereços, roles, etc.
  • Copiar um usuário
  • Recuperar a senha e desbloquar um usuário

 

Parte 1: Configurar o lado SAP

Para realizar essa tarefa, vamos dividir nosso exemplo em três partes, sendo cada uma a resolução de cada uma das nossas três necessidades. Algumas

 

Tarefa 1: Acessar os dados básicos de um usuário do SAP

Para isso, vamos criar um webservice baseado em uma RFC já pronta, a função BAPI_USER_GET_DETAIL.

ws_bapi_get_user_detail.pngFigura 1: Caminho para criação de Web Service

gerando ws - tela1.png

Figura 2: Criando Web Service - Tela 1 (nome e descrição do Web Service)

gerando ws - tela2.png

Figura 3: Criando Web Service - Tela 2 (opção para mapear o nome da função p/ gerar a operação)

gerando ws - tela3.png

Figura 4: Criando Web Service - Tela 3 (menos seguro, para simplificar nosso exemplo)

gerando ws - tela4.png

Figura 5: Criando Web Service - Tela 4 (meu pacote local $SDN)

gerando ws - tela5.png

Figura 6: Criando Web Service - Tela 5 (confirmação)


Após esses 5 telas, o Web Service está basicamente criado. Irá ser aberta uma tela de definição do serviço, que deveremos somente ativar e utilizar como base no futuro para verificar os parâmetros de entrada e saída.

gerando ws - tela6.png

Figura 7: Criando Web Service - Tela 6 (Definição do Serviço)

 

Nesse momento, para finalizar só precisamos pegar a URL do nosso WSDL, para utilizarmos nas nossas classes PHP. Para isso, iremos acessar os detalhes do Web Service na transação SOAMANAGER (necessita que o básico de Webdynpro esteja configurado no ambiente) e entrar nas configurações simplificadas, onde é conseguiremos acessar a URl de maneira bem simples:

soamanager_1.png

Figura 8: SOAMANAGER - Tela 1

soamanager_2.png

Figura 9: SOAMANAGER - Tela 2 (Não esquecer de marcar o checkbox 'User Name/Password (Basic)' e salvar, para gerar uma configuração válida)


Nesse momento, para finalizamos a tarefa 1! Vamos para a próxima tarefa.


Tarefa 2: Copiar um usuário

Para essa tarefa, vamos optar por desenvolver nosso próprio módulo de função e criar nossos Web Service.

 


Código-fonte do módulo de função:


FUNCTION zrw_user_copy.

*"----------------------------------------------------------------------

*"*"Local Interface:

*"  IMPORTING

*"     VALUE(USER_REFERENCE) LIKE  USR02-BNAME

*"     VALUE(NEW_USER) LIKE  USR02-BNAME

*"     VALUE(PASSWORD) TYPE  SUID_ST_NODE_PASSWORD-PASSWORD OPTIONAL

*"     VALUE(WITH_ADDRESS) TYPE  CHAR01 DEFAULT 'X'

*"     VALUE(WITH_PARAMETERS) TYPE  CHAR01 DEFAULT 'X'

*"     VALUE(WITH_REFUSER) TYPE  CHAR01 DEFAULT 'X'

*"     VALUE(WITH_DEFAULTS) TYPE  CHAR01 DEFAULT 'X'

*"     VALUE(WITH_UCLASS) TYPE  CHAR01 DEFAULT 'X'

*"  EXPORTING

*"     VALUE(NEW_PASS) TYPE  SUID_ST_NODE_PASSWORD

*"  EXCEPTIONS

*"      INTERNAL_ERROR

*"----------------------------------------------------------------------

   DATA: lv_new_user TYPE suid_st_node_root,

         ls_password TYPE suid_st_node_password.

 

   TRY.

       CALL METHOD cl_identity=>copy

         EXPORTING

           iv_id_source             = user_reference

           iv_id_destination        = new_user

           iv_copy_address          = with_address

           iv_copy_defaults         = with_defaults

           iv_copy_parameters       = with_parameters

           iv_copy_refuser          = with_refuser

           iv_copy_roles            = abap_true

           iv_copy_profiles         = abap_true

           iv_copy_groups           = abap_true

           iv_copy_personalization  = abap_true

           iv_copy_uclass           = with_uclass

           iv_copy_easy_access      = abap_true

         IMPORTING

           ev_node_root_destination = lv_new_user.

       IF lv_new_user-idref IS INITIAL.

         RAISE internal_error.

       ENDIF.

 

       IF password IS INITIAL.

         CALL METHOD lv_new_user-idref->if_identity_password~password_generate

           EXPORTING

             iv_return_pwd_only    = space

             iv_downward_comp      = abap_true

           IMPORTING

             ev_generated_password = new_pass.

       ELSE.

         ls_password-password = password.

         lv_new_user-idref->if_identity_password~set_password( ls_password ).

       ENDIF.

 

       lv_new_user-idref->if_identity_password~set_password_to_initial( ).

       cl_identity=>do_save( ).

 

       COMMIT WORK.

     CATCH cx_suid_identity .

       RAISE internal_error.

   ENDTRY.

ENDFUNCTION.


Essa função utiliza como base a classe CL_IDENTITY para realizar as operações de cópia e geração de senha. Não vou entrar em detalhes mas caso tenham dúvidas sobre o funcionamento da função, fiquem a vontade nos comentários. Repitam o procedimento de criação do Web Service da tarefa 1 e anotem a URL do WSDL.


Tarefa 3: Recuperar a senha e desbloquar um usuário

Vamos utilizar a mesma base da tarefa anterior, porém acessando alguns métodos diferentes:


FUNCTION zrw_user_reset_password.

*"----------------------------------------------------------------------

*"*"Local Interface:

*"  IMPORTING

*"     REFERENCE(IV_USER) TYPE  USR02-BNAME

*"     REFERENCE(IV_NEW_PASSWORD) TYPE  SUID_ST_NODE_PASSWORD-PASSWORD

  *"       OPTIONAL

*"  EXPORTING

*"     REFERENCE(EV_PASSWORD) TYPE  SUID_ST_NODE_PASSWORD-PASSWORD

*"  EXCEPTIONS

*"      INVALID_USER

*"----------------------------------------------------------------------

   DATA: lo_user     TYPE REF TO cl_identity,

         lt_users    TYPE suid_tt_node_root,

         lt_bnames   TYPE suid_tt_bname,

         ls_user     LIKE LINE OF lt_users,

         ls_bname    LIKE LINE OF lt_bnames,

         ls_password TYPE suid_st_node_password,

         lv_locked   TYPE boolean.

 

   TRY.

       ls_bname-bname = iv_user.

       APPEND ls_bname TO lt_bnames.

 

       CALL METHOD cl_identity=>retrieve_for_update

         EXPORTING

           it_bname     = lt_bnames

         IMPORTING

           et_node_root = lt_users.

 

       READ TABLE lt_users INTO ls_user INDEX 1.

       IF sy-subrc IS NOT INITIAL.

         RAISE invalid_user.

       ENDIF.

 

       IF iv_new_password IS INITIAL.

         CALL METHOD ls_user-idref->if_identity_password~password_generate

           EXPORTING

             iv_return_pwd_only    = space

             iv_downward_comp      = abap_true

           IMPORTING

             ev_generated_password = ls_password.

 

         ev_password = ls_password-password.

       ELSE.

         ev_password = ls_password-password = iv_new_password.

         ls_user-idref->if_identity_password~set_password( ls_password ).

       ENDIF.

 

       CALL METHOD ls_user-idref->get_lockstatus

         IMPORTING

           ev_locked_by_failed_logon = lv_locked.

       IF lv_locked EQ abap_true.

         ls_user-idref->action_unlock( ).

       ENDIF.

 

       ls_user-idref->if_identity_password~set_password_to_initial( ).

       cl_identity=>do_save( ).

 

       COMMIT WORK.

     CATCH cx_suid_identity .

   ENDTRY.

ENDFUNCTION.

 

Novamente não vou entrar em detalhes mas caso tenham dúvidas sobre o funcionamento da função, fiquem a vontade nos comentários. Repitam o procedimento de criação do Web Service da tarefa 1 e anotem a URL do WSDL.

 

Parte 2: Criar Arquivos PHP para consumir os Web Services criados

No nosso exemplo vamos usar como mdelo uma classe que iremos concentrar todos os webservices e um arquivo consumidor que irá instanciar um objeto dessa classe e utilizar as operações

 

Classe dos Webservices:

 

<?php
/**
*
* @author Renan
*      
*/
class SAPWebServices {
  const SERVER = 'http://localhost:8000';
  //WSDL paths
  const ZRW_WS_GET_USER_DETAIL  = '/sap/bc/srt/wsdl/bndg_005056C000081ED39DC1E10DA9C97287/soap11/wsdl11/allinone/standard/document?sap-client=800';
  const ZRW_WS_RESET_PASS = '/sap/bc/srt/wsdl/bndg_005056C000081ED39DCE159B661ABBB1/soap11/wsdl11/allinone/standard/document?sap-client=800';
  const ZRW_WS_COPY_USER   = '/sap/bc/srt/wsdl/bndg_005056C000081ED39DDE16E7906E7BB1/soap11/wsdl11/allinone/standard/document?sap-client=800';
  //default values
  const INITIAL_PASS = 'inicial123';
  const ABAP_TRUE = 'X';
  const ABAP_FALSE = '';
  /**
  *
  * @var array SAP Logon Details
  */
  private $SOAP_OPTS;
  /**
  *
  * @var SoapClient Soap Object
  */
  private $client;
  function __construct() {
  $this->SOAP_OPTS = array (
  'login' => 'RENAN',
  'password' => 'mypassword',
  'features' => SOAP_SINGLE_ELEMENT_ARRAYS
  );
  }
  /**
  * Call websevice ZRW_WS_GET_USER_DETAIL (BAPI_USER_GET_DETAIL)
  *
  * @param string $user_name      
  *
  */
  public function get_user_detail($user_name) {
  $this->client = new SoapClient ( SAPWebServices::SERVER . SAPWebServices::ZWEB_USER_DETAIL, $this->SOAP_OPTS );
  $params = array (
  'Username' => "$user_name",
  'Return' => ''
  );
  try {
  return $this->client->UserGetDetail ( $params );
  } catch ( SoapFault $e ) {
  throw $e;
  }
  }
  /**
  * Call websevice ZRW_WS_RESET_PASS
  *
  * @param string $user_name      
  * @param string $initial_password    
  */
  public function reset_password($user_name, $initial_password = NULL) {
  $this->client = new SoapClient ( SAPWebServices::SERVER . SAPWebServices::ZRW_WS_RESET_PASS, $this->SOAP_OPTS );
  $params = array (
  'Username'  => $user_name,
  'NewPassword' => $initial_password,
  'EvPassword'  => '',
  );
  try {
  return $this->client->ResetPassword ( $params );
  } catch ( SoapFault $e ) {
  throw $e;
  }
  }
  /**
  * Call websevice ZRW_WS_COPY_USER
  *
  * @param string $user_name      
  * @param string $user_reference      
  */
  public function clone_user($user, $user_reference, $initial_password = null) {
  $this->client = new SoapClient ( SAPWebServices::SERVER . SAPWebServices::ZRW_WS_COPY_USER, $this->SOAP_OPTS );
  $params = array (
  'UserReference' => $user_reference,
  'NewUser'       => $user,
  'Password'      => $initial_password,
  'NewPass'       => array('Password' => ''),
  'WithAddress'   => SAPWebServices::ABAP_FALSE,
  );
  try {
  return $this->client->UserCopy ( $params );
  } catch ( SoapFault $e ) {
  throw $e;
  }
  }
}
?>

Arquivo que usará a classe para consumir os Web Services:

 

<?php
require_once 'sap/SAPWebServices.php';
try {
  $sap = new SAPWebServices ();
  $result = $sap->get_user_detail('RENAN');
  $result = $sap->clone_user('TESTE_USER' , 'RW_TEMPLATE');
  $result = $sap->reset_password('TESTE_USER');
}
catch ( SoapFault $exception ) {
  print "***Caught Exception***<br />";
  echo '<pre>';
  print_r ( $exception );
  echo '</pre>';
  print "***END Exception***<br />";
  die ();
}
print "***Success***<br />";
echo '<pre>';
print_r ( $result );
echo '</pre>';
?>

 

Pronto! Se você seguiu todos os passos, você terá o seus arquivos PHP acessandos as RFCs do SAP via WebServices/Soap de maneira fácil e rápida, sem integradores de terceiros ou classes customizadas, tudo 100% nativo.

Comments

Delete Document

Are you sure you want to delete this document?

Actions