auth_controller.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package user
  2. import (
  3. "bufio"
  4. "eta/eta_mini_ht_api/common/component/config"
  5. logger "eta/eta_mini_ht_api/common/component/log"
  6. "eta/eta_mini_ht_api/common/contants"
  7. "eta/eta_mini_ht_api/common/exception"
  8. authUtils "eta/eta_mini_ht_api/common/utils/auth"
  9. "eta/eta_mini_ht_api/controllers"
  10. "eta/eta_mini_ht_api/service/auth"
  11. "eta/eta_mini_ht_api/service/user"
  12. "os"
  13. "strings"
  14. )
  15. type AuthController struct {
  16. controllers.BaseController
  17. }
  18. const ChinaAreaCode = "86"
  19. // LoginReq 获取验证码请求
  20. type LoginReq struct {
  21. VerifyCode string `json:"verifyCode"`
  22. Mobile string `json:"mobile"`
  23. AreaCode string `json:"areaCode"`
  24. }
  25. // Logout 小程序退出登录接口
  26. // @Summary 小程序退出登录接口
  27. // @Description 用户小程序退出登录
  28. // @Param mobile body LoginReq true "登录请求体"
  29. // @Success 200 {object} controllers.BaseResponse
  30. // @router /Logout [post]
  31. func (a *AuthController) Logout() {
  32. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  33. result = a.InitWrapData("退出登录失败")
  34. userInfo := a.Data["user"].(user.User)
  35. err = auth.Logout(userInfo.Id, userInfo.OpenId)
  36. if err != nil {
  37. a.FailedResult("退出登录失败", result)
  38. return
  39. }
  40. return
  41. })
  42. }
  43. // Login 小程序登录接口
  44. // @Summary 小程序用户登录
  45. // @Description 用户通过微信小程序登录
  46. // @Param mobile body LoginReq true "登录请求体"
  47. // @Success 200 {object} controllers.BaseResponse
  48. // @router /login [post]
  49. func (a *AuthController) Login() {
  50. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  51. result = a.InitWrapData("登录失败")
  52. loginReq := new(LoginReq)
  53. a.GetPostParams(loginReq)
  54. userInfo := a.Data["user"].(user.User)
  55. if userInfo.Mobile != "" && userInfo.Mobile != loginReq.Mobile {
  56. a.FailedResult("登录失败,已绑定手机号:"+userInfo.Mobile, result)
  57. err = exception.New(exception.IllegalAreaCode)
  58. return
  59. }
  60. mobileUser, err := user.GetUserByMobile(loginReq.Mobile)
  61. if err != nil {
  62. a.FailedResult("登录失败:"+userInfo.Mobile, result)
  63. err = exception.New(exception.BindMobileFailed)
  64. return
  65. }
  66. if mobileUser.Id > 0 && (mobileUser.Id != userInfo.Id && mobileUser.Mobile == loginReq.Mobile) {
  67. a.FailedResult("登录失败,该手机号已绑定过微信", result)
  68. err = exception.New(exception.IllegalAreaCode)
  69. return
  70. }
  71. if loginReq.AreaCode == "" || !checkValidAreaCode(loginReq.AreaCode) {
  72. a.FailedResult("非法的手机区号", result)
  73. err = exception.New(exception.IllegalAreaCode)
  74. return
  75. }
  76. if loginReq.AreaCode == ChinaAreaCode && !authUtils.IsValidMobile(loginReq.Mobile) {
  77. a.FailedResult("只支持86的区号", result)
  78. err = exception.New(exception.IllegalPhoneNumber)
  79. return
  80. }
  81. err = auth.CheckUser(loginReq.Mobile, loginReq.VerifyCode)
  82. if err != nil {
  83. a.FailedResult("验证码错误", result)
  84. logger.Warn("验证码校验失败:%v", err)
  85. return
  86. }
  87. //用户手机为空需要绑定手机
  88. if userInfo.Mobile == "" {
  89. //注册用户或者登录
  90. err = auth.BindMobile(userInfo.Id, loginReq.Mobile)
  91. if err != nil {
  92. a.FailedResult("登录异常,绑定手机失败", result)
  93. return
  94. }
  95. }
  96. //生成一个正式的登录token,生成登录流水
  97. token, err := auth.Login(userInfo.Id, userInfo.OpenId, loginReq.Mobile, loginReq.VerifyCode)
  98. if err != nil {
  99. a.FailedResult("登录异常,生成accessToken失败", result)
  100. return
  101. }
  102. a.SuccessResult("登录成功", &LoginResp{
  103. Token: token,
  104. }, result)
  105. return
  106. })
  107. }
  108. type LoginResp struct {
  109. Token string
  110. }
  111. // SmsCodeReq 获取验证码请求
  112. type SmsCodeReq struct {
  113. Mobile string `json:"mobile"`
  114. AreaCode string `json:"areaCode"`
  115. }
  116. // SMSCode 小程序手机验证码接口
  117. // @Summary 获取手机验证码
  118. // @Param mobile body SmsCodeReq true "小程序手机验证码接口"
  119. // @Success 200 {object} controllers.BaseResponse
  120. // @Description 用户发送手机验证码
  121. // @router /sendCode [post]
  122. func (a *AuthController) SMSCode() {
  123. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  124. result = a.InitWrapData("发送短信失败")
  125. mobile := new(SmsCodeReq)
  126. a.GetPostParams(mobile)
  127. if mobile.AreaCode == "" || !checkValidAreaCode(mobile.AreaCode) {
  128. a.FailedResult("发送短信失败", result)
  129. err = exception.New(exception.IllegalAreaCode)
  130. return
  131. }
  132. phoneNum := mobile.Mobile
  133. if mobile.AreaCode == ChinaAreaCode && !authUtils.IsValidMobile(phoneNum) {
  134. return result, exception.New(exception.IllegalPhoneNumber)
  135. }
  136. //发送短息
  137. err = auth.SendSMSCode(phoneNum)
  138. if err != nil {
  139. logger.Warn("发送短信失败:%v", err)
  140. return result, err
  141. }
  142. if err != nil {
  143. return result, err
  144. }
  145. result = &controllers.WrapData{Msg: "验证码发送成功"}
  146. return result, nil
  147. })
  148. }
  149. type RefreshTokenRes struct {
  150. Token string `json:"token"`
  151. Status string `json:"status"`
  152. IsBindMobile int `json:"isBindMobile"`
  153. TokenType string `json:"tokenType"`
  154. }
  155. // RefreshToken 更新token
  156. // @Summary 更新token
  157. // @Success 200 {object} controllers.BaseResponse
  158. // @Description 更新token
  159. // @router /refreshToken [get]
  160. func (a *AuthController) RefreshToken(code string) {
  161. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  162. result = a.InitWrapData("刷新token失败")
  163. if code == "" {
  164. logger.Error("code不能为空")
  165. return result, exception.New(exception.WeChatCodeEmpty)
  166. }
  167. //刷新token
  168. token, isBindMobile, status, tokenType, err := auth.RefreshToken(code)
  169. if err != nil {
  170. logger.Error("刷新token失败:%v", err)
  171. a.FailedResult("刷新token失败", result)
  172. return
  173. }
  174. a.SuccessResult("刷新token成功", RefreshTokenRes{
  175. Token: token,
  176. IsBindMobile: isBindMobile,
  177. TokenType: tokenType,
  178. Status: status,
  179. }, result)
  180. return
  181. })
  182. }
  183. // AreaCodes 小程序手机验证码接口
  184. // @Summary 获取手机验证码
  185. // @Param mobile body SmsCodeReq true "小程序手机验证码接口"
  186. // @Success 200 {object} controllers.BaseResponse
  187. // @Description 用户发送手机验证码
  188. // @router /areaCodes [get]
  189. func (a *AuthController) AreaCodes() {
  190. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  191. result = a.InitWrapData("获取区号失败")
  192. list, err := auth.GetAreaCodes()
  193. if err != nil {
  194. a.FailedResult("获取区号失败", result)
  195. }
  196. a.SuccessResult("获取区号成功", list, result)
  197. return
  198. })
  199. }
  200. type WXAppidResp struct {
  201. AppId string
  202. }
  203. // WXAppid 获取APPID
  204. // @Summary 获取APPID
  205. // @Success 200 {object} controllers.BaseResponse
  206. // @Description 获取APPID
  207. // @router /wxAppid [get]
  208. func (a *AuthController) WXAppid() {
  209. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  210. result = a.InitWrapData("获取AppId失败")
  211. appid := config.GetConfig(contants.WECHAT).(*config.WechatConfig).GetAppid()
  212. if err != nil {
  213. a.FailedResult("获取AppId失败", result)
  214. }
  215. a.SuccessResult("获取AppId成功", WXAppidResp{
  216. AppId: appid,
  217. }, result)
  218. return
  219. })
  220. }
  221. type FileResp struct {
  222. Content string
  223. }
  224. // Notice 获取注册须知
  225. // @Summary 获取注册须知
  226. // @Success 200 {object} controllers.BaseResponse
  227. // @Description 获取注册须知
  228. // @router /notice [get]
  229. func (a *AuthController) Notice() {
  230. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  231. result = a.InitWrapData("获取注册须知失败")
  232. fileConfig := config.GetConfig(contants.FILE).(*config.FileConfig)
  233. //publicKey := config.GetConfig(contants.FILE).(*config.FileConfig).GetPublicKey()
  234. noticeFile := fileConfig.GetNotice()
  235. content, err := readTextConfig(noticeFile)
  236. if err != nil {
  237. err = exception.New(exception.GetNoticeFileError)
  238. a.FailedResult("获取注册须知失败", result)
  239. }
  240. a.SuccessResult("获取注册须知成功", FileResp{
  241. Content: content,
  242. }, result)
  243. return
  244. })
  245. }
  246. // Disclaimer 获取免责声明
  247. // @Summary 获取免责声明
  248. // @Success 200 {object} controllers.BaseResponse
  249. // @Description 获取免责声明
  250. // @router /disclaimer [get]
  251. func (a *AuthController) Disclaimer() {
  252. controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
  253. result = a.InitWrapData("获取免责声明失败")
  254. fileConfig := config.GetConfig(contants.FILE).(*config.FileConfig)
  255. //publicKey := config.GetConfig(contants.FILE).(*config.FileConfig).GetPublicKey()
  256. disclaimerFile := fileConfig.GetDisclaimer()
  257. content, err := readTextConfig(disclaimerFile)
  258. if err != nil {
  259. a.FailedResult("获取免责声明失败", result)
  260. }
  261. a.SuccessResult("获取免责声明成功", FileResp{
  262. Content: content,
  263. }, result)
  264. return
  265. })
  266. }
  267. // 读取纯文本文件
  268. func readTextConfig(filename string) (content string, err error) {
  269. file, err := os.Open(filename)
  270. if err != nil {
  271. return "", err
  272. }
  273. defer file.Close()
  274. scanner := bufio.NewScanner(file)
  275. scanner.Split(bufio.ScanLines)
  276. var lines []string
  277. for scanner.Scan() {
  278. line := scanner.Text()
  279. lines = append(lines, line)
  280. }
  281. err = scanner.Err()
  282. return strings.Join(lines, "\n"), nil
  283. }
  284. func checkValidAreaCode(areaCode string) bool {
  285. list := auth.GetValidAreaCodes()
  286. if areaCode == "" || len(list) == 0 {
  287. return false
  288. }
  289. for _, code := range list {
  290. if areaCode == code {
  291. return true
  292. }
  293. }
  294. return false
  295. }