L’objectif de ce blog est de vous montrer comment créer/modifier/supprimer des feuilles Google via des programmes d’arrière-plan de SAP.
Comme il s’agit de tâches d’arrière-plan exécutées par le système SAP, ce n’est pas à l’utilisateur de s’authentifier auprès de Google puisqu’il n’y a pas d’action humaine. Nous ne pouvons donc pas choisir les méthodes où l’utilisateur s’authentifie directement pour effectuer l’extraction vers Google, comme ceci par exemple :
Pour utiliser cette méthode, vous devez consulter la documentation ici :
https://www.sap.com/documents/2018/07/56e0dd6d-0f7d-0010-87a3-c30de2ffd8ff.html
Dans le cas d’une connexion de serveur à serveur, nous travaillerons de cette manière :
Développement
Le contenu suivant est inspiré de cet article : https://blogs.sap.com/2019/11/10/connect-from-as-abap-to-google-cloud-platform-app-engine-resource-secured-with-google-identity-aware-proxy/?fbclid=IwAR2H4FpeB_HMuSw6yF9NFTpBFxKmQfTnwJwrEpKbAVxEfQdxh1P_Ae_Tm1U
- Créer un projet Google Cloud Platform :
- Dans le projet, créez un compte de service
Naviguez vers IAM&Admin -> Comptes de service et créez un nouveau compte de service. Saisissez un nom et une description et cliquez sur créer. Sur l’écran suivant, vous devez sélectionner un rôle.
Tapez IAP dans la recherche et sélectionnez le rôle IAP-secured Web App User.
- Et obtenir la clé au format P12
Après la création de votre compte de service, vous pouvez créer votre clé au format P12.
Le téléchargement du fichier P12 devrait commencer sur votre machine locale. Le compte de service permet d’accéder aux ressources du nuage, il faut donc le conserver en toute sécurité. Notez le secret indiqué pour une utilisation ultérieure.
- Importer le certificat du compte de service dans STRUST
Avant de pouvoir écrire du code ABAP et utiliser l’API Google, nous devons nous assurer de deux choses : Premièrement, nous devons importer le fichier P12 dans le système AS ABAP, deuxièmement, nous devons nous assurer que Google est une source de confiance pour la communication.
- Créer une nouvelle application SSF
Nous devons créer une nouvelle entrée dans la table SSFAPPLIC. Allez à la transaction SE16 et ouvrez la table. Créez une nouvelle entrée.
Utilisez JWR_SI pour APPLIC et sélectionnez tout sauf B_INCCERTS, B_DETACHED, B_ASKPWD. En tant que Description, nous définissons la Signature JWT. Cette entrée sera plus tard un nouveau noeud dans la transaction STRUST où nous pourrons importer des certificats. Sauvegardez la nouvelle entrée.
Ouvrez ensuite la transaction SSFA. Appuyez sur « New Entries ». Créez une nouvelle entrée comme indiqué ci-dessous
Nous avons maintenant un nouveau nœud dans la transaction STRUST.
- Importer des certificats dans STRUST
Ouvrez la transaction STRUST et un nouveau noeud devrait être disponible avec le nom « SSF JWT Signature ».
Passez en mode « Edition », faites un clic droit sur le nouveau nœud et sélectionnez « Créer ».
Dans la fenêtre suivante, réglez l’algorithme sur « RSA », la force de la clé sur « 2048 » et l’algorithme de signature sur « SHA256 ».
Confirmez la sélection et le nouveau nœud sera maintenant disponible pour les importations. Dans le menu du haut, sélectionnez « PSE->Import » et sélectionnez le fichier P12 du compte de service que vous avez téléchargé. Il se peut que vous deviez entrer le secret qui a été affiché lors du téléchargement du fichier P12 depuis GCP.
Le fichier P12 est maintenant chargé dans le nœud « File » de STRUST. Ensuite, nous devons le déplacer du nœud « File » vers la bonne application SSF. Dans le menu supérieur, sélectionnez « PSE->Save as ». Dans la fenêtre suivante, sélectionnez « SSF Application » et sélectionnez l’application SSF que nous avons créée dans les étapes précédentes (JWR_SI).
Confirmez la sélection et appuyez sur « Enregistrer ». Nous avons ainsi importé le fichier Service Account P12 dans l’ABAP AS et pouvons l’utiliser pour signer notre JWT pour les demandes adressées à GCP. Avec STRUST, nous disposons d’un endroit sûr pour stocker la clé privée du compte de service et les informations relatives au certificat.
La clé privée et le certificat du compte de service GCP ont été importés dans le système.
- Créer la connexion dans SAP
Ensuite, nous devons faire de Google une source de confiance pour la communication. Cela peut être réalisé en important l’autorité de certification racine de Google dans STRUST.
Téléchargez le certificat Google nécessaire à partir du navigateur (voir avec votre équipe SAP BASIS). Dans la transaction STRUST sur le client SSL Client SSL (Anonyme).
Google est maintenant une source de confiance pour la communication et nous avons créé les connexions HTTP qui seront utilisées pour la communication dans notre code ABAP plus tard.
Note : Vous pouvez tester votre connexion en cliquant sur « Connection test » :
Vous devriez obtenir une erreur 404 (c’est normal).
Si vous avez un message d’erreur SSL, vous avez un problème avec vos certificats Google.
Essayez de voir avec votre équipe SAP BASIS les erreurs dans les journaux ICM (TCODE SMICM).
- Créer les méthodes ABAP qui vont :
Créer et signer un jeton JWT dans SAP
L’envoyer à Google pour l’échanger contre un jeton d’authentification à placer dans l’en-tête de chaque appel API vers les ressources Google (drive, sheets, docs, etc…).
- Créer la classe ZCL_GCP_API_HANDLER
CLASS zcl_gcp_api_handler DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES:
BEGIN OF zgcp_response,
content TYPE string,
cookies TYPE tihttpcki,
code type i,
reason type string,
END OF zgcp_response.
CLASS-METHODS create_rs256_signed_jwt
IMPORTING
iv_jwt_header TYPE zgcp_jwt_header
iv_jwt_payload TYPE zgcp_jwt_payload
iv_ssf_profilename TYPE string
iv_ssf_id TYPE string
iv_ssf_result TYPE i
RETURNING VALUE(rv_signed_jwt_base64) TYPE string.
* RAISING zcx_gcp_api_handler.
CLASS-METHODS exchange_jwt_with_oidc_token
IMPORTING
iv_exchange_destination TYPE c
iv_jwt_token TYPE string
RETURNING VALUE(rv_oidc_base64) TYPE string.
* RAISING zcx_gcp_api_handler.
CLASS-METHODS do_api_request
IMPORTING
iv_destination TYPE c
iv_oidc_token TYPE string
iv_method TYPE string
iv_xcontent TYPE xstring OPTIONAL
iv_content TYPE string OPTIONAL
iv_sub_uri TYPE string OPTIONAL
it_header_fields TYPE tihttpnvp OPTIONAL
it_cookies TYPE tihttpcki OPTIONAL
iv_content_type TYPE string DEFAULT 'application/json'
RETURNING VALUE(rs_response) TYPE zgcp_response.
* RAISING zcx_gcp_api_handler.
CLASS-METHODS get_iat_unixtime RETURNING VALUE(rv_iat) TYPE int4.
PROTECTED SECTION.
PRIVATE SECTION.
TYPES:
ltty_tssfbin TYPE STANDARD TABLE OF ssfbin WITH KEY table_line WITHOUT FURTHER SECONDARY KEYS,
BEGIN OF oidc_token_json,
access_token TYPE string,
END OF oidc_token_json.
CLASS-METHODS string_to_binary_tab
IMPORTING
iv_string TYPE string
RETURNING VALUE(rt_bin_tab) TYPE ltty_tssfbin.
* RAISING zcx_gcp_api_handler.
CLASS-METHODS binary_tab_to_string
IMPORTING
it_bin_tab TYPE ltty_tssfbin
iv_length TYPE ssflen
RETURNING VALUE(rv_string) TYPE string.
* RAISING zcx_gcp_api_handler.
CLASS-METHODS base64_url_encode
CHANGING
iv_base64 TYPE string.
ENDCLASS.
CLASS ZCL_GCP_API_HANDLER IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_GCP_API_HANDLER=>BASE64_URL_ENCODE
* +-------------------------------------------------------------------------------------------------+
* | [<-->] IV_BASE64 TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD base64_url_encode.
REPLACE ALL OCCURRENCES OF '=' IN iv_base64 WITH ''.
REPLACE ALL OCCURRENCES OF '+' IN iv_base64 WITH '-'.
REPLACE ALL OCCURRENCES OF '/' IN iv_base64 WITH '_'.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_GCP_API_HANDLER=>BINARY_TAB_TO_STRING
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_BIN_TAB TYPE LTTY_TSSFBIN
* | [--->] IV_LENGTH TYPE SSFLEN
* | [<-()] RV_STRING TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD binary_tab_to_string.
CALL FUNCTION 'SCMS_BINARY_TO_STRING'
EXPORTING
input_length = iv_length
encoding = '4110'
IMPORTING
text_buffer = rv_string
TABLES
binary_tab = it_bin_tab
EXCEPTIONS
failed = 1
OTHERS = 2.
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_bintostr_conversion_failed.
* ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_GCP_API_HANDLER=>CREATE_RS256_SIGNED_JWT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_JWT_HEADER TYPE ZGCP_JWT_HEADER
* | [--->] IV_JWT_PAYLOAD TYPE ZGCP_JWT_PAYLOAD
* | [--->] IV_SSF_PROFILENAME TYPE STRING
* | [--->] IV_SSF_ID TYPE STRING
* | [--->] IV_SSF_RESULT TYPE I
* | [<-()] RV_SIGNED_JWT_BASE64 TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD create_rs256_signed_jwt.
DATA lt_input_bin TYPE STANDARD TABLE OF ssfbin.
DATA lt_output_bin TYPE STANDARD TABLE OF ssfbin.
DATA lv_input_length TYPE ssflen.
DATA lv_output_length TYPE ssflen.
DATA lv_output_crc TYPE ssfreturn.
DATA lt_signer TYPE STANDARD TABLE OF ssfinfo.
DATA lv_unix_iat TYPE string.
DATA(lv_jwt_payload) = /ui2/cl_json=>serialize(
data = iv_jwt_payload
pretty_name = /ui2/cl_json=>pretty_mode-low_case
).
DATA(lv_jwt_header) = /ui2/cl_json=>serialize(
data = iv_jwt_header
pretty_name = /ui2/cl_json=>pretty_mode-low_case
).
DATA(lv_jwt_header_base64) = cl_http_utility=>encode_base64( unencoded = lv_jwt_header ).
DATA(lv_jwt_payload_base64) = cl_http_utility=>encode_base64( unencoded = lv_jwt_payload ).
DATA(lv_data_base64) = |{ lv_jwt_header_base64 }.{ lv_jwt_payload_base64 }|.
base64_url_encode(
CHANGING
iv_base64 = lv_data_base64
).
TRY.
lt_input_bin = string_to_binary_tab( iv_string = lv_data_base64 ).
* CATCH zcx_gcp_api_handler INTO DATA(lo_cx).
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = lo_cx->textid.
ENDTRY.
lt_signer = VALUE #( ( id = iv_ssf_id profile = iv_ssf_profilename result = iv_ssf_result ) ).
lv_input_length = strlen( lv_data_base64 ).
CALL FUNCTION 'SSF_KRN_SIGN'
EXPORTING
str_format = 'PKCS1-V1.5'
b_inc_certs = abap_false
b_detached = abap_false
b_inenc = abap_false
ostr_input_data_l = lv_input_length
str_hashalg = 'SHA256'
IMPORTING
ostr_signed_data_l = lv_output_length
crc = lv_output_crc " SSF Return code
TABLES
ostr_input_data = lt_input_bin
signer = lt_signer
ostr_signed_data = lt_output_bin
EXCEPTIONS
ssf_krn_error = 1
ssf_krn_noop = 2
ssf_krn_nomemory = 3
ssf_krn_opinv = 4
ssf_krn_nossflib = 5
ssf_krn_signer_list_error = 6
ssf_krn_input_data_error = 7
ssf_krn_invalid_par = 8
ssf_krn_invalid_parlen = 9
ssf_fb_input_parameter_error = 10.
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_signature_failed.
* ENDIF.
TRY.
DATA(lv_signature) = binary_tab_to_string(
it_bin_tab = lt_output_bin
iv_length = lv_output_length
).
* CATCH zcx_gcp_api_handler INTO DATA(lo_zcx).
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = lo_zcx->textid.
ENDTRY.
DATA(lv_jwt) = |{ lv_data_base64 }.{ cl_http_utility=>encode_base64( unencoded = lv_signature ) }|.
base64_url_encode(
CHANGING
iv_base64 = lv_jwt
).
rv_signed_jwt_base64 = lv_jwt.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_GCP_API_HANDLER=>DO_API_REQUEST
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_DESTINATION TYPE C
* | [--->] IV_OIDC_TOKEN TYPE STRING
* | [--->] IV_METHOD TYPE STRING
* | [--->] IV_XCONTENT TYPE XSTRING(optional)
* | [--->] IV_CONTENT TYPE STRING(optional)
* | [--->] IV_SUB_URI TYPE STRING(optional)
* | [--->] IT_HEADER_FIELDS TYPE TIHTTPNVP(optional)
* | [--->] IT_COOKIES TYPE TIHTTPCKI(optional)
* | [--->] IV_CONTENT_TYPE TYPE STRING (default ='application/json')
* | [<-()] RS_RESPONSE TYPE ZGCP_RESPONSE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD do_api_request.
DATA lo_client_api TYPE REF TO if_http_client.
DATA lv_response TYPE string.
DATA lv_oidc TYPE string.
CALL METHOD cl_http_client=>create_by_destination
EXPORTING
destination = iv_destination
IMPORTING
client = lo_client_api
EXCEPTIONS
argument_not_found = 1
destination_not_found = 2
destination_no_authority = 3
plugin_not_active = 4
internal_error = 5
OTHERS = 6.
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_api_dest_not_found.
* ENDIF.
IF lo_client_api IS BOUND.
lv_oidc = |Bearer { iv_oidc_token }|.
lo_client_api->request->set_header_fields( fields = it_header_fields ).
lo_client_api->request->set_content_type( content_type = iv_content_type ).
lo_client_api->request->set_method( method = iv_method ).
* set jwt token auth
lo_client_api->request->set_header_field(
name = 'Authorization' ##NO_TEXT
value = lv_oidc
).
lo_client_api->request->set_header_field(
name = 'content-type'
value = iv_content_type
).
IF iv_sub_uri IS NOT INITIAL.
cl_http_utility=>set_request_uri(
request = lo_client_api->request
uri = iv_sub_uri
).
ENDIF.
IF iv_xcontent IS NOT INITIAL.
lo_client_api->request->set_data( data = iv_xcontent ).
ENDIF.
IF iv_content IS NOT INITIAL.
lo_client_api->request->set_cdata( data = iv_content ).
ENDIF.
LOOP AT it_cookies ASSIGNING FIELD-SYMBOL(<cookie>).
lo_client_api->request->set_cookie(
EXPORTING
name = <cookie>-name " Name of cookie
path = <cookie>-path " Path of Cookie
value = <cookie>-value " Cookie value
domain = <cookie>-xdomain " Domain Name of Cookie
expires = <cookie>-expires " Cookie expiry date
secure = <cookie>-secure " 0: unsaved; 1:saved
).
ENDLOOP.
lo_client_api->send( ).
lo_client_api->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
).
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_api_receive_failed.
* ENDIF.
rs_response-content = lo_client_api->response->get_data( ).
lo_client_api->response->get_status( IMPORTING code = rs_response-code
reason = rs_response-reason ).
lo_client_api->response->get_cookies( CHANGING cookies = rs_response-cookies ).
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_GCP_API_HANDLER=>EXCHANGE_JWT_WITH_OIDC_TOKEN
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_EXCHANGE_DESTINATION TYPE C
* | [--->] IV_JWT_TOKEN TYPE STRING
* | [<-()] RV_OIDC_BASE64 TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD exchange_jwt_with_oidc_token.
DATA lo_client TYPE REF TO if_http_client.
DATA ls_response TYPE oidc_token_json.
CALL METHOD cl_http_client=>create_by_destination
EXPORTING
destination = iv_exchange_destination
IMPORTING
client = lo_client
EXCEPTIONS
argument_not_found = 1
destination_not_found = 2
destination_no_authority = 3
plugin_not_active = 4
internal_error = 5
OTHERS = 6.
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_oauth_dest_not_found.
* ENDIF.
IF lo_client IS BOUND.
lo_client->request->set_method( if_http_request=>co_request_method_post ).
lo_client->request->set_formfield_encoding( formfield_encoding = if_http_entity=>co_formfield_encoding_encoded ).
lo_client->request->set_form_field(
EXPORTING
name = 'grant_type'
value = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
).
lo_client->request->set_form_field(
EXPORTING
name = 'assertion'
value = iv_jwt_token
).
lo_client->send( ).
lo_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
).
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_oauth_token_receive_fail.
* ENDIF.
DATA(lv_response_json) = lo_client->response->get_cdata( ).
/ui2/cl_json=>deserialize(
EXPORTING
json = lv_response_json
pretty_name = /ui2/cl_json=>pretty_mode-camel_case
CHANGING data = ls_response ).
* IF ls_response-id_token IS INITIAL.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_oauth_token_receive_fail.
* ENDIF.
rv_oidc_base64 = ls_response-access_token.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_GCP_API_HANDLER=>GET_IAT_UNIXTIME
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RV_IAT TYPE INT4
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_iat_unixtime.
DATA lv_unix_iat TYPE string.
GET TIME STAMP FIELD DATA(lv_timestamp).
CONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC' INTO DATE DATA(lv_date) TIME DATA(lv_time).
cl_pco_utility=>convert_abap_timestamp_to_java(
EXPORTING
iv_date = lv_date
iv_time = lv_time
iv_msec = 0
IMPORTING
ev_timestamp = lv_unix_iat
).
rv_iat = substring( val = lv_unix_iat off = 0 len = strlen( lv_unix_iat ) - 3 ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_GCP_API_HANDLER=>STRING_TO_BINARY_TAB
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_STRING TYPE STRING
* | [<-()] RT_BIN_TAB TYPE LTTY_TSSFBIN
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD string_to_binary_tab.
DATA lv_xstring TYPE xstring.
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = iv_string
encoding = '4110'
IMPORTING
buffer = lv_xstring
EXCEPTIONS
failed = 1
OTHERS = 2.
* IF sy-subrc <> 0.
* RAISE EXCEPTION TYPE zcx_gcp_api_handler
* EXPORTING
* textid = zcx_gcp_api_handler=>zcx_strtobin_conversion_failed.
* ENDIF.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_xstring
TABLES
binary_tab = rt_bin_tab.
ENDMETHOD.
ENDCLASS.
- Créer 2 structures zgcp_jwt_header et zgcp_jwt_payload.
ALG signifie Algorithme et comprendra l’algorithme utilisé pour le cryptage, à savoir RS256.
TYP signifie « token type » (type de jeton) et sera JWT.
ISS signifie émetteur et sera le nom de notre compte de service Google.
AUD signifie audience, c’est-à-dire le consommateur du jeton.
TARGET_AUDIENCE est l’identifiant de notre client OAUTH chez Google.
IAT signifie issued at time (émis à l’heure) et correspond à l’heure UNIX à laquelle nous avons créé le jeton.
EXP signifie expires et correspond à la date d’expiration du jeton en heure UNIX.
- Créez un programme qui appellera les méthodes ci-dessus pour s’identifier.
*&---------------------------------------------------------------------*
*& Report ZCL_GCP_JWT_AUTH_TEST
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZCL_GCP_JWT_AUTH_TEST.
*1
DATA(lv_iat) = zcl_gcp_api_handler=>get_iat_unixtime( ).
DATA(ls_jwt_payload) = VALUE zgcp_jwt_payload( iss = 'your email google service account'
* aud = 'https://www.googleapis.com/oauth2/v4/token'
scope = 'https://www.googleapis.com/auth/drive'
aud = 'https://oauth2.googleapis.com/token'
* target_audience = '110934787806204234349'
iat = lv_iat
exp = lv_iat + 30 ).
DATA(ls_jwt_header) = VALUE zgcp_jwt_header( typ = 'JWT'
alg = 'RS256' ).
*2
TRY.
DATA(lv_signed_jwt) = zcl_gcp_api_handler=>create_rs256_signed_jwt(
EXPORTING
iv_jwt_header = ls_jwt_header
iv_jwt_payload = ls_jwt_payload
iv_ssf_profilename = 'SAPJWR_SI400.pse'
iv_ssf_id = '<implicit>'
iv_ssf_result = 28
).
* CATCH zcx_gcp_api_handler.
ENDTRY.
*3
TRY.
DATA(lv_oidc) = zcl_gcp_api_handler=>exchange_jwt_with_oidc_token(
iv_exchange_destination = 'GCP_OAUTH2_TOKEN'
iv_jwt_token = lv_signed_jwt
).
* CATCH zcx_gcp_api_handler.
ENDTRY.
- Nous spécifions toutes les variables nécessaires à la création du JWT et à sa signature
- Lancement du programme pour générer et signer le JWT.
- Lancer la classe pour générer le jeton d’authentification en envoyant le JWT signé à Google qui renvoie un jeton. Le jeton Google se trouve dans la variable lv_oidc.
With this token, it is now possible to call google APIs by specifying the token in the call header.
Now we can create a test program calling the google sheets APIs with our authentication token
You can test your calls here :
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/update
By inspecting, it is possible to find the url to specify in the call to have this operation:
Pour voir des exemples d’appels dans SAP, j’ai créé un programme de test :
Exemple pour créer une feuille blanche :
Exemple d’ajout de valeurs dans la feuille de calcul :
Conclusion
Vous pouvez maintenant créer/modifier/supprimer des feuilles Google. En utilisant cette technique vous pouvez interagir avec toutes les API de google (drive, doc, sheet, etc…).