userPhoneUtil.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. package jy
  2. import (
  3. "fmt"
  4. "time"
  5. qutil "app.yhyue.com/moapp/jybase/common"
  6. mg "app.yhyue.com/moapp/jybase/mongodb"
  7. )
  8. type PhoneUtil struct {
  9. UserMgoDB mg.MongodbSim
  10. }
  11. func NewPhoneUtil(db mg.MongodbSim) *PhoneUtil {
  12. return &PhoneUtil{db}
  13. }
  14. func (this *PhoneUtil) Log(userId, operation, value string) {
  15. go this.UserMgoDB.Save("user_relation_log", map[string]interface{}{
  16. "s_userId": userId,
  17. "s_operation": operation,
  18. "s_updateValue": value,
  19. "l_createtime": time.Now().Unix(),
  20. })
  21. }
  22. // 获取微信关联字段
  23. func (this *PhoneUtil) getWxRelationMap(userId string) *map[string]interface{} {
  24. rData, _ := this.UserMgoDB.FindById("user", userId, `{"s_unionid":1,"s_name":1,"s_nickname":1,"s_headimageurl":1}`)
  25. if rData == nil || len(*rData) == 0 {
  26. return nil
  27. }
  28. delete(*rData, "_id")
  29. return rData
  30. }
  31. // 获取手机号
  32. func (this *PhoneUtil) getUserPhone(userId string) (phone string) {
  33. rData, _ := this.UserMgoDB.FindById("user", userId, `{"s_phone":1}`)
  34. if rData != nil && len(*rData) > 0 {
  35. phone, _ = (*rData)["s_phone"].(string)
  36. }
  37. return
  38. }
  39. // 绑定微信
  40. func (this *PhoneUtil) bindWeixin(phoneUserId string, wxRelationMap *map[string]interface{}, opera string) error {
  41. if !this.UserMgoDB.UpdateById("user", phoneUserId, map[string]interface{}{
  42. "$set": wxRelationMap,
  43. }) {
  44. return fmt.Errorf("建立Phone绑定异常")
  45. }
  46. //存日志
  47. this.Log(phoneUserId, fmt.Sprintf("%s_bindWeixin", opera), qutil.ObjToString((*wxRelationMap)["s_unionid"]))
  48. return nil
  49. }
  50. // 解绑微信
  51. func (this *PhoneUtil) unBindWeixin(phoneUserId, opera string) error {
  52. //查询解绑微信unionid
  53. logMap := this.getWxRelationMap(phoneUserId)
  54. if !this.UserMgoDB.UpdateById("user", phoneUserId, map[string]interface{}{
  55. "$unset": map[string]interface{}{"s_name": 1, "s_nickname": 1, "i_sex": 1, "s_country": 1, "s_province": 1, "s_city": 1, "s_headimageurl": 1, "s_m_openid": 1, "a_m_openid": 1, "i_ispush": 1, "s_unionid": 1, "i_applystatus": 1},
  56. }) {
  57. return fmt.Errorf("解除微信关联异常")
  58. }
  59. //存日志
  60. logUnionid := ""
  61. if logMap != nil && len(*logMap) > 0 {
  62. logUnionid, _ = (*logMap)["s_unionid"].(string)
  63. }
  64. this.Log(phoneUserId, fmt.Sprintf("%s_unBindWeixin", opera), logUnionid)
  65. return nil
  66. }
  67. // 绑定手机号
  68. func (this *PhoneUtil) bindPhone(weixinUserId, phone, email, opera string) error {
  69. data := map[string]interface{}{
  70. "s_m_phone": phone,
  71. "l_bindphonetime": time.Now().Unix(),
  72. }
  73. if EmailPattern.MatchString(email) {
  74. data["s_email"] = email
  75. }
  76. if !this.UserMgoDB.UpdateById("user", weixinUserId, map[string]interface{}{
  77. "$set": data,
  78. }) {
  79. return fmt.Errorf("建立微信绑定异常")
  80. }
  81. //存日志
  82. this.Log(weixinUserId, fmt.Sprintf("%s_bindPhone", opera), phone)
  83. return nil
  84. }
  85. // 解除手机号关联
  86. func (this *PhoneUtil) unBindPhone(weixinUserId, opera string) error {
  87. logPhone := this.getUserPhone(weixinUserId)
  88. if !this.UserMgoDB.UpdateById("user", weixinUserId, map[string]interface{}{
  89. "$unset": map[string]interface{}{"s_m_phone": 0},
  90. }) {
  91. return fmt.Errorf("解除手机关联异常")
  92. }
  93. //存日志
  94. this.Log(weixinUserId, fmt.Sprintf("%s_unBindPhone", opera), logPhone)
  95. return nil
  96. }
  97. //=============================================
  98. // 建立双向关联关系
  99. func (this *PhoneUtil) buildRelation(wxUserId, phoneUserId, phone string, wxRelationMap *map[string]interface{}, opera string) error {
  100. //建立双向关联关系
  101. if wxRelationMap == nil {
  102. wxRelationMap = this.getWxRelationMap(wxUserId)
  103. }
  104. if phone == "" {
  105. phone = this.getUserPhone(phoneUserId)
  106. }
  107. if wxRelationMap == nil || phone == "" {
  108. return fmt.Errorf("获取绑定关系异常")
  109. }
  110. if err := this.bindWeixin(phoneUserId, wxRelationMap, opera); err != nil {
  111. return err
  112. }
  113. if err := this.bindPhone(wxUserId, phone, qutil.InterfaceToStr((*wxRelationMap)["s_email"]), opera); err != nil {
  114. return err
  115. }
  116. return nil
  117. }
  118. // 解除双向绑定
  119. func (this *PhoneUtil) RelieveRelation(weixinId, phoneId, opera string) error {
  120. if err := this.unBindPhone(weixinId, opera); err != nil {
  121. return err
  122. }
  123. if err := this.unBindWeixin(phoneId, opera); err != nil {
  124. return err
  125. }
  126. return nil
  127. }
  128. // 查询是否存在双向关联关系
  129. func (this *PhoneUtil) QueryRelation(phone string) (wId, pId string, err error) {
  130. relationUser, _ := this.UserMgoDB.Find("user", map[string]interface{}{
  131. "i_appid": 2,
  132. "$or": []map[string]interface{}{
  133. map[string]interface{}{"s_phone": phone},
  134. map[string]interface{}{"s_m_phone": phone},
  135. },
  136. }, nil, `{"s_phone":1}`, false, -1, -1)
  137. if relationUser == nil || len(*relationUser) == 0 {
  138. return "", "", fmt.Errorf("未查询到用户信息")
  139. }
  140. if len(*relationUser) > 2 {
  141. return "", "", fmt.Errorf("查询异常")
  142. }
  143. if len(*relationUser) == 2 {
  144. for _, m := range *relationUser {
  145. if m["s_phone"] != nil {
  146. pId = mg.BsonIdToSId((m)["_id"])
  147. } else {
  148. wId = mg.BsonIdToSId((m)["_id"])
  149. }
  150. }
  151. if pId == "" || wId == "" {
  152. return "", "", fmt.Errorf("获取用户异常")
  153. }
  154. }
  155. return
  156. }
  157. //=============================================
  158. /*
  159. 微信账号绑定手机号判断是否存在
  160. param unionId:当前微信的s_unionid
  161. phone:要绑定的手机号
  162. return exists:是否存在
  163. relationPhoneId:需要建立关联关系的手机号用户id
  164. rule 1.不存在手机号,2.存在手机号用户,但此手机号未绑定微信 3.存在手机号用户,或绑定微信和当前账户绑定微信一致
  165. */
  166. func (this *PhoneUtil) BindPhoneIsOccupy(userId, unionId, phone string) (exists bool, relationPhoneId string) {
  167. //已经有微信账户绑定过
  168. if this.UserMgoDB.Count("user", map[string]interface{}{"i_appid": 2, "s_m_phone": phone, "s_phone": map[string]interface{}{"$exists": 0}}) > 0 {
  169. return true, ""
  170. }
  171. relationUser, _ := this.UserMgoDB.Find("user", map[string]interface{}{
  172. "i_appid": 2,
  173. "s_phone": phone,
  174. }, nil, `{"s_unionid":1}`, false, -1, -1)
  175. //不存在手机号用户
  176. if relationUser == nil || len(*relationUser) == 0 {
  177. return false, ""
  178. }
  179. for _, userData := range *relationUser {
  180. unionidTmp, _ := userData["s_unionid"].(string)
  181. //没绑定微信或绑定微信和当前账户绑定微信一致
  182. if unionidTmp == "" || unionidTmp == unionId {
  183. relationPhoneId = mg.BsonIdToSId(userData["_id"])
  184. } else {
  185. return true, ""
  186. }
  187. }
  188. //但此手机号未绑定微信
  189. if userId == relationPhoneId {
  190. return true, ""
  191. }
  192. return false, relationPhoneId
  193. }
  194. /*
  195. 绑定手机号
  196. param wxUserId:绑定手机号的微信
  197. relationPhoneId:存在关联的手机号账户
  198. phone:绑定的手机号
  199. wxRelationMap:相关联的微信信息
  200. */
  201. func (this *PhoneUtil) BindPhone(wxUserId, relationPhoneId, phone, email string, wxRelationMap *map[string]interface{}) error {
  202. if relationPhoneId == "" {
  203. //单独绑定手机号
  204. return this.bindPhone(wxUserId, phone, email, "BindPhone")
  205. } else {
  206. //绑定及建立双向关联
  207. return this.buildRelation(wxUserId, relationPhoneId, phone, wxRelationMap, "BindPhone")
  208. }
  209. }
  210. /*
  211. 更改手机号
  212. param phone要更改的手机号
  213. needMerge:当前账户是否需要合并
  214. return exists:是否存在
  215. relationPhoneId:需要建立关联关系的手机号用户id
  216. rule:在合并状态的微信账户,可以更换存在但未绑定微信的手机号;其他情况只能更换新手机号
  217. */
  218. func (this *PhoneUtil) ChangePhoneIsOccupy(phone string, isWxAndNeedMerge bool) (exists bool, relationPhoneId string) {
  219. if isWxAndNeedMerge {
  220. relationUser, _ := this.UserMgoDB.Find("user", map[string]interface{}{
  221. "i_appid": 2,
  222. "$or": []map[string]interface{}{
  223. map[string]interface{}{ //存在手机号未绑定微信的用户
  224. "s_unionid": map[string]interface{}{"$exists": 1},
  225. "s_phone": phone,
  226. },
  227. map[string]interface{}{ //手机号已绑定
  228. "s_m_phone": phone,
  229. },
  230. },
  231. }, nil, `{"s_unionid":1,"s_phone":1}`, false, -1, -1)
  232. if relationUser == nil || len(*relationUser) == 0 {
  233. return false, ""
  234. }
  235. for _, userData := range *relationUser {
  236. if userData["s_unionid"] == nil && userData["s_phone"] != nil {
  237. return false, mg.BsonIdToSId(userData["_id"])
  238. }
  239. }
  240. return true, ""
  241. } else {
  242. if this.UserMgoDB.Count("user", map[string]interface{}{
  243. "i_appid": 2,
  244. "$or": []map[string]interface{}{
  245. map[string]interface{}{ //手机号用户
  246. "s_m_phone": phone,
  247. },
  248. map[string]interface{}{ //手机号已被绑定的用户
  249. "s_phone": phone,
  250. },
  251. },
  252. }) > 0 {
  253. return true, ""
  254. }
  255. }
  256. return false, ""
  257. }
  258. /*
  259. 手机号账号绑定微信判断微信是否存在
  260. param phone:当前手机号
  261. unionId:要绑定的微信s_unionid
  262. return exists:是否存在
  263. relationWeixinId:需要建立关联关系的微信用户id
  264. rule 存在对应的微信 1.未绑定手机号 2.绑定手机号为当前账户手机号
  265. */
  266. func (this *PhoneUtil) BindWeixinIsOccupy(phone, unionId string) (exists bool, relationWeixinId string) {
  267. if wxBindNum := this.UserMgoDB.Count("user", map[string]interface{}{"i_appid": 2, "s_unionid": unionId}); wxBindNum > 0 {
  268. relationUser, _ := this.UserMgoDB.FindOneByField("user", map[string]interface{}{
  269. "i_appid": 2,
  270. "s_unionid": unionId,
  271. "s_phone": map[string]interface{}{"$exists": 0},
  272. "$or": []map[string]interface{}{
  273. map[string]interface{}{
  274. "s_m_phone": map[string]interface{}{"$exists": 0},
  275. },
  276. map[string]interface{}{
  277. "s_m_phone": phone,
  278. },
  279. },
  280. }, `{"_id":1}`)
  281. if relationUser != nil && len(*relationUser) > 0 {
  282. if relation := mg.BsonIdToSId((*relationUser)["_id"]); relation != "" {
  283. return false, mg.BsonIdToSId((*relationUser)["_id"])
  284. }
  285. }
  286. return true, ""
  287. }
  288. //全新微信账户
  289. return false, ""
  290. }
  291. /*
  292. 手机号账号绑定微信
  293. param phoneUserId:绑定微信的手机账户
  294. relationWeixinId:存在相关联的微信信息
  295. phone:当前手机账号手机号
  296. wxRelationMap:相关联的微信信息
  297. */
  298. func (this *PhoneUtil) BindWeixin(phoneUserId, relationWeixinId, phone string, wxRelationMap *map[string]interface{}, opear ...string) error {
  299. logFlag := "BindWeixin"
  300. if len(opear) == 1 {
  301. logFlag = opear[0]
  302. }
  303. if relationWeixinId == "" {
  304. return this.bindWeixin(phoneUserId, wxRelationMap, logFlag)
  305. } else {
  306. return this.buildRelation(relationWeixinId, phoneUserId, phone, wxRelationMap, logFlag)
  307. }
  308. }
  309. /*
  310. 手机号解绑微信
  311. param phoneUserId:绑定微信的手机账户
  312. relationWeixinId:存在相关联的微信信息
  313. */
  314. func (this *PhoneUtil) UnBindWeixin(phoneUserId, relationWeixinId string, opear ...string) error {
  315. logFlag := "UnBindWeixin"
  316. if len(opear) == 1 {
  317. logFlag = opear[0]
  318. }
  319. if relationWeixinId == "" {
  320. return this.unBindWeixin(phoneUserId, logFlag)
  321. } else {
  322. return this.RelieveRelation(relationWeixinId, phoneUserId, logFlag)
  323. }
  324. }