Files
wechat_ipad_pro/api/service/loginService.go

2028 lines
62 KiB
Go
Raw Normal View History

2026-02-17 13:06:23 +08:00
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, 请根据文档操作!!!"
2026-02-17 13:06:23 +08:00
}
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, 请根据文档操作!!!"
2026-02-17 13:06:23 +08:00
}
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, "获取二维码成功")
})
}