user.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. package addresslist
  2. import (
  3. "strings"
  4. "github.com/silenceper/wechat/v2/util"
  5. )
  6. const (
  7. // userSimpleListURL 获取部门成员
  8. userSimpleListURL = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist"
  9. // userGetURL 读取成员
  10. userGetURL = "https://qyapi.weixin.qq.com/cgi-bin/user/get"
  11. // userListIDURL 获取成员ID列表
  12. userListIDURL = "https://qyapi.weixin.qq.com/cgi-bin/user/list_id"
  13. // convertToOpenIDURL userID转openID
  14. convertToOpenIDURL = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid"
  15. // convertToUserIDURL openID转userID
  16. convertToUserIDURL = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid"
  17. )
  18. type (
  19. // UserSimpleListResponse 获取部门成员响应
  20. UserSimpleListResponse struct {
  21. util.CommonError
  22. UserList []*UserList
  23. }
  24. // UserList 部门成员
  25. UserList struct {
  26. UserID string `json:"userid"`
  27. Name string `json:"name"`
  28. Department []int `json:"department"`
  29. OpenUserID string `json:"open_userid"`
  30. }
  31. )
  32. // UserSimpleList 获取部门成员
  33. // @see https://developer.work.weixin.qq.com/document/path/90200
  34. func (r *Client) UserSimpleList(departmentID int) ([]*UserList, error) {
  35. var (
  36. accessToken string
  37. err error
  38. )
  39. if accessToken, err = r.GetAccessToken(); err != nil {
  40. return nil, err
  41. }
  42. var response []byte
  43. if response, err = util.HTTPGet(strings.Join([]string{
  44. userSimpleListURL,
  45. util.Query(map[string]interface{}{
  46. "access_token": accessToken,
  47. "department_id": departmentID,
  48. }),
  49. }, "?")); err != nil {
  50. return nil, err
  51. }
  52. result := &UserSimpleListResponse{}
  53. err = util.DecodeWithError(response, result, "UserSimpleList")
  54. if err != nil {
  55. return nil, err
  56. }
  57. return result.UserList, nil
  58. }
  59. // UserGetResponse 获取部门成员响应
  60. type UserGetResponse struct {
  61. util.CommonError
  62. UserID string `json:"userid"` // 成员UserID。对应管理端的帐号,企业内必须唯一。不区分大小写,长度为1~64个字节;第三方应用返回的值为open_userid
  63. Name string `json:"name"` // 成员名称;第三方不可获取,调用时返回userid以代替name;代开发自建应用需要管理员授权才返回;对于非第三方创建的成员,第三方通讯录应用也不可获取;未返回name的情况需要通过通讯录展示组件来展示名字
  64. Department []int `json:"department"` // 成员所属部门id列表,仅返回该应用有查看权限的部门id;成员授权模式下,固定返回根部门id,即固定为1。对授权了“组织架构信息”权限的第三方应用,返回成员所属的全部部门id
  65. Order []int `json:"order"` // 部门内的排序值,默认为0。数量必须和department一致,数值越大排序越前面。值范围是[0, 2^32)。成员授权模式下不返回该字段
  66. Position string `json:"position"` // 职务信息;代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  67. Mobile string `json:"mobile"` // 手机号码,代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  68. Gender string `json:"gender"` // 性别。0表示未定义,1表示男性,2表示女性。代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段。注:不可获取指返回值0
  69. Email string `json:"email"` // 邮箱,代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  70. BizMail string `json:"biz_mail"` // 企业邮箱,代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  71. IsLeaderInDept []int `json:"is_leader_in_dept"` // 表示在所在的部门内是否为部门负责人,数量与department一致;第三方通讯录应用或者授权了“组织架构信息-应用可获取企业的部门组织架构信息-部门负责人”权限的第三方应用可获取;对于非第三方创建的成员,第三方通讯录应用不可获取;上游企业不可获取下游企业成员该字段
  72. DirectLeader []string `json:"direct_leader"` // 直属上级UserID,返回在应用可见范围内的直属上级列表,最多有五个直属上级;第三方通讯录应用或者授权了“组织架构信息-应用可获取可见范围内成员组织架构信息-直属上级”权限的第三方应用可获取;对于非第三方创建的成员,第三方通讯录应用不可获取;上游企业不可获取下游企业成员该字段;代开发自建应用不可获取该字段
  73. Avatar string `json:"avatar"` // 头像url。 代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  74. ThumbAvatar string `json:"thumb_avatar"` // 头像缩略图url。第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  75. Telephone string `json:"telephone"` // 座机。代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  76. Alias string `json:"alias"` // 别名;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  77. Address string `json:"address"` // 地址。代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  78. OpenUserid string `json:"open_userid"` // 全局唯一。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的,最多64个字节。仅第三方应用可获取
  79. MainDepartment int `json:"main_department"` // 主部门,仅当应用对主部门有查看权限时返回。
  80. Extattr struct {
  81. Attrs []struct {
  82. Type int `json:"type"`
  83. Name string `json:"name"`
  84. Text struct {
  85. Value string `json:"value"`
  86. } `json:"text,omitempty"`
  87. Web struct {
  88. URL string `json:"url"`
  89. Title string `json:"title"`
  90. } `json:"web,omitempty"`
  91. } `json:"attrs"`
  92. } `json:"extattr"` // 扩展属性,代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  93. Status int `json:"status"` // 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业。 已激活代表已激活企业微信或已关注微信插件(原企业号)。未激活代表既未激活企业微信又未关注微信插件(原企业号)。
  94. QrCode string `json:"qr_code"` // 员工个人二维码,扫描可添加为外部联系人(注意返回的是一个url,可在浏览器上打开该url以展示二维码);代开发自建应用需要管理员授权且成员oauth2授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  95. ExternalPosition string `json:"external_position"` // 对外职务,如果设置了该值,则以此作为对外展示的职务,否则以position来展示。代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  96. ExternalProfile struct {
  97. ExternalCorpName string `json:"external_corp_name"`
  98. WechatChannels struct {
  99. Nickname string `json:"nickname"`
  100. Status int `json:"status"`
  101. } `json:"wechat_channels"`
  102. ExternalAttr []struct {
  103. Type int `json:"type"`
  104. Name string `json:"name"`
  105. Text struct {
  106. Value string `json:"value"`
  107. } `json:"text,omitempty"`
  108. Web struct {
  109. URL string `json:"url"`
  110. Title string `json:"title"`
  111. } `json:"web,omitempty"`
  112. Miniprogram struct {
  113. Appid string `json:"appid"`
  114. Pagepath string `json:"pagepath"`
  115. Title string `json:"title"`
  116. } `json:"miniprogram,omitempty"`
  117. } `json:"external_attr"`
  118. } `json:"external_profile"` // 成员对外属性,字段详情见对外属性;代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
  119. }
  120. // UserGet 获取部门成员
  121. // @see https://developer.work.weixin.qq.com/document/path/90196
  122. func (r *Client) UserGet(UserID string) (*UserGetResponse, error) {
  123. var (
  124. accessToken string
  125. err error
  126. )
  127. if accessToken, err = r.GetAccessToken(); err != nil {
  128. return nil, err
  129. }
  130. var response []byte
  131. if response, err = util.HTTPGet(
  132. strings.Join([]string{
  133. userGetURL,
  134. util.Query(map[string]interface{}{
  135. "access_token": accessToken,
  136. "department_id": UserID,
  137. }),
  138. }, "?")); err != nil {
  139. return nil, err
  140. }
  141. result := &UserGetResponse{}
  142. err = util.DecodeWithError(response, result, "UserGet")
  143. if err != nil {
  144. return nil, err
  145. }
  146. return result, nil
  147. }
  148. // UserListIDRequest 获取成员ID列表请求
  149. type UserListIDRequest struct {
  150. Cursor string `json:"cursor"`
  151. Limit int `json:"limit"`
  152. }
  153. // UserListIDResponse 获取成员ID列表响应
  154. type UserListIDResponse struct {
  155. util.CommonError
  156. NextCursor string `json:"next_cursor"`
  157. DeptUser []*DeptUser `json:"dept_user"`
  158. }
  159. // DeptUser 用户-部门关系
  160. type DeptUser struct {
  161. UserID string `json:"userid"`
  162. Department int `json:"department"`
  163. }
  164. // UserListID 获取成员ID列表
  165. // see https://developer.work.weixin.qq.com/document/path/96067
  166. func (r *Client) UserListID(req *UserListIDRequest) (*UserListIDResponse, error) {
  167. var (
  168. accessToken string
  169. err error
  170. )
  171. if accessToken, err = r.GetAccessToken(); err != nil {
  172. return nil, err
  173. }
  174. var response []byte
  175. if response, err = util.PostJSON(strings.Join([]string{
  176. userListIDURL,
  177. util.Query(map[string]interface{}{
  178. "access_token": accessToken,
  179. }),
  180. }, "?"), req); err != nil {
  181. return nil, err
  182. }
  183. result := &UserListIDResponse{}
  184. if err = util.DecodeWithError(response, result, "UserListID"); err != nil {
  185. return nil, err
  186. }
  187. return result, nil
  188. }
  189. type (
  190. // convertToOpenIDRequest userID转openID请求
  191. convertToOpenIDRequest struct {
  192. UserID string `json:"userid"`
  193. }
  194. // convertToOpenIDResponse userID转openID响应
  195. convertToOpenIDResponse struct {
  196. util.CommonError
  197. OpenID string `json:"openid"`
  198. }
  199. )
  200. // ConvertToOpenID userID转openID
  201. // see https://developer.work.weixin.qq.com/document/path/90202
  202. func (r *Client) ConvertToOpenID(userID string) (string, error) {
  203. var (
  204. accessToken string
  205. err error
  206. )
  207. if accessToken, err = r.GetAccessToken(); err != nil {
  208. return "", err
  209. }
  210. var response []byte
  211. if response, err = util.PostJSON(strings.Join([]string{
  212. convertToOpenIDURL,
  213. util.Query(map[string]interface{}{
  214. "access_token": accessToken,
  215. }),
  216. }, "?"), &convertToOpenIDRequest{
  217. UserID: userID,
  218. }); err != nil {
  219. return "", err
  220. }
  221. result := &convertToOpenIDResponse{}
  222. if err = util.DecodeWithError(response, result, "ConvertToOpenID"); err != nil {
  223. return "", err
  224. }
  225. return result.OpenID, nil
  226. }
  227. type (
  228. // convertToUserIDRequest openID转userID请求
  229. convertToUserIDRequest struct {
  230. OpenID string `json:"openid"`
  231. }
  232. // convertToUserIDResponse openID转userID响应
  233. convertToUserIDResponse struct {
  234. util.CommonError
  235. UserID string `json:"userid"`
  236. }
  237. )
  238. // ConvertToUserID openID转userID
  239. // see https://developer.work.weixin.qq.com/document/path/90202
  240. func (r *Client) ConvertToUserID(openID string) (string, error) {
  241. var (
  242. accessToken string
  243. err error
  244. )
  245. if accessToken, err = r.GetAccessToken(); err != nil {
  246. return "", err
  247. }
  248. var response []byte
  249. if response, err = util.PostJSON(strings.Join([]string{
  250. convertToUserIDURL,
  251. util.Query(map[string]interface{}{
  252. "access_token": accessToken,
  253. }),
  254. }, "?"), &convertToUserIDRequest{
  255. OpenID: openID,
  256. }); err != nil {
  257. return "", err
  258. }
  259. result := &convertToUserIDResponse{}
  260. if err = util.DecodeWithError(response, result, "ConvertToUserID"); err != nil {
  261. return "", err
  262. }
  263. return result.UserID, nil
  264. }