user.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package user
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/url"
  7. "github.com/silenceper/wechat/v2/officialaccount/context"
  8. "github.com/silenceper/wechat/v2/util"
  9. )
  10. const (
  11. userInfoURL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN"
  12. userInfoBatchURL = "https://api.weixin.qq.com/cgi-bin/user/info/batchget"
  13. updateRemarkURL = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=%s"
  14. userListURL = "https://api.weixin.qq.com/cgi-bin/user/get"
  15. )
  16. // User 用户管理
  17. type User struct {
  18. *context.Context
  19. }
  20. // NewUser 实例化
  21. func NewUser(context *context.Context) *User {
  22. user := new(User)
  23. user.Context = context
  24. return user
  25. }
  26. // Info 用户基本信息
  27. type Info struct {
  28. util.CommonError
  29. userInfo
  30. }
  31. // 用户基本信息
  32. type userInfo struct {
  33. Subscribe int32 `json:"subscribe"`
  34. OpenID string `json:"openid"`
  35. Nickname string `json:"nickname"`
  36. Sex int32 `json:"sex"`
  37. City string `json:"city"`
  38. Country string `json:"country"`
  39. Province string `json:"province"`
  40. Language string `json:"language"`
  41. Headimgurl string `json:"headimgurl"`
  42. SubscribeTime int32 `json:"subscribe_time"`
  43. UnionID string `json:"unionid"`
  44. Remark string `json:"remark"`
  45. GroupID int32 `json:"groupid"`
  46. TagIDList []int32 `json:"tagid_list"`
  47. SubscribeScene string `json:"subscribe_scene"`
  48. QrScene int `json:"qr_scene"`
  49. QrSceneStr string `json:"qr_scene_str"`
  50. }
  51. // OpenidList 用户列表
  52. type OpenidList struct {
  53. util.CommonError
  54. Total int `json:"total"`
  55. Count int `json:"count"`
  56. Data struct {
  57. OpenIDs []string `json:"openid"`
  58. } `json:"data"`
  59. NextOpenID string `json:"next_openid"`
  60. }
  61. // GetUserInfo 获取用户基本信息
  62. func (user *User) GetUserInfo(openID string) (userInfo *Info, err error) {
  63. var accessToken string
  64. accessToken, err = user.GetAccessToken()
  65. if err != nil {
  66. return
  67. }
  68. uri := fmt.Sprintf(userInfoURL, accessToken, openID)
  69. var response []byte
  70. response, err = util.HTTPGet(uri)
  71. if err != nil {
  72. return
  73. }
  74. userInfo = new(Info)
  75. err = json.Unmarshal(response, userInfo)
  76. if err != nil {
  77. return
  78. }
  79. if userInfo.ErrCode != 0 {
  80. err = fmt.Errorf("GetUserInfo Error , errcode=%d , errmsg=%s", userInfo.ErrCode, userInfo.ErrMsg)
  81. return
  82. }
  83. return
  84. }
  85. // BatchGetUserInfoParams 批量获取用户基本信息参数
  86. type BatchGetUserInfoParams struct {
  87. UserList []BatchGetUserListItem `json:"user_list"` // 需要批量获取基本信息的用户列表
  88. }
  89. // BatchGetUserListItem 需要获取基本信息的用户
  90. type BatchGetUserListItem struct {
  91. OpenID string `json:"openid"` // 用户的标识,对当前公众号唯一
  92. Lang string `json:"lang"` // 国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN
  93. }
  94. // InfoList 用户基本信息列表
  95. type InfoList struct {
  96. util.CommonError
  97. UserInfoList []userInfo `json:"user_info_list"`
  98. }
  99. // BatchGetUserInfo 批量获取用户基本信息
  100. func (user *User) BatchGetUserInfo(params BatchGetUserInfoParams) (*InfoList, error) {
  101. if len(params.UserList) > 100 {
  102. return nil, errors.New("params length must be less than or equal to 100")
  103. }
  104. ak, err := user.GetAccessToken()
  105. if err != nil {
  106. return nil, err
  107. }
  108. uri := fmt.Sprintf("%s?access_token=%s", userInfoBatchURL, ak)
  109. res, err := util.PostJSON(uri, params)
  110. if err != nil {
  111. return nil, err
  112. }
  113. var data InfoList
  114. err = util.DecodeWithError(res, &data, "BatchGetUserInfo")
  115. if err != nil {
  116. return nil, err
  117. }
  118. return &data, nil
  119. }
  120. // UpdateRemark 设置用户备注名
  121. func (user *User) UpdateRemark(openID, remark string) (err error) {
  122. var accessToken string
  123. accessToken, err = user.GetAccessToken()
  124. if err != nil {
  125. return
  126. }
  127. uri := fmt.Sprintf(updateRemarkURL, accessToken)
  128. var response []byte
  129. response, err = util.PostJSON(uri, map[string]string{"openid": openID, "remark": remark})
  130. if err != nil {
  131. return
  132. }
  133. return util.DecodeWithCommonError(response, "UpdateRemark")
  134. }
  135. // ListUserOpenIDs 返回用户列表
  136. func (user *User) ListUserOpenIDs(nextOpenid ...string) (*OpenidList, error) {
  137. accessToken, err := user.GetAccessToken()
  138. if err != nil {
  139. return nil, err
  140. }
  141. uri, _ := url.Parse(userListURL)
  142. q := uri.Query()
  143. q.Set("access_token", accessToken)
  144. if len(nextOpenid) > 0 && nextOpenid[0] != "" {
  145. q.Set("next_openid", nextOpenid[0])
  146. }
  147. uri.RawQuery = q.Encode()
  148. response, err := util.HTTPGet(uri.String())
  149. if err != nil {
  150. return nil, err
  151. }
  152. userlist := OpenidList{}
  153. err = util.DecodeWithError(response, &userlist, "ListUserOpenIDs")
  154. if err != nil {
  155. return nil, err
  156. }
  157. return &userlist, nil
  158. }
  159. // ListAllUserOpenIDs 返回所有用户OpenID列表
  160. func (user *User) ListAllUserOpenIDs() ([]string, error) {
  161. nextOpenid := ""
  162. openids := make([]string, 0)
  163. count := 0
  164. for {
  165. ul, err := user.ListUserOpenIDs(nextOpenid)
  166. if err != nil {
  167. return nil, err
  168. }
  169. openids = append(openids, ul.Data.OpenIDs...)
  170. count += ul.Count
  171. if ul.Total > count {
  172. nextOpenid = ul.NextOpenID
  173. } else {
  174. return openids, nil
  175. }
  176. }
  177. }