Esta guía sobre la integración ABAP de SAP Gemini API explica paso a paso cómo SAP (ABAP) se comunica de forma segura con la API Google Gemini (Generative Language API).
También te mostraremos cómo proceder desde los certificados en STRUST hasta el destino RFC en SM59 y luego el HTTP POST productivo en ABAP. También puedes encontrar más consejos en nuestro artículo ¿Qué es el SAP?
Tabla de contenido
- ¿Por qué integración ABAP de SAP Gemini API?
- Paso 1: SM59: Crear un destino HTTP para las API de Google
- Paso 2: STRUST: Certificados para el acceso HTTPS a las API de Google
- Paso 3: Integración ABAP de SAP Gemini API – Solicitud POST a Gemini (Ejemplo mínimo)
- Mejores prácticas para la integración ABAP de SAP Gemini API

¿Por qué integración ABAP de SAP Gemini API?
- Análisis de texto, resúmenes, clasificación y automatización basada en prompts directamente de ABAP.
- Además, la conexión es sencilla mediante una clave API y también mediante una interfaz REST estandarizada.
- Esto hace que la solución sea escalable desde la operación de prueba hasta el uso productivo.
Requisitos
- Primero, necesitas un sistema SAP con HTTPS (ICM) activo y CommonCryptoLib.
- También necesitas permisos para STRUST y SM59.
- Además, se requiere una clave API válida de Gemini.
- También necesitarás una utilidad JSON ABAP, como
/UI2/CL_JSON.
Paso 1: SM59: Crear un destino HTTP para las API de Google
Para que la integración SAP Gemini API ABAP funcione, primero se crea un destino HTTP en SM59 que SAP utiliza para direccionar servicios web o APIs externas.
Para , generativelanguage.googleapis.com la configuración básica se presenta por lo tanto así:
Crear una nueva conexión HTTP
- Luego haz clic en Crear.
- Después de eso, selecciona el tipo de conexión G – conexión HTTP a un servidor externo.
- Luego da un nombre descriptivo (por ejemplo, B.
GOOGLE_GENAI_APIo ).GOOGLE_GEMINI_API
Configuración técnica
- Anfitrión:
generativelanguage.googleapis.com - Número de servicio:
443, porque HTTPS utiliza este puerto - Prefijo de ruta: deje en blanco por ahora: la ruta completa se establece en el código ABAP
(p. ej. B./v1/models/gemini-2.5-flash:generateContent).
Inicio de sesión y seguridad
- SNC: no es obligatorio porque se usa HTTPS.
- SSL: Seleccione Activo (SSL Client Standard)
(o su identidad de cliente SSL dedicada, si se almacena en STRUST).
Registro y seguridad
Las API de Google generalmente no mantienen datos de usuario / contraseña en el destino. En su lugar, la autenticación se realiza en el código ABAP, ya sea mediante clave API en la cabecera o, alternativamente, mediante tokens OAuth 2.0 (cabecera
Authorization: Bearer ).
- Usuario/contraseña: permanece en blanco porque la autenticación se realiza en el código.
- Certificado de cliente SSL: Corresponde a la selección en Configuración técnica.
Si hay varias identidades, seleccione específicamente si es necesario.
Opciones especiales
- Proxy HTTP: mantener solo si el acceso a Internet pasa por él.
- Tiempos muertos: ajusta según sea necesario para captar respuestas lentas.
Resumen
- Anfitrión:
generativelanguage.googleapis.com - Servicio:
443 - Prefijo de ruta: en blanco (la ruta se establece en el código)
- SSL: Activo, estándar de cliente SSL
- Inicio de sesión: vacío (autenticación en código ABAP)
Paso 2: STRUST: Certificados para el acceso HTTPS a las API de Google
En STRUST, entonces mantienes los anclajes de confianza SSL/TLS para que tu sistema SAP acepte los certificados de servidor presentados por Google.
¿Dónde registrarse?
Primero, cambia al nodo cliente SSL (por defecto) en STRUST o, alternativamente, a la identidad específica de tu cliente SSL. Entonces verás en el lado derecho de la
Lista de certificados : todos los certificados que ya son familiares. Aquí, por tanto, la raíz y – si está disponible –
también están disponibles los certificados intermedios de la CA emisora de Google.
¿Qué certificados se requieren?
Google suele utilizar cadenas de CA conocidas, como Google Trust Services (GTS), GlobalSign o DigiCert. En muchos sistemas, los certificados raíz importantes ya están disponibles porque el sistema operativo o CCL a menudo los proporciona. Sin embargo, si falta algo, añade la cadena manualmente.
Detección y exportación de certificados
https://generativelanguage.googleapis.comen el navegador.- Haga clic en el icono del candado y vea la cadena de certificados.
- Certificados raíz y, si procede, intermedios (p. ej. GTS Root R1, GTS CA 1O1) en formato Base64-X.509
.cer( o.pem). Alternativamente, descárguelo desde las páginas oficiales de Google Trust Services.
Importar a STRUST
- Abra STRUST y seleccione Cliente SSL (predeterminado ).
- Luego usa el botón Importar Certificado y selecciona los archivos guardados.
- Luego añade los certificados a la lista y después haz una copia de seguridad de la base de datos para que los cambios hagan efecto.
- Después de la importación, las entradas deberían ser visibles, de lo contrario la importación fallará.
Comprueba la conexión
Luego ejecuta una Conexión de Prueba en SM59 en tu destino. Si la prueba falla, una
Certificado raíz o intermedio. Sin embargo, nota: Esta prueba solo verifica la red y el handshake TLS, mientras que la segunda
la autenticación mediante clave API u OAuth no está cubierta.
Resumen
- Ubicación: cliente SSL (predeterminado) (o el cliente SSL PSE utilizado).
- También se utilizan certificados raíz o intermedios de confianza de las CA de Google (por ejemplo, GTS Root R1, GTS CA 1O1) como contenido.
- Como acción, primero deberías comprobar la presencia y luego importar y guardar los certificados que faltan.
Siguiente paso en ABAP
Tan pronto como se completa el trabajo preparatorio, la comunicación real de la API (método HTTP, cabecera, cuerpo, autenticación) se realiza en el código,
por ejemplo, con CL_HTTP_CLIENT o alternativamente CL_REST_HTTP_CLIENT.
Paso 3: Integración ABAP de SAP Gemini API – Solicitud POST a Gemini (Ejemplo mínimo)
Punto de conexión de ejemplo (v1, modelo gemini-2.5-flash): /v1/models/gemini-2.5-flash:generateContent
REPORT z_ki_google_test.
DATA: lo_http TYPE REF TO if_http_client,
lv_body TYPE string,
lv_result TYPE string,
lv_api_key TYPE string VALUE '***PLACE_YOUR_API_KEY_SECURELY***'.
" 1) HTTP-Client aus SM59-Destination (G: HTTP)
cl_http_client=>create_by_destination(
EXPORTING destination = 'GEMINI'
IMPORTING client = lo_http ).
" 2) Header setzen
lo_http->request->set_method( if_http_request=>co_request_method_post ).
lo_http->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
lo_http->request->set_header_field( name = 'x-goog-api-key' value = lv_api_key ).
" 3) Request-Pfad (Endpoint) – setze ihn NUR hier ODER als Präfix in SM59 (nicht beides!)
lo_http->request->set_header_field(
name = '~request_uri'
value = '/v1/models/gemini-2.5-flash:generateContent' ).
" ---------- Request-JSON aufbauen (mit name_mappings für lowercase keys) ----------
TYPES: BEGIN OF ty_part_req,
text TYPE string,
END OF ty_part_req.
TYPES: ty_t_part_req TYPE STANDARD TABLE OF ty_part_req WITH EMPTY KEY.
TYPES: BEGIN OF ty_content_req,
parts TYPE ty_t_part_req,
END OF ty_content_req.
TYPES: ty_t_content_req TYPE STANDARD TABLE OF ty_content_req WITH EMPTY KEY.
TYPES: BEGIN OF ty_request,
contents TYPE ty_t_content_req,
END OF ty_request.
DATA ls_req TYPE ty_request.
DATA(lv_prompt_text) = |Erkläre KI in einem Satz.|.
APPEND VALUE ty_content_req(
parts = VALUE #( ( text = lv_prompt_text ) ) )
TO ls_req-contents.
DATA lt_req_map TYPE /ui2/cl_json=>name_mappings.
DATA lt_res_map TYPE /ui2/cl_json=>name_mappings.
" Request-Mapping (ABAP-Feldname -> JSON-Key, lowercase)
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'CONTENTS' json = 'contents' ) INTO TABLE lt_req_map.
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'PARTS' json = 'parts' ) INTO TABLE lt_req_map.
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'TEXT' json = 'text' ) INTO TABLE lt_req_map.
" Response-Mapping
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'CANDIDATES' json = 'candidates' ) INTO TABLE lt_res_map.
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'CONTENT' json = 'content' ) INTO TABLE lt_res_map.
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'PARTS' json = 'parts' ) INTO TABLE lt_res_map.
INSERT VALUE /ui2/cl_json=>name_mapping( abap = 'TEXT' json = 'text' ) INTO TABLE lt_res_map.
lv_body = /ui2/cl_json=>serialize(
data = ls_req
name_mappings = lt_req_map
compress = abap_true ).
" 4) Senden & Empfangen
lo_http->request->set_cdata( lv_body ).
lo_http->send( ).
lo_http->receive( ).
" 5) Antwort lesen (Status + Body)
DATA: lv_status TYPE i,
lv_reason TYPE string.
lo_http->response->get_status(
IMPORTING
code = lv_status
reason = lv_reason ).
lv_result = lo_http->response->get_cdata( ).
" ---------- Response-JSON deserialisieren ----------
TYPES: BEGIN OF ty_part_res,
text TYPE string,
END OF ty_part_res.
TYPES: ty_t_part_res TYPE STANDARD TABLE OF ty_part_res WITH EMPTY KEY.
TYPES: BEGIN OF ty_content_res,
parts TYPE ty_t_part_res,
END OF ty_content_res.
TYPES: BEGIN OF ty_candidate,
content TYPE ty_content_res,
END OF ty_candidate.
TYPES: ty_t_candidate TYPE STANDARD TABLE OF ty_candidate WITH EMPTY KEY.
TYPES: BEGIN OF ty_response,
candidates TYPE ty_t_candidate,
END OF ty_response.
DATA ls_resp TYPE ty_response.
TRY.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_result
name_mappings = lt_res_map
CHANGING data = ls_resp ).
DATA(lv_text) = ||.
IF lines( ls_resp-candidates ) > 0
AND lines( ls_resp-candidates[ 1 ]-content-parts ) > 0.
lv_text = ls_resp-candidates[ 1 ]-content-parts[ 1 ]-text.
ENDIF.
"=== ALV-Vorbereitung ======================================================
TYPES: BEGIN OF ty_company_info,
field TYPE string,
value TYPE string,
END OF ty_company_info.
DATA: lt_company_info TYPE STANDARD TABLE OF ty_company_info,
ls_company_info TYPE ty_company_info.
IF lv_status = 200 AND lv_text IS NOT INITIAL.
" Antwort in Zeilen aufteilen und Feld: Wert extrahieren
DATA(lt_lines) = VALUE stringtab( ).
SPLIT lv_text AT cl_abap_char_utilities=>newline INTO TABLE lt_lines.
LOOP AT lt_lines INTO DATA(lv_line).
IF lv_line CS ':'.
SPLIT lv_line AT ':' INTO ls_company_info-field ls_company_info-value.
CONDENSE ls_company_info-field.
SHIFT ls_company_info-value LEFT DELETING LEADING space.
ELSE.
ls_company_info-field = 'Text'.
ls_company_info-value = lv_line.
ENDIF.
APPEND ls_company_info TO lt_company_info.
CLEAR ls_company_info.
ENDLOOP.
ELSE.
" Fehlerfall als ALV zeigen
ls_company_info-field = |HTTP|.
ls_company_info-value = |{ lv_status } { lv_reason }|.
APPEND ls_company_info TO lt_company_info.
CLEAR ls_company_info.
ls_company_info-field = |Fehlermeldung|.
ls_company_info-value = lv_result.
APPEND ls_company_info TO lt_company_info.
ENDIF.
"=== ALV-Ausgabe ===========================================================
DATA: lo_alv TYPE REF TO cl_salv_table,
lo_columns TYPE REF TO cl_salv_columns_table,
lo_column TYPE REF TO cl_salv_column_table.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_company_info ).
lo_columns = lo_alv->get_columns( ).
lo_columns->set_optimize( abap_true ).
lo_column ?= lo_columns->get_column( 'FIELD' ).
lo_column->set_short_text( 'Kategorie' ).
lo_column->set_medium_text( 'Kategorie' ).
lo_column->set_long_text( 'Informationskategorie' ).
lo_column ?= lo_columns->get_column( 'VALUE' ).
lo_column->set_short_text( 'Inhalt' ).
lo_column->set_medium_text( 'Beschreibung' ).
lo_column->set_long_text( 'Detail' ).
lo_alv->display( ).
CATCH cx_root INTO DATA(lx).
" Fallback: Fehler in einfacher Liste ausgeben
WRITE: / 'JSON-/ALV-Fehler:', lx->get_text( ).
WRITE: / 'Raw-Response:', / lv_result.
ENDTRY.
lo_http->close( ).
Mejores prácticas para la integración ABAP de SAP Gemini API
- No codifique la clave API, pero guárdala de forma segura (almacenamiento seguro, variables, manejadores SICF).
- También deberías incluir tiempos de espera y repeticiones para que los estados de error se registren claramente.
- Además, mantén las preguntas cortas y claras para que las respuestas sean coherentes.
- Elección del modelo:
gemini-2.5-flashpor costo/velocidad,gemini-2.5-propor calidad.
Solución de problemas
- 401 No autorizado: Esto falta
x-goog-api-keyo es incorrecto. - 400 Solicitud incorrecta: Verifique la estructura JSON (
contents → parts → text). - 404 No encontrado: Por lo tanto, deberías comprobar el nombre del modelo y el URI.
- Los errores de handshake SSL se producen porque la cadena de CA en STRUST está incompleta.
- Proxy/Cortafuegos: Por lo tanto, deberías comprobar tanto el proxy como los compartidos de red de SM59.
Lista de verificación
- Importé la cadena de CA en STRUST para que TLS funcione
- Además, el host, el puerto 443 y SSL están activos en SM59
- La clave API se almacena de forma segura para que el encabezado también esté correctamente configurado
- Además, el punto final es correcto:
/v1/models/gemini-2.5-flash:generateContent - También hay tiempos de espera, intentos y registro de registros
Con esta lista de comprobación, completarás la integración SAP Gemini API ABAP. También garantiza que tu sistema funcione de forma fiable.


