Browse Source

change jwt-token

zjxpcyc 6 years ago
parent
commit
fe9a6a2b32
7 changed files with 466 additions and 228 deletions
  1. 43
    168
      controllers/auth.go
  2. 0
    1
      controllers/context.go
  3. 7
    0
      models/constant.go
  4. 11
    24
      service/customer/customer.go
  5. 302
    35
      service/sys.go
  6. 47
    0
      utils/jwt.go
  7. 56
    0
      utils/wechat.go

+ 43
- 168
controllers/auth.go View File

6
 	"spaceofcheng/services/models/model"
6
 	"spaceofcheng/services/models/model"
7
 	"spaceofcheng/services/service"
7
 	"spaceofcheng/services/service"
8
 	"spaceofcheng/services/utils"
8
 	"spaceofcheng/services/utils"
9
-	"strings"
10
-
11
-	"github.com/astaxie/beego"
9
+	"time"
12
 )
10
 )
13
 
11
 
14
 // Authenticate 权限验证
12
 // Authenticate 权限验证
15
 func (c *BaseController) authenticate() {
13
 func (c *BaseController) authenticate() {
16
-
17
-	// 默认 service
18
 	serv := service.NewSysServ(c.Context)
14
 	serv := service.NewSysServ(c.Context)
19
 
15
 
20
-	orgID := c.GetString(":org")
21
-	if orgID == "" {
22
-		c.ResponseError(errors.New("接口地址访问不正确"))
23
-	}
24
-	serv.SetOrgByID(orgID)
25
-
26
-	// 客户端类型
27
-	clientType := utils.GetClientType(c.Ctx.Request)
28
-
29
-	switch clientType {
30
-	case utils.ClientAdmin:
31
-		c.authPCAdmin(serv)
32
-	case utils.ClientWechat:
33
-		c.authWechat(serv)
34
-	default:
35
-		c.ResponseError(
36
-			errors.New("暂不支持的 API 场景"),
37
-			http.StatusBadRequest,
38
-		)
39
-	}
40
-}
16
+	// 鉴权 - 并初始化上下文
17
+	res := serv.AuthAndInitCtx(c.Ctx)
41
 
18
 
42
-// authPCAdmin PC管理端
43
-func (c *BaseController) authPCAdmin(serv *service.SysServ) {
44
-	if !c.needAuth() {
45
-		return
46
-	}
19
+	// 设置 TOKEN
20
+	c.setToken()
47
 
21
 
48
-	// 用户ID
49
-	userID := ""
50
-	userIDRaw := c.GetSession(SNUserID)
51
-	if userIDRaw != nil {
52
-		userID = userIDRaw.(string)
53
-	}
22
+	if res != nil {
23
+		code := http.StatusOK
24
+		if res["code"] != nil {
25
+			code = res["code"].(int)
26
+		}
54
 
27
 
55
-	if userID == "" {
56
-		c.ResponseError(
57
-			errors.New("用户未登录"),
58
-			http.StatusUnauthorized,
59
-		)
60
-	}
28
+		if code != http.StatusOK {
29
+			err := res["error"].(error)
30
+			data := map[string]interface{}{}
61
 
31
 
62
-	if err := serv.SetUserProfile(userID); err != nil {
63
-		// utils.LogError(err.Error())
32
+			if res["message"] != nil {
33
+				data = res["message"].(map[string]interface{})
34
+			}
64
 
35
 
65
-		c.ResponseError(
66
-			utils.LogError(err.Error()),
67
-			http.StatusInternalServerError,
68
-		)
36
+			c.ResponseData(data, err, code)
37
+		}
69
 	}
38
 	}
70
-
71
-	// 设置 Session
72
-	c.SetSession(SNUserID, userID)
73
 }
39
 }
74
 
40
 
