张延森 3 vuotta sitten
commit
8839a41f57

+ 34
- 0
api/api.go Näytä tiedosto

@@ -0,0 +1,34 @@
1
+package api
2
+
3
+// BindComponentByPC 构建PC端授权链接
4
+const BindComponentByPC = "https://mp.weixin.qq.com/cgi-bin/componentloginpage"
5
+
6
+// BindComponentByH5 构建移动端授权链接
7
+const BindComponentByH5 = "https://mp.weixin.qq.com/safe/bindcomponent"
8
+
9
+// StartPushTicket 启动票据推送服务
10
+const StartPushTicket = "https://api.weixin.qq.com/cgi-bin/component/api_start_push_ticket"
11
+
12
+// ComponentToken 获取令牌
13
+const ComponentToken = "https://api.weixin.qq.com/cgi-bin/component/api_component_token"
14
+
15
+// CreatePreAuthCode 获取预授权码
16
+const CreatePreAuthCode = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode"
17
+
18
+// QueryAuth 获取授权信息
19
+const QueryAuth = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth"
20
+
21
+// AuthorizerToken 获取/刷新接口调用令牌
22
+const AuthorizerToken = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token"
23
+
24
+// GetAuthorizerInfo 获取授权帐号信息
25
+const GetAuthorizerInfo = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info"
26
+
27
+// GetAuthorizerList 拉取所有已授权的帐号信息
28
+const GetAuthorizerList = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_list"
29
+
30
+// GetAuthorizerOption 获取授权方选项信息
31
+const GetAuthorizerOption = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option"
32
+
33
+// SetAuthorizerOption 设置授权方选项信息
34
+const SetAuthorizerOption = "https://api.weixin.qq.com/cgi-bin/component/api_set_authorizer_option"

+ 12
- 0
entity/authorization_change_notice.go Näytä tiedosto

@@ -0,0 +1,12 @@
1
+package entity
2
+
3
+// AuthorizationChangeNotice 授权变更通知
4
+type AuthorizationChangeNotice struct {
5
+	AppId                        string  `json:"AppId"`
6
+	CreateTime                   float64 `json:"CreateTime"`
7
+	InfoType                     string  `json:"InfoType"`
8
+	AuthorizerAppid              string  `json:"AuthorizerAppid"`
9
+	AuthorizationCode            string  `json:"AuthorizationCode"`
10
+	AuthorizationCodeExpiredTime float64 `json:"AuthorizationCodeExpiredTime"`
11
+	PreAuthCode                  string  `json:"PreAuthCode"`
12
+}

+ 10
- 0
entity/authorization_info.go Näytä tiedosto

@@ -0,0 +1,10 @@
1
+package entity
2
+
3
+// AuthorizationInfo 授权信息
4
+type AuthorizationInfo struct {
5
+	AuthorizerAppId        string     `json:"authorizer_appid"`
6
+	AuthorizerAccessToken  string     `json:"authorizer_access_token"`
7
+	ExpiresIn              float64    `json:"expires_in"`
8
+	AuthorizerRefreshToken string     `json:"authorizer_refresh_token"`
9
+	FuncInfo               []FuncInfo `json:"func_info"`
10
+}

+ 23
- 0
entity/authorizer_info.go Näytä tiedosto

@@ -0,0 +1,23 @@
1
+package entity
2
+
3
+// AuthorizerBasicInfo 公众号/小程序帐号基本信息
4
+type AuthorizerBasicInfo struct {
5
+	AuthorizerAppid string  `json:"authorizer_appid"`
6
+	RefreshToken    string  `json:"refresh_token"`
7
+	AuthTime        float64 `json:"auth_time"`
8
+}
9
+
10
+// AuthorizerInfo 公众号/小程序帐号信息
11
+type AuthorizerInfo struct {
12
+	NickName        string          `json:"nick_name"`
13
+	HeadImg         string          `json:"head_img"`
14
+	ServiceTypeInfo Enum            `json:"service_type_info"`
15
+	VerifyTypeInfo  Enum            `json:"verify_type_info"`
16
+	UserName        string          `json:"user_name"`
17
+	PrincipalName   string          `json:"principal_name"`
18
+	Signature       string          `json:"signature"`
19
+	Alias           string          `json:"alias"`
20
+	BusinessInfo    BusinessInfo    `json:"business_info"`
21
+	QrcodeUrl       string          `json:"qrcode_url"`
22
+	MiniProgramInfo MiniProgramInfo `json:"MiniProgramInfo"`
23
+}

+ 10
- 0
entity/business_info.go Näytä tiedosto

