当前位置: 首页 > news >正文

SAP RESTFUL接口方式发布SICF实现全路径

其他相关资料帖可参考:

https://blog.csdn.net/woniu_maggie/article/details/146210752
https://blog.csdn.net/SAPmatinal/article/details/134349125
https://blog.csdn.net/weixin_44382089/article/details/128283417

【业务场景】

外部系统不想通过RFC (需要安装SAP官网的组件DDL等架包才能支持SAP 远程RFC的JDBC访问,比较麻烦)和WEBSERIVE服务方式访问接口,可通过restful接口方式访问更方便

1.SE24新建CLASS类: ZCL_QUERY_GDDH_DATA

激活,然后添加interface接口:IF_HTTP_EXTENSION并激活。

2.实现IF_HTTP_EXTENSION~HANDLE_REQUEST

扩展方法IF_HTTP_EXTENSION~HANDLE_REQUEST, 可以根据GET/POST请求方式处理,这个接口采用的是POST请求方式

部分参数可以放到URL上面参数传入,若有TOKEN认证放在REQUEST请求的BODY里面以json方式传入,这个跟对方协商好就行,注意信息安全要求。

POST参数设置

 if_http_extension~handle_request.方法中获取接口的调用方式是GET / POST请求

METHOD if_http_extension~handle_request.

  "调用的方法 GET / POST
  DATA(lv_method) = server->request->get_method( ).

  CASE lv_method.
    WHEN 'GET'.
      me->get( server ).

    WHEN 'POST'.
      me->post( server ).

  ENDCASE.
ENDMETHOD. 

GET请求方式: 

  METHOD get.
    TYPES:
      BEGIN OF ty_input,
        token TYPE string,
      END OF ty_input.

    DATA: BEGIN OF ls_result,
            data    TYPE STANDARD TABLE OF ty_input,
            msg     TYPE string,
            success TYPE string,
          END OF ls_result.

    DATA: lt_fields       TYPE tihttpnvp,
          ls_fields       TYPE ihttpnvp,
          lv_header_query TYPE string,
          lv_data         TYPE string,
          lv_html         TYPE string,
          lv_body         TYPE string,
          lv_token        TYPE string,
          lv_content_type TYPE string,
          lv_md5          TYPE string,
          lv_algo         TYPE string,
          ls_info         TYPE zshr_pernr_info_gddh,
          lv_zphone       TYPE zphone,
          lv_icnum        TYPE psg_idnum.

    FIELD-SYMBOLS: <fs_field> LIKE LINE OF lt_fields.

    "Json结构
    DATA: BEGIN OF ls_request,
            datalist TYPE TABLE OF zshr_pernr_info_gddh,
          END OF ls_request.

    "传输结构
    DATA: ls_itab TYPE zshr_pernr_info_gddh,
          lt_itab TYPE TABLE OF zshr_pernr_info_gddh.

    server->request->get_form_fields( CHANGING fields = lt_fields ).
    IF lt_fields IS INITIAL.
      server->response->set_status( code = 404 reason = '未查询到传入参数,请检查' ).
    ENDIF.

    LOOP AT lt_fields INTO ls_fields.
      TRANSLATE ls_fields-name TO UPPER CASE.
      CASE ls_fields-name.
        WHEN 'ZPHONE'.
          lv_zphone = ls_fields-value.

        WHEN 'ICNUM'.
          lv_icnum = ls_fields-value.
        WHEN OTHERS.
      ENDCASE.
    ENDLOOP.

    IF lv_zphone IS INITIAL.
      server->response->set_status( code = 404 reason = '手机号码必传,请检查' ).
    ENDIF.

    CALL FUNCTION 'ZHRFM_USER_INFO_GDDH'
      EXPORTING
        iv_zphone = lv_zphone
        iv_icnum  = lv_icnum
      IMPORTING
        es_info   = ls_info.

    server->response->set_cdata(
        /ui2/cl_json=>serialize( data        = ls_info
                                 compress    = abap_true
                                 pretty_name = /ui2/cl_json=>pretty_mode-camel_case ) ).

    server->response->set_status( code = 200 reason = 'OK' ).
    lv_content_type = 'application/json'.
    server->response->set_content_type( lv_content_type ).

  ENDMETHOD.