75
-// authWechat 微信端
76
-func (c *BaseController) authWechat(serv *service.SysServ) {
77
-	custID := ""
78
-	custIDRaw := c.GetSession(SNCustID)
79
-	if custIDRaw != nil {
80
-		custID = custIDRaw.(string)
81
-	}
82
-
83
-	// 机构
84
-	org := c.Context.Get("org").(model.SysOrg)
85
-
86
-	// 微信配置
87
-	wxConf, err := serv.GetWeChatConfig(org.OrgId)
88
-	if err != nil {
89
-		utils.LogError("查询微信配置失败: " + err.Error())
90
-		c.ResponseError(
91
-			errors.New("没有找到微信相关配置"),
92
-			http.StatusBadRequest,
93
-		)
94
-	}
95
-	utils.WxClientSingleton(org.OrgId, wxConf)
41
+// setToken 设置 TOKEN
42
+// 15 分钟后过期
43
+func (c *BaseController) setToken() {
44
+	var token *utils.JWTToken
45
+	exp := time.Now().Local().Add(15 * time.Second)
96
 
46
 
97
-	// 用户微信信息
98
-	var wxDetail map[string]interface{}
47
+	if c.Context.Get("user") != nil {
48
+		user := c.Context.Get("user").(model.SysUser)
99
 
49
 
100
-	detailRaw := c.GetSession("wechat_user")
101
-	if detailRaw != nil {
102
-		wxDetail = detailRaw.(map[string]interface{})
103
-	} else {
104
-		// DEV MODE
105
-		if c.RunMode == "dev" {
106
-			wxDetail = map[string]interface{}{
107
-				"openid":     "OPENID",
108
-				"nickname":   "NICKNAME",
109
-				"sex":        "1",
110
-				"province":   "PROVINCE",
111
-				"city":       "CITY",
112
-				"country":    "COUNTRY",
113
-				"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
114
-				"unionid":    "o6_bmasdasdsad6_2sgVt7hMZOPfL",
115
-			}
116
-		} else {
117
-			wxDetail = c.getWechatDetail(org.OrgId, serv)
50
+		token = &utils.JWTToken{
51
+			Guest:  false,
52
+			ID:     user.UserId,
53
+			Expire: exp,
118
 		}
54
 		}
55
+	} else if c.Context.Get("userMap") != nil {
56
+		userMap := c.Context.Get("userMap").(model.TaUserMapping)
119
 
57
 
120
-		c.SetSession("wechat_user", wxDetail)
121
-	}
122
-
123
-	c.Context.Set("wxInfo", wxDetail)
124
-
125
-	// 用户映射检查
126
-	userMap, err := serv.CheckWechatUserMapping(wxDetail)
127
-	if err != nil {
128
-		c.ResponseError(
129
-			utils.LogError("获取人员映射账户失败: "+err.Error()),
130
-			http.StatusInternalServerError,
131
-		)
132
-	}
133
-	c.Context.Set("userMap", *userMap)
134
-
135
-	if !c.needAuth() {
136
-		return
137
-	}
138
-	// 未登录或者绑定, 返回 406
139
-	if custID == "" && userMap.UserId == "" {
140
-		// 新增用户信息
141
-		cust, err := serv.SaveNewCustomer(wxDetail, userMap)
142
-		if err != nil {
143
-			c.ResponseError(err)
58
+		token = &utils.JWTToken{
59
+			Guest:  false,
60
+			ID:     userMap.Openid,
61
+			Expire: exp,
144
 		}
62
 		}
145
-		custID = cust.CustomerId
146
-		// c.ResponseError(
147
-		// 	errors.New("用户未登录或绑定"),
148
-		// 	http.StatusNotAcceptable,
149
-		// )
150
-	}
151
-
152
-	if custID == "" {
153
-		custID = userMap.UserId
154
-	}
155
-	if custID != "" {
156
-		if err := serv.SetCustomer(custID); err != nil {
157
-			utils.LogError(err.Error())
158
-
159
-			c.ResponseError(
160
-				errors.New("内部错误, 请重试"),
161
-				http.StatusInternalServerError,
162
-			)
63
+	} else {
64
+		token = &utils.JWTToken{
65
+			Guest:  true,
66
+			Expire: exp,
163
 		}
67
 		}
164
-
165
-		// 设置 Session
166
-		c.SetSession(SNCustID, custID)
167
-	}
168
-}
169
-
170
-func (c *BaseController) needAuth() bool {
171
-	route := c.Ctx.Input.URL()
172
-	apiPrefix := beego.AppConfig.String("api::prefix")
173
-	guestAPI := beego.AppConfig.String("api::guest")
174
-
175
-	if strings.Index(route, apiPrefix+strings.Split(guestAPI, ":")[0]) > -1 {
176
-		return false
177
-	}
178
-
179
-	return true
180
-}
181
-
182
-// getWechatDetail 获取微信个人信息详情
183
-func (c *BaseController) getWechatDetail(org string, serv *service.SysServ) map[string]interface{} {
184
-	// 微信 code
185
-	code := c.GetString("code")
186
-	if code == "" {
187
-		c.ResponseData(
188
-			map[string]interface{}{
189
-				"appid": utils.GetWxAppID(org),
190
-			},
191
-			errors.New("获取微信信息失败"),
192
-			http.StatusUnauthorized,
193
-		)
194
 	}
68
 	}
195
 
69
 
196
-	usr, err := utils.WxClientFor(org).GetUserInfo(code)
70
+	tokenEncode, err := utils.CreateToken(token.ToMap())
197
 	if err != nil {
71
 	if err != nil {
72
+		utils.LogError("系统生成 Token 失败: " + err.Error())
198
 		c.ResponseError(
73
 		c.ResponseError(
199
-			utils.LogError("获取微信个人信息失败: "+err.Error()),
74
+			errors.New("系统异常, 请退出重试"),
200
 			http.StatusInternalServerError,
75
 			http.StatusInternalServerError,
201
 		)
76
 		)
202
 	}
77
 	}
203
 
78
 
204
-	return usr
79
+	c.Ctx.Output.Header(utils.TokenHeader, utils.TokenSchema+" "+tokenEncode)
205
 }
80
 }