@@ -0,0 +1,10 @@
1
+package entity
2
+
3
+// BusinessInfo 功能的开通状况(0代表未开通,1代表已开通)
4
+type BusinessInfo struct {
5
+	OpenStore float64 `json:"open_store"`
6
+	OpenScan  float64 `json:"open_scan"`
7
+	OpenPay   float64 `json:"open_pay"`
8
+	OpenCard  float64 `json:"open_card"`
9
+	OpenShake float64 `json:"open_shake"`
10
+}

+ 6
- 0
entity/entity.go Näytä tiedosto

@@ -0,0 +1,6 @@
1
+package entity
2
+
3
+// Enum 通用枚举类型
4
+type Enum struct {
5
+	ID float64 `json:"id"`
6
+}

+ 13
- 0
entity/error.go Näytä tiedosto

@@ -0,0 +1,13 @@
1
+package entity
2
+
3
+import "fmt"
4
+
5
+// Error 通用错误
6
+type Error struct {
7
+	Code    float64 `json:"errcode"`
8
+	Message string  `json:"errmsg"`
9
+}
10
+
11
+func (e Error) Error() string {
12
+	return fmt.Sprintf("[%d] - %s", int(e.Code), e.Message)
13
+}

+ 6
- 0
entity/func_info.go Näytä tiedosto

@@ -0,0 +1,6 @@
1
+package entity
2
+
3
+// FuncInfo 权限
4
+type FuncInfo struct {
5
+	FuncscopeCategory Enum `json:"funcscope_category"`
6
+}

+ 23
- 0
entity/mini_program_info.go Näytä tiedosto

@@ -0,0 +1,23 @@
1
+package entity
2
+
3
+// MiniProgramNetwork 小程序配置的合法域名信息
4
+type MiniProgramNetwork struct {
5
+	RequestDomain   []string `json:"RequestDomain"`
6
+	WsRequestDomain []string `json:"WsRequestDomain"`
7
+	UploadDomain    []string `json:"UploadDomain"`
8
+	DownloadDomain  []string `json:"DownloadDomain"`
9
+	BizDomain       []string `json:"BizDomain"`
10
+	UDPDomain       []string `json:"UDPDomain"`
11
+}
12
+
13
+// MiniProgramCategory 小程序配置的类目信息
14
+type MiniProgramCategory struct {
15
+	First  string `json:"first"`
16
+	Second string `json:"second"`
17
+}
18
+
19
+// MiniProgramInfo 小程序配置
20
+type MiniProgramInfo struct {
21
+	Network    MiniProgramNetwork    `json:"network"`
22
+	Categories []MiniProgramCategory `json:"categories"`
23
+}

+ 3
- 0
go.mod Näytä tiedosto

@@ -0,0 +1,3 @@
1
+module gitee.com/yansen_zh/wechat-oplatform-sdk
2
+
3
+go 1.17

+ 65
- 0
service/authorizer_info.go Näytä tiedosto

@@ -0,0 +1,65 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+	"net/url"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
10
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
11
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
12
+)
13
+
14
+// AuthorizerInfoParam 获取授权帐号信息参数
15
+type AuthorizerInfoParam struct {
16
+	ComponentAppId  string `json:"component_appid"`
17
+	AuthorizerAppId string `json:"authorizer_appid"`
18
+}
19
+
20
+// AuthorizerInfoResult 获取授权帐号信息结果
21
+type AuthorizerInfoResult struct {
22
+	entity.Error
23
+	AuthorizationInfo entity.AuthorizationInfo `json:"authorization_info"`
24
+	AuthorizerInfo    entity.AuthorizerInfo    `json:"authorizer_info"`
25
+}
26
+
27
+// GetAuthorizerInfo 获取授权帐号信息
28
+func GetAuthorizerInfo(componentAccessToken string, param AuthorizerInfoParam) (*AuthorizerInfoResult, error) {
29
+	if componentAccessToken == "" {
30
+		return nil, errors.New("获取授权帐号信息 第三方平台的 component_access_token 不能为空")
31
+	}
32
+
33
+	if param.ComponentAppId == "" {
34
+		return nil, errors.New("获取授权帐号信息 第三方平台的 appid 不能为空")
35
+	}
36
+
37
+	if param.AuthorizerAppId == "" {
38
+		return nil, errors.New("获取授权帐号信息 授权方 appid 不能为空")
39
+	}
40
+
41
+	data, e1 := json.Marshal(param)
42
+	if e1 != nil {
43
+		return nil, e1
44
+	}
45
+
46
+	queryParam := url.Values{}
47
+	queryParam.Set("component_access_token", componentAccessToken)
48
+
49
+	apiUrl, _ := utils.ParseURL(api.GetAuthorizerInfo, &queryParam)
50
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
51
+	if e2 != nil {
52
+		return nil, e2
53
+	}
54
+
55
+	result := AuthorizerInfoResult{}
56
+	if err := json.Unmarshal(resp, &result); err != nil {
57
+		return nil, err
58
+	}
59
+
60
+	if result.Code != 0 {
61
+		return &result, result.Error
62
+	}
63
+
64
+	return &result, nil
65
+}

