package service import ( "fmt" "net/url" "regexp" "strconv" "strings" "sync" "time" "xiawan/wx/api/req" "xiawan/wx/api/utils" "xiawan/wx/api/vo" "xiawan/wx/clientsdk/baseinfo" "xiawan/wx/clientsdk/baseutils" "xiawan/wx/clientsdk/proxynet" "xiawan/wx/db" "xiawan/wx/db/table" "xiawan/wx/protobuf/wechat" "xiawan/wx/srv/srvconfig" "xiawan/wx/srv/wxface" "github.com/gin-gonic/gin" "github.com/gogf/guuid" "github.com/lunny/log" ) // GetLoginQrCodeShow 展示登录二维码 func GetLoginQrCodeShow(queryKey string) (*wechat.LoginQRCodeResponse, vo.DTO) { iwxConnect := checkExIdReturn(queryKey, uint32(0)) //queryKey 为空字符串 if iwxConnect == nil { return nil, vo.NewFail("逻辑错误!") } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatus() { return nil, vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!", } } if !iwxConnect.IsConnected() { iwxConnect.Stop() err := iwxConnect.Start() if err != nil { return nil, vo.NewFail(err.Error()) } } iwxConnect.GetWXAccount().GetUserInfo().Session = []byte{} iwxConnect.GetWXAccount().GetUserInfo().Uin = 0 iwxConnect.GetWXAccount().GetUserInfo().CheckSumKey = []byte{} //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequest() if err != nil { return nil, vo.NewFail("检查扫码状态失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return nil, vo.NewFail("检查扫码状态失败!err:" + err.Error()) } return loginQrCodeResp, vo.NewSuccess(gin.H{}, "") } // 提取62 func Get62DataService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取基本信息 wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } //获取请求管理器 resp, err := utils.GenerateWxDat(wxAccount.GetUserInfo().DeviceInfo.Imei) if err != nil { return vo.NewFail(err.Error()) } return vo.DTO{ Code: vo.SUCCESS, Success: true, Data: resp, Data62: resp, Text: "", } }) } // GetLoginQrCodeNewService 自动生成UUID 可使用代理 直登 func GetLoginQrCodeNewServiceDirect(queryKey string, model req.GetLoginQrCodeModel, ipadOrmac string) vo.DTO { // 去除头尾空格 queryKey = strings.TrimSpace(queryKey) return checkExIdPerform(queryKey, baseinfo.ClientVersion, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 使用使用代理 proxyKey := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) var proxyInfo *proxynet.WXProxyInfo // 代理替换逻辑 if len(model.Proxy) > 0 && len(model.Proxy) < 5 && !strings.Contains(model.Proxy, "4") { // 从数据库获取代理映射 proxyMapping, err := db.GetProxyMapping(model.Proxy) if err != nil { return vo.NewFail("代理获取失败: " + err.Error()) } if proxyMapping == nil || proxyMapping.ProxyValue == "" { return vo.NewFail("无效的代理编号") } model.Proxy = proxyMapping.ProxyValue } // if len(model.Proxy) > 0 && !strings.Contains(model.Proxy, "测试") { if len(model.Proxy) > 0 { // 设置代理 proxyInfo = proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(proxyKey) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(proxyKey, &newModel) } if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!在线状态良好!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) // 设置初始化状态为 false currentCache := iwxConnect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) if iwxConnect.IsConnected() { iwxConnect.Stop() // 等待一秒 time.Sleep(time.Second * 3) err := iwxConnect.Start() time.Sleep(time.Second * 1) if err != nil { return vo.NewFail(err.Error()) } } else { iwxConnect.Stop() time.Sleep(time.Second * 2) err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } if ipadOrmac == "mac" { userinfo := wxAccount.GetUserInfo() userinfo.DeviceInfo.DeviceName = "MacBook Pro" userinfo.DeviceInfo.OsType = "iMac MacBookPro16,1 OSX OSX11.5.2 build(20G95)" userinfo.ClientVersion = baseinfo.MacVersion } // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Session = []byte{} wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequestDirect() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } go func(k string) { error := db.SETObj(k, model) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } }(proxyKey) // 生成62数据 // 先尝试从数据库获取设备信息 deviceInfo := wxAccount.GetUserInfo().DeviceInfo var data62 string var generateErr error if deviceInfo != nil && deviceInfo.Imei != "" { // 使用数据库中的 Imei data62, generateErr = utils.GenerateWxDat(deviceInfo.Imei) } else { // 生成新的 Imei imei := baseutils.RandomSmallHexString(32) data62, generateErr = utils.GenerateWxDat(imei) if generateErr == nil { wxAccount.GetUserInfo().DeviceInfo.Imei = imei wxAccount.GetUserInfo().LoginDataInfo.LoginData = data62 } } if generateErr != nil { return vo.NewFail(generateErr.Error()) } // 保存62数据到Redis缓存 data62Key := fmt.Sprintf("%s%s", "wechat:62data:", queryKey) err = db.SETExpirationObj(data62Key, data62, -1) // 5分钟过期 if err != nil { log.Error("保存62数据到Redis失败: " + err.Error()) } return vo.DTO{ Code: vo.SUCCESS, Data: resp, Text: "获取二维码成功", Success: true, Data62: data62, } }) } // GetLoginQrCodeNewService 自动生成UUID 可使用代理 正常 func GetLoginQrCodeNewService(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { // 去除头尾空格 queryKey = strings.TrimSpace(queryKey) return checkExIdPerform(queryKey, baseinfo.ClientVersion, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 使用使用代理 proxyKey := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) var proxyInfo *proxynet.WXProxyInfo // 代理替换逻辑 if len(model.Proxy) > 0 && len(model.Proxy) < 5 && !strings.Contains(model.Proxy, "4") { // 从数据库获取代理映射 proxyMapping, err := db.GetProxyMapping(model.Proxy) if err != nil { return vo.NewFail("代理获取失败: " + err.Error()) } if proxyMapping == nil || proxyMapping.ProxyValue == "" { return vo.NewFail("无效的代理编号") } model.Proxy = proxyMapping.ProxyValue } if len(model.Proxy) > 0 && !strings.Contains(model.Proxy, "测试") { // 设置代理 proxyInfo = proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(proxyKey) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(proxyKey, &newModel) } if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!在线状态良好!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) // 设置初始化状态为 false currentCache := iwxConnect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) if iwxConnect.IsConnected() { iwxConnect.Stop() // 等待一秒 time.Sleep(time.Second * 3) err := iwxConnect.Start() time.Sleep(time.Second * 1) if err != nil { return vo.NewFail(err.Error()) } } else { iwxConnect.Stop() time.Sleep(time.Second * 2) err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Session = []byte{} wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequest() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } go func(k string) { error := db.SETObj(k, model) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } }(proxyKey) // 生成62数据 // 先尝试从数据库获取设备信息 deviceInfo := wxAccount.GetUserInfo().DeviceInfo var data62 string var generateErr error if deviceInfo != nil && deviceInfo.Imei != "" { // 使用数据库中的 Imei data62, generateErr = utils.GenerateWxDat(deviceInfo.Imei) } else { // 生成新的 Imei imei := baseutils.RandomSmallHexString(32) data62, generateErr = utils.GenerateWxDat(imei) if generateErr == nil { wxAccount.GetUserInfo().DeviceInfo.Imei = imei wxAccount.GetUserInfo().LoginDataInfo.LoginData = data62 } } if generateErr != nil { return vo.NewFail(generateErr.Error()) } // 保存62数据到Redis缓存 data62Key := fmt.Sprintf("%s%s", "wechat:62data:", queryKey) err = db.SETExpirationObj(data62Key, data62, 60*5) // 5分钟过期 if err != nil { log.Error("保存62数据到Redis失败: " + err.Error()) } return vo.DTO{ Code: vo.SUCCESS, Data: resp, Text: "获取二维码成功", Success: true, Data62: data62, } }) } // GetLoginQrCodeNewService 自动生成UUID 可使用代理 func GetLoginQrCodeNewServiceX(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { return checkExIdPerform(queryKey, baseinfo.ClientVersionNotVerify, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() // 使用使用代理 proxyKey := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) if len(model.Proxy) > 0 { // 设置代理 proxyInfo := proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(proxyKey) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(proxyKey, &newModel) } if newModel.Proxy != "" { proxyInfo := proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) isReConnected := false if !iwxConnect.IsConnected() { err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } else { isReConnected = true // 关闭 iwxConnect.Stop() time.Sleep(200 * time.Millisecond) // 重新连接 iwxConnect.Start() } //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequestX() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } go func() { errorCount := 0 defer func() { if r := recover(); r != nil { // 这里可以记录日志或者执行其他的恢复操作 if errorCount < 5 { errorCount += 1 iwxConnect.Start() time.Sleep(1000 * time.Millisecond) reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) } } }() if isReConnected { time.Sleep(2000 * time.Millisecond) iwxConnect.Start() } //发送检查二维码状态请求 reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) }() resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } go func(k string) { error := db.SETObj(k, model) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } }(proxyKey) return vo.NewSuccess(resp, "") }) } // 发送验证码 func WxBindOpMobileForRegService(queryKey string, m req.WxBindOpMobileForModel) vo.DTO { return checkExIdPerform(queryKey, uint32(0), func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) if len(m.Proxy) > 0 { // 设置代理 proxyInfo := proxynet.ParseWXProxyInfo(m.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) //存redis缓存 error := db.SETObj(key, m) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo := proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } if !iwxConnect.IsConnected() { err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() resp, err := reqInvoker.SendWxBindOpMobileForRequest(m.OpCode, m.PhoneNumber, m.VerifyCode) if err != nil { return vo.NewFail(err.Error()) } //存redis缓存 /*key := fmt.Sprintf("%s%s", "wechat:sms:", queryKey) exists, _ := db.Exists(key) userInfo := &baseinfo.UserInfo{} if exists { error := db.GETObj(key, &userInfo) if error != nil { log.Error("redis is error=" + error.Error()) } } else { userInfo = connect.GetWXAccount().GetUserInfo() userInfo.DeviceInfoA16 = nil error := db.SETExpirationObj(key, &userInfo, 60*60*5) if error != nil { log.Error("保存redis is error=" + error.Error()) } } // 长链接初始化MMTLS dialer := clientsdk.GetDialer(userInfo) tmpMMInfo, err := mmtls.InitMMTLSInfoLong(dialer, userInfo.LongHost, userInfo.ShortHost, nil) if err != nil { return vo.NewFail(err.Error()) } userInfo.MMInfo = tmpMMInfo resp, err := clientsdk.SendWxBindOpMobileForRegRequest(userInfo, m.OpCode, m.PhoneNumber, m.VerifyCode) if err != nil { return vo.NewFail(err.Error()) } // 获取登录二维码响应 WXBindOpMobileForReg := &wechat.BindOpMobileForRegResponse{} err = clientsdk.ParseResponseData(userInfo, resp, WXBindOpMobileForReg)*/ return vo.NewSuccessObj(resp, wxAccount.GetUserInfo().UUID) }) } // CheckLoginQrCodeStatusService 检测扫码状态 func CheckLoginQrCodeStatusService(queryKey string) vo.DTO { // 去除首尾空格 queryKey = strings.TrimSpace(queryKey) return getExistWxConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { // 连接不存在,尝试从缓存获取状态信息 if iwxConnect == nil { statusCache := db.GetCheckStatusCache(queryKey) if statusCache != nil { // 如果状态缓存存在,直接返回状态 return vo.NewSuccessObj(statusCache, statusCache.Msg) } // 从持久化存储尝试恢复最后的状态 lastStatus := db.GetLastLoginStatus(queryKey) if lastStatus != nil { return vo.NewSuccessObj(lastStatus, "登录处理中,请稍候...") } return vo.NewFail("逻辑错误!") } // 连接存在,优先使用当前连接的状态 wxAccount := iwxConnect.GetWXAccount() data62 := wxAccount.GetUserInfo().LoginDataInfo.LoginData ticket := wxAccount.GetUserInfo().Ticket // 检查连接是否仍然有效 if !iwxConnect.IsConnected() { // 重启这个连接 iwxConnect.Stop() // 等待 2000 毫秒 time.Sleep(time.Millisecond * 2000) return vo.NewFail("不存在状态") } // 如果连接有效,检查账号状态 if wxAccount.GetLoginState() == baseinfo.MMLoginStateOnLine { // 账号已经在线,返回一个特殊状态 return vo.NewSuccessObj(map[string]interface{}{ "state": 2, // 表示扫码成功 "loginState": "online", "data62": data62, "ticket": ticket, }, "账号已登录") } // 检查是否有状态缓存,如果有则返回缓存状态(但更新data62和ticket) statusCache := db.GetCheckStatusCache(queryKey) if statusCache != nil { // 更新缓存中的data62和ticket为当前连接的值 statusCache.Data62 = data62 statusCache.Ticket = ticket // 保持原有逻辑,直接返回statusCache,但设置微信验证字段到DTO result := vo.NewSuccessObj(statusCache, statusCache.Msg) // 如果有ticket,在DTO中添加微信验证信息(不影响原有数据) if ticket != "" { result.WechatVerifyUrl = fmt.Sprintf("ticket=%s", ticket) result.VerifyInstructions = "这个就是第二步返回的key, 请根据文档操作!!!" } return result } // 如果连接存在但没有状态缓存,返回一个包含ticket的状态(保持原有格式) responseData := map[string]interface{}{ "state": 0, // 表示等待扫码 "loginState": "waiting", "data62": data62, "ticket": ticket, } result := vo.NewSuccessObj(responseData, "等待扫码") // 如果有ticket,在DTO级别添加微信验证信息(不影响Data字段中的原有数据) if ticket != "" { result.WechatVerifyUrl = fmt.Sprintf("ticket=%s", ticket) result.VerifyInstructions = "这个就是第二步返回的key, 请根据文档操作!!!" } return result }) } // GetInItStatusService 初始化状态 func GetInItStatusService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { // 获取二级缓存器 iwxCache := connect.GetWXCache() msg := "初始化未完成!" if iwxCache.IsInitFinished() { msg = "初始化完成!" } return vo.NewSuccessObj(iwxCache.IsInitFinished(), msg) }) } // WakeUpLoginService 发送唤醒登录 func WakeUpLoginService(queryKey string, model *req.GetLoginQrCodeModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if connect == nil { return vo.NewFail("逻辑错误!") } reqInvoker := connect.GetWXReqInvoker() //判断在线情况(唤醒无需退出登录) if connect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该微信号在线状态良好!无需唤醒!", } } else { connect.Stop() // 设置初始化状态为 false currentCache := connect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) time.Sleep(time.Second * 2) } wxAccount := connect.GetWXAccount() // 设置代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } var proxyInfo *proxynet.WXProxyInfo if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} //发送唤醒登录 pushResp, err := reqInvoker.SendPushQrLoginNotice() if err != nil { return vo.NewFail(err.Error()) } if pushResp.GetBaseResponse().GetRet() == 0 { //启动长连接检测扫码状态 err = reqInvoker.SendCheckLoginQrcodeRequest(pushResp.GetUUID(), pushResp.GetNotifyKey().GetBuffer()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } } else { connect.Stop() return vo.NewSuccessObj(pushResp, "发送唤醒登录失败!") } return vo.NewSuccessObj(pushResp, "发送唤醒登录成功!请在手机微信上确认登录!") }) } // GetLoginStatusService 获取登录状态 func GetLoginStatusService(queryKey string, loginJournal bool, autoLogin bool) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { isOnline := false var errMsg string var loginTime = "" // 本次登录时间 var expiryTime = "" // 卡密过期时间 var onlineTime = "" // 本次登录连续在线时间(距离上次手动登录) var onlineDays = 0 // 上述天数 var totalOnline = "" // 总计在线时间 //取用户信息 wxAccount := connect.GetWXAccount() //取登录状态 loginState := wxAccount.GetLoginState() switch loginState { case baseinfo.MMLoginStateOnLine: errMsg, isOnline = "账号在线状态良好!", true case baseinfo.MMLoginStateOffLine: errMsg = "账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState())) case baseinfo.MMLoginStateNoLogin: errMsg = "该账号需要重新登录!loginState == MMLoginStateNoLogin " default: errMsg = db.GetUSerLoginErrMsg(wxAccount.GetUserInfo().GetUserName()) } //判断在线情况 掉线或者离线会通过Token 登录确认掉线状态 if autoLogin { if connect != nil { if connect.CheckOnLineStatus() { errMsg, isOnline = "账号在线状态良好!", true has, _ := db.HasLicense(queryKey) expiryTime = has.ExpiryDate loginTime = wxAccount.GetUserInfo().LastLoginTime.Format("2006-01-02 15:04:05") onlineTime, onlineDays = wxAccount.GetUserInfo().GetOnlineTime() totalOnline, _ = wxAccount.GetUserInfo().GetDeviceCreateTime() } else { errMsg, isOnline = "账号状态异常", false } } else { errMsg = "未获取到长链接,状态未知!" } } logs := make([]table.UserLoginLog, 0) //登录日志 if loginJournal { //Mysql 从数据库查询记录 logs = db.GetLoginJournal(wxAccount.GetUserInfo().GetUserName()) } targetIp := "" userInfoEntity := db.GetUserInfoEntity(queryKey) if userInfoEntity != nil { targetIp = userInfoEntity.TargetIp } if !isOnline { // 账号离线 return vo.NewFail(errMsg) } return vo.NewSuccess(gin.H{ "proxyUrl": wxAccount.GetUserInfo().GetProxyUrl(), "loginState": int32(wxAccount.GetLoginState()), "targetIp": targetIp, "loginErrMsg": errMsg, "expiryTime": expiryTime, "loginTime": loginTime, "onlineDays": onlineDays, "onlineTime": "本次在线: " + onlineTime, "totalOnline": "总计在线: " + totalOnline, "loginJournal": gin.H{ "count": len(logs), "logs": logs, }, }, "") }) } var onceInit sync.Once = sync.Once{} func InitLoginStatusService(queryKey string, loginJournal bool, autoLogin bool, model req.GetLoginQrCodeModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取用户信息 wxAccount := connect.GetWXAccount() // 获取数据库中的真实登录状态,不要强制设置为1 dbUserInfo := db.GetUSerInfoByUUID(queryKey) if dbUserInfo != nil { wxAccount.GetUserInfo().SetLoginState(dbUserInfo.GetLoginState()) } else { // 如果数据库中没有记录,设置为未登录状态 wxAccount.GetUserInfo().SetLoginState(uint32(baseinfo.MMLoginStateNoLogin)) } version := srvconfig.GlobalSetting.Version redisVersion := make(map[string]string) // redis 中获取 db.GETObj("groupVersion", &redisVersion) if redisVersion["groupVersion"] != version { redisVersion["groupVersion"] = version // 只执行一次 do go func() { onceInit.Do(func() { // 等 100 秒执行 time.Sleep(100 * time.Second) db.SETExpirationObj("groupVersion", &redisVersion, -1) }) }() } else { wxAccount.GetUserInfo().SetIsServerRestart(true) go func() { // 10 秒内不发送信息 time.Sleep(10 * time.Second) wxAccount.GetUserInfo().SetIsServerRestart(false) }() } // 使用使用代理 if len(model.Proxy) > 0 { // 设置代理 log.Printf("设置代理 %s => %s", queryKey, model.Proxy) proxyInfo := proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } isOnline := false var errMsg string var loginTime = "" // 本次登录时间 var expiryTime = "" // 卡密过期时间 var onlineTime = "" // 本次登录连续在线时间(距离上次手动登录) var onlineDays = 0 // 上述天数 var totalOnline = "" // 总计在线时间 //取登录状态 loginState := wxAccount.GetLoginState() switch loginState { case baseinfo.MMLoginStateOnLine: errMsg, isOnline = "账号在线状态良好!", true case baseinfo.MMLoginStateOffLine: errMsg = "账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState())) case baseinfo.MMLoginStateNoLogin: errMsg = "该账号需要重新登录!loginState == MMLoginStateNoLogin " default: // "登录成功!" 或 其他登录错误 errMsg = db.GetUSerLoginErrMsg(wxAccount.GetUserInfo().GetUserName()) } if srvconfig.GlobalSetting.IsInitOld { UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "true" db.SETExpirationObj("old_"+UUID, &oldObj, 0) } //判断在线情况 掉线或者离线会通过Token 登录确认掉线状态 if autoLogin { if connect != nil { // 只对已登录的用户尝试检查在线状态,避免未登录用户的重连尝试 if loginState != baseinfo.MMLoginStateNoLogin && loginState != baseinfo.MMLoginStateLogout { if connect.CheckOnLineStatus() { // 判断是否老号 errMsg, isOnline = "账号在线状态良好!", true has, _ := db.HasLicense(queryKey) expiryTime = has.ExpiryDate loginTime = wxAccount.GetUserInfo().LastLoginTime.Format("2006-01-02 15:04:05") onlineTime, onlineDays = wxAccount.GetUserInfo().GetOnlineTime() totalOnline, _ = wxAccount.GetUserInfo().GetDeviceCreateTime() } } else { // 未登录用户不尝试重连,直接返回失败状态 errMsg = "该账号需要重新登录!loginState == MMLoginStateNoLogin" isOnline = false } } else { errMsg = "未获取到长链接,状态未知!" } } logs := make([]table.UserLoginLog, 0) //登录日志 if loginJournal { //Mysql 从数据库查询记录 logs = db.GetLoginJournal(wxAccount.GetUserInfo().GetUserName()) } targetIp := "" userInfoEntity := db.GetUserInfoEntity(queryKey) if userInfoEntity != nil { targetIp = userInfoEntity.TargetIp } if !isOnline { // 账号离线 return vo.NewFail(errMsg) } return vo.NewSuccess(gin.H{ "proxyUrl": wxAccount.GetUserInfo().GetProxyUrl(), "loginState": int32(wxAccount.GetLoginState()), "targetIp": targetIp, "loginErrMsg": errMsg, "expiryTime": expiryTime, "loginTime": loginTime, "onlineDays": onlineDays, "onlineTime": "本次在线: " + onlineTime, "totalOnline": "总计在线: " + totalOnline, "loginJournal": gin.H{ "count": len(logs), "logs": logs, }, }, "") }) } // DeviceIdLoginService 账号密码登录 62 func DeviceIdLoginService(queryKey string, m req.DeviceIdLoginModel) vo.DTO { return checkExIdPerform(queryKey, baseinfo.ClientVersion, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { if m.LoginData == "" || m.UserName == "" || m.Password == "" { return vo.NewFail("登录数据错误!") } //queryKey 为空字符串 if iwxConnect == nil { iwxConnect = CreateWXConnectByQueryKey(guuid.New().String(), m.Proxy, nil) } //取用户信息 wxAccount := iwxConnect.GetWXAccount() //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!", } } if !iwxConnect.IsConnected() { err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) if len(m.Proxy) > 0 { // 设置代理 proxyInfo := proxynet.ParseWXProxyInfo(m.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) //存redis缓存 error := db.SETObj(key, m) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo := proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } userInfo := wxAccount.GetUserInfo() userInfo.LoginDataInfo = baseinfo.LoginDataInfo{ UserName: m.UserName, PassWord: m.Password, LoginData: m.LoginData, } checkDeviceToken(userInfo) fmt.Println("userInfo.DeviceInfo", userInfo.DeviceInfo) //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() err := reqInvoker.SendManualAuthByDeviceIdRequest() if err != nil { return vo.NewFail("发送登录请求失败!err - " + err.Error()) } return vo.NewSuccess(gin.H{"uuid": wxAccount.GetUserInfo().UUID}, "发送登录请求成功!") }) } // 获取DeviceToken func GetFpInItNlService() vo.DTO { return checkExIdPerform("", uint32(0), func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //获取请求管理器 reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.SendDeviceTokenRequest() if err != nil { return vo.NewFail("发送登录请求失败!err - " + err.Error()) } return vo.NewSuccessObj(resp, "") }) } // 短信登录 func SmsLoginService(queryKey string, m req.DeviceIdLoginModel) vo.DTO { return checkExIdPerform(queryKey, uint32(0), func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { if m.UserName == "" || m.Password == "" { return vo.NewFail("登录数据错误!") } //queryKey 为空字符串 if iwxConnect == nil { iwxConnect = CreateWXConnectByQueryKey(guuid.New().String(), m.Proxy, nil) } wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatus() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!", } } if !iwxConnect.IsConnected() { err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) if len(m.Proxy) > 0 { // 设置代理 proxyInfo := proxynet.ParseWXProxyInfo(m.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) //存redis缓存 error := db.SETObj(key, m) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo := proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } userInfo := wxAccount.GetUserInfo() userInfo.LoginDataInfo = baseinfo.LoginDataInfo{ UserName: m.UserName, PassWord: m.Password, Ticket: m.Ticket, } //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() err := reqInvoker.SendManualAuthByDeviceIdRequest() if err != nil { return vo.NewFail("发送登录请求失败!err - " + err.Error()) } return vo.NewSuccess(gin.H{"uuid": wxAccount.GetUserInfo().UUID}, "发送登录请求成功!") }) } // A16LoginService A16数据登录 func A16LoginService(queryKey string, m req.DeviceIdLoginModel) vo.DTO { return checkExIdPerform(queryKey, baseinfo.AndroidClientVersion, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { if m.LoginData == "" || m.UserName == "" || m.Password == "" { return vo.NewFail("登录数据错误!") } //queryKey 为空字符串 if iwxConnect == nil { iwxConnect = CreateWXConnectByQueryKey(guuid.New().String(), m.Proxy, nil) } wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatus() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!", } } if !iwxConnect.IsConnected() { err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) if len(m.Proxy) > 0 { // 设置代理 proxyInfo := proxynet.ParseWXProxyInfo(m.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) //存redis缓存 error := db.SETObj(key, m) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo := proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } userInfo := wxAccount.GetUserInfo() userInfo.LoginDataInfo = baseinfo.LoginDataInfo{ UserName: m.UserName, PassWord: m.Password, LoginData: m.LoginData, NewType: m.Type, } //判断如果是A16数据 if strings.HasPrefix(userInfo.LoginDataInfo.LoginData, "A") { if userInfo.DeviceInfoA16 == nil { userInfo.DeviceInfoA16 = &baseinfo.AndroidDeviceInfo{} } deviceId := m.LoginData if m.DeviceInfo.ImeI == "" { userInfo.DeviceInfoA16.Imei = userInfo.DeviceInfoA16.AndriodImei(deviceId) } else { userInfo.DeviceInfoA16.Imei = m.DeviceInfo.ImeI } if m.DeviceInfo.AndroidId == "" { userInfo.DeviceInfoA16.AndriodId = userInfo.DeviceInfoA16.AndriodID(deviceId) } else { userInfo.DeviceInfoA16.AndriodId = m.DeviceInfo.AndroidId } if m.DeviceInfo.Model == "" { userInfo.DeviceInfoA16.PhoneModel = userInfo.DeviceInfoA16.AndroidPhoneModel(deviceId) } else { userInfo.DeviceInfoA16.PhoneModel = m.DeviceInfo.Model } if m.DeviceInfo.Manufacturer == "" { userInfo.DeviceInfoA16.Manufacturer = userInfo.DeviceInfoA16.AndroidManufacturer(deviceId) } else { userInfo.DeviceInfoA16.Manufacturer = m.DeviceInfo.Manufacturer } } userInfo.ClientVersion = 0x28004050 checkDeviceToken(userInfo) //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() err := reqInvoker.SendManualAuthByDeviceIdRequest() if err != nil { return vo.NewFail("发送登录请求失败!err - " + err.Error()) } return vo.NewSuccess(gin.H{"uuid": wxAccount.GetUserInfo().UUID}, "发送登录请求成功!") }) } // PhoneDeviceLoginService 铺助新手机登录 func PhoneDeviceLoginService(queryKey string, m req.PhoneLoginModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取基本信息 wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } //获取请求管理器 reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.GetA8KeyRequest(2, 4, m.Url, baseinfo.ThrIdGetA8Key) //flag:=strings.Contains(resp.GetFullURL(), "https://login.weixin.qq.com") if err != nil { return vo.NewFail(err.Error()) } if resp.BaseResponse.GetRet() == 0 { urlv := resp.GetFullURL() v, _ := utils.GetHTML(urlv, resp.HttpHeader) var action = regexp.MustCompile(`action\="([^"]*)"`) if len(action.FindStringSubmatch(v)) <= 0 { return vo.NewSuccessObj(nil, "二维码已失效!") } postUrl := "https://login.weixin.qq.com" + action.FindStringSubmatch(v)[1] rsp, ck := utils.GetHTML(postUrl, resp.HttpHeader) apiUrl := "https://login.weixin.qq.com" + action.FindStringSubmatch(rsp)[1] fmt.Println("apiUrl", apiUrl) data := url.Values{} rspv := utils.HttpPost(postUrl, data, ck) return vo.NewSuccessObj(rspv, "") } return vo.NewSuccessObj(nil, "失败!") }) } // 获取设备 func GetSafetyInfoService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取基本信息 wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } //获取请求管理器 reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.SendGetSafetyInfoRequest() if err != nil { return vo.NewFail(err.Error()) } return vo.NewSuccessObj(resp, "") }) } // 删除设备 func DelSafeDeviceService(queryKey string, m req.DelSafeDeviceModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取基本信息 wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } //获取请求管理器 reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.SendDelSafeDeviceRequest(m.DeviceUUID) if err != nil { return vo.NewFail(err.Error()) } return vo.NewSuccessObj(resp, "") }) } // 获取硬件设备情况 func GetBoundHardDeviceService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取基本信息 wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } //获取请求管理器 reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.SendGetBoundHardDeviceRequest() if err != nil { return vo.NewFail(err.Error()) } return vo.NewSuccessObj(resp, "") }) } // 检测微信登录环境 func CheckCanSetAliasService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //取基本信息 wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } //获取请求管理器 reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.SendCheckCanSetAliasRequest() if err != nil { return vo.NewFail(err.Error()) } return vo.NewSuccessObj(resp, "") }) } func IWXConnectMgrService() vo.DTO { //获取实例管理器 connectMgr := WXServer.GetWXConnectMgr() return vo.NewSuccessObj(connectMgr.ShowConnectInfo(), "") } func GetConnectInfo() vo.DTO { //获取实例管理器 connectMgr := WXServer.GetWXConnectMgr() return vo.NewSuccessObj(connectMgr.GetConnectInfo(), "") } // MacLoginService Mac设备登录 func MacLoginService(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { // 去除头尾空格 queryKey = strings.TrimSpace(queryKey) return checkExIdPerform(queryKey, uint32(baseinfo.MacVersion), func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 使用使用代理 proxyKey := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) var proxyInfo *proxynet.WXProxyInfo // 代理替换逻辑 if len(model.Proxy) > 0 && len(model.Proxy) < 5 && !strings.Contains(model.Proxy, "4") { // 从数据库获取代理映射 proxyMapping, err := db.GetProxyMapping(model.Proxy) if err != nil { return vo.NewFail("代理获取失败: " + err.Error()) } if proxyMapping == nil || proxyMapping.ProxyValue == "" { return vo.NewFail("无效的代理编号") } model.Proxy = proxyMapping.ProxyValue } if len(model.Proxy) > 0 && !strings.Contains(model.Proxy, "测试") { // 设置代理 proxyInfo = proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(proxyKey) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(proxyKey, &newModel) } if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!在线状态良好!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) // 设置初始化状态为 false currentCache := iwxConnect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) if iwxConnect.IsConnected() { iwxConnect.Stop() // 等待一秒 time.Sleep(time.Second * 3) err := iwxConnect.Start() time.Sleep(time.Second * 1) if err != nil { return vo.NewFail(err.Error()) } } else { iwxConnect.Stop() time.Sleep(time.Second * 2) err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } userinfo := wxAccount.GetUserInfo() userinfo.DeviceInfo.DeviceName = baseinfo.MacDeviceName userinfo.DeviceInfo.OsType = baseinfo.MacDeviceType userinfo.ClientVersion = baseinfo.MacVersion // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Session = []byte{} wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequest() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } go func(k string) { error := db.SETObj(k, model) if error != nil { log.Error("保存 redis wechat:Proxy is error=" + error.Error()) } }(proxyKey) // 生成62数据 // 先尝试从数据库获取设备信息 deviceInfo := wxAccount.GetUserInfo().DeviceInfo var data62 string var generateErr error if deviceInfo != nil && deviceInfo.Imei != "" { // 使用数据库中的 Imei data62, generateErr = utils.GenerateWxDat(deviceInfo.Imei) } else { // 生成新的 Imei imei := baseutils.RandomSmallHexString(32) data62, generateErr = utils.GenerateWxDat(imei) if generateErr == nil { wxAccount.GetUserInfo().DeviceInfo.Imei = imei wxAccount.GetUserInfo().LoginDataInfo.LoginData = data62 } } if generateErr != nil { return vo.NewFail(generateErr.Error()) } // 保存62数据到Redis缓存 data62Key := fmt.Sprintf("%s%s", "wechat:62data:", queryKey) err = db.SETExpirationObj(data62Key, data62, 60*5) // 5分钟过期 if err != nil { log.Error("保存62数据到Redis失败: " + err.Error()) } // 获取ticket ticket := wxAccount.GetUserInfo().Ticket return vo.DTO{ Code: vo.SUCCESS, Data: resp, Text: "获取二维码成功", Success: true, Data62: data62, Ticket: ticket, } }) } // AndroidPadLoginService 安卓平板设备登录 func AndroidPadLoginService(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { // 去除头尾空格 queryKey = strings.TrimSpace(queryKey) return checkExIdPerform(queryKey, uint32(baseinfo.AndroidPadClientVersion), func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) var proxyInfo *proxynet.WXProxyInfo // 代理替换逻辑 if len(model.Proxy) > 0 && len(model.Proxy) < 5 && !strings.Contains(model.Proxy, "4") { // 从数据库获取代理映射 proxyMapping, err := db.GetProxyMapping(model.Proxy) if err != nil { return vo.NewFail("代理获取失败: " + err.Error()) } if proxyMapping == nil || proxyMapping.ProxyValue == "" { return vo.NewFail("无效的代理编号") } model.Proxy = proxyMapping.ProxyValue } if len(model.Proxy) > 0 && !strings.Contains(model.Proxy, "测试") { // 设置代理 proxyInfo = proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!在线状态良好!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) // 设置初始化状态为 false currentCache := iwxConnect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) if iwxConnect.IsConnected() { iwxConnect.Stop() // 等待一秒 time.Sleep(time.Second * 3) err := iwxConnect.Start() time.Sleep(time.Second * 1) if err != nil { return vo.NewFail(err.Error()) } } else { iwxConnect.Stop() time.Sleep(time.Second * 2) err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } userinfo := wxAccount.GetUserInfo() userinfo.DeviceInfo.DeviceName = baseinfo.AndroidPadDeviceName userinfo.DeviceInfo.OsType = baseinfo.AndroidPadDeviceType userinfo.ClientVersion = baseinfo.AndroidPadClientVersion // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Session = []byte{} wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequest() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } return vo.NewSuccess(resp, "获取二维码成功") }) } // CarLoginService 车载登录 func CarLoginService(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { // 去除头尾空格 queryKey = strings.TrimSpace(queryKey) return checkExIdPerform(queryKey, uint32(baseinfo.CarClientVersion), func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) var proxyInfo *proxynet.WXProxyInfo // 代理替换逻辑 if len(model.Proxy) > 0 && len(model.Proxy) < 5 && !strings.Contains(model.Proxy, "4") { // 从数据库获取代理映射 proxyMapping, err := db.GetProxyMapping(model.Proxy) if err != nil { return vo.NewFail("代理获取失败: " + err.Error()) } if proxyMapping == nil || proxyMapping.ProxyValue == "" { return vo.NewFail("无效的代理编号") } model.Proxy = proxyMapping.ProxyValue } if len(model.Proxy) > 0 && !strings.Contains(model.Proxy, "测试") { // 设置代理 proxyInfo = proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!在线状态良好!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) // 设置初始化状态为 false currentCache := iwxConnect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) if iwxConnect.IsConnected() { iwxConnect.Stop() // 等待一秒 time.Sleep(time.Second * 3) err := iwxConnect.Start() time.Sleep(time.Second * 1) if err != nil { return vo.NewFail(err.Error()) } } else { iwxConnect.Stop() time.Sleep(time.Second * 2) err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } userinfo := wxAccount.GetUserInfo() userinfo.DeviceInfo.DeviceName = baseinfo.CarDeviceName userinfo.DeviceInfo.OsType = baseinfo.CarDeviceType // userinfo.DeviceInfo.OsType = baseinfo.CarDeviceType userinfo.ClientVersion = baseinfo.CarClientVersion // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Session = []byte{} wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequest() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } return vo.NewSuccess(resp, "获取二维码成功") }) } // WinLoginService windows登录 func WinLoginService(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { // 去除头尾空格 queryKey = strings.TrimSpace(queryKey) return checkExIdPerform(queryKey, uint32(baseinfo.WinClientVersion), func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { //queryKey 为空字符串 if iwxConnect == nil { return vo.NewFail("逻辑错误!") } wxAccount := iwxConnect.GetWXAccount() //请求管理器 reqInvoker := iwxConnect.GetWXReqInvoker() // 使用使用代理 key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) var proxyInfo *proxynet.WXProxyInfo // 代理替换逻辑 if len(model.Proxy) > 0 && len(model.Proxy) < 5 && !strings.Contains(model.Proxy, "4") { // 从数据库获取代理映射 proxyMapping, err := db.GetProxyMapping(model.Proxy) if err != nil { return vo.NewFail("代理获取失败: " + err.Error()) } if proxyMapping == nil || proxyMapping.ProxyValue == "" { return vo.NewFail("无效的代理编号") } model.Proxy = proxyMapping.ProxyValue } if len(model.Proxy) > 0 && !strings.Contains(model.Proxy, "测试") { // 设置代理 proxyInfo = proxynet.ParseWXProxyInfo(model.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } else { exists, _ := db.Exists(key) newModel := &req.GetLoginQrCodeModel{ Proxy: "", Check: false, } if exists { //获取代理 db.GETObj(key, &newModel) } if newModel.Proxy != "" { proxyInfo = proxynet.ParseWXProxyInfo(newModel.Proxy) wxAccount.GetUserInfo().SetProxy(proxyInfo) } } //wxAccount := iwxConnect.GetWXAccount() //检查是否在线会进行一次二次登录如果用户退出或者掉线才能重新获取二维码 if iwxConnect.CheckOnLineStatusLogin() { return vo.DTO{ Code: vo.FAIL_Bound, Data: nil, Text: "该链接已绑定微信号!在线状态良好!", } } // 清除旧的状态缓存,确保使用新的二维码状态 db.ClearCheckStatusCache(queryKey) // 设置初始化状态为 false currentCache := iwxConnect.GetWXCache() currentCache.SetScanFinish(false) currentCache.SetInitNewSyncFinished(false) if iwxConnect.IsConnected() { iwxConnect.Stop() // 等待一秒 time.Sleep(time.Second * 3) err := iwxConnect.Start() time.Sleep(time.Second * 1) if err != nil { return vo.NewFail(err.Error()) } } else { iwxConnect.Stop() time.Sleep(time.Second * 2) err := iwxConnect.Start() if err != nil { return vo.NewFail(err.Error()) } } userinfo := wxAccount.GetUserInfo() userinfo.DeviceInfo.DeviceName = baseinfo.WinDeviceName11 userinfo.DeviceInfo.OsType = baseinfo.WinDeviceType11 userinfo.ClientVersion = baseinfo.WinClientVersion // 设置 UUID := wxAccount.GetUserInfo().UUID oldObj := make(map[string]string) oldObj["old"] = "false" db.SETExpirationObj("old_"+UUID, &oldObj, 0) wxAccount.GetUserInfo().Session = []byte{} wxAccount.GetUserInfo().Uin = 0 wxAccount.GetUserInfo().CheckSumKey = []byte{} // 检查reqInvoker是否为空 if reqInvoker == nil { return vo.NewFail("微信请求调用器为空") } // 检查wxconn是否已连接 if !iwxConnect.IsConnected() { return vo.NewFail("微信服务器未连接") } //发送获取二维码请求 loginQrCodeResp, err := reqInvoker.SendGetLoginQrcodeRequest() if err != nil { return vo.NewFail("获取二维码失败!err:" + err.Error()) } err = reqInvoker.SendCheckLoginQrcodeRequest(loginQrCodeResp.GetUuid(), loginQrCodeResp.GetAes().GetKey()) if err != nil { return vo.NewFail("检查扫码状态失败!err:" + err.Error()) } resp := gin.H{ "baseResp": loginQrCodeResp.GetBaseResponse(), "Txt": "建议返回data=之后内容自定义生成二维码", "QrCodeUrl": "https://api.pwmqr.com/qrcode/create/?url=http://weixin.qq.com/x/" + loginQrCodeResp.GetUuid(), } //是否为新链接 if newIWXConnect { resp["Key"] = wxAccount.GetUserInfo().UUID } return vo.NewSuccess(resp, "获取二维码成功") }) }