github.com/chanxuehong/wechat@v0.0.0-20230222024006-36f0325263cd/mp/user/list.go (about)

     1  package user
     2  
     3  import (
     4  	"net/url"
     5  
     6  	"github.com/chanxuehong/wechat/mp/core"
     7  )
     8  
     9  // 获取用户列表返回的数据结构
    10  type ListResult struct {
    11  	TotalCount int `json:"total"` // 关注该公众账号的总用户数
    12  	ItemCount  int `json:"count"` // 拉取的OPENID个数, 最大值为10000
    13  
    14  	Data struct {
    15  		OpenIdList []string `json:"openid,omitempty"`
    16  	} `json:"data"` // 列表数据, OPENID的列表
    17  
    18  	// 拉取列表的最后一个用户的OPENID, 如果 next_openid == "" 则表示没有了用户数据
    19  	NextOpenId string `json:"next_openid"`
    20  }
    21  
    22  // List 获取用户列表.
    23  //
    24  //	NOTE: 每次最多能获取 10000 个用户, 可以多次指定 nextOpenId 来获取以满足需求, 如果 nextOpenId == "" 则表示从头获取
    25  func List(clt *core.Client, nextOpenId string) (rslt *ListResult, err error) {
    26  	var incompleteURL string
    27  	if nextOpenId == "" {
    28  		incompleteURL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token="
    29  	} else {
    30  		incompleteURL = "https://api.weixin.qq.com/cgi-bin/user/get?next_openid=" + url.QueryEscape(nextOpenId) + "&access_token="
    31  	}
    32  
    33  	var result struct {
    34  		core.Error
    35  		ListResult
    36  	}
    37  	if err = clt.GetJSON(incompleteURL, &result); err != nil {
    38  		return
    39  	}
    40  	if result.ErrCode != core.ErrCodeOK {
    41  		err = &result.Error
    42  		return
    43  	}
    44  	rslt = &result.ListResult
    45  	return
    46  }
    47  
    48  // =====================================================================================================================
    49  
    50  // UserIterator
    51  //
    52  //	iter, err := NewUserIterator(clt, "NextOpenId")
    53  //	if err != nil {
    54  //	    // TODO: 增加你的代码
    55  //	}
    56  //
    57  //	for iter.HasNext() {
    58  //	    openids, err := iter.NextPage()
    59  //	    if err != nil {
    60  //	        // TODO: 增加你的代码
    61  //	    }
    62  //	    // TODO: 增加你的代码
    63  //	}
    64  type UserIterator struct {
    65  	clt *core.Client
    66  
    67  	lastListResult *ListResult
    68  	nextPageCalled bool
    69  }
    70  
    71  func (iter *UserIterator) TotalCount() int {
    72  	return iter.lastListResult.TotalCount
    73  }
    74  
    75  func (iter *UserIterator) HasNext() bool {
    76  	if !iter.nextPageCalled {
    77  		return iter.lastListResult.ItemCount > 0 || iter.lastListResult.NextOpenId != ""
    78  	}
    79  	return iter.lastListResult.NextOpenId != ""
    80  }
    81  
    82  func (iter *UserIterator) NextPage() (openIdList []string, err error) {
    83  	if !iter.nextPageCalled {
    84  		iter.nextPageCalled = true
    85  		openIdList = iter.lastListResult.Data.OpenIdList
    86  		return
    87  	}
    88  
    89  	rslt, err := List(iter.clt, iter.lastListResult.NextOpenId)
    90  	if err != nil {
    91  		return
    92  	}
    93  
    94  	iter.lastListResult = rslt
    95  
    96  	openIdList = rslt.Data.OpenIdList
    97  	return
    98  }
    99  
   100  // NewUserIterator 获取用户遍历器, 从 nextOpenId 开始遍历, 如果 nextOpenId == "" 则表示从头遍历.
   101  func NewUserIterator(clt *core.Client, nextOpenId string) (iter *UserIterator, err error) {
   102  	// 逻辑上相当于第一次调用 UserIterator.NextPage,
   103  	// 因为第一次调用 UserIterator.HasNext 需要数据支撑, 所以提前获取了数据
   104  	rslt, err := List(clt, nextOpenId)
   105  	if err != nil {
   106  		return
   107  	}
   108  
   109  	iter = &UserIterator{
   110  		clt:            clt,
   111  		lastListResult: rslt,
   112  		nextPageCalled: false,
   113  	}
   114  	return
   115  }