+ 74
- 0
service/authorizer_list.go Näytä tiedosto

@@ -0,0 +1,74 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+	"net/url"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
10
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
11
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
12
+)
13
+
14
+// AuthorizerListParam 拉取所有已授权的帐号信息参数
15
+type AuthorizerListParam struct {
16
+	ComponentAppId string `json:"component_appid"`
17
+	Offset         int    `json:"offset"`
18
+	Count          int    `json:"count"`
19
+}
20
+
21
+// AuthorizerListResult 拉取所有已授权的帐号信息结果
22
+type AuthorizerListResult struct {
23
+	entity.Error
24
+	TotalCount float64                      `json:"total_count"`
25
+	List       []entity.AuthorizerBasicInfo `json:"list"`
26
+}
27
+
28
+// AuthorizerList 拉取所有已授权的帐号信息
29
+func AuthorizerList(componentAccessToken string, param AuthorizerListParam) (*AuthorizerListResult, error) {
30
+	if componentAccessToken == "" {
31
+		return nil, errors.New("拉取所有已授权的帐号信息 第三方平台的 component_access_token 不能为空")
32
+	}
33
+
34
+	if param.ComponentAppId == "" {
35
+		return nil, errors.New("拉取所有已授权的帐号信息 第三方平台的 appid 不能为空")
36
+	}
37
+
38
+	if param.Offset < 0 {
39
+		param.Offset = 0
40
+	}
41
+
42
+	if param.Count < 0 {
43
+		param.Count = 100
44
+	}
45
+
46
+	if param.Count > 500 {
47
+		param.Count = 500
48
+	}
49
+
50
+	data, e1 := json.Marshal(param)
51
+	if e1 != nil {
52
+		return nil, e1
53
+	}
54
+
55
+	queryParam := url.Values{}
56
+	queryParam.Set("component_access_token", componentAccessToken)
57
+
58
+	apiUrl, _ := utils.ParseURL(api.GetAuthorizerList, &queryParam)
59
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
60
+	if e2 != nil {
61
+		return nil, e2
62
+	}
63
+
64
+	result := AuthorizerListResult{}
65
+	if err := json.Unmarshal(resp, &result); err != nil {
66
+		return nil, err
67
+	}
68
+
69
+	if result.Code != 0 {
70
+		return &result, result.Error
71
+	}
72
+
73
+	return &result, nil
74
+}

+ 132
- 0
service/authorizer_option.go Näytä tiedosto