+ 0
- 1
controllers/context.go View File

12
 * user					SysUser 									用户基本信息
12
 * user					SysUser 									用户基本信息
13
 * customer			TaCustomer 								会员基本信息
13
 * customer			TaCustomer 								会员基本信息
14
 * userMap				TaUserMapping 						用户/会员 映射第三方账户
14
 * userMap				TaUserMapping 						用户/会员 映射第三方账户
15
-* wxInfo				map[string]interface{} 		微信信息
16
 * cases					[]SysUserCase 						用户所有案场信息
15
 * cases					[]SysUserCase 						用户所有案场信息
17
 * currentCase		SysUserCase 							当前案场
16
 * currentCase		SysUserCase 							当前案场
18
 * org						SysOrg 										用户当前组织
17
 * org						SysOrg 										用户当前组织

+ 7
- 0
models/constant.go View File

117
 	GIVE_GIFT_GYM            = "gym"
117
 	GIVE_GIFT_GYM            = "gym"
118
 )
118
 )
119
 
119
 
120
+// 卡券发放类型
121
+const (
122
+	GIVE_TYPE_SYSTEM  = "system"
123
+	GIVE_TYPE_CASE    = "case"
124
+	GIVE_TYPE_CHANNEL = "channel"
125
+)
126
+
120
 // 游泳健身卡种类
127
 // 游泳健身卡种类
