附近小店
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

389 linhas
10 KiB

  1. package svc
  2. import (
  3. "applet/app/db"
  4. "applet/app/db/model"
  5. "applet/app/e"
  6. "applet/app/lib/mob"
  7. "applet/app/lib/sms"
  8. "applet/app/lib/zhimeng"
  9. "applet/app/md"
  10. "applet/app/svc"
  11. "applet/app/utils"
  12. "applet/app/utils/cache"
  13. "applet/app/utils/logx"
  14. sms2 "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/sms"
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "github.com/gin-gonic/gin"
  19. "github.com/syyongx/php2go"
  20. "github.com/tidwall/gjson"
  21. "math/rand"
  22. "time"
  23. "xorm.io/xorm"
  24. )
  25. func Login(c *gin.Context) {
  26. r := new(md.LoginResponse)
  27. requestBody := new(md.FastLoginRequestBody)
  28. if err := c.ShouldBindJSON(&requestBody); err != nil {
  29. e.OutErr(c, e.ERR_INVALID_ARGS, err)
  30. return
  31. }
  32. user, _ := db.UserFindByMobileAll(svc.MasterDb(c), requestBody.Mobile)
  33. if user == nil {
  34. e.OutErr(c, 400, e.NewErr(400, "账号不存在"))
  35. return
  36. }
  37. if user.Password != utils.Md5(requestBody.Password) {
  38. e.OutErr(c, 400, e.NewErr(400, "密码不正确"))
  39. return
  40. }
  41. if err := svc.FastLoginUserExist(c, r, requestBody); err != nil {
  42. if e.ErrorIsAccountBan(err) {
  43. e.OutErr(c, e.ERR_USER_IS_BAN, err)
  44. return
  45. }
  46. e.OutErr(c, 400, err)
  47. return
  48. }
  49. e.OutSuc(c, r, nil)
  50. return
  51. }
  52. func LoginFastIn(c *gin.Context) {
  53. var req map[string]string
  54. if err := c.ShouldBindJSON(&req); err != nil {
  55. e.OutErr(c, e.ERR_INVALID_ARGS, err)
  56. return
  57. }
  58. if req["phone"] == "" {
  59. e.OutErr(c, 400, e.NewErr(400, "手机号不能为空"))
  60. return
  61. }
  62. if req["captcha"] == "" {
  63. e.OutErr(c, 400, e.NewErr(400, "验证码不能为空"))
  64. return
  65. }
  66. mob1, errr := mob.GetMobSDK(c.GetString("mid"))
  67. if errr != nil {
  68. e.OutErr(c, e.ERR_MOB_CONFIG, errr)
  69. return
  70. }
  71. if req["zone"] == "" {
  72. req["zone"] = "86"
  73. }
  74. send := map[string]interface{}{
  75. "phone": req["phone"],
  76. "zone": req["zone"],
  77. "code": req["captcha"],
  78. }
  79. var ok bool
  80. var err error
  81. // h5(wap) 登录
  82. smsPlatform := sms.GetSmsPlatform(c)
  83. key := fmt.Sprintf("%s_SMS_FastLogin_%s", db.SysCfgGet(c, "app_name"), req["phone"])
  84. if smsPlatform == "ljioe" {
  85. b, err := cache.GetBytes(key)
  86. if err != nil {
  87. e.OutErr(c, e.ERR_MOB_SMS_NO_EXISTS, err)
  88. return
  89. }
  90. if req["captcha"] != gjson.GetBytes(b, "data.captcha").String() {
  91. e.OutErr(c, e.ERR_MOB_SMS_NO_SAME, err)
  92. return
  93. }
  94. ok = true
  95. } else {
  96. c.Set("not_deduction_doing", "1")
  97. ok, err = mob1.MobSMS(c, send)
  98. if err != nil {
  99. e.OutErr(c, 400, err.Error())
  100. return
  101. }
  102. }
  103. r := new(md.LoginResponse)
  104. requestBody := &md.FastLoginRequestBody{
  105. Mobile: req["phone"],
  106. }
  107. if ok {
  108. // 短信验证通过
  109. user, isExist, err := db.UserGetByMobileIgnoreDelete(db.DBs[c.GetString("mid")], req["phone"], req["zone"])
  110. if err != nil {
  111. e.OutErr(c, e.ERR, err)
  112. return
  113. }
  114. //用户已注册过,获取用户信息并返回
  115. if isExist {
  116. if user.DeleteAt != 0 {
  117. e.OutErr(c, e.ERR_USER_IS_BAN)
  118. return
  119. }
  120. if err := svc.FastLoginUserExist(c, r, requestBody); err != nil {
  121. if e.ErrorIsAccountBan(err) {
  122. e.OutErr(c, e.ERR_USER_IS_BAN, err)
  123. return
  124. }
  125. e.OutErr(c, 400, err)
  126. return
  127. }
  128. e.OutSuc(c, r, nil)
  129. return
  130. }
  131. if err := FastLoginUserNoExist(c, r, requestBody); err != nil {
  132. // 创建失败时清空用户
  133. if r.UserID != "" {
  134. UserDeleteOne(c, r.UserID)
  135. }
  136. e.OutErr(c, e.ERR, err)
  137. return
  138. }
  139. cache.Del(key)
  140. // 返回登陆响应
  141. e.OutSuc(c, r, nil)
  142. return
  143. }
  144. // 验证码无效或者过期,验证码错误
  145. e.OutErr(c, e.ERR_SMS_AUTH, err)
  146. return
  147. }
  148. func FastLoginUserNoExist(c *gin.Context, r *md.LoginResponse, requestBody *md.FastLoginRequestBody) error {
  149. user := new(model.User)
  150. user.Username = requestBody.Mobile
  151. user.Password = utils.Md5(requestBody.Mobile)
  152. if requestBody.Password != "" {
  153. user.Password = utils.Md5(requestBody.Password)
  154. }
  155. user.Platform = c.GetHeader("platform")
  156. user.Phone = requestBody.Mobile
  157. appNameCn := db.SysCfgGet(c, "app_name_cn")
  158. user.Nickname = appNameCn + requestBody.Mobile[len(requestBody.Mobile)-4:len(requestBody.Mobile)]
  159. user.Zone = "86"
  160. lvs, err := db.UserLevlAll(c, db.DBs[c.GetString("mid")])
  161. if err != nil || len(lvs) == 0 {
  162. return errors.New("会员等级不存在")
  163. }
  164. user.Level = lvs[0].Id
  165. user.State = 1
  166. user.CreateAt = time.Now()
  167. user.UpdateAt = time.Now()
  168. // ---- 插入用户-----!
  169. exist, err := userCheck(c, user, db.UserInsert)
  170. if err != nil {
  171. return err
  172. }
  173. if exist {
  174. return errors.New("Register user is exist")
  175. }
  176. r.UserID = utils.IntToStr(user.Uid)
  177. // 生成jwt
  178. appName := db.SysCfgGet(c, "app_name")
  179. token, err := utils.GenToken(user.Uid, user.Username, user.Phone, appName, "", "")
  180. if err != nil {
  181. return logx.Warn(err)
  182. }
  183. // Insert user profile
  184. userProfile := new(model.UserProfile)
  185. userProfile.ArkidToken = token
  186. userProfile.Uid = user.Uid
  187. if userProfile.AvatarUrl == "" {
  188. userProfile.AvatarUrl = db.SysCfgGet(c, "app_user_default_avatar")
  189. }
  190. userProfile.IsNew = 1
  191. exist, err = userProfileCheck(c, userProfile, db.UserProfileInsert)
  192. if err != nil {
  193. return err
  194. }
  195. if exist {
  196. return errors.New("user Profile is exist")
  197. }
  198. //debug
  199. //生成邀请码 防止卡死
  200. GetInviteCode(c, user, userProfile)
  201. // 异步处理 有效会员和新会员
  202. // 写入缓存
  203. key := fmt.Sprintf("%s:token:%s", c.GetString("mid"), user.Username)
  204. _, err = cache.SetEx(key, token, 39528000) // 半年
  205. if err != nil {
  206. return logx.Warn(err)
  207. }
  208. r.Token = token
  209. r.UserID = utils.IntToStr(user.Uid)
  210. return nil
  211. }
  212. func GetInviteCode(c *gin.Context, user *model.User, userProfile *model.UserProfile) {
  213. if userProfile.InviteCode != "" {
  214. return
  215. }
  216. cc := c.Copy() // 传递上下文给 goroutine 的话 一定要使用副本,这样才能保证上下文的输出安全
  217. //生成邀请码的线程 直接访问怕慢
  218. go UserInviteCode(cc, &md.User{
  219. Info: user,
  220. Profile: userProfile,
  221. })
  222. return
  223. }
  224. func userCheck(c *gin.Context, user *model.User, f func(*xorm.Engine, *model.User) (int64, error)) (bool, error) {
  225. fmt.Println("user in userCheck is ", utils.SerializeStr(user))
  226. isExist, err := db.UserIsExistByMobile(db.DBs[c.GetString("mid")], user.Username)
  227. if isExist {
  228. return isExist, nil
  229. }
  230. _, err = f(db.DBs[c.GetString("mid")], user)
  231. return false, err
  232. }
  233. func userProfileCheck(c *gin.Context, userProfile *model.UserProfile, f func(*xorm.Engine, *model.UserProfile) (int64, error)) (bool, error) {
  234. isExist, err := db.UserProfileIsExistByUserID(db.DBs[c.GetString("mid")], userProfile.Uid)
  235. if isExist {
  236. return isExist, nil
  237. }
  238. _, err = f(db.DBs[c.GetString("mid")], userProfile)
  239. return false, err
  240. }
  241. func UserDeleteOne(c *gin.Context, id interface{}) (int64, error) {
  242. _, err := db.UserDelete(db.DBs[c.GetString("mid")], id)
  243. if err != nil {
  244. return 0, err
  245. }
  246. // 删除用户
  247. _, err = db.UserProfileDelete(db.DBs[c.GetString("mid")], id)
  248. if err != nil {
  249. return 0, err
  250. }
  251. // 删除用户关系
  252. _, err = db.UserRelateDelete(db.DBs[c.GetString("mid")], id)
  253. if err != nil {
  254. return 0, err
  255. }
  256. // 将他的下级pid清零
  257. us, err := db.UserProfileByPuid(db.DBs[c.GetString("mid")], id)
  258. if err != nil {
  259. return 0, err
  260. }
  261. for _, item := range *us {
  262. item.ParentUid = 0
  263. _, err = db.UserProfileUpdate(db.DBs[c.GetString("mid")], item.Uid, &item, "parent_uid")
  264. if err != nil {
  265. continue
  266. }
  267. }
  268. return 1, nil
  269. }
  270. func LoginSendSms(c *gin.Context) {
  271. var req map[string]string
  272. if err := c.ShouldBindJSON(&req); err != nil {
  273. e.OutErr(c, e.ERR_INVALID_ARGS, err)
  274. return
  275. }
  276. if req["phone"] == "" {
  277. e.OutErr(c, 400, e.NewErr(400, "手机号不能为空"))
  278. return
  279. }
  280. isExist, err := db.UserisExistByMobile(db.DBs[c.GetString("mid")], req["phone"])
  281. if err != nil {
  282. e.OutErr(c, e.ERR, err)
  283. return
  284. }
  285. userdata, _ := db.UserFindByPhoneOrNickname(db.DBs[c.GetString("mid")], req["phone"])
  286. if userdata != nil && userdata.State == 2 {
  287. e.OutErr(c, 400, e.NewErr(400, "账号已冻结"))
  288. return
  289. }
  290. types := ""
  291. if !isExist {
  292. types = "register"
  293. } else if isExist {
  294. types = "login"
  295. }
  296. smsType := svc.SysCfgGet(c, "sms_type")
  297. c.Set("sms_type", smsType)
  298. if c.GetString("sms_type") == "1" {
  299. count := sms2.SmsNumGetSmsNum(db.Db, "putong", c.GetString("mid"))
  300. if count-1 < 0 {
  301. e.OutErr(c, e.ERR_MOB_SMS_NO_AVA, err)
  302. return
  303. }
  304. } else {
  305. count, _ := zhimeng.SmsNum(db.Db, c.GetString("mid"), c.GetString("sms_type"), db.SysCfgGet(c, "third_zm_sms_key"), db.SysCfgGet(c, "third_zm_sms_secret"))
  306. if count-1 < 0 {
  307. e.OutErr(c, e.ERR_MOB_SMS_NO_AVA, err)
  308. return
  309. }
  310. }
  311. appName := db.SysCfgGet(c, "sms_push_sign")
  312. captcha := createCaptcha()
  313. content := fmt.Sprintf("【%s】验证码:%s", appName, captcha)
  314. key := fmt.Sprintf("%s_SMS_%s", db.SysCfgGet(c, "app_name"), req["phone"])
  315. templateCode := ""
  316. switch types {
  317. case "login":
  318. content = fmt.Sprintf("【%s】快捷登录验证码:%s", appName, captcha)
  319. key = fmt.Sprintf("%s_SMS_FastLogin_%s", db.SysCfgGet(c, "app_name"), req["phone"])
  320. templateCode = "login"
  321. case "register":
  322. content = fmt.Sprintf("【%s】注册验证码:%s", appName, captcha)
  323. key = fmt.Sprintf("%s_SMS_FastLogin_%s", db.SysCfgGet(c, "app_name"), req["phone"])
  324. templateCode = "register"
  325. }
  326. marshal, _ := json.Marshal(c.Request.Header)
  327. waykeys := "app_" + c.ClientIP() + "_" + utils.IntToStr(utils.GetApiVersion(c)) + "_" + c.Request.RequestURI + "_" + string(marshal)
  328. postData := map[string]interface{}{
  329. "content": content,
  330. "mobile": req["phone"],
  331. "templateCode": templateCode,
  332. "way": php2go.Base64Encode(waykeys),
  333. }
  334. requestBody := new(md.Register)
  335. requestBody.Mobile = req["phone"]
  336. requestBody.Captcha = captcha
  337. if requestBody.Zone == "" {
  338. requestBody.Zone = "86"
  339. }
  340. err = sms.GetSmsConfig(c, requestBody.Zone, postData)
  341. if err != nil {
  342. e.OutErr(c, 400, err)
  343. return
  344. }
  345. tmp := struct {
  346. Data md.Register `json:"data"`
  347. CacheTime int64 `json:"cache_time"`
  348. }{
  349. Data: *requestBody,
  350. CacheTime: time.Now().Unix(),
  351. }
  352. if _, err := cache.SetEx(key, utils.Serialize(tmp), 180); err != nil {
  353. e.OutErr(c, e.ERR, err)
  354. return
  355. }
  356. //存入一个缓存 用于邀请码注册时候判断
  357. keys := fmt.Sprintf("%s_SMSCHECK_%s", c.GetString("mid"), requestBody.Mobile)
  358. tmps := struct {
  359. Check int `json:"check"`
  360. CacheTime int64 `json:"cache_time"`
  361. }{
  362. Check: 1,
  363. CacheTime: time.Now().Unix(),
  364. }
  365. if _, err := cache.SetEx(keys, utils.Serialize(tmps), 3600); err != nil {
  366. e.OutErr(c, e.ERR, err)
  367. return
  368. }
  369. e.OutSuc(c, "验证码已发送,3分钟内有效", nil)
  370. return
  371. }
  372. func createCaptcha() string {
  373. return fmt.Sprintf("%05v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
  374. }