@@ -0,0 +1,132 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+	"net/url"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
10
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
11
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
12
+)
13
+
14
+// GetAuthorizerOptionParam 获取授权方选项信息参数
15
+type GetAuthorizerOptionParam struct {
16
+	ComponentAppId  string `json:"component_appid"`
17
+	AuthorizerAppId string `json:"authorizer_appid"`
18
+	OptionName      string `json:"option_name"`
19
+}
20
+
21
+// GetAuthorizerOptionResult 获取授权方选项信息结果
22
+type GetAuthorizerOptionResult struct {
23
+	entity.Error
24
+	AuthorizerAppId string `json:"authorizer_appid"`
25
+	OptionName      string `json:"option_name"`
26
+	OptionValue     string `json:"option_value"`
27
+}
28
+
29
+// GetAuthorizerOption 获取授权方选项信息
30
+func GetAuthorizerOption(componentAccessToken string, param GetAuthorizerOptionParam) (*GetAuthorizerOptionResult, error) {
31
+	if componentAccessToken == "" {
32
+		return nil, errors.New("获取授权方选项信息 第三方平台的 component_access_token 不能为空")
33
+	}
34
+
35
+	if param.ComponentAppId == "" {
36
+		return nil, errors.New("获取授权方选项信息 授权公众号或小程序的 appid 不能为空")
37
+	}
38
+
39
+	if param.AuthorizerAppId == "" {
40
+		return nil, errors.New("获取授权方选项信息 第三方平台的 appid 不能为空")
41
+	}
42
+
43
+	if param.OptionName == "" {
44
+		return nil, errors.New("获取授权方选项信息 选项名称 不能为空")
45
+	}
46
+
47
+	data, e1 := json.Marshal(param)
48
+	if e1 != nil {
49
+		return nil, e1
50
+	}
51
+
52
+	queryParam := url.Values{}
53
+	queryParam.Set("component_access_token", componentAccessToken)
54
+
55
+	apiUrl, _ := utils.ParseURL(api.GetAuthorizerOption, &queryParam)
56
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
57
+	if e2 != nil {
58
+		return nil, e2
59
+	}
60
+
61
+	result := GetAuthorizerOptionResult{}
62
+	if err := json.Unmarshal(resp, &result); err != nil {
63
+		return nil, err
64
+	}
65
+
66
+	if result.Code != 0 {
67
+		return &result, result.Error
68
+	}
69
+
70
+	return &result, nil
71
+}
72
+
73
+// SetAuthorizerOptionParam 设置授权方选项信息参数
74
+type SetAuthorizerOptionParam struct {
75
+	ComponentAppId  string `json:"component_appid"`
76
+	AuthorizerAppId string `json:"authorizer_appid"`
77
+	OptionName      string `json:"option_name"`
78
+	OptionValue     string `json:"option_value"`
79
+}
80
+
81
+// SetAuthorizerOptionResult 设置授权方选项信息结果
82
+type SetAuthorizerOptionResult struct {
83
+	entity.Error
84
+}
85
+
86
+// SetAuthorizerOption 设置授权方选项信息
87
+func SetAuthorizerOption(componentAccessToken string, param SetAuthorizerOptionParam) (*SetAuthorizerOptionResult, error) {
88
+	if componentAccessToken == "" {
89
+		return nil, errors.New("设置授权方选项信息 第三方平台的 component_access_token 不能为空")
90
+	}
91
+
92
+	if param.ComponentAppId == "" {
93
+		return nil, errors.New("设置授权方选项信息 授权公众号或小程序的 appid 不能为空")
94
+	}
95
+
96
+	if param.AuthorizerAppId == "" {
97
+		return nil, errors.New("设置授权方选项信息 第三方平台的 appid 不能为空")
98
+	}
99
+
100
+	if param.OptionName == "" {
101
+		return nil, errors.New("设置授权方选项信息 选项名称 不能为空")
102
+	}
103
+
104
+	if param.OptionValue == "" {
105
+		return nil, errors.New("设置授权方选项信息 设置的选项值 不能为空")
106
+	}
107
+
108
+	data, e1 := json.Marshal(param)
109
+	if e1 != nil {
110
+		return nil, e1
111
+	}
112
+
113
+	queryParam := url.Values{}
114
+	queryParam.Set("component_access_token", componentAccessToken)
115
+
116
+	apiUrl, _ := utils.ParseURL(api.SetAuthorizerOption, &queryParam)
117
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
118
+	if e2 != nil {
119
+		return nil, e2
120
+	}
121
+
122
+	result := SetAuthorizerOptionResult{}
123
+	if err := json.Unmarshal(resp, &result); err != nil {
124
+		return nil, err
125
+	}
126
+
127
+	if result.Code != 0 {
128
+		return &result, result.Error
129
+	}
130
+
131
+	return &result, nil
132
+}

+ 71
- 0
service/authorizer_token.go Näytä tiedosto

@@ -0,0 +1,71 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+	"net/url"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
10
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
11
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
12
+)
13
+
14
+// AuthorizerTokenParam 获取/刷新接口调用令牌参数
15
+type AuthorizerTokenParam struct {
16
+	ComponentAppId         string `json:"component_appid"`
17
+	AuthorizerAppId        string `json:"authorizer_appid"`
18
+	AuthorizerRefreshToken string `json:"authorizer_refresh_token"`
19
+}
20
+
21
+// AuthorizerTokenResult 获取/刷新接口调用令牌结果
22
+type AuthorizerTokenResult struct {
23
+	entity.Error
24
+	AuthorizerAccessToken  string  `json:"authorizer_access_token"`
25
+	ExpiresIn              float64 `json:"expires_in"`
26
+	AuthorizerRefreshToken string  `json:"authorizer_refresh_token"`
27
+}
28
+
29
+// AuthorizerToken 获取/刷新接口调用令牌
30
+func AuthorizerToken(componentAccessToken string, param AuthorizerTokenParam) (*AuthorizerTokenResult, error) {
31
+	if componentAccessToken == "" {
32
+		return nil, errors.New("获取/刷新接口调用令牌 第三方平台的 component_access_token 不能为空")
33
+	}
34
+
35
+	if param.ComponentAppId == "" {
36
+		return nil, errors.New("获取/刷新接口调用令牌 第三方平台的 appid 不能为空")
37
+	}
38
+
39
+	if param.AuthorizerAppId == "" {
40
+		return nil, errors.New("获取/刷新接口调用令牌 授权方 appid 不能为空")
41
+	}
42
+
43
+	if param.AuthorizerRefreshToken == "" {
44
+		return nil, errors.New("获取/刷新接口调用令牌 刷新令牌 不能为空")
45
+	}
46
+
47
+	data, e1 := json.Marshal(param)
48
+	if e1 != nil {
49
+		return nil, e1
50
+	}
51
+
52
+	queryParam := url.Values{}
53
+	queryParam.Set("component_access_token", componentAccessToken)
54
+
55
+	apiUrl, _ := utils.ParseURL(api.AuthorizerToken, &queryParam)
56
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
57
+	if e2 != nil {
58
+		return nil, e2
59
+	}
60
+
61
+	result := AuthorizerTokenResult{}
62
+	if err := json.Unmarshal(resp, &result); err != nil {
63
+		return nil, err
64
+	}
65
+
66
+	if result.Code != 0 {
67
+		return &result, result.Error
68
+	}
69
+
70
+	return &result, nil
71
+}

