From e7fdcf9534186754e08612e05a62a9629dbb9b9c Mon Sep 17 00:00:00 2001 From: GargantuaX Date: Mon, 1 Mar 2021 15:38:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=85=AC=E4=BC=97=E5=8F=B7?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E8=BF=81=E7=A7=BB=EF=BC=8C=E8=8E=B7=E5=8F=96?= =?UTF-8?q?openID=E5=8F=98=E5=8C=96=E6=8E=A5=E5=8F=A3=20(#370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * * 公众号菜单管理,set相关函数,返回btn本身,方便以字面量的方式创建多个菜单,更直观,方便管理 * * golangci-lint fix * * 获取二维码ticket接口没有往上抛接口错误 * * 增加GetOpenID方法,以获取消息的生产用户openID * * 支持公众号账号迁移,获取openID变化接口 * * bugfix * * golint fix * * golint fix --- officialaccount/user/migrate.go | 87 +++++++++++++++++++++++++++++++++ officialaccount/user/user.go | 2 +- util/util.go | 41 ++++++++++++++++ util/util_test.go | 18 +++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 officialaccount/user/migrate.go create mode 100644 util/util.go create mode 100644 util/util_test.go diff --git a/officialaccount/user/migrate.go b/officialaccount/user/migrate.go new file mode 100644 index 0000000..97e63f0 --- /dev/null +++ b/officialaccount/user/migrate.go @@ -0,0 +1,87 @@ +//Package user migrate 用于微信公众号账号迁移,获取openID变化 +//参考文档:https://kf.qq.com/faq/1901177NrqMr190117nqYJze.html +package user + +import ( + "errors" + "fmt" + + "github.com/silenceper/wechat/v2/util" +) + +const ( + changeOpenIDURL = "https://api.weixin.qq.com/cgi-bin/changeopenid" +) + +// ChangeOpenIDResult OpenID迁移变化 +type ChangeOpenIDResult struct { + OriOpenID string `json:"ori_openid"` + NewOpenID string `json:"new_openid"` + ErrMsg string `json:"err_msg,omitempty"` +} + +// ChangeOpenIDResultList OpenID迁移变化列表 +type ChangeOpenIDResultList struct { + util.CommonError + List []ChangeOpenIDResult `json:"result_list"` +} + +// ListChangeOpenIDs 返回指定OpenID变化列表 +// fromAppID 为老账号AppID +// openIDs 为老账号的openID,openIDs限100个以内 +// AccessToken 为新账号的AccessToken +func (user *User) ListChangeOpenIDs(fromAppID string, openIDs ...string) (list *ChangeOpenIDResultList, err error) { + list = &ChangeOpenIDResultList{} + //list.List = make([]ChangeOpenIDResult, 0) + if len(openIDs) > 100 { + err = errors.New("openIDs length must be lt 100") + return + } + + if fromAppID == "" { + err = errors.New("fromAppID is required") + return + } + + accessToken, err := user.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", changeOpenIDURL, accessToken) + var resp []byte + var req struct { + FromAppID string `json:"from_appid"` + OpenidList []string `json:"openid_list"` + } + req.FromAppID = fromAppID + req.OpenidList = append(req.OpenidList, openIDs...) + resp, err = util.PostJSON(uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(resp, list, "ListChangeOpenIDs") + if err != nil { + return + } + + return +} + +// ListAllChangeOpenIDs 返回所有用户OpenID列表 +// fromAppID 为老账号AppID +// openIDs 为老账号的openID +// AccessToken 为新账号的AccessToken +func (user *User) ListAllChangeOpenIDs(fromAppID string, openIDs ...string) (list []ChangeOpenIDResult, err error) { + list = make([]ChangeOpenIDResult, 0) + chunks := util.SliceChunk(openIDs, 100) + for _, chunk := range chunks { + result, err := user.ListChangeOpenIDs(fromAppID, chunk...) + if err != nil { + return list, err + } + list = append(list, result.List...) + } + return +} diff --git a/officialaccount/user/user.go b/officialaccount/user/user.go index d802019..8cffa36 100644 --- a/officialaccount/user/user.go +++ b/officialaccount/user/user.go @@ -139,7 +139,7 @@ func (user *User) ListUserOpenIDs(nextOpenid ...string) (*OpenidList, error) { // ListAllUserOpenIDs 返回所有用户OpenID列表 func (user *User) ListAllUserOpenIDs() ([]string, error) { nextOpenid := "" - openids := []string{} + openids := make([]string, 0) count := 0 for { ul, err := user.ListUserOpenIDs(nextOpenid) diff --git a/util/util.go b/util/util.go new file mode 100644 index 0000000..f18d6fb --- /dev/null +++ b/util/util.go @@ -0,0 +1,41 @@ +package util + +//SliceChunk 用于将字符串切片分块 +func SliceChunk(src []string, chunkSize int) (chunks [][]string) { + total := len(src) + chunks = make([][]string, 0) + if chunkSize < 1 { + chunkSize = 1 + } + if total == 0 { + return + } + + chunkNum := total / chunkSize + if total%chunkSize != 0 { + chunkNum++ + } + + chunks = make([][]string, chunkNum) + + for i := 0; i < chunkNum; i++ { + for j := 0; j < chunkSize; j++ { + offset := i*chunkSize + j + if offset >= total { + return + } + + if chunks[i] == nil { + actualChunkSize := chunkSize + if i == chunkNum-1 && total%chunkSize != 0 { + actualChunkSize = total % chunkSize + } + chunks[i] = make([]string, actualChunkSize) + } + + chunks[i][j] = src[offset] + } + } + + return +} diff --git a/util/util_test.go b/util/util_test.go new file mode 100644 index 0000000..ac4d844 --- /dev/null +++ b/util/util_test.go @@ -0,0 +1,18 @@ +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSliceChunk(t *testing.T) { + src1 := []string{"1", "2", "3", "4", "5"} + assert.Equal(t, [][]string{{"1", "2"}, {"3", "4"}, {"5"}}, SliceChunk(src1, 2)) + assert.Equal(t, [][]string{{"1", "2", "3", "4", "5"}}, SliceChunk(src1, 5)) + assert.Equal(t, [][]string{{"1", "2", "3", "4", "5"}}, SliceChunk(src1, 6)) + assert.Equal(t, [][]string{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}, SliceChunk(src1, 1)) + assert.Equal(t, [][]string{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}, SliceChunk(src1, 0)) + assert.Equal(t, [][]string{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}, SliceChunk(src1, -100)) + assert.Equal(t, [][]string{}, SliceChunk(nil, 5)) +}