package QQ::weixin::work; =pod =encoding utf8 =head1 Name QQ::weixin::work =head1 DESCRIPTION 腾讯ä¼ä¸šå¾®ä¿¡->æœåŠ¡ç«¯API接å£æ–‡æ¡£ =head1 SYNOPSIS L<https://work.weixin.qq.com/api/doc/90000/90135/90664> æœåŠ¡ç«¯API开放了丰富的能力接å£ï¼Œå¼€å‘者å¯ä»¥å€ŸåŠ©æŽ¥å£èƒ½åŠ›ï¼Œå®žçŽ°ä¼ä¸šæœåŠ¡åŠä¼ä¸šå¾®ä¿¡çš„集æˆã€‚ 支æŒçš„能力,通过目录导航å¯ä»¥å¿«é€Ÿé¢„è§ˆï¼Œç›®å½•æ ‘æŒ‰åŠŸèƒ½å—èšåˆå½’类,如通讯录管ç†ã€æ¶ˆæ¯æŽ¨é€ç‰ã€‚ =head2 ä¼ä¸šå¼€å‘æµç¨‹å¦‚下: 1.获å–ä¼ä¸šå¾®ä¿¡çš„CorpIDå’ŒCorpSecret:ä¼ä¸šå¾®ä¿¡ç®¡ç†å‘˜é€šè¿‡å¯ç”¨åº”用,获å–CorpIDå’ŒCorpSecret 2.å¼€å‘对接相关接å£ï¼šå¼€å‘测试应用,对接ä¼ä¸šå¾®ä¿¡æŽ¥å£ =head1 æƒé™è¯´æ˜Ž æ¯ä¸ªåº”用有ä¸åŒçš„secret,代表了对应用的ä¸åŒæƒé™ =cut use strict; use Encode; use LWP::UserAgent; use JSON; use utf8; our $VERSION = '0.06'; our @EXPORT = qw/ gettoken getcallbackip get_api_domain_ip /; =head1 FUNCTION =head2 gettoken(corpid,corpsecrect); 获å–ACCESS_TOKEN =head3 SYNOPSIS L<https://developer.work.weixin.qq.com/document/path/91039> =head3 å‚数说明 å‚æ•° å¿…é¡» 说明 corpid 是 ä¼ä¸šID,获å–æ–¹å¼å‚考:术è¯è¯´æ˜Ž-corpid L<https://work.weixin.qq.com/api/doc/90000/90135/91039#14953/corpid> corpsecret 是 应用的å‡è¯å¯†é’¥ï¼ŒèŽ·å–æ–¹å¼å‚考:术è¯è¯´æ˜Ž-secret L<https://work.weixin.qq.com/api/doc/90000/90135/91039#14953/secret> =head3 RETURN 返回结果 { "errcode": 0, "errmsg": "ok", "access_token": "accesstoken000001", "expires_in": 7200 } =head4 RETURN å‚数说明 å‚æ•° 说明 errcode 出错返回ç ,为0表示æˆåŠŸï¼Œéž0表示调用失败 errmsg 返回ç æç¤ºè¯ access_token 获å–到的å‡è¯ï¼Œæœ€é•¿ä¸º512å—节 expires_in å‡è¯çš„有效时间(秒) =head3 注æ„事项 å¼€å‘者需è¦ç¼“å˜access_token,用于åŽç»æŽ¥å£çš„调用(注æ„:ä¸èƒ½é¢‘ç¹è°ƒç”¨gettoken接å£ï¼Œå¦åˆ™ä¼šå—到频率拦截)。当access_token失效或过期时,需è¦é‡æ–°èŽ·å–。 access_token的有效期通过返回的expires_inæ¥ä¼ 达,æ£å¸¸æƒ…况下为7200秒(2å°æ—¶ï¼‰ï¼Œæœ‰æ•ˆæœŸå†…é‡å¤èŽ·å–返回相åŒç»“果,过期åŽèŽ·å–会返回新的access_token。 由于ä¼ä¸šå¾®ä¿¡æ¯ä¸ªåº”用的access_token是彼æ¤ç‹¬ç«‹çš„,所以进行缓å˜æ—¶éœ€è¦åŒºåˆ†åº”用æ¥è¿›è¡Œå˜å‚¨ã€‚ access_token至少ä¿ç•™512å—节的å˜å‚¨ç©ºé—´ã€‚ ä¼ä¸šå¾®ä¿¡å¯èƒ½ä¼šå‡ºäºŽè¿è¥éœ€è¦ï¼Œæå‰ä½¿access_token失效,开å‘者应实现access_token失效时é‡æ–°èŽ·å–的逻辑。 =cut sub gettoken { if ( @_ && $_[0] && $_[1] ) { my $corpid = $_[0]; my $corpsecret = $_[1]; my $ua = LWP::UserAgent->new; $ua->timeout(30); $ua->env_proxy; my $response = $ua->get("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$corpid&corpsecret=$corpsecret"); if ($response->is_success) { return from_json($response->decoded_content,{utf8 => 1, allow_nonref => 1}); } } return 0; } =head2 getcallbackip(access_token); 获å–ä¼ä¸šå¾®ä¿¡æœåŠ¡å™¨çš„ip段 =head3 SYNOPSIS L<https://developer.work.weixin.qq.com/document/path/90930#33-获å–ä¼ä¸šå¾®ä¿¡æœåŠ¡å™¨çš„ip段> ä¼ä¸šå¾®ä¿¡åœ¨å›žè°ƒä¼ä¸šæŒ‡å®šçš„URL时,是通过特定的IPå‘é€å‡ºåŽ»çš„。如果ä¼ä¸šéœ€è¦åšé˜²ç«å¢™é…置,那么å¯ä»¥é€šè¿‡è¿™ä¸ªæŽ¥å£èŽ·å–到所有相关的IP段。IP段有å˜æ›´å¯èƒ½ï¼Œå½“IP段å˜æ›´æ—¶ï¼Œæ–°æ—§IP段会åŒæ—¶ä¿ç•™ä¸€æ®µæ—¶é—´ã€‚建议ä¼ä¸šæ¯å¤©å®šæ—¶æ‹‰å–IP段,更新防ç«å¢™è®¾ç½®ï¼Œé¿å…å› IP段å˜æ›´å¯¼è‡´ç½‘络ä¸é€šã€‚ =head3 å‚数说明 å‚æ•° å¿…é¡» 说明 access_token 是 调用接å£å‡è¯ =head3 RETURN 返回结果 { "ip_list":[ "182.254.11.176", "182.254.78.66" ], "errcode":0, "errmsg":"ok" } =head4 RETURN å‚数说明 å‚æ•° 类型 说明 ip_list StringArray ä¼ä¸šå¾®ä¿¡å›žè°ƒçš„IP段 errcode int 错误ç ,0表示æˆåŠŸï¼Œéž0表示调用失败 errmsg string 错误信æ¯ï¼Œè°ƒç”¨å¤±è´¥ä¼šæœ‰ç›¸å…³çš„错误信æ¯è¿”回 =head3 注æ„事项 若调用失败,会返回errcodeåŠerrmsg(判æ–是å¦è°ƒç”¨å¤±è´¥ï¼Œæ ¹æ®errcodeå˜åœ¨å¹¶ä¸”值éž0) æ ¹æ®errcode值éž0,判æ–调用失败。以下是access_token过期的返回示例: { "ip_list":[], "errcode":42001, "errmsg":"access_token expired, hint: [1576065934_28_e0fae07666aa64636023c1fa7e8f49a4], from ip: 9.30.0.138, more info at https://open.work.weixin.qq.com/devtool/query?e=42001" } =cut sub getcallbackip { if ( @_ && $_[0] ) { my $access_token = $_[0]; my $ua = LWP::UserAgent->new; $ua->timeout(30); $ua->env_proxy; my $response = $ua->get("https://qyapi.weixin.qq.com/cgi-bin/getcallbackip?access_token=$access_token"); if ($response->is_success) { return from_json($response->decoded_content,{utf8 => 1, allow_nonref => 1}); } } return 0; } =head2 get_api_domain_ip(access_token); 获å–ä¼ä¸šå¾®ä¿¡API域åIP段 =head3 SYNOPSIS L<https://developer.work.weixin.qq.com/document/path/92520> API域åIPå³qyapi.weixin.qq.com的解æžåœ°å€ï¼Œç”±å¼€å‘者调用ä¼ä¸šå¾®ä¿¡ç«¯çš„接入IP。如果ä¼ä¸šéœ€è¦åšé˜²ç«å¢™é…置,那么å¯ä»¥é€šè¿‡è¿™ä¸ªæŽ¥å£èŽ·å–到所有相关的IP段。IP段有å˜æ›´å¯èƒ½ï¼Œå½“IP段å˜æ›´æ—¶ï¼Œæ–°æ—§IP段会åŒæ—¶ä¿ç•™ä¸€æ®µæ—¶é—´ã€‚建议ä¼ä¸šæ¯å¤©å®šæ—¶æ‹‰å–IP段,更新防ç«å¢™è®¾ç½®ï¼Œé¿å…å› IP段å˜æ›´å¯¼è‡´ç½‘络ä¸é€šã€‚ =head3 å‚数说明 å‚æ•° å¿…é¡» 说明 access_token 是 调用接å£å‡è¯ =head3 RETURN 返回结果 { "ip_list":[ "182.254.11.176", "182.254.78.66" ], "errcode":0, "errmsg":"ok" } =head4 RETURN å‚数说明 å‚æ•° 类型 说明 ip_list StringArray ä¼ä¸šå¾®ä¿¡å›žè°ƒçš„IP段 errcode int 错误ç ,0表示æˆåŠŸï¼Œéž0表示调用失败 errmsg string 错误信æ¯ï¼Œè°ƒç”¨å¤±è´¥ä¼šæœ‰ç›¸å…³çš„错误信æ¯è¿”回 =head3 注æ„事项 若调用失败,会返回errcodeåŠerrmsg(判æ–是å¦è°ƒç”¨å¤±è´¥ï¼Œæ ¹æ®errcodeå˜åœ¨å¹¶ä¸”值éž0) æ ¹æ®errcode值éž0,判æ–调用失败。以下是access_token过期的返回示例: { "ip_list":[], "errcode":42001, "errmsg":"access_token expired, hint: [1576065934_28_e0fae07666aa64636023c1fa7e8f49a4], from ip: 9.30.0.138, more info at https://open.work.weixin.qq.com/devtool/query?e=42001" } =cut sub get_api_domain_ip { if ( @_ && $_[0] ) { my $access_token = $_[0]; my $ua = LWP::UserAgent->new; $ua->timeout(30); $ua->env_proxy; my $response = $ua->get("https://qyapi.weixin.qq.com/cgi-bin/get_api_domain_ip?access_token=$access_token"); if ($response->is_success) { return from_json($response->decoded_content,{utf8 => 1, allow_nonref => 1}); } } return 0; } 1; __END__