SAP上创建合同后,把合同上的甲方、乙方、合同金额、税率等信息需要传输到上上签系统上进行创建法务合同,并让上上签签署合同后把合同状态更新会SAP。
CSDN上有两位朋友写的很详细了,比如:
https://blog.csdn.net/xiefireworks/article/details/124809161
https://blog.csdn.net/BinGeneral/article/details/125270841
但是用这些例子进行测试的过程,也是磕磕碰碰,从上周接手与上上签的对接任务后,前后碰到好几个问题,弄了大概4-5天后,终于测试通过的,以下我把碰到问题过程和具体的做法列下:
1. ABAP上调用API 通过代理服务器
通常,SAP系统是不与外网进行通信的,SAP服务器也安装在DMZ区,所以,为了在ECC上调用公网的API,需要通过内网的代理服务器,方法如下:
把代理服务器的IP 和 端口作为参数,创建http client:
CALL METHOD CL_HTTP_CLIENT=>CREATE_BY_URL
EXPORTING
URL = LV_URL
PROXY_HOST = '223.122.12.26'
PROXY_SERVICE = '8798'
IMPORTING
CLIENT = LO_HTTP_CLIENT
EXCEPTIONS
ARGUMENT_NOT_FOUND = 1
PLUGIN_NOT_ACTIVE = 2
INTERNAL_ERROR = 3
OTHERS = 4.
2. 调用上上签的refresh token 方法'
上上签的Token获取不需要签名,所以比较简单:
REPORT ZZZZZZ5.
*&---------------------------------------------------------------------*
*& Report ZSRM0011
*&
*&---------------------------------------------------------------------*
*&
*& 本程序用于获取API接口的Access Token
*&---------------------------------------------------------------------*
DATA: LO_HTTP_CLIENT TYPE REF TO IF_HTTP_CLIENT,
LO_CONV TYPE REF TO CL_ABAP_CONV_IN_CE,
LV_REQUEST_BODY TYPE STRING,
LV_URL TYPE STRING,
LV_XSTR TYPE XSTRING,
LV_STR TYPE STRING,
LV_RESULT TYPE STRING.
DATA: LC_CODE TYPE STRING,
LC_MSG TYPE STRING,
LV_CODE TYPE SY-SUBRC,
LV_CODEC TYPE C LENGTH 10,
LV_ERR TYPE STRING,
LV_MSG TYPE STRING.
DATA: LV_GRANT_TYPE TYPE STRING,
LV_CLIENT_ID TYPE STRING,
LV_CLIENT_SECRET TYPE STRING,
LV_TIMESTAMP TYPE STRING,
LV_USERNAME TYPE STRING,
LV_PASSWORD TYPE STRING,
LV_SCOPE TYPE STRING,
LV_SIGN TYPE STRING.
DATA: LV_DATE(10) TYPE C,
LV_TIME(8) TYPE C,
LV_USERNAME2 TYPE STRING,
LV_TIMESTAMP_TMP TYPE TIMESTAMP,
LV_HASH_MD5 TYPE HASH160 .
DATA: LT_RESULT_TAB TYPE TABLE OF STRING WITH HEADER LINE.
DATA: LV_LINE_DATA TYPE STRING,
LV_KEY TYPE STRING,
LV_TEXT TYPE STRING.
TYPES: BEGIN OF TY_RESULT,
VALUE TYPE STRING,
TEXT TYPE STRING,
END OF TY_RESULT.
DATA: LT_RESULT TYPE TABLE OF TY_RESULT,
LS_RESULT TYPE TY_RESULT.
LV_URL = 'https://api.bestsign.info/api/oa2/client-credentials/token'.
"Timestamp
GET TIME STAMP FIELD LV_TIMESTAMP_TMP.
LV_TIMESTAMP = LV_TIMESTAMP_TMP.
WRITE SY-DATUM TO LV_DATE USING EDIT MASK '____-__-__'.
WRITE SY-UZEIT TO LV_TIME USING EDIT MASK '__:__:__'.
CONCATENATE LV_DATE LV_TIME INTO LV_TIMESTAMP SEPARATED BY SPACE.
LV_REQUEST_BODY = '{ "clientId":"1657177378014361488","clientSecret":"5889b85281234b1a80b66fcfdb1e3499" }'.
"密码转换成MD5
CALL FUNCTION 'CALCULATE_HASH_FOR_CHAR'
EXPORTING
ALG = 'MD5'
DATA = LV_PASSWORD
* LENGTH = 0
IMPORTING
HASH = LV_HASH_MD5
EXCEPTIONS
UNKNOWN_ALG = 1
PARAM_ERROR = 2
INTERNAL_ERROR = 3
OTHERS = 4.
IF SY-SUBRC = 0 .
LV_PASSWORD = LV_HASH_MD5 .
ENDIF.
"计算Sign值
CONCATENATE LV_CLIENT_SECRET LV_TIMESTAMP LV_CLIENT_ID LV_USERNAME
LV_PASSWORD LV_GRANT_TYPE LV_CLIENT_SECRET
INTO LV_SIGN.
CALL FUNCTION 'CALCULATE_HASH_FOR_CHAR'
EXPORTING
ALG = 'MD5'
DATA = LV_SIGN
* LENGTH = 0
IMPORTING
HASH = LV_HASH_MD5
EXCEPTIONS
UNKNOWN_ALG = 1
PARAM_ERROR = 2
INTERNAL_ERROR = 3
OTHERS = 4.
IF SY-SUBRC = 0 .
LV_SIGN = LV_HASH_MD5.
ENDIF.
TRANSLATE LV_SIGN TO UPPER CASE.
*******************************************************************************
* 开始调用API
*******************************************************************************
CALL METHOD CL_HTTP_CLIENT=>CREATE_BY_URL
EXPORTING
URL = LV_URL
PROXY_HOST = '211.144.11.22'
PROXY_SERVICE = '11111'
IMPORTING
CLIENT = LO_HTTP_CLIENT
EXCEPTIONS
ARGUMENT_NOT_FOUND = 1
PLUGIN_NOT_ACTIVE = 2
INTERNAL_ERROR = 3
OTHERS = 4.
LO_HTTP_CLIENT->REFRESH_REQUEST( ).
LO_HTTP_CLIENT->REFRESH_RESPONSE( ).
** Set request method to GET or POST
LO_HTTP_CLIENT->REQUEST->SET_METHOD( IF_HTTP_REQUEST=>CO_REQUEST_METHOD_POST ).
LO_HTTP_CLIENT->REQUEST->SET_VERSION( IF_HTTP_ENTITY=>CO_PROTOCOL_VERSION_1_1 ).
*
CALL METHOD LO_HTTP_CLIENT->REQUEST->SET_HEADER_FIELD
EXPORTING
NAME = 'Content-Type'
"value = 'multipart/form-data'.
"value = 'text/html;charset=utf-8'. "发送字符串时只能用utf-8编码
VALUE = 'application/json'.
LO_HTTP_CLIENT->REQUEST->SET_CDATA( LV_REQUEST_BODY ).
"Send data
CALL METHOD LO_HTTP_CLIENT->SEND
EXCEPTIONS
HTTP_COMMUNICATION_FAILURE = 1
HTTP_INVALID_STATE = 2.
CLEAR: LV_CODE, LV_ERR.
LO_HTTP_CLIENT->GET_LAST_ERROR(
IMPORTING
CODE = LV_CODE
MESSAGE = LV_ERR ).
IF LV_CODE IS NOT INITIAL.
LO_HTTP_CLIENT->CLOSE( ).
WRITE LV_CODE TO LV_CODEC LEFT-JUSTIFIED NO-SIGN NO-GROUPING.
CONCATENATE LC_CODE LV_CODEC
LC_MSG LV_ERR
INTO LV_MSG SEPARATED BY SPACE.
"MESSAGE e001 WITH lv_msg.
RETURN.
ENDIF.
LO_HTTP_CLIENT->REFRESH_RESPONSE( ).
CALL METHOD LO_HTTP_CLIENT->RECEIVE
EXCEPTIONS
HTTP_COMMUNICATION_FAILURE = 1
HTTP_INVALID_STATE = 2
HTTP_PROCESSING_FAILED = 3.
LO_HTTP_CLIENT->GET_LAST_ERROR(
IMPORTING
CODE = LV_CODE
MESSAGE = LV_ERR ).
IF LV_CODE IS NOT INITIAL.
LO_HTTP_CLIENT->CLOSE( ).
WRITE LV_CODE TO LV_CODEC LEFT-JUSTIFIED NO-SIGN NO-GROUPING.
CONCATENATE LC_CODE LV_CODEC
LC_MSG LV_ERR
INTO LV_MSG SEPARATED BY SPACE.
"MESSAGE e001 WITH lv_msg.
RETURN.
ENDIF.
CLEAR LV_RESULT .
LV_XSTR = LO_HTTP_CLIENT->RESPONSE->GET_DATA( ).
IF SY-SUBRC = 0 .
LO_HTTP_CLIENT->CLOSE( ).
ENDIF.
CALL METHOD CL_ABAP_CONV_IN_CE=>CREATE
EXPORTING
INPUT = LV_XSTR
ENCODING = 'UTF-8'
REPLACEMENT = '?'
IGNORE_CERR = ABAP_TRUE
RECEIVING
CONV = LO_CONV.
TRY.
CALL METHOD LO_CONV->READ
IMPORTING
DATA = LV_STR.
CATCH CX_SY_CONVERSION_CODEPAGE.
CATCH CX_SY_CODEPAGE_CONVERTER_INIT.
CATCH CX_PARAMETER_INVALID_TYPE.
CATCH CX_PARAMETER_INVALID_RANGE.
ENDTRY.
*******************************************************************************
* 返回结果处理
*******************************************************************************
ZUI2_CL_JSON=>DESERIALIZE( EXPORTING JSON = LV_STR CHANGING DATA = LS_RESULT ).
WRITE: /(10) 'Code:',
(10) LV_STR-code,
(16) 'Message:',
(40) LV_STR-message.
"更新数据
if LV_STR-code = '0'.
endif.
message s001 with 'Refresh Token 接口调用成功'.
以上是基础部分,私钥签署文章,请查阅第二部分