auth_controller.go 9.5 KB

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