POST请求方式:

  METHOD post.
    TYPES:
      BEGIN OF ty_input,
        token TYPE string,
      END OF ty_input.

    DATA: BEGIN OF ls_result,
            data    TYPE STANDARD TABLE OF ty_input,
            msg     TYPE string,
            success TYPE string,
          END OF ls_result.

    DATA: lt_fields       TYPE tihttpnvp,
          ls_fields       TYPE ihttpnvp,
          lv_header_query TYPE string,
          lv_data         TYPE string,
          lv_html         TYPE string,
          lv_body         TYPE string,
          lv_token        TYPE string,
          lv_content_type TYPE string,
          lv_md5          TYPE string,
          lv_algo         TYPE string,
          ls_info         TYPE zshr_pernr_info_gddh,
          lv_zphone       TYPE zphone,
          lv_icnum        TYPE psg_idnum.

    FIELD-SYMBOLS: <fs_field> LIKE LINE OF lt_fields.

    "Json结构
    DATA: BEGIN OF ls_request,
            datalist TYPE TABLE OF zshr_pernr_info_gddh,
          END OF ls_request.

    "传输结构
    DATA: ls_itab TYPE zshr_pernr_info_gddh,
          lt_itab TYPE TABLE OF zshr_pernr_info_gddh.

    " get HEADER fields
    server->request->get_header_fields( CHANGING fields = lt_fields  ).
    lv_data = server->request->if_http_entity~get_cdata( ).

    "获取HTTP Body
    lv_body = server->request->get_cdata( ).

    "对方采用了basis认证登录方式
*lv_token = '7815696ecbf1c96f'.
**TOKEN加密认证
*    TRY.
*        lv_algo = 'MD5'.         " MD5, SHA1, SHA256, SHA384, SHA512
*        cl_abap_message_digest=>calculate_hash_for_char( EXPORTING if_algorithm = lv_algo
*                                                                   if_data      = lv_token
*                                                         IMPORTING
*                                                                   ef_hashstring = lv_md5 ).
*      CATCH cx_root INTO DATA(e_text).
*    ENDTRY.
*
*
*    "将Json转换成内表
*    TRY.
*
*        CALL METHOD /ui2/cl_json=>deserialize(
*          EXPORTING
*            json        = lv_body
*            pretty_name = /ui2/cl_json=>pretty_mode-camel_case
*          CHANGING
*            data        = ls_result ).

*
*        IF ls_result-data IS NOT INITIAL.
*          READ TABLE ls_result-data INTO DATA(ls_data) INDEX 1.
*          IF sy-subrc EQ 0.
*            IF ls_data-token NE lv_md5.
*              server->response->set_status( code = 400 reason = 'Token Authority Check failed' ).
*              server->response->set_cdata(
*                      /ui2/cl_json=>serialize( data        = ls_info
*                                               compress    = abap_true
*                                               pretty_name = /ui2/cl_json=>pretty_mode-camel_case ) ).
*              EXIT.
*            ENDIF.
*          ENDIF.
*        ENDIF.
*
*      CATCH cx_sy_move_cast_error.
*      CATCH cx_root.
*    ENDTRY..

    " Read the fields table and look for name "~query_string" -- this will contain the URL query
    READ TABLE lt_fields ASSIGNING <fs_field> WITH KEY name = '~query_string'.
    IF sy-subrc EQ 0.
      SPLIT <fs_field>-value AT '&' INTO TABLE DATA(lt_data).
      DELETE lt_data INDEX 1.
      LOOP AT lt_data INTO DATA(lw_data).
        CASE sy-tabix.
          WHEN 1.
            SPLIT lw_data AT '=' INTO DATA(lv_str1) lv_zphone.
          WHEN 2.
            SPLIT lw_data AT '=' INTO DATA(lv_str2) lv_icnum.
        ENDCASE.
      ENDLOOP.
    ENDIF.

    IF lv_zphone IS INITIAL.
      CONCATENATE '{"message": "Please input ZPHONE'
                        'as query parameter."}'
                   INTO lv_html SEPARATED BY space.