121
 const (
128
 const (
122
 	GYM_CARD_ONCE    = "once"
129
 	GYM_CARD_ONCE    = "once"

+ 11
- 24
service/customer/customer.go View File

1
 package customer
1
 package customer
2
 
2
 
3
 import (
3
 import (
4
+	"encoding/json"
4
 	"errors"
5
 	"errors"
5
 	"spaceofcheng/services/models"
6
 	"spaceofcheng/services/models"
6
 	"spaceofcheng/services/models/cases"
7
 	"spaceofcheng/services/models/cases"
104
 	}
105
 	}
105
 
106
 
106
 	if cust == nil {
107
 	if cust == nil {
107
-		wxInfoRaw := s.ctx.Get("wxInfo")
108
-		if wxInfoRaw == nil {
109
-			return nil, errors.New("请确定使用微信端登录")
108
+		wxInfo := utils.WechatUser{}
109
+		if err := json.Unmarshal([]byte(userMap.AccountInfo), &wxInfo); err != nil {
110
+			utils.LogError("解析用户微信映射信息失败: " + err.Error())
111
+			return nil, errors.New("系统数据异常")
110
 		}
112
 		}
111
 
113
 
112
-		wxInfo := wxInfoRaw.(map[string]interface{})
113
 		// 更新用户手机号码信息及userid信息
114
 		// 更新用户手机号码信息及userid信息
114
-		openid := wxInfo["openid"].(string)
115
-		customer, err := s.dao.GetCustWithWXByOpenID(openid)
115
+		customer, err := s.dao.GetCustWithWXByOpenID(wxInfo.OpenID)
116
 
116
 
117
 		newCust := model.TaCustomer{
117
 		newCust := model.TaCustomer{
118
 			CustomerId: customer.CustomerId,
118
 			CustomerId: customer.CustomerId,
128
 			return nil, err
128
 			return nil, err
129
 		}
129
 		}
130
 
130
 
131
-		// newCust, err := s.SaveNewCustomer(wxInfo, "", "", user.Phone, user.UserId)
132
-		// if err != nil {
133
-		// 	utils.LogError(err.Error())
134
-		// 	return nil, err
135
-		// }
136
 		cust = &newCust
131
 		cust = &newCust
137
 	} else {
132
 	} else {
138
 		if cust.Status != models.STATUS_NORMAL {
133
 		if cust.Status != models.STATUS_NORMAL {
168
 
163
 
169
 	// 用户不存在, 则新增
164
 	// 用户不存在, 则新增
170
 	if cust == nil {
165
 	if cust == nil {
171
-		wxInfoRaw := s.ctx.Get("wxInfo")
172
-		if wxInfoRaw == nil {
173
-			return nil, errors.New("请确定使用微信端登录")
166
+		wxInfo := utils.WechatUser{}
167
+		if err := json.Unmarshal([]byte(userMap.AccountInfo), &wxInfo); err != nil {
168
+			utils.LogError("解析用户微信映射信息失败: " + err.Error())
169
+			return nil, errors.New("系统数据异常")
174
 		}
170
 		}
175
 
171
 
176
-		wxInfo := wxInfoRaw.(map[string]interface{})
177
-
178
 		// 更新用户手机号码信息及userid信息
172
 		// 更新用户手机号码信息及userid信息
179
-		openid := wxInfo["openid"].(string)
180
-		customer, err := s.dao.GetCustWithWXByOpenID(openid)
173
+		customer, err := s.dao.GetCustWithWXByOpenID(wxInfo.OpenID)
181
 		newCust := model.TaCustomer{
174
 		newCust := model.TaCustomer{
182
 			CustomerId:  customer.CustomerId,
175
 			CustomerId:  customer.CustomerId,
183
 			Phone:       phone,
176
 			Phone:       phone,
228
 			return nil, err
221
 			return nil, err
229
 		}
222
 		}
230
 
223
 
231
-		// newCust, err := s.SaveNewCustomer(wxInfo, caseID, userID, phone, "")
232
-		// if err != nil {
233
-		// 	utils.LogError(err.Error())
234
-		// 	return nil, err
235
-		// }
236
-
237
 		cust = &newCust
224
 		cust = &newCust
238
 	} else {
225
 	} else {
239
 		if cust.Status != models.STATUS_NORMAL {
226
 		if cust.Status != models.STATUS_NORMAL {

+ 302
- 35
service/sys.go View File

3
 import (
3
 import (
4
 	"encoding/json"
4
 	"encoding/json"
5
 	"errors"
5
 	"errors"
6
+	"net/http"
6
 	"spaceofcheng/services/models"
7
 	"spaceofcheng/services/models"
7
 	"spaceofcheng/services/models/customer"
8
 	"spaceofcheng/services/models/customer"
8
 	"spaceofcheng/services/models/model"
9
 	"spaceofcheng/services/models/model"
9
 	"spaceofcheng/services/utils"
10
 	"spaceofcheng/services/utils"
11
+	"strings"
10
 
12
 
11
 	"github.com/astaxie/beego"
13
 	"github.com/astaxie/beego"
14
+	"github.com/astaxie/beego/context"
12
 )
15
 )
13
 
16
 
14
 const (
17
 const (
17
 
20
 
18
 // SysServ 系统处理
21
 // SysServ 系统处理
19
 type SysServ struct {
22
 type SysServ struct {
23
+	org         model.SysOrg
20
 	ctx         *utils.Context
24
 	ctx         *utils.Context
21
 	dao         *models.SysDAO
25
 	dao         *models.SysDAO
22
 	customerdao *customer.CustomerDAO
26
 	customerdao *customer.CustomerDAO
31
 	}
35
 	}
32
 }
36
 }
33
 
37
 
38
+// AuthAndInitCtx 鉴权
39
+// gctx 是 beego 框架中的 Context
40
+func (s *SysServ) AuthAndInitCtx(gctx *context.Context) map[string]interface{} {
41
+	// 确认机构
42
+	orgID := gctx.Input.Query(":org")
43
+	if orgID == "" {
44
+		return map[string]interface{}{
45
+			"code":  http.StatusBadRequest,
46
+			"error": errors.New("接口地址访问不正确"),
47
+		}
48
+	}
49
+	if err := s.SetOrgByID(orgID); err != nil {
50
+		return map[string]interface{}{
51
+			"code":  http.StatusInternalServerError,
52
+			"error": err,
53
+		}
54
+	}
55
+
56
+	// 获取 token
57
+	token, err := s.getToken(gctx)
58
+	if err != nil {
59
+		return map[string]interface{}{
60
+			"code":  http.StatusInternalServerError,
61
+			"error": err,
62
+		}
63
+	}
64
+	if token != nil {
65
+		s.ctx.Set("token", *token)
66
+	}
67
+
68
+	// 客户端类型
69
+	// 通过 UA 判断
70
+	clientType := utils.GetClientType(gctx.Request)
71
+
72
+	// pc 管理端
73
+	if clientType == utils.ClientAdmin {
74
+		return s.authPCAdmin(gctx)
75
+	}
76
+
77
+	// wechat 端
78
+	if clientType == utils.ClientWechat {
79
+		return s.authWechat(gctx)
80
+	}
81
+
82
+	return map[string]interface{}{
83
+		"code":  http.StatusBadRequest,
84
+		"error": errors.New("暂无该客户端的 API"),
85
+	}
86
+}
87
+
88
+// authPCAdmin
89
+// 管理端 API 校验
90
+func (s *SysServ) authPCAdmin(gctx *context.Context) map[string]interface{} {
91
+	if !s.needAuth(gctx) {
92
+		return nil
93
+	}
94
+
95
+	token := utils.JWTToken{}
96
+	if s.ctx.Get("token") != nil {
97
+		token = s.ctx.Get("token").(utils.JWTToken)
98
+	}
99
+
100
+	if token.ID == "" || token.Guest == true {
101
+		return map[string]interface{}{
102
+			"code":  http.StatusUnauthorized,
103
+			"error": errors.New("用户未登录"),
104
+		}
105
+	}
106
+
107
+	if err := s.SetUserProfile(token.ID); err != nil {
108
+		return map[string]interface{}{
109
+			"code":  http.StatusInternalServerError,
110
+			"error": err,
111
+		}
112
+	}
113
+
114
+	return nil
115
+}
116
+
117
+func (s *SysServ) authWechat(gctx *context.Context) map[string]interface{} {
118
+	// 微信 code
119
+	code := gctx.Input.Query("code")
120
+
121
+	token := utils.JWTToken{}
122
+	if s.ctx.Get("token") != nil {
123
+		token = s.ctx.Get("token").(utils.JWTToken)
124
+	}
125
+
126
+	var wxUser *utils.WechatUser
127
+	var openID string
128
+
129
+	// 未登录 或 未验证
130
+	if token.ID == "" {
131
+		// 需要微信验证
132
+		if code == "" {
133
+			return map[string]interface{}{
134
+				"code":  http.StatusUnauthorized,
135
+				"error": errors.New("请授权微信用户登录"),
136
+				"message": map[string]interface{}{
137
+					"appid": utils.GetWxAppID(s.org.OrgId),
138
+				},
139
+			}
140
+		}
141
+
142
+		// 微信用户信息
143
+		var err error
144
+		wxUser, err = s.wechartSignIn(gctx, code)
145
+		if err != nil {
146
+			return map[string]interface{}{
147
+				"code":  http.StatusInternalServerError,
148
+				"error": err,
149
+			}
150
+		}
151
+
152
+		if wxUser == nil {
153
+			return map[string]interface{}{
154
+				"code":  http.StatusInternalServerError,
155
+				"error": errors.New("请先关注公众号"),
156
+			}
157
+		}
158
+
159
+		openID = wxUser.OpenID
160
+	} else {
161
+		openID = token.ID
162
+	}
163
+
164
+	// 查询数据库是否存在已有映射
165
+	userMapList, err := s.dao.GetUserMappingByOpenID(openID)
166
+	if err != nil {
167
+		utils.LogError("校验人员失败: " + err.Error())
168
+		return map[string]interface{}{
169
+			"code":  http.StatusInternalServerError,
170
+			"error": errors.New("校验人员失败"),
171
+		}
172
+	}
173
+
174
+	var userMapping *model.TaUserMapping
175
+	for _, ump := range userMapList {
176
+		if openID == ump.Openid && models.ACCMAP_WECHAT == ump.AccountType {
177
+			userMapping = &ump
178
+		}
179
+	}
180
+
181
+	// 如果尚无人员映射信息, 代表人员初次使用本系统
182
+	if userMapping == nil {
183
+		// 如果没有微信用户信息, 代表产生了未知异常
184
+		if wxUser == nil || wxUser.UnionID == "" {
185
+			return map[string]interface{}{
186
+				"code":  http.StatusInternalServerError,
187
+				"error": errors.New("系统异常, 请清空缓存后重试"),
188
+			}
189
+		}
190
+
191
+		wxInfoJSON, err := json.Marshal(wxUser)
192
+		if err != nil {
193
+			utils.LogError("转换微信json信息失败: " + err.Error())
194
+			return map[string]interface{}{
195
+				"code":  http.StatusInternalServerError,
196
+				"error": errors.New("微信信息异常"),
197
+			}
198
+		}
199
+
200
+		userMapping = &model.TaUserMapping{
201
+			AccountType: models.ACCMAP_WECHAT,
202
+			Openid:      openID,
203
+			Uuid:        wxUser.UnionID,
204
+			AccountInfo: string(wxInfoJSON),
205
+		}
206
+	}
207
+
208
+	// 更新映射信息, 没有的话则插入
209
+	err = s.dao.UpdateUserMapping(userMapping)
210
+	if err != nil {
211
+		utils.LogError("保存用户映射信息失败: " + err.Error())
212
+		return map[string]interface{}{
213
+			"code":  http.StatusInternalServerError,
214
+			"error": errors.New("更新用户信息失败"),
215
+		}
216
+	}
217
+	s.ctx.Set("userMap", *userMapping)
218
+
219
+	if !s.needAuth(gctx) {
220
+		return nil
221
+	}
222
+
223
+	var cust *model.TaCustomer
224
+
225
+	// 如果只有映射, 但是没有人员信息
226
+	// 则新增人员
227
+	if userMapping.UserId == "" {
228
+		cust, err = s.saveNewCustomer(wxUser, userMapping)
229
+		if err != nil {
230
+			return map[string]interface{}{
231
+				"code":  http.StatusInternalServerError,
232
+				"error": err,
233
+			}
234
+		}
235
+	} else {
236
+		cust, err = s.customerdao.GetCustomerByID(userMapping.UserId)
237
+		if err != nil {
238
+			utils.LogError("查询用户信息失败: " + err.Error())
239
+			return map[string]interface{}{
240
+				"code":  http.StatusInternalServerError,
241
+				"error": err,
242
+			}
243
+		}
244
+	}
245
+	s.ctx.Set("customer", *cust)
246
+
247
+	if cust.UserId != "" {
248
+		if err := s.SetUserProfile(cust.UserId); err != nil {
249
+			return map[string]interface{}{
250
+				"code":  http.StatusInternalServerError,
251
+				"error": err,
252
+			}
253
+		}
254
+	}
255
+
256
+	return nil
257
+}
258
+
259
+// wechartSignIn 使用 code 微信登录
260
+func (s *SysServ) wechartSignIn(gctx *context.Context, code string) (*utils.WechatUser, error) {
261
+	if beego.BConfig.RunMode == "dev" {
262
+		return &utils.WechatUser{
263
+			OpenID: "OPENID",
264
+		}, nil
265
+	}
266
+
267
+	// 初始化微信配置
268
+	if err := s.initWechatClient(s.org.OrgId); err != nil {
269
+		utils.LogError("初始化微信客户端失败: " + err.Error())
270
+		return nil, errors.New("初始化微信客户端失败")
271
+	}
272
+
273
+	// 获取 微信信息
274
+	// 可能出现的情况是 openid 获取到了, 但是详情没有获取到
275
+	wxUserMap, err := utils.WxClientFor(s.org.OrgId).GetUserInfo(code)
276
+	if err != nil {
277
+		utils.LogError("获取微信信息失败: " + err.Error())
278
+
279
+		if wxUserMap == nil {
280
+			return nil, errors.New("获取微信信息失败")
281
+		}
282
+	}
283
+
284
+	return utils.MapToWechatUser(wxUserMap), nil
285
+}
286
+
287
+func (s *SysServ) getToken(gctx *context.Context) (*utils.JWTToken, error) {
288
+	tokenRaw := gctx.Input.Header(utils.TokenHeader)
289
+	if tokenRaw == "" {
290
+		return nil, nil
291
+	}
292
+
293
+	tokenEnStr := strings.Trim(strings.TrimLeft(tokenRaw, utils.TokenSchema), " ")
294
+
295
+	token, err := utils.PareseToken(tokenEnStr)
296
+	if err != nil {
297
+		utils.LogError("解析 Token 失败: " + err.Error())
298
+		return nil, errors.New("解析 Token 失败")
299
+	}
300
+
301
+	return utils.MapToJWTToken(token), nil
302
+}
303
+
304
+func (s *SysServ) needAuth(gctx *context.Context) bool {
305
+	route := gctx.Input.URL()
306
+	apiPrefix := beego.AppConfig.String("api::prefix")
307
+	guestAPI := beego.AppConfig.String("api::guest")
308
+
309
+	if strings.Index(route, apiPrefix+strings.Split(guestAPI, ":")[0]) > -1 {
310
+		return false
311
+	}
312
+
313
+	return true
314
+}
315
+
34
 // SetUserProfile 设置用户信息
316
 // SetUserProfile 设置用户信息
35
 func (s *SysServ) SetUserProfile(id string) error {
317
 func (s *SysServ) SetUserProfile(id string) error {
36
 	user, err := s.dao.GetPureUserInfo(id)
318
 	user, err := s.dao.GetPureUserInfo(id)
60
 	return nil
342
 	return nil
61
 }
343
 }
62
 
344
 
63
-// SetCustomer 设置客户信息
64
-func (s *SysServ) SetCustomer(id string) error {
65
-	cust, err := s.dao.GetCustomer(id)
66
-	if err != nil {
67
-		return utils.LogError("获取客户基本信息失败: " + err.Error())
68
-	}
69
-
70
-	s.ctx.Set("customer", *cust)
71
-	return nil
72
-}
73
-
74
-// SaveNewCustomer 新增用户
75
-func (s *SysServ) SaveNewCustomer(wxInfo map[string]interface{}, userMap *model.TaUserMapping) (*model.TaCustomer, error) {
76
-	// 微信相关字段
77
-	nickyName := wxInfo["nickname"].(string)
78
-	sex := wxInfo["sex"].(float64)
79
-	headimgurl := wxInfo["headimgurl"].(string)
80
-
81
-	org := s.ctx.Get("org").(model.SysOrg)
82
-
345
+// saveNewCustomer 新增用户
346
+func (s *SysServ) saveNewCustomer(wxUser *utils.WechatUser, userMap *model.TaUserMapping) (*model.TaCustomer, error) {
83
 	cust := model.TaCustomer{
347
 	cust := model.TaCustomer{
84
-		CustomerName: nickyName,
85
-		Name:         nickyName,
86
-		Sex:          int(sex),
87
-		Headimgurl:   headimgurl,
88
-		OrgId:        org.OrgId,
348
+		CustomerName: wxUser.NickName,
349
+		Name:         wxUser.NickName,
350
+		Sex:          int(wxUser.Sex),
351
+		Headimgurl:   wxUser.HeadImgURL,
352
+		OrgId:        s.org.OrgId,
89
 	}
353
 	}
90
 
354
 
91
 	if err := s.customerdao.SaveCustomer(&cust); err != nil {
355
 	if err := s.customerdao.SaveCustomer(&cust); err != nil {
130
 
394
 
131
 	accountRaw, err := json.Marshal(user)
395
 	accountRaw, err := json.Marshal(user)
132
 	if err != nil {
396
 	if err != nil {
133
-		beego.Error(err)
134
 		return nil, err
397
 		return nil, err
135
 	}
398
 	}
136
 	account := string(accountRaw)
399
 	account := string(accountRaw)
146
 	userMapList, err := s.dao.GetUserMappingByOpenID(openID)
409
 	userMapList, err := s.dao.GetUserMappingByOpenID(openID)
147
 
410
 
148
 	if err != nil {
411
 	if err != nil {
149
-		beego.Error(err)
150
 		return nil, err
412
 		return nil, err
151
 	}
413
 	}
152
 
414
 
172
 	return &userMapping, nil
434
 	return &userMapping, nil
173
 }
435
 }
174
 
436
 
175
-// GetWeChatConfig 获取微信配置
176
-func (s SysServ) GetWeChatConfig(org string) (map[string]string, error) {
177
-	conf, err := s.dao.GetWeChatConfig(org)
437
+// initWechatClient 初始化微信客户端
438
+func (s SysServ) initWechatClient(orgID string) error {
439
+	conf, err := s.dao.GetWeChatConfig(orgID)
178
 	if err != nil {
440
 	if err != nil {
179
-		return nil, err
441
+		utils.LogError("获取微信配置失败: " + err.Error())
442
+		return errors.New("获取微信配置失败")
180
 	}
443
 	}
181
 
444
 
182
-	if conf.ConfId == "" {
183
-		return nil, errors.New("未找到微信配置")
445
+	if conf == nil || conf.ConfId == "" {
446
+		return errors.New("未找到微信配置")
184
 	}
447
 	}
185
 
448
 
186
-	return map[string]string{
449
+	cert := map[string]string{
187
 		"appid":  conf.Appid,
450
 		"appid":  conf.Appid,
188
 		"secret": conf.Secret,
451
 		"secret": conf.Secret,
189
 		"token":  conf.Token,
452
 		"token":  conf.Token,
190
 		"aeskey": conf.Aeskey,
453
 		"aeskey": conf.Aeskey,
191
 		"wxid":   conf.Wxid,
454
 		"wxid":   conf.Wxid,
192
-	}, nil
455
+	}
456
+
457
+	utils.WxClientSingleton(orgID, cert)
458
+	return nil
193
 }
459
 }
194
 
460
 
195
 // SetOrgByID 获取组织
461
 // SetOrgByID 获取组织
203
 	}
469
 	}
204
 
470
 
205
 	s.ctx.Set("org", *org)
471
 	s.ctx.Set("org", *org)
472
+	s.org = *org
206
 
473
 
207
 	return nil
474
 	return nil
208
 }
475
 }

+ 47
- 0
utils/jwt.go View File

2
 
2
 
3
 import (
3
 import (
4
 	"errors"
4
 	"errors"
5
+	"time"
5
 
6
 
6
 	jwt "github.com/dgrijalva/jwt-go"
7
 	jwt "github.com/dgrijalva/jwt-go"
7
 )
8
 )
8
 
9
 
10
+const (
11
+	TokenHeader = "Authorization"
12
+	TokenSchema = "Bearer"
13
+)
14
+
9
 var tokenSignedKey = []byte(`Yansen is so handsome!`)
15
 var tokenSignedKey = []byte(`Yansen is so handsome!`)
10
 
16
 
11
 // CreateToken 获取token
17
 // CreateToken 获取token
32
 
38
 
33
 	return nil, errors.New("Token 解析 未知错误")
39
 	return nil, errors.New("Token 解析 未知错误")
34
 }
40
 }
41
+
42
+// JWTToken token 内容
43
+type JWTToken struct {
44
+	Guest    bool
45
+	ID       string
46
+	Password string
47
+	Expire   time.Time
48
+}
49
+
50
+// ToMap 转 map
51
+func (t *JWTToken) ToMap() map[string]interface{} {
52
+	return map[string]interface{}{
53
+		"guest":    t.Guest,
54
+		"user":     t.ID,
55
+		"password": t.Password,
56
+		"exp":      t.Expire,
57
+	}
58
+}
59
+
60
+// MapToJWTToken map 映射 Token
61
+func MapToJWTToken(data map[string]interface{}) *JWTToken {
62
+	token := JWTToken{}
63
+
64
+	if data["guest"] != nil {
65
+		token.Guest = data["guest"].(bool)
66
+	}
67
+
68
+	if data["user"] != nil {
69
+		token.ID = data["user"].(string)
70
+	}
71
+
72
+	if data["password"] != nil {
73
+		token.Password = data["password"].(string)
74
+	}
75
+
76
+	if data["exp"] != nil {
77
+		token.Expire = data["exp"].(time.Time)
78
+	}
79
+
80
+	return &token
81
+}

+ 56
- 0
utils/wechat.go View File

6
 
6
 
7
 var wxClients map[string]*wx.Client
7
 var wxClients map[string]*wx.Client
8
 
8
 
9
+type WechatUser struct {
10
+	OpenID     string  `json:"openid"`
11
+	NickName   string  `json:"nickname"`
12
+	Sex        float64 `json:"sex"`
13
+	Province   string  `json:"province"`
14
+	City       string  `json:"city"`
15
+	Country    string  `json:"country"`
16
+	HeadImgURL string  `json:"headimgurl"`
17
+	UnionID    string  `json:"unionid"`
18
+}
19
+
9
 // WxClientSingleton 初始化
20
 // WxClientSingleton 初始化
10
 func WxClientSingleton(org string, cert map[string]string) {
21
 func WxClientSingleton(org string, cert map[string]string) {
11
 	if wxClients == nil {
22
 	if wxClients == nil {
32
 func init() {
43
 func init() {
33
 	wx.SetLogInst(defaultLogger)
44
 	wx.SetLogInst(defaultLogger)
34
 }
45
 }
46
+
47
+// MapToWechatUser 映射微信人员
48
+func MapToWechatUser(data map[string]interface{}) *WechatUser {
49
+	subscribe, has := data["subscribe"]
50
+	if has {
51
+		if subscribe == nil {
52
+			return nil
53
+		}
54
+
55
+		sub := subscribe.(float64)
56
+		if sub == 0 {
57
+			return nil
58
+		}
59
+	}
60
+
61
+	user := WechatUser{
62
+		OpenID: data["openid"].(string),
63
+	}
64
+
65
+	if data["sex"] != nil {
66
+		user.Sex = data["sex"].(float64)
67
+	}
68
+
69
+	if data["province"] != nil {
70
+		user.Province = data["province"].(string)
71
+	}
72
+
73
+	if data["city"] != nil {
74
+		user.City = data["city"].(string)
75
+	}
76
+
77
+	if data["country"] != nil {
78
+		user.Country = data["country"].(string)
79
+	}
80
+
81
+	if data["headimgurl"] != nil {
82
+		user.HeadImgURL = data["headimgurl"].(string)
83
+	}
84
+
85
+	if data["unionid"] != nil {
86
+		user.UnionID = data["unionid"].(string)
87
+	}
88
+
89
+	return &user
90
+}