Integración con otros sistemas
A continuación voy a indicar como hacer la integración con otros sistemas en este caso pondré como ejemplo la integración entre SAP R/3 y CRM Dynamics, mediante un Web services RES.
La comunicación entre los sistemas será mediante XML, pongo un ejemplo de un XML
<?xml version=»1.0″?>
<ProductoR3Config xmlns:xsi=»http://www.w3.org/2001/XMLSchema-instance» xmlns:xsd=»http://www.w3.org/2001/XMLSchema» xmlns=»http://crm.dynamics.unedisa.neoris.es/integracion/v1-0/»>
<CodigoProductoR3>SDLGASTOS81</CodigoProductoR3>
<Nombre>Nombre a enviar</Nombre>
<CreatedOn>2009-12-28T15:39:32</CreatedOn>
</ProductoR3Config>
Código para realizar la comunicación entre sistemas
Personalmente me gusta programar con clases, así que pondre como ejemplo la siguiente clase:
En este caso no declararemos ningún atributo:
Vamos a crear los siguientes métodos:
Muestro como va quedar la sección pública de la clase:
class ZCONEXION_CRM_PETCRM definition
public
create public .
*»* public components of class ZCONEXION_CRM_PETCRM
*»* do not include other source files here!!!
public section.
methods CONSTRUCTOR .
methods GET_URL
importing
!IM_IDENTIFICADOR type ANY
exporting
!EX_URL type STRING .
methods CREAR_CLIENTE_HTTP
importing
!IM_URL type STRING
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_VERSION
importing
!IM_VERSION type I
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_POST
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_GET
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_DATOS_GET
importing
!IM_DATOS type STRING
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods CONVERTIR_FORMATO_GET
importing
!IM_ESTRUCTURA type ANY
!IM_NOMBRE_ESTRUCTURA type STRING
exporting
!EX_CONVERSION type STRING .
methods CONVERTIR_FORMATO_POST
importing
!IM_ESTRUCTURA type ANY
!IM_NOMBRE_ESTRUCTURA type STRING
exporting
!EX_CONVERSION type STRING .
methods SET_DATOS_CABECERA
importing
!IM_DATOS_CABECERA type TIHTTPNVP
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods RELLENAR_CABECERA
importing
!IM_NOMBRE type IHTTPNAM
!IM_VALOR type IHTTPVAL
exporting
!EX_DATOS_CABECERA type TIHTTPNVP .
methods ENVIAR_DATOS
importing
!IM_CLIENTE_HTTP type ref to IF_HTTP_CLIENT
!IM_DATO type ANY
exporting
!EX_RESULTADO type STRING .
methods SET_DATOS_BODY
importing
!IM_DATOS_BODY type STRING
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods GET_CLAVE
importing
!IM_NOMBRE_SO10 type TDOBNAME
exporting
!EX_CLAVE type IHTTPVAL .
methods GET_LONGITUD
importing
!IM_XML type STRING
exporting
!EX_LONGITUD type IHTTPVAL .
En la sección pública podemos ver los datos de entrada y salida de los métodos.
Método para obtener la URL
Se tendrá que tener una tabla de parámetros, en la que pondremos la URL de conexión contra el Web services.
METHOD get_url.
CONSTANTS: lc_clase TYPE kschl VALUE ‘WWW’,
lc_codigo TYPE zcm_codigo_iva VALUE ‘W’.
SELECT SINGLE valores INTO ex_url
FROM zcm_parametros
WHERE kschl EQ lc_clase
AND codigo EQ lc_codigo.
ENDMETHOD.
Crear cliente http
Lo primero que se tiene que hacer es crear un cliente http, que es el que nos proporcionará las herramientas de conexión.
- Datos de entrada al método
IM_URL Importing Type STRING
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
METHOD CREAR_CLIENTE_HTTP.
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = im_url
IMPORTING
client = ex_cliente_http
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
ENDMETHOD.
Indicar Versión
Se tendrá que poner la versión del protolo http:
- Datos de entrada al método
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
IM_VERSION Importing Type I
METHOD set_version.
CONSTANTS: lc_cero TYPE i VALUE 0,
lc_uno TYPE i VALUE 1.
IF lc_cero EQ im_version.
CALL METHOD ex_cliente_http->request->set_version( if_http_request=>co_protocol_version_1_0 ).
ELSEIF lc_uno EQ im_version.
CALL METHOD ex_cliente_http->request->set_version( if_http_request=>co_protocol_version_1_1 ).
ENDIF.» lc_cero EQ im_version.
ENDMETHOD.
Envío datos mediante POST
Cuando no se envían los datos por la URL, sino que se envía mediante un XML.
- Datos de entrada al método
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
method SET_POST.
CALL METHOD ex_cliente_http->request->set_method( if_http_request=>co_request_method_post ).
endmethod.
Envío de datos mediante GET
Este método envia las variables dentro de la propia URL (dirección) de la página, concatenadas(unidas) por ampertands(&)
- Datos de entrada al método
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
method SET_GET.
CALL METHOD ex_cliente_http->request->set_method( if_http_request=>co_request_method_get ).
endmethod.
Rellenar GET
Aquí se rellena mediante un String, pongo un ejemplo: im_datos = ‘codigopostal=28030&grupoproductoid=ae90b27f-e9e7-e311-a548-6c3be5be5ec4&codigopais=ES&codigoprovincia=28’
- Datos de entrada al método
IM_DATOS Importing Type STRING
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
METHOD set_datos_get.
cl_http_utility=>set_query( request = ex_cliente_http->request query = im_datos ).
ENDMETHOD.
Conventir formato GET
Yo en estos casos tengo declarada una estructura en la SE11, con los campos a enviar en el GET.
- Datos de entrada al método
IM_ESTRUCTURA Importing Type ANY
IM_NOMBRE_ESTRUCTURA Importing Type STRING
EX_CONVERSION Exporting Type STRING
METHOD convertir_formato_get.
TYPE-POOLS: slis.
CONSTANTS: lc_af TYPE string VALUE ‘<‘,
lc_cf TYPE string VALUE ‘>’,
lc_ac TYPE string VALUE ‘</’,
lc_igual TYPE string VALUE ‘=’,
lc_amp TYPE string VALUE ‘&’.
FIELD-SYMBOLS: <ls_estructura> TYPE ANY,
<lt_table> TYPE STANDARD TABLE.
DATA: ls_estructura TYPE REF TO data,
lt_table TYPE REF TO data.
DATA: lv_xml_out TYPE string.
DATA: lv_sobrante TYPE string,
lv_total TYPE string,
lv_corte TYPE string,
lv_corte_final TYPE string,
lv_valor TYPE string.
DATA: lv_name TYPE dd02l-tabname,
lt_fieldcat TYPE slis_t_fieldcat_alv,
ls_fieldcat TYPE slis_fieldcat_alv.
DATA: lv_contador TYPE i VALUE 0.
CREATE DATA ls_estructura TYPE (im_nombre_estructura).
CREATE DATA lt_table TYPE STANDARD TABLE OF (im_nombre_estructura).
ASSIGN ls_estructura->* TO <ls_estructura>.
ASSIGN lt_table->* TO <lt_table>.
<ls_estructura> = im_estructura.
APPEND <ls_estructura> TO <lt_table>.
CALL TRANSFORMATION (‘ID’)
SOURCE tab = <lt_table>
RESULT XML lv_xml_out.
lv_corte = im_nombre_estructura.
TRANSLATE lv_corte TO UPPER CASE.
CONCATENATE lc_af lv_corte lc_cf INTO lv_corte.
SPLIT lv_xml_out AT lv_corte INTO lv_sobrante lv_total.
lv_name = im_nombre_estructura.
CALL FUNCTION ‘REUSE_ALV_FIELDCATALOG_MERGE’
EXPORTING
i_structure_name = lv_name
CHANGING
ct_fieldcat = lt_fieldcat
EXCEPTIONS
inconsistent_interface = 1
program_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.» sy-subrc <> 0.
LOOP AT lt_fieldcat INTO ls_fieldcat.
CLEAR: lv_corte,
lv_corte_final,
lv_sobrante,
lv_valor.
CONCATENATE lc_af ls_fieldcat-fieldname lc_cf INTO lv_corte.
CONCATENATE lc_ac ls_fieldcat-fieldname lc_cf INTO lv_corte_final.
SPLIT lv_total AT lv_corte INTO lv_sobrante lv_total.
SPLIT lv_total AT lv_corte_final INTO lv_valor lv_total.
IF lv_contador EQ 0.
CONCATENATE ls_fieldcat-fieldname lc_igual lv_valor INTO ex_conversion.
ELSE.
CONCATENATE ex_conversion lc_amp ls_fieldcat-fieldname lc_igual lv_valor INTO ex_conversion.
ENDIF.» lv_contador EQ 0.
ADD 1 TO lv_contador.
ENDLOOP.» LOOP AT lt_fieldcat INTO ls_fieldcat.
ENDMETHOD.
Convertir formato POST
En este caso lo que vamos hacer es convertir los campos de una estructura en la SE11 en un XML.
- Datos de entrada al método
IM_ESTRUCTURA Importing Type ANY
IM_NOMBRE_ESTRUCTURA Importing Type STRING
EX_CONVERSION Exporting Type STRING
METHOD convertir_formato_post.
FIELD-SYMBOLS: <ls_estructura> TYPE ANY,
<lt_table> TYPE STANDARD TABLE.
DATA: ls_estructura TYPE REF TO data,
lt_table TYPE REF TO data.
DATA: lv_xml_out TYPE string.
CREATE DATA ls_estructura TYPE (im_nombre_estructura).
CREATE DATA lt_table TYPE STANDARD TABLE OF (im_nombre_estructura).
ASSIGN ls_estructura->* TO <ls_estructura>.
ASSIGN lt_table->* TO <lt_table>.
<ls_estructura> = im_estructura.
APPEND <ls_estructura> TO <lt_table>.
CALL TRANSFORMATION (‘ID’)
SOURCE tab = <lt_table>
RESULT XML ex_conversion.
ENDMETHOD.
Set datos cabecera
- Datos de entrada al método
IM_DATOS_CABECERA Importing Type TIHTTPNVP
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
METHOD set_datos_cabecera.
CALL METHOD ex_cliente_http->request->set_header_fields
EXPORTING
fields = im_datos_cabecera.
ENDMETHOD.
Rellenar la cabecera
- Datos de entrada al método
IM_NOMBRE Importing Type IHTTPNAM
IM_VALOR Importing Type IHTTPVAL
EX_DATOS_CABECERA Exporting Type TIHTTPNVP
METHOD rellenar_cabecera.
DATA: ls_cabecera TYPE ihttpnvp.
ls_cabecera-name = im_nombre.
ls_cabecera-value = im_valor.
APPEND ls_cabecera TO ex_datos_cabecera.
ENDMETHOD.
Enviar los datos
- Datos de entrada al método
IM_CLIENTE_HTTP Importing Type Ref To IF_HTTP_CLIENT
IM_DATO Importing Type ANY
EX_RESULTADO Exporting Type STRING
METHOD enviar_datos.
CONSTANTS: lc_error_envio TYPE string VALUE ‘Error de envío’,
lc_uno TYPE zflag VALUE ‘1’,
lc_cero TYPE zflag VALUE ‘0’,
lc_error TYPE zflag_error VALUE ‘E’,
lc_correcto TYPE zflag_error VALUE ‘C’.
DATA: lv_code TYPE sysubrc,
lv_codigo TYPE string,
lv_errortext TYPE string.
DATA: lv_rango TYPE numc10,
ls_log_envio TYPE zlog_crm,
ls_log_recepcion TYPE zlog_crm.
DATA: lv_http_rc TYPE sy-subrc.
CALL FUNCTION ‘NUMBER_GET_NEXT’ » número para el Log
EXPORTING
nr_range_nr = ’01’
object = ‘ZCRM_LOG’
quantity = ‘1’
IMPORTING
number = lv_rango.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ls_log_envio-id_numero = lv_rango.
ls_log_envio-fecha = sy-datum.
ls_log_envio-hora = sy-uzeit.
ls_log_envio-flag = lc_cero.
ls_log_envio-identificador = im_dato.
CALL METHOD im_cliente_http->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.
IF sy-subrc <> 0.
ex_resultado = lc_error_envio.
ENDIF.
CALL METHOD im_cliente_http->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
IF sy-subrc = 0.
ex_resultado = im_cliente_http->response->get_cdata( ).
im_cliente_http->response->get_status( IMPORTING code = lv_http_rc ).
IF lv_http_rc <> 200.» Error de recepción
ls_log_envio-flag_error = lc_correcto.
CONCATENATE ‘Envío correcto de:’ im_dato INTO ls_log_envio-descripcion SEPARATED BY space.
ls_log_recepcion-id_numero = lv_rango.
ls_log_recepcion-fecha = sy-datum.
ls_log_recepcion-hora = sy-uzeit.
ls_log_recepcion-flag = lc_uno.
ls_log_recepcion-identificador = im_dato.
ls_log_recepcion-flag_error = lc_error.
CONCATENATE ‘Respuesta CRM: datos incorrectos en’ im_dato INTO ls_log_recepcion-descripcion SEPARATED BY space.
ELSE.» Todo correcto
ls_log_envio-flag_error = lc_correcto.
CONCATENATE ‘Envío correcto de:’ im_dato INTO ls_log_envio-descripcion SEPARATED BY space.
ls_log_recepcion-id_numero = lv_rango.
ls_log_recepcion-fecha = sy-datum.
ls_log_recepcion-hora = sy-uzeit.
ls_log_recepcion-flag = lc_uno.
ls_log_recepcion-identificador = im_dato.
ls_log_recepcion-flag_error = lc_correcto.
CONCATENATE ‘Recepción correcta de:’ im_dato INTO ls_log_recepcion-descripcion SEPARATED BY space.
ENDIF.» lv_http_rc <> 200.
ELSEIF sy-subrc <> 0.» error de envío y recepción
CALL METHOD im_cliente_http->get_last_error
IMPORTING
code = lv_code
MESSAGE = lv_errortext.
lv_codigo = lv_code.
CONCATENATE ‘communication_error : ‘ lv_codigo ‘message: ‘ lv_errortext INTO ex_resultado SEPARATED BY space.
ls_log_envio-flag_error = lc_error.
CONCATENATE ‘Envío incorrecto de:’ im_dato INTO ls_log_envio-descripcion SEPARATED BY space.
ls_log_recepcion-id_numero = lv_rango.
ls_log_recepcion-fecha = sy-datum.
ls_log_recepcion-hora = sy-uzeit.
ls_log_recepcion-flag = lc_uno.
ls_log_recepcion-identificador = im_dato.
ls_log_recepcion-flag_error = lc_error.
CONCATENATE ‘Recepción incorrecta de:’ im_dato INTO ls_log_recepcion-descripcion SEPARATED BY space.
ENDIF.» sy-subrc = 0.
INSERT zlog_crm FROM ls_log_envio.
INSERT zlog_crm FROM ls_log_recepcion.
COMMIT WORK AND WAIT.
CALL METHOD im_cliente_http->close( ).
ENDMETHOD.
Set datos body
- Datos de entrada al método
IM_DATOS_BODY Importing Type STRING
EX_CLIENTE_HTTP Exporting Type Ref To IF_HTTP_CLIENT
METHOD set_datos_body.
CALL METHOD ex_cliente_http->request->set_cdata
EXPORTING
data = im_datos_body.
ENDMETHOD.
Get longitud
Método muy importante ya que tendremos que saber la longitud del XML cuando digamos que lo enviamos en formato UTF-8, ya que sino se indica la logitud abra problemas en la conversión del formato.
- Datos de entrada al método
IM_XML Importing Type STRING
EX_LONGITUD Exporting Type IHTTPVAL
METHOD get_longitud.
DATA: lv_xml_change TYPE xstring.
DATA: cl_cvto_utf8 TYPE REF TO cl_abap_conv_out_ce.
DATA: lv_long TYPE i VALUE 0.
cl_cvto_utf8 = cl_abap_conv_out_ce=>create( encoding = ‘UTF-8’ ).
cl_cvto_utf8->write( data = im_xml ).
lv_xml_change = cl_cvto_utf8->get_buffer( ).
lv_long = XSTRLEN( lv_xml_change ).
MOVE lv_long TO ex_longitud.
ENDMETHOD.
Función de llamada al Web services
TYPE-POOLS: truxs.
CONSTANTS: lc_nombre_estructura TYPE string VALUE ‘zcm_petcrm’,
lc_version_uno TYPE i VALUE 1,
lc_autorizar TYPE ihttpnam VALUE ‘Authorization’,
lc_content_valor TYPE ihttpval VALUE ‘text/xml; charset=utf-8’,
lc_content_type TYPE ihttpnam VALUE ‘Content-Type’,
lc_content_lenght TYPE ihttpnam VALUE ‘Content-Length’,
lc_so10 TYPE tdobname VALUE ‘ZCLAVE_CRM’,
lc_estado TYPE kschl VALUE ‘LINE’,
lc_activo TYPE char200 VALUE ‘ON’.
DATA: carga_materiales TYPE REF TO zcarga_materiales_petcrm.
DATA: conexion TYPE REF TO zconexion_crm_petcrm.
DATA: lv_cliente TYPE REF TO if_http_client.
DATA: lv_url TYPE string.
DATA: ls_material TYPE zcm_petcrm,
ls_material_mem TYPE zcm_petcrm.
DATA: lv_xml TYPE string.
DATA: lv_clave TYPE ihttpval.
DATA: lt_cabecera TYPE tihttpnvp.
DATA: lt_material TYPE TABLE OF zcm_petcrm.
DATA: lt_string TYPE aco_tt_string.
DATA: xml_out TYPE aco_string.
DATA: lv_resultado TYPE string.
DATA: ls_marm TYPE xdmarm.
DATA: lv_estado TYPE char200.
DATA: lv_longitud TYPE ihttpval.
* break neo02.
SELECT SINGLE valores INTO lv_estado
FROM zcm_parametros
WHERE kschl EQ lc_estado
AND valores EQ lc_activo.
IF sy-subrc EQ 0.
CHECK i_mara_new-matnr CP ‘SDL*’.
COMMIT WORK AND WAIT.» Espero que se actualicen las modificaciones
CREATE OBJECT carga_materiales TYPE zcarga_materiales_petcrm.
CREATE OBJECT conexion TYPE zconexion_crm_petcrm.
carga_materiales->datos_modificar( EXPORTING im_matnr = i_mara_new-matnr IMPORTING ex_material = ls_material ).
TRANSLATE ls_material-matnr TO UPPER CASE.
IF ls_material-kmein IS INITIAL.» Si el material es nuevo
LOOP AT t_marm_new INTO ls_marm.
IF sy-tabix EQ 1.
ls_material-kmein = ls_marm-meinh.
ELSEIF sy-tabix EQ 2.
ls_material-meinh = ls_marm-meinh.
ls_material-umren = ls_marm-umren.
ENDIF.» sy-tabix EQ 1.
ENDLOOP.» AT t_marm_new INTO ls_marm.
ls_material_mem = ls_material.
EXPORT ls_material_mem FROM ls_material_mem TO SHARED MEMORY indx(al) ID ‘AJC’.
ELSE.
conexion->get_url( EXPORTING im_identificador = ls_material-matnr IMPORTING ex_url = lv_url ).
conexion->crear_cliente_http( EXPORTING im_url = lv_url IMPORTING ex_cliente_http = lv_cliente ).
conexion->set_version( EXPORTING im_version = lc_version_uno IMPORTING ex_cliente_http = lv_cliente ).
conexion->set_post( IMPORTING ex_cliente_http = lv_cliente ).
conexion->rellenar_cabecera( EXPORTING im_nombre = lc_content_type im_valor = lc_content_valor IMPORTING ex_datos_cabecera = lt_cabecera ).
conexion->get_clave( EXPORTING im_nombre_so10 = lc_so10 IMPORTING ex_clave = lv_clave ).
conexion->rellenar_cabecera( EXPORTING im_nombre = lc_autorizar im_valor = lv_clave IMPORTING ex_datos_cabecera = lt_cabecera ).
conexion->set_datos_cabecera( EXPORTING im_datos_cabecera = lt_cabecera IMPORTING ex_cliente_http = lv_cliente ).
conexion->convertir_formato_post( EXPORTING im_estructura = ls_material im_nombre_estructura = lc_nombre_estructura IMPORTING ex_conversion = lv_xml ).
carga_materiales->convertir_xml( EXPORTING im_conversion = lv_xml im_nombre_estructura = lc_nombre_estructura IMPORTING ex_conversion = lv_xml ).
conexion->get_longitud( EXPORTING im_xml = lv_xml IMPORTING ex_longitud = lv_longitud ).
conexion->rellenar_cabecera( EXPORTING im_nombre = lc_content_lenght im_valor = lv_longitud IMPORTING ex_datos_cabecera = lt_cabecera ).
conexion->set_datos_body( EXPORTING im_datos_body = lv_xml IMPORTING ex_cliente_http = lv_cliente ).
conexion->enviar_datos( EXPORTING im_cliente_http = lv_cliente im_dato = ls_material-matnr IMPORTING ex_resultado = lv_resultado ).
ENDIF.» ls_material-kmein IS INITIAL.
ENDIF.» sy-subrc EQ 0.
ENDFUNCTION.