123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. package service
  2. import (
  3. "wechat-conf/utils"
  4. )
  5. const (
  6. PAGENUM = 10
  7. )
  8. // SysServ 系统处理
  9. type SysServ struct {
  10. ctx *utils.Context
  11. }
  12. // NewSysServ 初始化
  13. func NewSysServ(ctx *utils.Context) *SysServ {
  14. return &SysServ{
  15. ctx: ctx,
  16. }
  17. }
  18. // // AuthAndInitCtx 鉴权
  19. // // gctx 是 beego 框架中的 Context
  20. // func (s *SysServ) AuthAndInitCtx(gctx *context.Context) map[string]interface{} {
  21. // // 确认机构
  22. // orgID := gctx.Input.Query(":org")
  23. // if orgID == "" {
  24. // return map[string]interface{}{
  25. // "code": http.StatusBadRequest,
  26. // "error": errors.New("接口地址访问不正确"),
  27. // }
  28. // }
  29. // if err := s.SetOrgByID(orgID); err != nil {
  30. // return map[string]interface{}{
  31. // "code": http.StatusInternalServerError,
  32. // "error": err,
  33. // }
  34. // }
  35. // // 客户端类型
  36. // // 通过 UA 判断
  37. // clientType := utils.GetClientType(gctx.Request)
  38. // // pc 管理端
  39. // if clientType == utils.ClientAdmin {
  40. // return s.authPCAdmin(gctx)
  41. // }
  42. // // 小程序 端
  43. // if strings.Index(gctx.Input.URI(), "/wechat/mini") > -1 {
  44. // return s.authMini(gctx)
  45. // }
  46. // // wechat 端
  47. // if clientType == utils.ClientWechat {
  48. // return s.authWechat(gctx)
  49. // }
  50. // // if clientType == utils.ClientMini {
  51. // // return s.authMini(gctx)
  52. // // }
  53. // return map[string]interface{}{
  54. // "code": http.StatusBadRequest,
  55. // "error": errors.New("暂无该客户端的 API"),
  56. // }
  57. // }
  58. // // NewToken 设置 TOKEN
  59. // // 15 分钟后过期
  60. // func (s *SysServ) NewToken(batch string) string {
  61. // var token *utils.JWTToken
  62. // exp := time.Now().Local().Add(15 * time.Second)
  63. // if s.ctx.Get("userMap") != nil {
  64. // userMap := s.ctx.Get("userMap").(model.TaUserMapping)
  65. // token = &utils.JWTToken{
  66. // Guest: false,
  67. // ID: userMap.Openid,
  68. // Expire: exp,
  69. // BatchNo: batch,
  70. // }
  71. // } else if s.ctx.Get("user") != nil {
  72. // user := s.ctx.Get("user").(model.SysUser)
  73. // token = &utils.JWTToken{
  74. // Guest: false,
  75. // ID: user.UserId,
  76. // Expire: exp,
  77. // BatchNo: batch,
  78. // }
  79. // } else {
  80. // token = &utils.JWTToken{
  81. // Guest: true,
  82. // Expire: exp,
  83. // }
  84. // }
  85. // tokenEncodeStr, err := utils.CreateToken(token.ToMap())
  86. // if err != nil {
  87. // utils.LogError("系统生成 Token 失败: " + err.Error())
  88. // return ""
  89. // }
  90. // // 入库
  91. // if !token.Guest {
  92. // if err := models.InsertToken(tokenEncodeStr, token.ID, batch, exp); err != nil {
  93. // utils.LogError("入库 Token 失败: " + err.Error())
  94. // return tokenEncodeStr
  95. // }
  96. // }
  97. // return tokenEncodeStr
  98. // }
  99. // // authPCAdmin
  100. // // 管理端 API 校验
  101. // func (s *SysServ) authPCAdmin(gctx *context.Context) map[string]interface{} {
  102. // if !s.needAuth(gctx) {
  103. // return nil
  104. // }
  105. // // 获取 token
  106. // token, err := s.getToken(gctx)
  107. // if err != nil {
  108. // // token 报错一律视为需要重新登录
  109. // return map[string]interface{}{
  110. // "code": http.StatusUnauthorized,
  111. // "error": err,
  112. // }
  113. // }
  114. // if token.ID == "" || token.Guest == true {
  115. // return map[string]interface{}{
  116. // "code": http.StatusUnauthorized,
  117. // "error": errors.New("用户未登录"),
  118. // }
  119. // }
  120. // if err := s.SetUserProfile(token.ID); err != nil {
  121. // return map[string]interface{}{
  122. // "code": http.StatusInternalServerError,
  123. // "error": err,
  124. // }
  125. // }
  126. // return nil
  127. // }
  128. // func (s *SysServ) authWechat(gctx *context.Context) map[string]interface{} {
  129. // var wxUser *utils.WechatUser
  130. // var openID string
  131. // if beego.BConfig.RunMode == "dev" {
  132. // openID = "OPENID"
  133. // } else {
  134. // // 初始化微信配置
  135. // if err := s.initWechatClient(s.org.OrgId); err != nil {
  136. // utils.LogError("初始化微信服务失败: " + err.Error())
  137. // return map[string]interface{}{
  138. // "code": http.StatusInternalServerError,
  139. // "error": errors.New("初始化微信服务失败"),
  140. // }
  141. // }
  142. // // 微信 code
  143. // code := gctx.Input.Query("code")
  144. // // 获取 token
  145. // token, err := s.getToken(gctx)
  146. // if err != nil {
  147. // tokenStr := s.ctx.Get("token").(string)
  148. // if tokenStr != "" {
  149. // // token 报错一律视为需要重新登录
  150. // return map[string]interface{}{
  151. // "code": http.StatusUnauthorized,
  152. // "error": err,
  153. // "message": map[string]interface{}{
  154. // "appid": utils.GetWxAppID(s.org.OrgId),
  155. // },
  156. // }
  157. // }
  158. // }
  159. // // 未登录 或 未验证
  160. // if token == nil || token.ID == "" {
  161. // if code == "" {
  162. // return map[string]interface{}{
  163. // "code": http.StatusUnauthorized,
  164. // "error": errors.New("请授权微信用户登录"),
  165. // "message": map[string]interface{}{
  166. // "appid": utils.GetWxAppID(s.org.OrgId),
  167. // },
  168. // }
  169. // }
  170. // // 微信用户信息
  171. // var err error
  172. // wxUser, err = s.wechartSignIn(gctx, code)
  173. // if err != nil {
  174. // return map[string]interface{}{
  175. // "code": http.StatusInternalServerError,
  176. // "error": err,
  177. // }
  178. // }
  179. // if wxUser == nil {
  180. // return map[string]interface{}{
  181. // "code": http.StatusInternalServerError,
  182. // "error": errors.New("请先关注公众号"),
  183. // }
  184. // }
  185. // utils.LogError("获取到微信人员: ", wxUser)
  186. // openID = wxUser.OpenID
  187. // } else {
  188. // openID = token.ID
  189. // }
  190. // }
  191. // // 查询数据库是否存在已有映射
  192. // userMapList, err := models.GetUserMappingByOpenID(openID)
  193. // if err != nil {
  194. // utils.LogError("校验人员失败: " + err.Error())
  195. // return map[string]interface{}{
  196. // "code": http.StatusInternalServerError,
  197. // "error": errors.New("校验人员失败"),
  198. // }
  199. // }
  200. // var userMapping *model.TaUserMapping
  201. // for _, ump := range userMapList {
  202. // if openID == ump.Openid && models.ACCMAP_WECHAT == ump.AccountType {
  203. // userMapping = &ump
  204. // }
  205. // }
  206. // // 如果尚无人员映射信息, 代表人员初次使用本系统
  207. // if userMapping == nil {
  208. // // 如果没有微信用户信息, 代表产生了未知异常
  209. // if wxUser == nil || wxUser.OpenID == "" {
  210. // return map[string]interface{}{
  211. // "code": http.StatusInternalServerError,
  212. // "error": errors.New("系统异常, 请清空缓存后重试"),
  213. // }
  214. // }
  215. // wxInfoJSON, err := json.Marshal(wxUser)
  216. // if err != nil {
  217. // utils.LogError("转换微信json信息失败: " + err.Error())
  218. // return map[string]interface{}{
  219. // "code": http.StatusInternalServerError,
  220. // "error": errors.New("微信信息异常"),
  221. // }
  222. // }
  223. // userMapping = &model.TaUserMapping{
  224. // AccountType: models.ACCMAP_WECHAT,
  225. // Openid: openID,
  226. // Uuid: wxUser.UnionID,
  227. // AccountInfo: string(wxInfoJSON),
  228. // }
  229. // }
  230. // // 防止JSON解析失败
  231. // if userMapping.AccountInfo == "" {
  232. // userMapping.AccountInfo = "{}"
  233. // }
  234. // // 更新映射信息, 没有的话则插入
  235. // err = models.EditUserMapping(userMapping)
  236. // if err != nil {
  237. // utils.LogError("保存用户映射信息失败: " + err.Error())
  238. // return map[string]interface{}{
  239. // "code": http.StatusInternalServerError,
  240. // "error": errors.New("更新用户信息失败"),
  241. // }
  242. // }
  243. // s.ctx.Set("userMap", *userMapping)
  244. // // if !s.needAuth(gctx) {
  245. // // return nil
  246. // // }
  247. // var cust *model.TaCustomer
  248. // // 如果只有映射, 但是没有人员信息
  249. // // 则新增人员
  250. // if userMapping.UserId == "" {
  251. // cust, err = s.saveNewCustomer(wxUser, userMapping)
  252. // if err != nil {
  253. // return map[string]interface{}{
  254. // "code": http.StatusInternalServerError,
  255. // "error": err,
  256. // }
  257. // }
  258. // } else {
  259. // cust, err = models.GetCustomerByID(userMapping.UserId)
  260. // if err != nil {
  261. // utils.LogError("查询用户信息失败: " + err.Error())
  262. // return map[string]interface{}{
  263. // "code": http.StatusInternalServerError,
  264. // "error": err,
  265. // }
  266. // }
  267. // }
  268. // s.ctx.Set("customer", *cust)
  269. // if cust.UserId != "" {
  270. // if err := s.SetUserProfile(cust.UserId); err != nil {
  271. // return map[string]interface{}{
  272. // "code": http.StatusInternalServerError,
  273. // "error": err,
  274. // }
  275. // }
  276. // }
  277. // return nil
  278. // }
  279. // // 小程序端暂时无人员或者其他业务要求
  280. // func (s *SysServ) authMini(gctx *context.Context) map[string]interface{} {
  281. // if err := s.initMiniClient(s.org.OrgId); err != nil {
  282. // utils.LogError("初始化小程序服务失败: " + err.Error())
  283. // return map[string]interface{}{
  284. // "code": http.StatusInternalServerError,
  285. // "error": errors.New("初始化小程序服务失败"),
  286. // }
  287. // }
  288. // return nil
  289. // }
  290. // // wechartSignIn 使用 code 微信登录
  291. // func (s *SysServ) wechartSignIn(gctx *context.Context, code string) (*utils.WechatUser, error) {
  292. // // 获取 微信信息
  293. // // 可能出现的情况是 openid 获取到了, 但是详情没有获取到
  294. // wxUserMap, err := utils.WxClientFor(s.org.OrgId).GetUserInfo(code)
  295. // if err != nil {
  296. // utils.LogError("获取微信信息失败: " + err.Error())
  297. // if wxUserMap == nil {
  298. // return nil, errors.New("获取微信信息失败")
  299. // }
  300. // }
  301. // return utils.MapToWechatUser(wxUserMap), nil
  302. // }
  303. // func (s *SysServ) getToken(gctx *context.Context) (*utils.JWTToken, error) {
  304. // tokenEnStr := gctx.Input.Query("token")
  305. // if tokenEnStr == "" {
  306. // tokenRaw := gctx.Input.Header(utils.TokenHeader)
  307. // if tokenRaw == "" {
  308. // return new(utils.JWTToken), nil
  309. // }
  310. // tokenEnStr = strings.Trim(strings.TrimLeft(tokenRaw, utils.TokenSchema), " ")
  311. // } else {
  312. // tokenEnStr = strings.Trim(strings.TrimLeft(tokenEnStr, utils.TokenSchema), " ")
  313. // }
  314. // s.ctx.Set("token", tokenEnStr)
  315. // token, err := utils.PareseToken(tokenEnStr)
  316. // if err != nil {
  317. // utils.LogError("解析 Token 失败: " + err.Error())
  318. // return nil, errors.New("解析Token失败或已过期")
  319. // }
  320. // // 校验 token
  321. // tk, err := models.GetToken(tokenEnStr)
  322. // if err != nil {
  323. // utils.LogError("查询 Token 失败: " + err.Error())
  324. // return nil, errors.New("校验Token失败或已过期")
  325. // }
  326. // if tk.Status == models.STATUS_DEL {
  327. // return nil, errors.New("超时 或者 Token 已过期")
  328. // }
  329. // s.ctx.Set("token-batch", tk.BatchNo)
  330. // return utils.MapToJWTToken(token), nil
  331. // }
  332. // // UpdateTokenExpire 更新 token 为过期
  333. // // 如果发生错误, 此处选择忽略
  334. // func (s *SysServ) UpdateTokenExpire(token, uid string) {
  335. // if err := models.UpdateTokenExpire(token, uid); err != nil {
  336. // utils.LogError("更新 Token 过期失败: " + err.Error())
  337. // }
  338. // }
  339. // func (s *SysServ) needAuth(gctx *context.Context) bool {
  340. // route := gctx.Input.URL()
  341. // apiPrefix := beego.AppConfig.String("api::prefix")
  342. // guestAPI := beego.AppConfig.String("api::guest")
  343. // if strings.Index(route, apiPrefix+strings.Split(guestAPI, ":")[0]) > -1 {
  344. // return false
  345. // }
  346. // return true
  347. // }
  348. // // SetUserProfile 设置用户信息
  349. // func (s *SysServ) SetUserProfile(id string) error {
  350. // user, err := models.GetPureUserInfo(id)
  351. // if err != nil {
  352. // return utils.LogError("获取用户基本信息失败: " + err.Error())
  353. // }
  354. // s.ctx.Set("user", *user)
  355. // cases, err := models.GetUserCase(id)
  356. // if err != nil {
  357. // return utils.LogError("获取用户案场信息失败: " + err.Error())
  358. // }
  359. // s.ctx.Set("cases", cases)
  360. // found := false
  361. // for _, cs := range cases {
  362. // if cs.IsBelong == models.BOOL_TRUE {
  363. // found = true
  364. // s.ctx.Set("currentCase", cs)
  365. // }
  366. // }
  367. // if !found {
  368. // utils.LogError("用户没有设置默认案场")
  369. // }
  370. // return nil
  371. // }
  372. // // saveNewCustomer 新增用户
  373. // func (s *SysServ) saveNewCustomer(wxUser *utils.WechatUser, userMap *model.TaUserMapping) (*model.TaCustomer, error) {
  374. // cust := model.TaCustomer{
  375. // CustomerName: wxUser.NickName,
  376. // Name: wxUser.NickName,
  377. // Sex: int(wxUser.Sex),
  378. // Headimgurl: wxUser.HeadImgURL,
  379. // OrgId: s.org.OrgId,
  380. // }
  381. // if err := models.SaveCustomer(&cust); err != nil {
  382. // utils.LogError("更新客户信息失败: " + err.Error())
  383. // return nil, errors.New("更新客户信息失败")
  384. // }
  385. // account := new(model.TaCustomerAccount)
  386. // account.CustomerId = cust.CustomerId
  387. // account.CustomerName = cust.CustomerName
  388. // account.OrgId = cust.OrgId
  389. // account.Amount = "0"
  390. // account.Points = "0"
  391. // account.PayedAmount = "0"
  392. // account.PayedPoints = "0"
  393. // if err := models.SaveAccount(account); err != nil {
  394. // utils.LogError("插入账户信息失败: " + err.Error())
  395. // return nil, errors.New("更新客户信息失败")
  396. // }
  397. // // 更新映射表信息
  398. // userMap.UserId = cust.CustomerId
  399. // if err := models.UpdateUserMapping(userMap, []string{"user_id"}); err != nil {
  400. // utils.LogError("更新用户映射信息失败:" + err.Error())
  401. // return nil, errors.New("映射用户信息失败")
  402. // }
  403. // return &cust, nil
  404. // }
  405. // // initWechatClient 初始化微信客户端
  406. // func (s *SysServ) initWechatClient(orgID string) error {
  407. // cert, err := models.GetWeChatConfig(orgID, models.WECHAT_WX)
  408. // if err != nil {
  409. // utils.LogError("获取微信配置失败: " + err.Error())
  410. // return errors.New("获取微信配置失败")
  411. // }
  412. // if cert == nil {
  413. // return errors.New("未找到微信配置")
  414. // }
  415. // utils.WxClientSingleton(orgID, cert)
  416. // return nil
  417. // }
  418. // func (s *SysServ) initMiniClient(orgID string) error {
  419. // cert, err := models.GetWeChatConfig(orgID, models.WECHAT_MINI)
  420. // if err != nil {
  421. // utils.LogError("获取小程序配置失败: " + err.Error())
  422. // return errors.New("获取小程序配置失败")
  423. // }
  424. // if cert == nil {
  425. // return errors.New("未找到小程序配置")
  426. // }
  427. // utils.MiniClientSingleton(orgID, cert)
  428. // return nil
  429. // }