ABAP呼叫阿里雲介面-簡訊服務-HTTP協議及簽名(abap版本)
阿新 • • 發佈:2021-01-31
阿里雲介面文件請參考官網地址
https://help.aliyun.com/document_detail/56189.html?spm=a2c4g.11186623.6.669.65fe7e6aztgHDF
此處僅介紹使用ABAP完成阿里雲簡訊服務簽名請求的完成。
第一步:請求引數
1. abap 生成的uuid為32位不帶“-”
2. 特殊格式時間戳需要拼接
CONSTANTS: c_accesssecret TYPE string VALUE 'testSecret&', c_accesskeyid TYPE string VALUE 'testId'. *& 1. 填充引數 " 1.1 系統引數 GET TIME STAMP FIELD lv_timestampsap. WRITE lv_timestampsap TO lv_timestampjava USING EDIT MASK lv_timestampformat TIME ZONE '0'. TRY . lv_uuid = cl_system_uuid=>create_uuid_c32_static( ). CATCH cx_uuid_error. ENDTRY. APPEND VALUE #( key = 'SignatureMethod' value = 'HMAC-SHA1' ) TO lt_parameter. APPEND VALUE #( key = 'SignatureNonce' value = lv_uuid ) TO lt_parameter. APPEND VALUE #( key = 'AccessKeyId' value = c_accesskeyid ) TO lt_parameter. APPEND VALUE #( key = 'SignatureVersion' value = '1.0' ) TO lt_parameter. APPEND VALUE #( key = 'Timestamp' value = lv_timestampjava ) TO lt_parameter. " 1.2 業務引數 APPEND VALUE #( key = 'Action' value = 'SendSms' ) TO lt_parameter. APPEND VALUE #( key = 'Version' value = '2017-05-25' ) TO lt_parameter. APPEND VALUE #( key = 'RegionId' value = 'cn-hangzhou' ) TO lt_parameter. APPEND VALUE #( key = 'PhoneNumbers' value = '15300000001' ) TO lt_parameter. APPEND VALUE #( key = 'SignName' value = '阿里雲簡訊測試專用') TO lt_parameter. APPEND VALUE #( key = 'TemplateParam' value = '{"customer":"test"}' ) TO lt_parameter. APPEND VALUE #( key = 'TemplateCode' value = 'SMS_71390007' ) TO lt_parameter.
第二步:根據引數Key排序(順序)
" 2.1 根據引數Key排序(順序)
SORT lt_parameter BY key.
第三步:構造待簽名的請求串
1. sap自帶的escape function 含pop特殊規則,不用再做替換
" 2.2 拼接URL編碼後的引數值 LOOP AT lt_parameter INTO ls_parameter. lv_sortquerystring_temp = lv_sortquerystring_temp && '&' && escape( val = ls_parameter-key format = cl_abap_format=>e_uri_full ) && '=' && escape( val = ls_parameter-value format = cl_abap_format=>e_uri_full ). ENDLOOP. " 2.3 特殊URL編碼 POP特殊的一種規則,即在一般的URLEncode後再增加三種字元替換 "使用escap format cl_abap_format=>e_uri_full 時滿足最終條件不用如下轉換 *REPLACE ALL OCCURRENCES OF '+' IN lv_sortquerystring_temp WITH '%20'. *REPLACE ALL OCCURRENCES OF '*' IN lv_sortquerystring_temp WITH '%2A'. *REPLACE ALL OCCURRENCES OF '%7E' IN lv_sortquerystring_temp WITH '~'. lv_sortquerystring = lv_sortquerystring_temp. SHIFT lv_sortquerystring LEFT DELETING LEADING '&'."移除第一個& " 2.4. 按POP的簽名規則拼接成最終的待簽名串 lv_sortquerystring = 'GET' && '&' && escape( val = '/' format = cl_abap_format=>e_uri_full ) && '&' && escape( val = lv_sortquerystring format = cl_abap_format=>e_uri_full ) .
第四步:簽名
1. 簽名使用HmacSHA1演算法返回的Base64加密字串,並作url編碼
" 3.1 設定簽名 key lo_cl_abap_hmac = cl_abap_hmac=>get_instance( if_key = cl_abap_hmac=>string_to_xstring( if_input = c_accesssecret ) ). " 3.2 生成簽名 " 3.2 生成簽名 TRY. lo_cl_abap_hmac->final( EXPORTING if_data = cl_abap_hmac=>string_to_xstring( if_input = lv_sortquerystring ) IMPORTING ef_hmacb64string = lv_signature ) . CATCH cx_abap_message_digest . ENDTRY. " 3.2 最終生成的簽名也要做特殊URL編碼 lv_signature = escape( val = lv_signature format = cl_abap_format=>e_uri_full ).
第五步:增加簽名結果到請求引數中,傳送請求。
*& 4. 生成最終請求url
lv_url = 'http://dysmsapi.aliyuncs.com/?Signature=' && lv_signature && lv_sortquerystring_temp.
DATA: lv_out_put TYPE string.
lv_out_put = lv_out_put && 'SignatureNonce:' && cl_bcs_convert=>gc_crlf && lv_uuid && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'Timestamp:' && cl_bcs_convert=>gc_crlf && lv_timestampjava && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'sortedQueryString:' && cl_bcs_convert=>gc_crlf && lv_sortquerystring && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'signature:' && cl_bcs_convert=>gc_crlf && lv_signature && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'URL:' && cl_bcs_convert=>gc_crlf && lv_url && cl_bcs_convert=>gc_crlf.
cl_demo_text=>display_string( lv_out_put ).
ps:
1. 使用function escape 可以使用不同的format, cl_abap_format=>e_uri_full 符合要求的,同樣還有其它格式如cl_abap_format=>e_url_full和java示例中的url 編碼效果一致,需要再做pop特殊替換
2. 如果沒有function escape,可以使用方法cl_http_utility=>if_http_utility~escape_url,問題是該方法url編碼後的字元為小寫,不符合當前要求,另外編碼規則的不同點暫時發現的為"(",")“,“+”,“*”。
3. 暫留後續封裝
DATA: lv_char_str TYPE char1024,
lt_result TYPE match_result_tab,
ls_result TYPE match_result.
" url encodeing
lv_char_str = cl_http_utility=>if_http_utility~escape_url( iv_urlstring ).
FIND ALL OCCURRENCES OF REGEX '%..' IN lv_char_str RESULTS lt_result.
LOOP AT lt_result INTO ls_result.
TRANSLATE lv_char_str+ls_result-offset(ls_result-length) TO UPPER CASE.
ENDLOOP.
"該方法不會轉換()
REPLACE ALL OCCURRENCES OF '(' IN lv_char_str WITH '%28'.
REPLACE ALL OCCURRENCES OF ')' IN lv_char_str WITH '%29'.
" 特殊URL編碼 POP特殊的一種規則,即在一般的URLEncode後再增加三種字元替換
* REPLACE ALL OCCURRENCES OF '+' IN lv_char_str WITH '%20'.
* REPLACE ALL OCCURRENCES OF '*' IN lv_char_str WITH '%2A'.
REPLACE ALL OCCURRENCES OF '%7E' IN lv_char_str WITH '~'.
附加完整的Java簽名Demo程式碼
TYPES: BEGIN OF ty_parameter,
key TYPE string,
value TYPE string,
END OF ty_parameter.
DATA: lo_cl_abap_hmac TYPE REF TO cl_abap_hmac.
DATA: lv_signature TYPE string,
lv_sortquerystring TYPE string,
lv_sortquerystring_temp TYPE string.
DATA: lt_parameter TYPE TABLE OF ty_parameter,
ls_parameter TYPE ty_parameter.
DATA: lv_timestampsap TYPE timestamp,
lv_timestampformat TYPE char30 VALUE '____-__-__T__:__:__Z',
lv_timestampjava TYPE char30,
lv_uuid TYPE char36.
DATA: lv_url TYPE string.
CONSTANTS: c_accesssecret TYPE string VALUE 'testSecret&',
c_accesskeyid TYPE string VALUE 'testId'.
*& 1. 填充引數
" 1.1 系統引數
GET TIME STAMP FIELD lv_timestampsap.
WRITE lv_timestampsap TO lv_timestampjava USING EDIT MASK lv_timestampformat TIME ZONE '0'.
TRY .
lv_uuid = cl_system_uuid=>create_uuid_c32_static( ).
CATCH cx_uuid_error.
ENDTRY.
APPEND VALUE #( key = 'SignatureMethod' value = 'HMAC-SHA1' ) TO lt_parameter.
APPEND VALUE #( key = 'SignatureNonce' value = lv_uuid ) TO lt_parameter.
APPEND VALUE #( key = 'AccessKeyId' value = c_accesskeyid ) TO lt_parameter.
APPEND VALUE #( key = 'SignatureVersion' value = '1.0' ) TO lt_parameter.
APPEND VALUE #( key = 'Timestamp' value = lv_timestampjava ) TO lt_parameter.
" 1.2 業務引數
APPEND VALUE #( key = 'Action' value = 'SendSms' ) TO lt_parameter.
APPEND VALUE #( key = 'Version' value = '2017-05-25' ) TO lt_parameter.
APPEND VALUE #( key = 'RegionId' value = 'cn-hangzhou' ) TO lt_parameter.
APPEND VALUE #( key = 'PhoneNumbers' value = '15300000001' ) TO lt_parameter.
APPEND VALUE #( key = 'SignName' value = '阿里雲簡訊測試專用' ) TO lt_parameter.
APPEND VALUE #( key = 'TemplateParam' value = '{"customer":"test"}') TO lt_parameter.
APPEND VALUE #( key = 'TemplateCode' value = 'SMS_71390007' ) TO lt_parameter.
*& 2. 構造待簽名的請求串
" 2.1 根據引數Key排序(順序)
SORT lt_parameter BY key.
" 2.2 拼接URL編碼後的引數值
LOOP AT lt_parameter INTO ls_parameter.
lv_sortquerystring_temp = lv_sortquerystring_temp && '&' && escape( val = ls_parameter-key format = cl_abap_format=>e_uri_full )
&& '=' && escape( val = ls_parameter-value format = cl_abap_format=>e_uri_full ).
ENDLOOP.
" 2.3 特殊URL編碼 POP特殊的一種規則,即在一般的URLEncode後再增加三種字元替換
"使用escap format cl_abap_format=>e_uri_full 時滿足最終條件不用如下轉換
*REPLACE ALL OCCURRENCES OF '+' IN lv_sortquerystring_temp WITH '%20'.
*REPLACE ALL OCCURRENCES OF '*' IN lv_sortquerystring_temp WITH '%2A'.
*REPLACE ALL OCCURRENCES OF '%7E' IN lv_sortquerystring_temp WITH '~'.
lv_sortquerystring = lv_sortquerystring_temp.
SHIFT lv_sortquerystring LEFT DELETING LEADING '&'."移除第一個&
" 2.4. 按POP的簽名規則拼接成最終的待簽名串
lv_sortquerystring = 'GET' && '&' && escape( val = '/' format = cl_abap_format=>e_uri_full ) && '&'
&& escape( val = lv_sortquerystring format = cl_abap_format=>e_uri_full ) .
*& 3. 生成簽名
" 3.1 設定簽名 key
lo_cl_abap_hmac = cl_abap_hmac=>get_instance( if_key = cl_abap_hmac=>string_to_xstring( if_input = c_accesssecret ) ).
" 3.2 生成簽名
" 3.2 生成簽名
TRY.
lo_cl_abap_hmac->final( EXPORTING if_data = cl_abap_hmac=>string_to_xstring( if_input = lv_sortquerystring )
IMPORTING ef_hmacb64string = lv_signature ) .
CATCH cx_abap_message_digest .
ENDTRY.
" 3.2 最終生成的簽名也要做特殊URL編碼
lv_signature = escape( val = lv_signature format = cl_abap_format=>e_uri_full ).
*& 4. 生成最終請求url
lv_url = 'http://dysmsapi.aliyuncs.com/?Signature=' && lv_signature && lv_sortquerystring_temp.
DATA: lv_out_put TYPE string.
lv_out_put = lv_out_put && 'SignatureNonce:' && cl_bcs_convert=>gc_crlf && lv_uuid && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'Timestamp:' && cl_bcs_convert=>gc_crlf && lv_timestampjava && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'sortedQueryString:' && cl_bcs_convert=>gc_crlf && lv_sortquerystring && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'signature:' && cl_bcs_convert=>gc_crlf && lv_signature && cl_bcs_convert=>gc_crlf.
lv_out_put = lv_out_put && 'URL:' && cl_bcs_convert=>gc_crlf && lv_url && cl_bcs_convert=>gc_crlf.
cl_demo_text=>display_string( lv_out_put ).