+ 82
- 0
service/bind_component.go Näytä tiedosto

@@ -0,0 +1,82 @@
1
+package service
2
+
3
+import (
4
+	"errors"
5
+	"net/url"
6
+	"strconv"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
10
+)
11
+
12
+// BindComponentParam 构建授权链接入参
13
+type BindComponentParam struct {
14
+	ComponentAppId string
15
+	PreAuthCode    string
16
+
17
+	// RedirectUri 不需要转码
18
+	RedirectUri string
19
+	AuthType    int
20
+	BizAppId    string
21
+}
22
+
23
+// BindComponentByPC 构建PC端授权链接
24
+func BindComponentByPC(param BindComponentParam) (*url.URL, error) {
25
+	return BindComponent("PC", param)
26
+}
27
+
28
+// BindComponentByH5 构建H5端授权链接
29
+func BindComponentByH5(param BindComponentParam) (*url.URL, error) {
30
+	return BindComponent("H5", param)
31
+}
32
+
33
+// BindComponent 构建授权链接
34
+func BindComponent(client string, param BindComponentParam) (*url.URL, error) {
35
+	isH5 := client == "H5"
36
+
37
+	if param.ComponentAppId == "" {
38
+		return nil, errors.New("构建授权链接 第三方平台的 appid 不能为空")
39
+	}
40
+
41
+	if param.PreAuthCode == "" {
42
+		return nil, errors.New("构建授权链接 预授权码 不能为空")
43
+	}
44
+
45
+	if param.RedirectUri == "" {
46
+		return nil, errors.New("构建授权链接 回调 URI 不能为空")
47
+	}
48
+
49
+	if param.AuthType < 1 || param.AuthType > 3 {
50
+		param.AuthType = 3
51
+	}
52
+
53
+	queryParams := url.Values{}
54
+	if isH5 {
55
+		queryParams.Set("action", "bindcomponent")
56
+		queryParams.Set("no_scan", "1")
57
+	}
58
+	queryParams.Set("component_appid", param.ComponentAppId)
59
+	queryParams.Set("pre_auth_code", param.PreAuthCode)
60
+	queryParams.Set("redirect_uri", param.RedirectUri)
61
+	// auth_type、biz_appid 两个字段互斥
62
+	if param.BizAppId != "" {
63
+		queryParams.Set("biz_appid", param.BizAppId)
64
+	} else {
65
+		queryParams.Set("auth_type", strconv.Itoa(param.AuthType))
66
+	}
67
+
68
+	apiUrl := api.BindComponentByPC
69
+	if isH5 {
70
+		apiUrl = api.BindComponentByH5
71
+	}
72
+	u, err := utils.ParseURL(apiUrl, &queryParams)
73
+	if err != nil {
74
+		return nil, err
75
+	}
76
+
77
+	if isH5 {
78
+		u.Fragment = "wechat_redirect"
79
+	}
80
+
81
+	return u, nil
82
+}

+ 60
- 0
service/component_token.go Näytä tiedosto

