userPhoneUtil.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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(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. return false, relationPhoneId
  190. }
  191. /*
  192. 绑定手机号
  193. param wxUserId:绑定手机号的微信
  194. relationPhoneId:存在关联的手机号账户
  195. phone:绑定的手机号
  196. wxRelationMap:相关联的微信信息
  197. */
  198. func (this *PhoneUtil) BindPhone(wxUserId, relationPhoneId, phone, email string, wxRelationMap *map[string]interface{}) error {
  199. if relationPhoneId == "" {
  200. //单独绑定手机号
  201. return this.bindPhone(wxUserId, phone, email, "BindPhone")
  202. } else {
  203. //绑定及建立双向关联
  204. return this.buildRelation(wxUserId, relationPhoneId, phone, wxRelationMap, "BindPhone")
  205. }
  206. }
  207. /*
  208. 更改手机号
  209. param phone要更改的手机号
  210. needMerge:当前账户是否需要合并
  211. return exists:是否存在
  212. relationPhoneId:需要建立关联关系的手机号用户id
  213. rule:在合并状态的微信账户,可以更换存在但未绑定微信的手机号;其他情况只能更换新手机号
  214. */
  215. func (this *PhoneUtil) ChangePhoneIsOccupy(phone string, isWxAndNeedMerge bool) (exists bool, relationPhoneId string) {
  216. if isWxAndNeedMerge {
  217. relationUser, _ := this.UserMgoDB.Find("user", map[string]interface{}{
  218. "i_appid": 2,
  219. "$or": []map[string]interface{}{
  220. map[string]interface{}{ //存在手机号未绑定微信的用户
  221. "s_unionid": map[string]interface{}{"$exists": 1},
  222. "s_phone": phone,
  223. },
  224. map[string]interface{}{ //手机号已绑定
  225. "s_m_phone": phone,
  226. },
  227. },
  228. }, nil, `{"s_unionid":1,"s_phone":1}`, false, -1, -1)
  229. if relationUser == nil || len(*relationUser) == 0 {
  230. return false, ""
  231. }
  232. for _, userData := range *relationUser {
  233. if userData["s_unionid"] == nil && userData["s_phone"] != nil {
  234. return false, mg.BsonIdToSId(userData["_id"])
  235. }
  236. }
  237. return true, ""
  238. } else {
  239. if this.UserMgoDB.Count("user", map[string]interface{}{
  240. "i_appid": 2,
  241. "$or": []map[string]interface{}{
  242. map[string]interface{}{ //手机号用户
  243. "s_m_phone": phone,
  244. },
  245. map[string]interface{}{ //手机号已被绑定的用户
  246. "s_phone": phone,
  247. },
  248. },
  249. }) > 0 {
  250. return true, ""
  251. }
  252. }
  253. return false, ""
  254. }
  255. /*
  256. 手机号账号绑定微信判断微信是否存在
  257. param phone:当前手机号
  258. unionId:要绑定的微信s_unionid
  259. return exists:是否存在
  260. relationWeixinId:需要建立关联关系的微信用户id
  261. rule 存在对应的微信 1.未绑定手机号 2.绑定手机号为当前账户手机号
  262. */
  263. func (this *PhoneUtil) BindWeixinIsOccupy(phone, unionId string) (exists bool, relationWeixinId string) {
  264. if wxBindNum := this.UserMgoDB.Count("user", map[string]interface{}{"i_appid": 2, "s_unionid": unionId}); wxBindNum > 0 {
  265. relationUser, _ := this.UserMgoDB.FindOneByField("user", map[string]interface{}{
  266. "i_appid": 2,
  267. "s_unionid": unionId,
  268. "s_phone": map[string]interface{}{"$exists": 0},
  269. "$or": []map[string]interface{}{
  270. map[string]interface{}{
  271. "s_m_phone": map[string]interface{}{"$exists": 0},
  272. },
  273. map[string]interface{}{
  274. "s_m_phone": phone,
  275. },
  276. },
  277. }, `{"_id":1}`)
  278. if relationUser != nil && len(*relationUser) > 0 {
  279. if relation := mg.BsonIdToSId((*relationUser)["_id"]); relation != "" {
  280. return false, mg.BsonIdToSId((*relationUser)["_id"])
  281. }
  282. }
  283. return true, ""
  284. }
  285. //全新微信账户
  286. return false, ""
  287. }
  288. /*
  289. 手机号账号绑定微信
  290. param phoneUserId:绑定微信的手机账户
  291. relationWeixinId:存在相关联的微信信息
  292. phone:当前手机账号手机号
  293. wxRelationMap:相关联的微信信息
  294. */
  295. func (this *PhoneUtil) BindWeixin(phoneUserId, relationWeixinId, phone string, wxRelationMap *map[string]interface{}, opear ...string) error {
  296. logFlag := "BindWeixin"
  297. if len(opear) == 1 {
  298. logFlag = opear[0]
  299. }
  300. if relationWeixinId == "" {
  301. return this.bindWeixin(phoneUserId, wxRelationMap, logFlag)
  302. } else {
  303. return this.buildRelation(relationWeixinId, phoneUserId, phone, wxRelationMap, logFlag)
  304. }
  305. }
  306. /*
  307. 手机号解绑微信
  308. param phoneUserId:绑定微信的手机账户
  309. relationWeixinId:存在相关联的微信信息
  310. */
  311. func (this *PhoneUtil) UnBindWeixin(phoneUserId, relationWeixinId string, opear ...string) error {
  312. logFlag := "UnBindWeixin"
  313. if len(opear) == 1 {
  314. logFlag = opear[0]
  315. }
  316. if relationWeixinId == "" {
  317. return this.unBindWeixin(phoneUserId, logFlag)
  318. } else {
  319. return this.RelieveRelation(relationWeixinId, phoneUserId, logFlag)
  320. }
  321. }