SAP ABAP 动态结构实现发送企业微信应用消息
企业微信官方接口:
应用支持推送文本、图片、视频、文件、图文等类型。
请求方式:POST(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
大概思路:
1. 封装调用企业微信函数 SE37 :ZWECHAT_SEND_MESSAGE_MSGTYPE
注:
a. I_MSGTYPE 参数值 作为动态值新增到表结构,构造企业微信API body
b. I_MESSAGE 参数值 为json格式的消息内容
2.程序调用 ZWECHAT_SEND_MESSAGE_MSGTYPE,传入处理过的 I_MESSAGE
代码实现:
1. SE37 :ZWECHAT_SEND_MESSAGE_MSGTYPE
1 FUNCTION zwechat_send_message_msgtype. 2 *"---------------------------------------------------------------------- 3 *"*"本地接口: 4 *" IMPORTING 5 *" VALUE(I_MESSAGE) TYPE STRING 6 *" VALUE(I_MSGTYPE) TYPE STRING 7 *" EXPORTING 8 *" VALUE(E_MESSAGE) TYPE STRING 9 *" TABLES 10 *" T_TOUSER STRUCTURE ZWECHAT_NOTIFYER OPTIONAL 11 *" T_TOPARTY STRUCTURE ZWECHAT_NOTIFYER OPTIONAL 12 *" T_TOTAG STRUCTURE ZWECHAT_NOTIFYER OPTIONAL 13 *"---------------------------------------------------------------------- 14 15 16 DATA:url TYPE string VALUE 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token='."接口地址 17 DATA:i_agentid TYPE string VALUE '小程序ID'. 18 DATA:i_corpid TYPE string VALUE '公司的ID'. 19 DATA:i_corpsecret TYPE string VALUE '企业应用secret'. 20 21 DATA:access_token TYPE string. 22 DATA:lv_client TYPE REF TO if_http_client. 23 24 DATA:l_touser TYPE string. 25 DATA:l_toparty TYPE string. 26 DATA:l_totag TYPE string. 27 28 29 "http通用参数 30 TYPES:BEGIN OF ty_common, 31 touser TYPE string, "成员ID列表,多个接收者用‘|’分隔,最多支持1000个 32 toparty TYPE string, "部门ID列表,多个接收者用‘|’分隔,最多支持100个 33 totag TYPE string, "标签ID列表,多个接收者用‘|’分隔,最多支持100个 34 msgtype TYPE string, "消息类型 35 agentid TYPE string, "企业应用的id 36 safe TYPE i, "表示是否是保密消息,0表示可对外分享,1表示不能分享且内容显示水印,默认为0 37 enable_id_trans TYPE i, "是否开启id转译,0表示否,1表示是,默认0。仅第三方应用需要用到,企业自建应用可以忽略 38 enable_duplicate_check TYPE i, "是否开启重复消息检查,0表示否,1表示是,默认0 39 duplicate_check_interval TYPE i, "是否重复消息检查的时间间隔,默认1800s,最大不超过4小时 40 END OF ty_common. 41 42 43 "http返回 44 TYPES:BEGIN OF t_record, 45 errcode TYPE string, 46 errmsg TYPE string, 47 END OF t_record. 48 49 DATA:json TYPE string. 50 DATA:record TYPE t_record. 51 DATA:common TYPE ty_common. 52 53 DATA:ev_data(6000) TYPE c."返回 54 DATA:lv_json TYPE string. 55 56 57 *--动态创建结构和表 58 DATA: 59 dref_str TYPE REF TO data, 60 struct_type TYPE REF TO cl_abap_structdescr, 61 elem_type TYPE REF TO cl_abap_elemdescr, 62 comp_tab TYPE cl_abap_structdescr=>component_table WITH HEADER LINE. 63 64 "动态创建结构类型 65 * struct_type ?= cl_abap_structdescr=>describe_by_name( 'ZTPP200' ). "根据名称获取系统创建好的结构 66 struct_type ?= cl_abap_structdescr=>describe_by_data( common ). "根据程序中定义的结构,创建结构类型 67 68 "获取该结构类型中,结构组件(字段) 69 comp_tab[] = struct_type->get_components( )."组成结构体的各个字段组件 70 71 "扩展结构字段 72 elem_type ?= cl_abap_elemdescr=>get_string( ). 73 comp_tab-name = i_msgtype. "新增成员的类型名称,消息类型 74 comp_tab-type = elem_type. "新增成员的类型对象 75 INSERT comp_tab INTO comp_tab INDEX 1. 76 77 78 "根据新的组件创建结构类型 79 struct_type = cl_abap_structdescr=>create( comp_tab[] ). 80 "根据结构类型,创建结构对象 81 CREATE DATA dref_str TYPE HANDLE struct_type. 82 83 FIELD-SYMBOLS: <is_str> TYPE any. 84 "引用创建的动态构造 85 IF dref_str IS BOUND. 86 ASSIGN dref_str->* TO <is_str>. 87 ENDIF. 88 89 90 91 *--基本检查 92 CHECK ( t_touser[] IS NOT INITIAL 93 OR t_toparty[] IS NOT INITIAL 94 OR t_totag[] IS NOT INITIAL ) AND i_message IS NOT INITIAL. 95 96 97 CLEAR:l_touser,l_toparty,l_totag,lv_json,ev_data,record,json. 98 99 *--通知人员处理 100 DATA(l_lines) = lines( t_touser ). 101 102 LOOP AT t_touser. "人员ID 103 IF sy-tabix = l_lines. 104 l_touser = t_touser-notifyer && l_touser && ''. 105 ELSE. 106 l_touser = l_touser && '|' && t_touser-notifyer. 107 ENDIF. 108 ENDLOOP. 109 110 CLEAR:l_lines. 111 l_lines = lines( t_totag ). 112 LOOP AT t_toparty. "部门ID 113 IF sy-tabix = l_lines. 114 l_toparty = t_toparty-notifyer && l_toparty && ''. 115 ELSE. 116 l_toparty = l_toparty && '|' && t_toparty-notifyer. 117 ENDIF. 118 ENDLOOP. 119 120 CLEAR:l_lines. 121 l_lines = lines( t_totag ). 122 LOOP AT t_totag. "标签ID 123 IF sy-tabix = l_lines. 124 l_totag = t_totag-notifyer && l_totag && ''. 125 ELSE. 126 l_totag = l_totag && '|' && t_totag-notifyer. 127 ENDIF. 128 ENDLOOP. 129 130 131 *--message处理 132 FIELD-SYMBOLS:<fs_msg_value> TYPE any. 133 "用指针<fs_msg_value>指向工作区<is_str>中的一个字段,字段名为i_msgtype. 134 ASSIGN COMPONENT i_msgtype OF STRUCTURE <is_str> TO <fs_msg_value>. 135 "给指针指向的字段赋值 136 <fs_msg_value> = i_message. "接口message传值 137 138 *--通用参数处理 139 MOVE-CORRESPONDING VALUE ty_common( touser = l_touser 140 toparty = l_toparty 141 totag = l_totag 142 msgtype = i_msgtype 143 agentid = i_agentid 144 enable_duplicate_check = 1 ) TO <is_str>. "开启重复消息检查 145 146 "abap结构转json 147 /ui2/cl_json=>serialize( EXPORTING data = <is_str> 148 pretty_name = 'L' "空大写,L小写,X驼峰,Y增强驼峰 149 RECEIVING r_json = lv_json ). 150 151 152 "特殊字符反转义 153 lv_json = replace( val = lv_json 154 sub = '\"' 155 with = '"' 156 occ = '0' ). 157 158 lv_json = replace( val = lv_json 159 sub = '\\' 160 with = '\' 161 occ = '0' ). 162 163 lv_json = replace( val = lv_json 164 sub = '"{' 165 with = '{' 166 occ = '0' ). 167 168 lv_json = replace( val = lv_json 169 sub = '}"' 170 with = '}' 171 occ = '0' ). 172 173 174 175 *--http请求处理 176 CALL FUNCTION 'ZWECHAT_GET_ACCESS_TOKEN' "获取token 177 EXPORTING 178 i_corpid = i_corpid 179 i_corpsecret = i_corpsecret 180 IMPORTING 181 o_access_token = access_token. 182 183 184 url = url && access_token. 185 186 187 CALL METHOD cl_http_client=>create_by_url 188 EXPORTING 189 url = url 190 IMPORTING 191 client = lv_client 192 EXCEPTIONS 193 argument_not_found = 1 194 plugin_not_active = 2 195 internal_error = 3 196 OTHERS = 4. 197 198 199 lv_client->request->set_header_field( name = '~request_method' value = 'POST' )."调用方法get OR post 200 lv_client->request->set_content_type( 'application/json' ). 201 202 "传入参数json格式 203 lv_client->request->set_cdata( lv_json ). 204 205 206 CALL METHOD lv_client->send( 207 EXCEPTIONS 208 http_communication_failure = 1 209 http_invalid_state = 2 ). 210 * Prepare client-receive: 211 212 CALL METHOD lv_client->receive 213 EXCEPTIONS 214 http_communication_failure = 1 215 http_invalid_state = 2 216 http_processing_failed = 3 217 OTHERS = 4. 218 219 * Get HTML: 220 ev_data = lv_client->response->get_cdata( )."返回值 221 222 json = ev_data. 223 224 /ui2/cl_json=>deserialize( EXPORTING json = json CHANGING data = record ). 225 226 e_message = record-errmsg. 227 228 229 ENDFUNCTION.
2.程序调用 ZWECHAT_SEND_MESSAGE_MSGTYPE
1 FORM frm_send_wechat . 2 3 DATA:BEGIN OF ls_textcard, 4 title TYPE string VALUE 'FDPPM质量预警监控平台推送', 5 description TYPE string, 6 url TYPE string VALUE 'https://exmail.qq.com/login', 7 btntxt TYPE string VALUE '更多', 8 END OF ls_textcard. 9 10 DATA:lv_json TYPE string. 11 DATA:e_message TYPE string. 12 CLEAR:lv_json. 13 14 DATA:l_week LIKE scal-week. 15 16 17 SELECT ad_smtpadr FROM zmm_t_0003 INTO TABLE @DATA(lt_wechat_tag) WHERE status = 'W' AND zprogram = @sy-repid. 18 19 CHECK lt_wechat_tag[] IS NOT INITIAL. 20 21 CALL FUNCTION 'DATE_GET_WEEK' 22 EXPORTING 23 date = s_budat-low 24 IMPORTING 25 week = l_week 26 * EXCEPTIONS 27 * DATE_INVALID = 1 28 * OTHERS = 2 29 . 30 IF sy-subrc <> 0. 31 * Implement suitable error handling here 32 ENDIF. 33 34 CONDENSE lv_count_v. 35 CONDENSE lv_count_m. 36 37 IF s_budat-high IS INITIAL. 38 s_budat-high = sy-datum. 39 ENDIF. 40 41 ls_textcard-description = '<div class=\"gray\">' && s_budat-low && '-' && s_budat-high && '</div>'. 42 ls_textcard-description = ls_textcard-description && '<div class=\"normal\">' && '【' && l_week+0(4) && 'W' && l_week+4(2) && '】'. 43 ls_textcard-description = ls_textcard-description && '供应商来料不良情况汇总-Week</div>'. 44 ls_textcard-description = ls_textcard-description && '<div class=\"normal\">未达标供应商个数:' && lv_count_v && '</div>'. 45 ls_textcard-description = ls_textcard-description && '<div class=\"normal\">不良物料号个数:' && lv_count_m && '</div>'. 46 ls_textcard-description = ls_textcard-description && '<div class=\"highlight\">具体明细已发送至您的邮箱</div>'. 47 48 "abap数据转json 49 CLEAR:lv_json. 50 /ui2/cl_json=>serialize( EXPORTING data = ls_textcard 51 pretty_name = 'L' "空大写,L小写,X驼峰,Y增强驼峰 52 RECEIVING r_json = lv_json ). 53 54 lv_json = replace( val = lv_json sub = '\"' with = '"' occ = '0' ). 55 lv_json = replace( val = lv_json sub = '\\' with = '\' occ = '0' ). 56 57 CALL FUNCTION 'ZWECHAT_SEND_MESSAGE_MSGTYPE' 58 EXPORTING 59 i_message = lv_json 60 i_msgtype = 'textcard' 61 IMPORTING 62 e_message = e_message 63 TABLES 64 t_totag = lt_wechat_tag[]. 65 66 ENDFORM.
3.实现效果:企业微信通知