@@ -0,0 +1,60 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+
7
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
10
+)
11
+
12
+// ComponentTokenParam 获取令牌参数
13
+type ComponentTokenParam struct {
14
+	ComponentAppId        string `json:"component_appid"`
15
+	ComponentAppSecret    string `json:"component_appsecret"`
16
+	ComponentVerifyTicket string `json:"component_verify_ticket"`
17
+}
18
+
19
+// ComponentTokenResult 获取令牌结果
20
+type ComponentTokenResult struct {
21
+	entity.Error
22
+	ComponentAccessToken string  `json:"component_access_token"`
23
+	ExpiresIn            float64 `json:"expires_in"`
24
+}
25
+
26
+// ComponentVerifyTicket 获取令牌
27
+func ComponentToken(param ComponentTokenParam) (*ComponentTokenResult, error) {
28
+	if param.ComponentAppId == "" {
29
+		return nil, errors.New("获取令牌 第三方平台的 appid 不能为空")
30
+	}
31
+
32
+	if param.ComponentAppSecret == "" {
33
+		return nil, errors.New("获取令牌 第三方平台的 appsecret 不能为空")
34
+	}
35
+
36
+	if param.ComponentVerifyTicket == "" {
37
+		return nil, errors.New("获取令牌 推送 ticket 不能为空")
38
+	}
39
+
40
+	data, e1 := json.Marshal(param)
41
+	if e1 != nil {
42
+		return nil, e1
43
+	}
44
+
45
+	resp, e2 := request.PostJSON(api.ComponentToken, data)
46
+	if e2 != nil {
47
+		return nil, e2
48
+	}
49
+
50
+	result := ComponentTokenResult{}
51
+	if err := json.Unmarshal(resp, &result); err != nil {
52
+		return nil, err
53
+	}
54
+
55
+	if result.Code != 0 {
56
+		return &result, result.Error
57
+	}
58
+
59
+	return &result, nil
60
+}

+ 60
- 0
service/pre_auth_code.go Näytä tiedosto

@@ -0,0 +1,60 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+	"net/url"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
10
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
11
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
12
+)
13
+
14
+// PreAuthCodeParam 获取预授权码参数
15
+type PreAuthCodeParam struct {
16
+	ComponentAppId string `json:"component_appid"`
17
+}
18
+
19
+// PreAuthCodeResult 获取预授权码结果
20
+type PreAuthCodeResult struct {
21
+	entity.Error
22
+	PreAuthCode string  `json:"pre_auth_code"`
23
+	ExpiresIn   float64 `json:"expires_in"`
24
+}
25
+
26
+// CreatePreAuthCode 获取预授权码
27
+func CreatePreAuthCode(componentAccessToken string, param PreAuthCodeParam) (*PreAuthCodeResult, error) {
28
+	if componentAccessToken == "" {
29
+		return nil, errors.New("获取预授权码 第三方平台的 component_access_token 不能为空")
30
+	}
31
+
32
+	if param.ComponentAppId == "" {
33
+		return nil, errors.New("获取预授权码 第三方平台的 appid 不能为空")
34
+	}
35
+
36
+	data, e1 := json.Marshal(param)
37
+	if e1 != nil {
38
+		return nil, e1
39
+	}
40
+
41
+	queryParam := url.Values{}
42
+	queryParam.Set("component_access_token", componentAccessToken)
43
+
44
+	apiUrl, _ := utils.ParseURL(api.CreatePreAuthCode, &queryParam)
45
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
46
+	if e2 != nil {
47
+		return nil, e2
48
+	}
49
+
50
+	result := PreAuthCodeResult{}
51
+	if err := json.Unmarshal(resp, &result); err != nil {
52
+		return nil, err
53
+	}
54
+
55
+	if result.Code != 0 {
56
+		return &result, result.Error
57
+	}
58
+
59
+	return &result, nil
60
+}

+ 53
- 0
service/push_ticket.go Näytä tiedosto

@@ -0,0 +1,53 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+
7
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
10
+)
11
+
12
+// PushTicketParam 启动票据推送服务参数
13
+type PushTicketParam struct {
14
+	ComponentAppId  string `json:"component_appid"`
15
+	ComponentSecret string `json:"component_secret"`
16
+}
17
+
18
+// PushTicketResult 启动票据推送服务参数
19
+type PushTicketResult struct {
20
+	entity.Error
21
+}
22
+
23
+// StartPushTicket 启动 ticket 推送服务
24
+func StartPushTicket(param PushTicketParam) (*PushTicketResult, error) {
25
+	if param.ComponentAppId == "" {
26
+		return nil, errors.New("启动 ticket 推送服务 第三方平台的 appid 不能为空")
27
+	}
28
+
29
+	if param.ComponentSecret == "" {
30
+		return nil, errors.New("启动 ticket 推送服务 第三方平台的 appsecret 不能为空")
31
+	}
32
+
33
+	data, e1 := json.Marshal(param)
34
+	if e1 != nil {
35
+		return nil, e1
36
+	}
37
+
38
+	resp, e2 := request.PostJSON(api.StartPushTicket, data)
39
+	if e2 != nil {
40
+		return nil, e2
41
+	}
42
+
43
+	result := PushTicketResult{}
44
+	if err := json.Unmarshal(resp, &result); err != nil {
45
+		return nil, err
46
+	}
47
+
48
+	if result.Code != 0 {
49
+		return &result, result.Error
50
+	}
51
+
52
+	return &result, nil
53
+}