*" Output to HTML
      server->response->set_cdata(
        EXPORTING
          data   = lv_html    " Character data
      ).
      server->response->set_status( code = 400 reason = 'Please input ZPHONE' ).
    ENDIF.

    CALL FUNCTION 'ZHRFM_USER_INFO_GDDH'
      EXPORTING
        iv_zphone = lv_zphone
        iv_icnum  = lv_icnum
      IMPORTING
        es_info   = ls_info.

    server->response->set_status( code = 200 reason = 'OK' ).
    lv_content_type = 'application/json'.

    "设置返回格式Json
    server->response->set_content_type( 'application/json' ).

    "返回Body数据
    server->response->set_cdata(
   /ui2/cl_json=>serialize( data        = ls_info
                            compress    = abap_true
                            pretty_name = /ui2/cl_json=>pretty_mode-camel_case ) ).


  ENDMETHOD.

3.事务代码SICF定义REST服务,配置用户密码(需要认证可不配置),添加处理类

登录认证方式

SU01新增后台接口访问用户,用户类型:S(服务)

 若对方采用默认的BASIC Auth权限认证登录方式,提供接口访问用户密码给用户。

对请求添加Basic Authentication账号密码,否则无法获取

对方访问的时候会弹出用户密码登录这是SAP认证方式,如何避免弹窗呢?

如果SICF服务配置了后台访问的用户密码,安全会话设置了不受限制,则不受弹窗。但是安全考虑还是需要对方采用basic auth认证访问登录,也可以再加token认证匹配双层check。sicf此处用户密码不配置如果给外围系统访问的话。

SAP这边默认是basic认证方式, 如果访问方接口调用直接在对方那边维护好咱们给的接口用户就不会弹出来了 。当然你还可以用别的认证方式甚至免密登录都可以。你可以试试postman然后维护好你的密码就肯定不再需要认证了。

注意因为对方basis认证登录所以sicf用户密码不配置,代码中的TOKEN获取MD5加密匹配验证的逻辑可跟对方协商是否需要。

SICF发布服务名称:ZRS_GDDH_DATA

处理器清单配置ZCL_QUERY_GDDH_DATA

保存激活.测试服务

SICF发布服务给对方的各个系统访问地址,对方对各个环境访问地址和端口等做防火墙网络策略申请:各个环境访问的域名或IP地址,及对应端口,还要用RFC方式还是HTTP方式访问可能涉及到不同的端口访问。以及生产环境主服务器(负载均衡),还是各个应用节点服务器访问申请可以跟BASIS确认好。

最后使用SOUPUI 或者POSTMAN接口调用联通测试

token验证处理

token有放body的有放header的,取token再调业务接口的模式跟对方协商好就行。 

 token方式http处理,token放请求header中处理方式:

"拼接后续要使用的tken
  CONCATENATE 'Bearer' re_login-access_token INTO re_login-access_token SEPARATED BY space.
  lo_http_client->request->if_http_entity~set_content_type( content_type = 'application/json' ).
  lo_http_client->request->if_http_entity~set_header_field( name = 'Accept' value = 'application/json' ).
  lo_http_client->request->set_method( if_http_request=>co_request_method_post ).
 
 
  lo_http_client->request->if_http_entity~set_header_field( name   = 'Authorization' value = re_login-access_token ).

token放在请求body中的处理方式如下:

简单一点可以理解为,双方约定用一个相同的accesskey访问密钥字符串(比如XXXX-2025),做MD5方式加密,对方JAVA端给这个值放入到请求头. sap端对这个请求获取JAVA传入的请求头属性,然后也给“XXXX-2025”这个字符串加密,看跟JAVA传入的请求头里面的数据是否一致,一致就通过,否则就报错

