企微通讯录管理功能对接

AI摘要
本文分享企业微信通讯录管理的PHP代码实现,重点涵盖部门与员工管理的核心API接口。包括部门创建/更新/删除/查询,以及用户增删改查、批量操作等关键功能,提供可直接使用的服务类代码示例。

写在前面

企微通讯录管理包含:成员、部门、标签、回调通知等功能api…
其中成员【user】和部门【department】,也就是员工管理相关和组织架构管理相关比较通用,故此记录相关功能接口,以备不时之需!
企微通讯录管理功能简图:

企微通讯录管理功能对接

核心代码

组织架构管理

<?php namespace App\Service; use Illuminate\Support\Facades\Http; class OpenWeChatDepartmentService extends OpenWeChatService { /** * 创建部门 * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=ACCESS_TOKEN * 入参: * { * "name": "广州研发中心", * "name_en": "RDGZ", * "parentid": 1, * "id": 2 * "order": 1, * } * @param $name | 部门名 * @param $parentId | 上级id * @param null $id | 部门id:32位整型, 不传递企业微信自动生成 * @param null $nameEn | 部门英文/别名 * @param int $order | 有效范围:[0, 2^32) * @return mixed => $response: {"errcode":0,"errmsg":"created","id":2} * @throws \Exception */ public function create($name, $parentId, $id = null, $nameEn = null, $order = 1) { $data['name'] = $name; $data['parentid'] = $parentId; $data['order'] = $order; if ($id) { $data['id'] = $id; } if ($nameEn) { $data['name_en'] = $nameEn; } $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token' . $this->getAccessToken(); try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('创建部门【/department/create】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('创建部门【/department/create】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 更新部门 * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token=ACCESS_TOKEN * 入参: * { * "id": 2 * "name": "广州研发中心", * "name_en": "RDGZ", * "parentid": 1, * "order": 1, * } * @param $id | 部门id:32位整型, 不传递企业微信自动生成 * @param null $name | 部门名 * @param null $nameEn | 部门英文/别名 * @param null $parentId | 上级id * @param int $order | 有效范围:[0, 2^32) * @return mixed => $response: {"errcode":0,"errmsg":"updated"} * @throws \Exception */ public function update($id, $name = null, $nameEn = null, $parentId = null, $order = 1) { $data['id'] = $id; $data['order'] = $order; if ($name) { $data['name'] = $name; } if ($nameEn) { $data['name_en'] = $nameEn; } if ($parentId) { $data['parentid'] = $parentId; } $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token' . $this->getAccessToken(); try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('更新部门【/department/update】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('更新部门【/department/update】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 删除部门 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=ACCESS_TOKEN&id=ID * @param $id * @return mixed => $response: {"errcode":0,"errmsg":"deleted"} * @throws \Exception */ public function delete($id) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=' . $this->getAccessToken() . '&id=' . $id; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('删除部门【/department/delete】详情失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('删除部门【/department/delete】详情失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取部门列表 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=ID * @param null $id * @return mixed => $response: {"errcode":0,"errmsg":"ok","department":[{"id":2,"name":"广州研发中心","name_en":"RDGZ","department_leader":["zhangsan","lisi"],"parentid":1,"order":10}]} * @throws \Exception */ public function list($id = null) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=' . $this->getAccessToken(); if ($id) { $url .= '&id=' . $id; } try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取部门列表【/department/list】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取部门列表【/department/list】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取子部门ID列表 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/simplelist?access_token=ACCESS_TOKEN&id=ID * @param null $id * @return mixed => $response: {"errcode":0,"errmsg":"ok","department_id":[{"id":2,"parentid":1,"order":10}]} * @throws \Exception */ public function simpleList($id = null) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/simplelist?access_token=' . $this->getAccessToken(); if ($id) { $url .= '&id=' . $id; } try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取子部门ID列表【/department/simplelist】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取子部门ID列表【/department/simplelist】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取部门详情 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/get?access_token=ACCESS_TOKEN&id=ID * @param $id * @return mixed => $response: {"errcode":0,"errmsg":"ok","department":{"id":2,"name":"广州研发中心","name_en":"RDGZ","department_leader":["zhangsan","lisi"],"parentid":1,"order":10}} * @throws \Exception */ public function get($id) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/get?access_token=' . $this->getAccessToken() . '&id=' . $id; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取部门详情【/department/get】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取部门详情【/department/get】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } } 

员工管理

<?php namespace App\Service; use Illuminate\Support\Facades\Http; class OpenWeChatUserService extends OpenWeChatService { /** * 新增用户 * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=ACCESS_TOKEN * 通常使用常见参数即可:userid,name,alias,mobile,department,gender,email,biz_mail,main_department * 入参: * { * "userid": "zhangsan", //必须,全局唯一 * "name": "张三", //必须 * "alias": "jackzhang", * "mobile": "+86 13800000000", //全局唯一,mobile/email二者不能同时为空 * "department": [1, 2], //必须 * "order": [10, 40], * "position": "产品经理", * "gender": "1", * "email": "zhangsan@gzdev.com", //全局唯一,mobile/email二者不能同时为空 * "biz_mail": "zhangsan@qyycs2.wecom.work", * "is_leader_in_dept": [1, 0], * "direct_leader": ["lisi"], * "enable": 1, * "avatar_mediaid": "2-G6nrLmr5EC3MNb_-zL1dDdzkd0p7cNliYu9V5w7o8K0", * "telephone": "020-123456", * "address": "广州市海珠区新港中路", * "main_department": 1, * "extattr": {}, * "to_invite": true, * "external_position": "高级产品经理", * "external_profile": {} * } * @param $data * @return mixed => $response: {"errcode":0,"errmsg":"created"} * @throws \Exception */ public function create($data) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=' . $this->getAccessToken(); try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('新增用户【/user/create】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('新增用户【/user/create】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取用户详情 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID * 如若需要获取员工敏感信息。请使用应用“通讯录同步”的密钥secret * @param $userId * @return mixed => https://developer.work.weixin.qq.com/document/path/90196 * @throws \Exception */ public function get($userId) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=' . $this->getAccessToken() . '&userid=' . $userId; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取用户详情【/user/get】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取用户详情【/user/get】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 更新用户 * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=ACCESS_TOKEN * 通常使用常见参数即可:userid,name,alias,mobile,department,gender,email,biz_mail,main_department * 入参: * { * "userid": "zhangsan", //必须,全局唯一 * "name": "张三", //必须 * "alias": "jackzhang", * "mobile": "+86 13800000000", //全局唯一,mobile/email二者不能同时为空 * "department": [1, 2], //必须 * "order": [10, 40], * "position": "产品经理", * "gender": "1", * "email": "zhangsan@gzdev.com", //全局唯一,mobile/email二者不能同时为空 * "biz_mail": "zhangsan@qyycs2.wecom.work", * "is_leader_in_dept": [1, 0], * "direct_leader": ["lisi"], * "enable": 1, * "avatar_mediaid": "2-G6nrLmr5EC3MNb_-zL1dDdzkd0p7cNliYu9V5w7o8K0", * "telephone": "020-123456", * "address": "广州市海珠区新港中路", * "main_department": 1, * "extattr": {}, * "external_position": "高级产品经理", * "external_profile": {} * } * @param $data * @return mixed => $response: {"errcode":0,"errmsg":"updated"} * @throws \Exception */ public function update($data) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=' . $this->getAccessToken(); try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('更新用户【/user/update】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('更新用户【/user/update】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 删除用户 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/delete?access_token=ACCESS_TOKEN&userid=USERID * @param $userId * @return mixed => $response: {"errcode":0,"errmsg":"deleted"} * @throws \Exception */ public function delete($userId) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/delete?access_token=' . $this->getAccessToken() . '&userid=' . $userId; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('删除用户【/user/delete】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('删除用户【/user/delete】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 批量删除 * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete?access_token=ACCESS_TOKEN * @param $userIdList * @return mixed => $response: {"errcode":0,"errmsg":"deleted"} * @throws \Exception */ public function batchdelete($userIdList) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete?access_token=' . $this->getAccessToken(); $data = [ 'useridlist' => $userIdList, ]; try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('批量删除用户【/user/batchdelete】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('批量删除用户【/user/batchdelete】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取部门成员 * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID * @param $departmentId | 必填:根据部门id获取 * @return mixed => $response: {"errcode":0,"errmsg":"ok","userlist":[{"userid":"zhangsan","name":"张三","department":[1,2],"open_userid":"xxxxxx"}]} * @throws \Exception */ public function getUserSimpleList($departmentId) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=' . $this->getAccessToken() . '&department_id=' . $departmentId; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取部门成员【/user/simplelist】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取部门成员【/user/simplelist】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取成员列表(返回完整字段) * 请求方式:GET(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID * @param $departmentId | 必填:根据部门id获取 * @return mixed => https://developer.work.weixin.qq.com/document/path/90201 * @throws \Exception */ public function getUserList($departmentId) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=' . $this->getAccessToken() . '&department_id=' . $departmentId; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取成员列表【/user/list】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取成员列表【/user/list】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 【按需】userid与openid互换 * 请求方式:POST(HTTPS) * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token=ACCESS_TOKEN */ public function convertToOpenId() { } /** * 【按需】登录二次验证 * 请求方式:GET(HTTPS) * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?access_token=ACCESS_TOKEN&userid=USERID */ public function authSuccess() { } /** * 【按需】邀请成员 * 请求方式:POST(HTTPS) * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/batch/invite?access_token=ACCESS_TOKEN */ public function invite() { } /** * 获取加入企业二维码 * 请求方式:GET(HTTPS) * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/corp/get_join_qrcode?access_token=ACCESS_TOKEN&size_type=SIZE_TYPE * @param int $sizeType | 1: 171 x 171; 2: 399 x 399; 3: 741 x 741; 4: 2052 x 2052 * @return mixed => $response: {"errcode":0,"errmsg":"ok","join_qrcode":"https://work.weixin.qq.com/wework_admin/genqrcode?action=join&vcode=3db1fab03118ae2aa1544cb9abe84&r=hb_share_api_mjoin&qr_size=3"} * @throws \Exception */ public function getJoinQrcode($sizeType = 1) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/corp/get_join_qrcode?access_token=' . $this->getAccessToken() . '&size_type=' . $sizeType; try { $response = Http::get($url)->json(); } catch (\Exception $e) { throw new \Exception('获取加入企业二维码【/corp/get_join_qrcode】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取加入企业二维码【/corp/get_join_qrcode】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 手机号获取userid * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=ACCESS_TOKEN * @param $mobile * @return mixed => $response: {"errcode":0,"errmsg":"ok","userid":"zhangsan"} * @throws \Exception */ public function getUserId($mobile) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=' . $this->getAccessToken(); $data = [ 'mobile' => $mobile, ]; try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('手机号获取userid【/user/getuserid】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('手机号获取userid【/user/getuserid】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 邮箱获取userid * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/get_userid_by_email?access_token=ACCESS_TOKEN * @param $email * @param int $emailType | 1-企业邮箱(默认);2-个人邮箱 * @return mixed => $response: {"errcode":0,"errmsg":"ok","userid":"zhangsan"} * @throws \Exception */ public function getUserIdByEmail($email, $emailType = 1) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/get_userid_by_email?access_token=' . $this->getAccessToken(); $data = [ 'email' => $email, 'email_type' => $emailType, ]; try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('邮箱获取userid【/user/get_userid_by_email】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('邮箱获取userid【/user/get_userid_by_email】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } /** * 获取成员ID列表 * 请求方式:POST(HTTPS) * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token=ACCESS_TOKEN * @param string $cursor 上一次返回的查询的游标next_cursor,首次为空(一般成员<=10000,不需要传参) * @param int $limit * @return mixed => $response: {"errcode":0,"errmsg":"ok","next_cursor":"aaaaaaaaa","dept_user":[{"userid":"zhangsan","department":1}]} * @throws \Exception */ public function getUserIds($cursor = null, $limit = 10000) { $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token=' . $this->getAccessToken(); $data['limit'] = $limit; if ($cursor) { $data['cursor'] = $cursor; } try { $response = Http::post($url, $data)->json(); } catch (\Exception $e) { throw new \Exception('获取成员ID列表【/user/list_id】失败,请求失败:' . $url); } if (isset($response['errcode']) && $response['errcode'] <> 0) { throw new \Exception('获取成员ID列表【/user/list_id】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE)); } return $response; } } 

其他

附:博客:企微登录功能对接

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 8

大兄弟,你贴的也太全了吧cv直接可以用了啊

1年前 评论

注释写这么好不要命啦 !

1年前 评论
一念沧海一念桑田 1年前

纯请教,为什么会喜欢用这种写法啊?我现在就遇到了以前的前辈代码里面在请求底层对异常做这种再封装的处理,导致后面我想要对不同的异常进行判断处理的时候还得去解析这个字符串,真是难受。本来我直接对返回的 $response JSON 字符串进行解析后判断里面的 code 就行了,结果链接成不一样的字符串之后还得去解析这玩意,而且这个 ErrorMessage 很显然也不会直接返给前端给用户看吧,所以这样处理的意义是什么呢

throw new \Exception('创建部门【/department/create】失败,响应:' . json_encode($response, JSON_UNESCAPED_UNICODE));
1年前 评论
snakelis 1年前
Ranger9527 (作者) 1年前
Ranger9527 (作者) 1年前
itdream

注释写的不错

1年前 评论