+ 64
- 0
service/query_auth.go Näytä tiedosto

@@ -0,0 +1,64 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"errors"
6
+	"net/url"
7
+
8
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/api"
9
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/entity"
10
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils"
11
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/request"
12
+)
13
+
14
+// QueryAuthParam 获取授权信息参数
15
+type QueryAuthParam struct {
16
+	ComponentAppId    string `json:"component_appid"`
17
+	AuthorizationCode string `json:"authorization_code"`
18
+}
19
+
20
+// QueryAuthResult 获取授权信息结果
21
+type QueryAuthResult struct {
22
+	entity.Error
23
+	AuthorizationInfo entity.AuthorizationInfo `json:"authorization_info"`
24
+}
25
+
26
+// QueryAuth 获取授权信息
27
+func QueryAuth(componentAccessToken string, param QueryAuthParam) (*QueryAuthResult, error) {
28
+	if componentAccessToken == "" {
29
+		return nil, errors.New("获取授权信息 第三方平台的 component_access_token 不能为空")
30
+	}
31
+
32
+	if param.ComponentAppId == "" {
33
+		return nil, errors.New("获取授权信息 第三方平台的 appid 不能为空")
34
+	}
35
+
36
+	if param.AuthorizationCode == "" {
37
+		return nil, errors.New("获取授权信息 授权码 不能为空")
38
+	}
39
+
40
+	data, e1 := json.Marshal(param)
41
+	if e1 != nil {
42
+		return nil, e1
43
+	}
44
+
45
+	queryParam := url.Values{}
46
+	queryParam.Set("component_access_token", componentAccessToken)
47
+
48
+	apiUrl, _ := utils.ParseURL(api.QueryAuth, &queryParam)
49
+	resp, e2 := request.PostJSON(apiUrl.String(), data)
50
+	if e2 != nil {
51
+		return nil, e2
52
+	}
53
+
54
+	result := QueryAuthResult{}
55
+	if err := json.Unmarshal(resp, &result); err != nil {
56
+		return nil, err
57
+	}
58
+
59
+	if result.Code != 0 {
60
+		return &result, result.Error
61
+	}
62
+
63
+	return &result, nil
64
+}

+ 31
- 0
service/verify_ticket.go Näytä tiedosto

@@ -0,0 +1,31 @@
1
+package service
2
+
3
+import (
4
+	"encoding/xml"
5
+
6
+	"gitee.com/yansen_zh/wechat-oplatform-sdk/utils/encrypt"
7
+)
8
+
9
+// ComponentVerifyTicketResult 获取验证票据结果
10
+type ComponentVerifyTicketResult struct {
11
+	AppId                 string  `xml:"AppId"`
12
+	CreateTime            float64 `xml:"CreateTime"`
13
+	InfoType              string  `xml:"InfoType"`
14
+	ComponentVerifyTicket string  `xml:"ComponentVerifyTicket"`
15
+}
16
+
17
+// ComponentVerifyTicket 获取验证票据
18
+func VerifyTicket(data []byte, encodingAESKey, iv string) (*ComponentVerifyTicketResult, error) {
19
+	bt, err := encrypt.MsgDecode(data, encodingAESKey, iv)
20
+	if nil != err {
21
+		return nil, err
22
+	}
23
+
24
+	res := ComponentVerifyTicketResult{}
25
+
26
+	if e := xml.Unmarshal(bt, &res); e != nil {
27
+		return nil, e
28
+	}
29
+
30
+	return &res, nil
31
+}

+ 1
- 0
utils/encrypt/encrypt.go Näytä tiedosto

@@ -0,0 +1 @@
1
+package encrypt

+ 101
- 0
utils/encrypt/msg_encrypt.go Näytä tiedosto