双方约定好一个accesskey访问密钥字符串,用MD5加密,再从对方传过来的请求BODY中获取token是否匹配一致,加密后的值比对,一致就返回,否则就报错。

*lv_token = '7815696ecbf1c96fuwuj2025'.
**加密
*    TRY.
*        lv_algo = 'MD5'.         " MD5, SHA1, SHA256, SHA384, SHA512
*        cl_abap_message_digest=>calculate_hash_for_char( EXPORTING if_algorithm = lv_algo
*                                                                   if_data      = lv_token
*                                                         IMPORTING
*                                                                   ef_hashstring = lv_md5 ).
*      CATCH cx_root INTO DATA(e_text).
*    ENDTRY.

*    "将Json转换成内表
*    TRY.
*
*        CALL METHOD /ui2/cl_json=>deserialize(
*          EXPORTING
*            json        = lv_body
*            pretty_name = /ui2/cl_json=>pretty_mode-camel_case
*          CHANGING
*            data        = ls_result ).
*
*        IF ls_result-data IS NOT INITIAL.
*          READ TABLE ls_result-data INTO DATA(ls_data) INDEX 1.
*          IF sy-subrc EQ 0.
*            IF ls_data-token NE lv_md5.
*              server->response->set_status( code = 400 reason = 'Token Authority Check failed' ).
*              server->response->set_cdata(
*                      /ui2/cl_json=>serialize( data        = ls_info
*                                               compress    = abap_true
*                                               pretty_name = /ui2/cl_json=>pretty_mode-camel_case ) ).
*              EXIT.
*            ENDIF.
*          ENDIF.
*        ENDIF.
*
*      CATCH cx_sy_move_cast_error.
*      CATCH cx_root.
*    ENDTRY..

另外,关于登录身份认证,JAVA等外围系统有白名单的概念,就是有一些外部接口是不需要做登录认证的,都是通过token的方式,比如签名方式。一些外部接口就不需要走登录认证。 比如有个接口要给非公司内部的系统调用,访问用户都没有内部员工账号,不能登录公司统一的IDM/authing用户单点登录统一身份认证平台。 

相关文章:

  • 【Vue】组件及组件化, 组件生命周期
  • enumerable 和 configurable 属性详解
  • 海康对接摄像头
  • Docker快速构建并启动Springboot程序,快速发布和上线/
  • 前端基础知识ES6系列 - 03(数组新增了哪些扩展)
  • 论文阅读:强化预训练
  • html打印合同模板
  • 人工智能AI
  • 《零基础读懂新能源汽车》——V2G/电池梯次利用/氢能源生态级技术拆解与商业预言
  • Java八股文——Spring「SpringBoot 篇」
  • 全连接层和卷积层
  • 学习threejs,使用TSL计算粒子鼠标特效
  • 【AI时代速通QT】第一节:C++ Qt 简介与环境安装
  • uniapp 腾讯云 COS 访问控制实战(细粒度权限管理)
  • PHP7+MySQL5.6 雪里开简易预约制访客管理系统V1.0
  • IGBT(绝缘栅双极型晶体管)简介
  • Vue3 + TypeScript + Element Plus 表格行按钮不触发 row-click 事件、不触发勾选行,只执行按钮的 click 事件
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的新零售融合路径研究
  • elementui使用Layout布局-对齐方式
  • 零基础玩转物联网-串口转以太网模块如何快速实现与HTTP服务器通信
  • 哈尔滨排名seo公司/数字营销服务商seo
  • 做网站赚钱一般做什么/企业网站的作用有哪些
  • web前端自己做网站/微信营销号
  • 打开陕西建设厅网站/深圳网络推广代运营
  • 网站建设优化服务精英/百度竞价员
  • 设计师效果图网站/seo外包公司多少钱