@@ -0,0 +1,101 @@
1
+package encrypt
2
+
3
+import (
4
+	"bytes"
5
+	"crypto/aes"
6
+	"crypto/cipher"
7
+	"encoding/base64"
8
+	"errors"
9
+)
10
+
11
+// MsgEncode 使用 AES CBC 模式加密数据
12
+// data 为待加密数据
13
+func MsgEncode(data []byte, encodingAESKey, iv string) ([]byte, error) {
14
+	if encodingAESKey == "" {
15
+		return nil, errors.New("加密 EncodingAESKey 为空")
16
+	}
17
+
18
+	if iv == "" {
19
+		return nil, errors.New("加密 IV 为空")
20
+	}
21
+
22
+	if nil == data || len(data) == 0 {
23
+		return nil, errors.New("待加密 消息 为空")
24
+	}
25
+
26
+	aesKey, e1 := base64.StdEncoding.DecodeString(encodingAESKey + "=")
27
+	if e1 != nil {
28
+		return nil, e1
29
+	}
30
+
31
+	block, e2 := aes.NewCipher(aesKey)
32
+	if e2 != nil {
33
+		return nil, e2
34
+	}
35
+
36
+	blockSize := block.BlockSize()
37
+	dist := pkcs7(data, blockSize)
38
+
39
+	// CBC
40
+	mode := cipher.NewCBCEncrypter(block, []byte(iv))
41
+	mode.CryptBlocks(dist, data)
42
+
43
+	// 如果需要拿到字符串, 请使用
44
+	// fmt.Sprintf("%x", xxx)
45
+	// 或者使用 base64 转码
46
+	return dist, nil
47
+}
48
+
49
+// MsgDecode 是 MsgEncode 的反操作, 用来解密数据
50
+// data 为待解密数据
51
+func MsgDecode(data []byte, encodingAESKey, iv string) ([]byte, error) {
52
+	if encodingAESKey == "" {
53
+		return nil, errors.New("解密 EncodingAESKey 为空")
54
+	}
55
+
56
+	if iv == "" {
57
+		return nil, errors.New("解密 IV 为空")
58
+	}
59
+
60
+	if nil == data || len(data) == 0 {
61
+		return nil, errors.New("待解密 消息 为空")
62
+	}
63
+
64
+	aesKey, e1 := base64.StdEncoding.DecodeString(encodingAESKey + "=")
65
+	if e1 != nil {
66
+		return nil, e1
67
+	}
68
+
69
+	block, err := aes.NewCipher(aesKey)
70
+	if err != nil {
71
+		return nil, err
72
+	}
73
+
74
+	dist := make([]byte, len(data))
75
+
76
+	mode := cipher.NewCBCDecrypter(block, []byte(iv))
77
+	mode.CryptBlocks(dist, data)
78
+
79
+	// 如果需要拿到字符串, 请使用
80
+	// fmt.Sprintf("%s", xxx)
81
+	return unpkcs7(dist), nil
82
+}
83
+
84
+// pkcs7 填充
85
+func pkcs7(data []byte, blockSize int) []byte {
86
+	paddingBlock := blockSize - len(data)%blockSize
87
+	if paddingBlock == 0 {
88
+		paddingBlock = blockSize
89
+	}
90
+
91
+	padding := bytes.Repeat([]byte{byte(paddingBlock)}, paddingBlock)
92
+	return append(data, padding...)
93
+}
94
+
95
+// unpkcs7 取消 pkcs7 填充
96
+func unpkcs7(data []byte) []byte {
97
+	length := len(data)
98
+
99
+	unpadding := int(data[length-1])
100
+	return data[:(length - unpadding)]
101
+}

+ 3
- 0
utils/request/content_type.go Näytä tiedosto

@@ -0,0 +1,3 @@
1
+package request
2
+
3
+const ContentTypeJSON = "application/json"

+ 34
- 0
utils/request/request.go Näytä tiedosto

@@ -0,0 +1,34 @@
1
+package request
2
+
3
+import (
4
+	"bytes"
5
+	"errors"
6
+	"io"
7
+	"net/http"
8
+)
9
+
10
+func post(url string, contentType string, body []byte) ([]byte, error) {
11
+	resp, e1 := http.Post(url, contentType, bytes.NewReader(body))
12
+	if e1 != nil {
13
+		return nil, e1
14
+	}
15
+
16
+	if resp.StatusCode > 299 {
17
+		return nil, errors.New(resp.Status)
18
+	}
19
+
20
+	body, e2 := io.ReadAll(resp.Body)
21
+	resp.Body.Close()
22
+	if e2 != nil {
23
+		return nil, e2
24
+	}
25
+
26
+	return body, nil
27
+}
28
+
29
+// PostJSON 使用 POST 方式发送 json 数据
30
+func PostJSON(url string, body []byte) ([]byte, error) {
31
+
32
+	return post(url, ContentTypeJSON, body)
33
+
34
+}

+ 17
- 0
utils/url.go Näytä tiedosto

@@ -0,0 +1,17 @@
1
+package utils
2
+
3
+import "net/url"
4
+
5
+// ParseURL 解析URL
6
+func ParseURL(rawURL string, param *url.Values) (*url.URL, error) {
7
+	u, err := url.Parse(rawURL)
8
+	if err != nil {
9
+		return nil, err
10
+	}
11
+
12
+	if nil != param {
13
+		u.RawQuery = param.Encode()
14
+	}
15
+
16
+	return u, nil
17
+}