package clientsdk import ( "bytes" "compress/zlib" "crypto/md5" "crypto/rand" "encoding/base64" "encoding/hex" "encoding/xml" "errors" "fmt" "html/template" "io" "io/ioutil" "net/http" "net/url" "regexp" "strconv" "strings" "time" "xiawan/wx/api/req" "xiawan/wx/api/utils" "xiawan/wx/api/vo" "xiawan/wx/lib" "github.com/gogo/protobuf/proto" "github.com/google/uuid" "github.com/lunny/log" "xiawan/wx/clientsdk/android" "xiawan/wx/clientsdk/baseinfo" "xiawan/wx/clientsdk/baseutils" "xiawan/wx/clientsdk/cecdh" "xiawan/wx/clientsdk/extinfo" clientsdk "xiawan/wx/clientsdk/hybrid" "xiawan/wx/clientsdk/mmtls" "xiawan/wx/protobuf/wechat" ) // 获取登录二维码 直登 func SendLoginQRCodeRequestDirect(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { // 重新生成AesKey userInfo.SessionKey = baseutils.RandomBytes(16) var request wechat.LoginQRCodeRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // AESKey var aesKey wechat.AESKey var tmpAesKeyLen = uint32(16) aesKey.Len = &tmpAesKeyLen aesKey.Key = []byte(userInfo.SessionKey) request.Aes = &aesKey // OpCode var tmpOpcode = uint32(0) request.Opcode = &tmpOpcode // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeGetLoginQRCode, 7) // 初始化代理信息 resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getloginqrcode", sendData) if err != nil { return nil, err } userInfo.ClientVersion = baseinfo.ClientVersion userInfo.DeviceInfo.DeviceName = baseinfo.IPadDeviceName userInfo.DeviceInfo.OsType = baseinfo.DeviceTypeIos return DecodePackHeader(resp, nil) } // SendLoginQRCodeRequest 获取登陆二维码 正常 func SendLoginQRCodeRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { // 重新生成AesKey userInfo.SessionKey = baseutils.RandomBytes(16) var request wechat.LoginQRCodeRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // AESKey var aesKey wechat.AESKey var tmpAesKeyLen = uint32(16) aesKey.Len = &tmpAesKeyLen aesKey.Key = []byte(userInfo.SessionKey) request.Aes = &aesKey // OpCode var tmpOpcode = uint32(0) request.Opcode = &tmpOpcode // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeGetLoginQRCode, 7) // 初始化代理信息 resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getloginqrcode", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendLoginQRCodeRequest 获取登陆二维码(绕过验证码) func SendLoginQRCodeRequestX(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { // 重新生成AesKey userInfo.SessionKey = baseutils.RandomBytes(16) // 构造请求 var request wechat.LoginQRCodeRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // AESKey var aesKey wechat.AESKey var tmpAesKeyLen = uint32(16) aesKey.Len = &tmpAesKeyLen aesKey.Key = []byte(userInfo.SessionKey) request.Aes = &aesKey // OpCode var tmpOpcode = uint32(0) request.Opcode = &tmpOpcode // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeGetLoginQRCode, 7) // 初始化代理信息 resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getloginqrcode", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendManualAuth 发送ManualAuth请求 func sendManualAuthByAccountData(userInfo *baseinfo.UserInfo, accountData []byte) (*baseinfo.PackHeader, error) { // 打包加密数据 subHeader := make([]byte, 0) tmpBytes := baseutils.Int32ToBytes(uint32(len(accountData))) subHeader = append(subHeader, tmpBytes[0:]...) // 获取 deviceDataRequest deviceData := GetManualAuthAesReqDataMarshal(userInfo) tmpBytes = baseutils.Int32ToBytes(uint32(len(deviceData))) subHeader = append(subHeader, tmpBytes[0:]...) // 加密压缩 accountData newAccountData := baseutils.CompressAndRsaByVer(accountData, userInfo.GetLoginRsaVer()) tmpBytes = baseutils.Int32ToBytes(uint32(len(newAccountData))) subHeader = append(subHeader, tmpBytes[0:]...) subHeader = append(subHeader, newAccountData[0:]...) // 压缩加密 deviceData newDeviceData := baseutils.CompressAes(userInfo.SessionKey, deviceData) subHeader = append(subHeader, newDeviceData[0:]...) // 发送登陆请求 sendData := Pack(userInfo, subHeader, baseinfo.MMRequestTypeManualAuth, 17) // 初始化代理信息 resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/manualauth", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendManualAuthA16发送A16登录请求 func SendManualAuthA16(userInfo *baseinfo.UserInfo, accountData []byte) (*baseinfo.PackHeader, error) { /*req := &wechat.ManualAuthRequest{ RsaReqData: GetManualAuthRsaReqDataProtobuf(userInfo,userInfo.LoginDataInfo.UserName,userInfo.LoginDataInfo.PassWord), AesReqData: GetManualAuthAesReqDataA16Protobuf(userInfo), }*/ // 发送请求 // 打包加密数据 subHeader := make([]byte, 0) tmpBytes := baseutils.Int32ToBytes(uint32(len(accountData))) subHeader = append(subHeader, tmpBytes[0:]...) // 获取 deviceDataRequest deviceData := GetManualAuthAesReqDataA16Protobuf(userInfo) tmpBytes = baseutils.Int32ToBytes(uint32(len(deviceData))) subHeader = append(subHeader, tmpBytes[0:]...) // 加密压缩 accountData newAccountData := baseutils.CompressAndRsaByVer(accountData, userInfo.GetLoginRsaVer()) tmpBytes = baseutils.Int32ToBytes(uint32(len(newAccountData))) subHeader = append(subHeader, tmpBytes[0:]...) subHeader = append(subHeader, newAccountData[0:]...) // 压缩加密 deviceData newDeviceData := baseutils.CompressAes(userInfo.SessionKey, deviceData) subHeader = append(subHeader, newDeviceData[0:]...) // 发送登陆请求 sendData := Pack(userInfo, subHeader, baseinfo.MMRequestTypeManualAuth, 17) // 初始化代理信息 resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/manualauth", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendManualAuth 发送登陆请求 func SendManualAuth(userInfo *baseinfo.UserInfo, newpass string, wxid string) (*baseinfo.PackHeader, error) { var tmpNid uint32 = 713 userInfo.EcPublicKey, userInfo.EcPrivateKey = cecdh.GenerateEccKey() authRequest := &wechat.ManualAuthAccountRequest{} // aes_key var aesKey wechat.AESKey var tmpAesKeyLen uint32 = 16 aesKey.Len = &tmpAesKeyLen aesKey.Key = []byte(userInfo.SessionKey) authRequest.Aes = &aesKey // 其它参数 var ecdhKey wechat.ECDHKey var key wechat.SKBuiltinString_ key.Buffer = userInfo.EcPublicKey var tmpLen = (uint32)(len(userInfo.EcPublicKey)) key.Len = &tmpLen ecdhKey.Nid = &tmpNid ecdhKey.Key = &key authRequest.EcdhKey = &ecdhKey authRequest.UserName = &wxid userInfo.WxId = wxid //判断是否为iPad登录的伪密码 if !strings.HasPrefix(newpass, "extdevnewpwd_") { newpass = baseutils.Md5Value(newpass) } authRequest.Password_1 = &newpass // 序列化 accountData, err := proto.Marshal(authRequest) if err != nil { return nil, err } if !strings.HasPrefix(userInfo.LoginDataInfo.LoginData, "A") && userInfo.DeviceInfo != nil { return sendManualAuthByAccountData(userInfo, accountData) } return SendManualAuthA16(userInfo, accountData) } // 获取DeviceToken IOS func SendIosDeviceTokenRequest(userInfo *baseinfo.UserInfo) (*wechat.TrustResp, error) { deviceIos := userInfo.DeviceInfo fmt.Println("iphonever", deviceIos.IphoneVer, "osType", deviceIos.OsType, "deviceName", deviceIos.DeviceName, userInfo.ClientVersion, baseinfo.ClientVersion, 11111) deviceId := Get62Key(userInfo.LoginDataInfo.LoginData) if deviceId[:2] != "49" { deviceId = "49" + deviceId[2:] } clientVersion := userInfo.ClientVersion if !(int(clientVersion) > 0) { clientVersion = baseinfo.ClientVersion } installTime := strconv.FormatInt(time.Now().Add(-2592234*time.Second).Unix(), 10) // 一个月前(偏移234秒)秒级时间戳 kernBootTime := strconv.FormatInt(time.Now().Add(-2592230*time.Second).Unix()*1000, 10) // 一个月前(偏移230秒)毫秒秒级时间戳 uuid1, uuid2 := baseinfo.IOSUuid(deviceId) td := &wechat.TrustReq{ Td: &wechat.TrustData{ Tdi: []*wechat.TrustDeviceInfo{ {Key: proto.String("deviceid"), Val: proto.String(deviceId)}, {Key: proto.String("sdi"), Val: proto.String(extinfo.GetCidMd5(deviceId, extinfo.GetCid(0x0262626262626)))}, {Key: proto.String("idfv"), Val: proto.String(uuid1)}, {Key: proto.String("idfa"), Val: proto.String(uuid2)}, {Key: proto.String("device_model"), Val: proto.String(deviceIos.IphoneVer)}, {Key: proto.String("os_version"), Val: proto.String(deviceIos.OsType)}, {Key: proto.String("core_count"), Val: proto.String("6")}, {Key: proto.String("carrier_name"), Val: proto.String("")}, {Key: proto.String("is_jailbreak"), Val: proto.String("0")}, {Key: proto.String("device_name"), Val: proto.String(deviceIos.DeviceName)}, {Key: proto.String("client_version"), Val: proto.String(fmt.Sprintf("%v", clientVersion))}, {Key: proto.String("plist_version"), Val: proto.String(fmt.Sprintf("%v", clientVersion))}, {Key: proto.String("language"), Val: proto.String("zh")}, {Key: proto.String("locale_country"), Val: proto.String("CN")}, {Key: proto.String("screen_width"), Val: proto.String("834")}, {Key: proto.String("screen_height"), Val: proto.String("1112")}, {Key: proto.String("install_time"), Val: proto.String(installTime)}, {Key: proto.String("kern_boottime"), Val: proto.String(kernBootTime)}, }, }, } pb, _ := proto.Marshal(td) var b bytes.Buffer w := zlib.NewWriter(&b) w.Write(pb) w.Close() zt := new(ZT) zt.Init() // encData := zt.Encrypt(b.Bytes()) encData := android.SaeEncrypt07(b.Bytes()) randKey := make([]byte, 16) _, _ = io.ReadFull(rand.Reader, randKey) fp := &wechat.FPFresh{ BaseRequest: &wechat.BaseRequest{ SessionKey: []byte{}, Uin: proto.Uint32(0), DeviceId: append([]byte(deviceId), 0), ClientVersion: proto.Uint32(clientVersion), OsType: &userInfo.DeviceInfo.OsType, Scene: proto.Uint32(0), }, SessKey: randKey, Ztdata: &wechat.ZTData{ Version: []byte("00000007"), Encrypted: proto.Uint64(1), Data: encData, TimeStamp: proto.Int64(int64(time.Now().Unix())), OpType: proto.Uint64(5), Uin: proto.Uint64(0), }, } reqData, _ := proto.Marshal(fp) hec := &android.Client{} DeviceTypeIos := deviceIos.OsType if DeviceTypeIos == "" { DeviceTypeIos = baseinfo.DeviceTypeIos } hec.Init("IOS", int(clientVersion), DeviceTypeIos) hecData := hec.HybridEcdhPackIosEn(3789, 0, nil, reqData) // 初始化代理信息 MMInfo := userInfo.GetMMInfo() MMInfo.Dialer = userInfo.GetDialer() recvData, err := mmtls.MMHTTPPostData(MMInfo, "/cgi-bin/micromsg-bin/fpinitnl", hecData) if err != nil { return &wechat.TrustResp{}, err } if len(recvData) <= 31 { return &wechat.TrustResp{}, errors.New(hex.EncodeToString(recvData)) } ph := hec.HybridEcdhPackIosUn(recvData) DTResp := &wechat.TrustResp{} _ = proto.Unmarshal(ph.Data, DTResp) return DTResp, nil } // 获取DeviceToken func SendAndroIdDeviceTokenRequest(userInfo *baseinfo.UserInfo) (*wechat.TrustResp, error) { Android16 := userInfo.DeviceInfoA16 td := &wechat.TrustReq{ Td: &wechat.TrustData{ Tdi: []*wechat.TrustDeviceInfo{ {Key: proto.String("IMEI"), Val: proto.String(Android16.AndriodImei(Android16.DeviceIdStr[:15]))}, {Key: proto.String("AndroidID"), Val: proto.String(Android16.AndriodID(Android16.DeviceIdStr[:15]))}, {Key: proto.String("PhoneSerial"), Val: proto.String(Android16.AndriodPhoneSerial(Android16.DeviceIdStr[:15]))}, {Key: proto.String("cid"), Val: proto.String("")}, {Key: proto.String("WidevineDeviceID"), Val: proto.String(Android16.AndriodWidevineDeviceID(Android16.DeviceIdStr[:15]))}, {Key: proto.String("WidevineProvisionID"), Val: proto.String(Android16.AndriodWidevineProvisionID(Android16.DeviceIdStr[:15]))}, {Key: proto.String("GSFID"), Val: proto.String("")}, {Key: proto.String("SoterID"), Val: proto.String("")}, {Key: proto.String("SoterUid"), Val: proto.String("")}, {Key: proto.String("FSID"), Val: proto.String(Android16.AndriodFSID(Android16.DeviceIdStr[:15]))}, {Key: proto.String("BootID"), Val: proto.String("")}, {Key: proto.String("IMSI"), Val: proto.String("")}, {Key: proto.String("PhoneNum"), Val: proto.String("")}, {Key: proto.String("WeChatInstallTime"), Val: proto.String("1556077144")}, {Key: proto.String("PhoneModel"), Val: proto.String(Android16.AndroidPhoneModel(Android16.DeviceIdStr[:15]))}, {Key: proto.String("BuildBoard"), Val: proto.String("bullhead")}, {Key: proto.String("BuildBootloader"), Val: proto.String(Android16.AndroidBuildBoard(Android16.DeviceIdStr[:15]))}, {Key: proto.String("SystemBuildDate"), Val: proto.String("Fri Sep 28 23:37:27 UTC 2019")}, {Key: proto.String("SystemBuildDateUTC"), Val: proto.String("1538177847")}, {Key: proto.String("BuildFP"), Val: proto.String(Android16.AndroidBuildFP(Android16.DeviceIdStr[:15]))}, {Key: proto.String("BuildID"), Val: proto.String(Android16.AndroidBuildID(Android16.DeviceIdStr[:15]))}, {Key: proto.String("BuildBrand"), Val: proto.String("google")}, {Key: proto.String("BuildDevice"), Val: proto.String("bullhead")}, {Key: proto.String("BuildProduct"), Val: proto.String("bullhead")}, {Key: proto.String("Manufacturer"), Val: proto.String(Android16.AndroidManufacturer(Android16.DeviceIdStr[:15]))}, {Key: proto.String("RadioVersion"), Val: proto.String(Android16.AndroidRadioVersion(Android16.DeviceIdStr[:15]))}, {Key: proto.String("AndroidVersion"), Val: proto.String(Android16.AndroidVersion())}, {Key: proto.String("SdkIntVersion"), Val: proto.String("27")}, {Key: proto.String("ScreenWidth"), Val: proto.String("1080")}, {Key: proto.String("ScreenHeight"), Val: proto.String("1794")}, {Key: proto.String("SensorList"), Val: proto.String("BMI160 accelerometer#Bosch#0.004788#1,BMI160 gyroscope#Bosch#0.000533#1,BMM150 magnetometer#Bosch#0.000000#1,BMP280 pressure#Bosch#0.005000#1,BMP280 temperature#Bosch#0.010000#1,RPR0521 Proximity Sensor#Rohm#1.000000#1,RPR0521 Light Sensor#Rohm#10.000000#1,Orientation#Google#1.000000#1,BMI160 Step detector#Bosch#1.000000#1,Significant motion#Google#1.000000#1,Gravity#Google#1.000000#1,Linear Acceleration#Google#1.000000#1,Rotation Vector#Google#1.000000#1,Geomagnetic Rotation Vector#Google#1.000000#1,Game Rotation Vector#Google#1.000000#1,Pickup Gesture#Google#1.000000#1,Tilt Detector#Google#1.000000#1,BMI160 Step counter#Bosch#1.000000#1,BMM150 magnetometer (uncalibrated)#Bosch#0.000000#1,BMI160 gyroscope (uncalibrated)#Bosch#0.000533#1,Sensors Sync#Google#1.000000#1,Double Twist#Google#1.000000#1,Double Tap#Google#1.000000#1,Device Orientation#Google#1.000000#1,BMI160 accelerometer (uncalibrated)#Bosch#0.004788#1")}, {Key: proto.String("DefaultInputMethod"), Val: proto.String("com.google.android.inputmethod.latin")}, {Key: proto.String("InputMethodList"), Val: proto.String("Google \345\215\260\345\272\246\350\257\255\351\224\256\347\233\230#com.google.android.apps.inputmethod.hindi,Google \350\257\255\351\237\263\350\276\223\345\205\245#com.google.android.googlequicksearchbox,Google \346\227\245\350\257\255\350\276\223\345\205\245\346\263\225#com.google.android.inputmethod.japanese,Google \351\237\251\350\257\255\350\276\223\345\205\245\346\263\225#com.google.android.inputmethod.korean,Gboard#com.google.android.inputmethod.latin,\350\260\267\346\255\214\346\213\274\351\237\263\350\276\223\345\205\245\346\263\225#com.google.android.inputmethod.pinyin")}, {Key: proto.String("DeviceID"), Val: proto.String(Android16.DeviceIdStr[:15])}, {Key: proto.String("OAID"), Val: proto.String("")}, }, }, } pb, _ := proto.Marshal(td) var b bytes.Buffer w := zlib.NewWriter(&b) w.Write(pb) w.Close() zt := new(android.ZT) zt.Init() encData := zt.Encrypt(b.Bytes()) randKey := make([]byte, 16) io.ReadFull(rand.Reader, randKey) fp := &wechat.FPFresh{ BaseRequest: GetBaseRequest(userInfo), SessKey: randKey, Ztdata: &wechat.ZTData{ Version: []byte("00000003"), // apad 此处为 "00000003\x00" Encrypted: proto.Uint64(1), Data: encData, TimeStamp: proto.Int64(int64(time.Now().Unix())), OpType: proto.Uint64(5), Uin: proto.Uint64(0), }, } reqData, _ := proto.Marshal(fp) hec := &android.Client{} hec.Init("Android", int(baseinfo.AndroidClientVersion), baseinfo.AndroidDeviceType) sendData := hec.HybridEcdhPackAndroidEn(3789, 10002, 0, nil, reqData) MMInfo := userInfo.GetMMInfo() MMInfo.Dialer = userInfo.GetDialer() recvData, err := mmtls.MMHTTPPostData(MMInfo, "/cgi-bin/micromsg-bin/fpinitnl", sendData) if err != nil { return &wechat.TrustResp{}, err } if len(recvData) <= 31 { return &wechat.TrustResp{}, errors.New(hex.EncodeToString(recvData)) } ph := hec.HybridEcdhPackAndroidUn(recvData) DTResp := &wechat.TrustResp{} _ = proto.Unmarshal(ph.Data, DTResp) return DTResp, nil } // 获取DeviceToken func SendDeviceTokenRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { deviceInfo := userInfo.DeviceInfo deviceId := hex.EncodeToString(deviceInfo.DeviceID) ServerVersion := userInfo.ClientVersion if !(int(ServerVersion) > 0) { ServerVersion = baseinfo.ServerVersion } data, err := extinfo.GetZTData(deviceId, deviceInfo.OsType, deviceInfo.OsTypeNumber, deviceInfo.DeviceName, uint64(ServerVersion)) if err != nil { return nil, err } request := wechat.TrustRequest{ BaseRequest: GetBaseRequest(userInfo), RandomKey: userInfo.SessionKey, SpamBuff: data, } // 发送请求 src, _ := proto.Marshal(&request) //sendData := Pack(userInfo, src, 3789, 12) secKeyMgr := NewSecLoginKeyMgrByVer(146) reqData := src //加密 encrypt, epKey, token, ecdhpairkey, err := clientsdk.HybridEncrypt(reqData, secKeyMgr.WeChatPubKey) if err != nil { log.Error("加密 error", err.Error()) } ecdhPacket := &wechat.EcdhPacket{ Type: proto.Uint32(1), Key: &wechat.BufferT{ ILen: proto.Uint32(415), Buffer: ecdhpairkey.PubKey, }, Token: token, Url: proto.String(""), ProtobufData: encrypt, } secKeyMgr.PubKey = ecdhpairkey.PubKey secKeyMgr.PriKey = ecdhpairkey.PriKey secKeyMgr.SourceData = reqData secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, epKey[24:]...) secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, reqData...) ecdhDataPacket, err := proto.Marshal(ecdhPacket) if err != nil { log.Error("ecdhDataPacket error", err.Error()) } packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, 3789, ecdhDataPacket, ecdhDataPacket, uint32(len(ecdhDataPacket)), 12, uint32(0x4e)) //设置Hybrid 加密密钥版本 packHeader.HybridKeyVer = secKeyMgr.WeChatPubKeyVersion //开始组头 //packHeader.ReqData= PackHeaderSerialize(packHeader, false) sendData := PackHeaderSerialize(packHeader, true) MMInfo := userInfo.GetMMInfo() MMInfo.Dialer = userInfo.GetDialer() resp, err := mmtls.MMHTTPPostData(MMInfo, "/cgi-bin/micromsg-bin/fpinitnl", sendData) if err != nil { return nil, err } packHeader, err = DecodePackHeader(resp, nil) if err != nil { return nil, err } packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256) if err != nil { return nil, err } return packHeader, err } // 二次登录-new func SendSecautouthRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { userInfo.EcPublicKey, userInfo.EcPrivateKey = cecdh.GenerateEccKey() autoAuthKey := &wechat.AutoAuthKey{} err := proto.Unmarshal(userInfo.AutoAuthKey, autoAuthKey) if err != nil { return nil, err } userInfo.SessionKey = autoAuthKey.EncryptKey.Buffer var tmpNid uint32 = 713 var key wechat.SKBuiltinString_ key.Buffer = userInfo.EcPublicKey var tmpLen = (uint32)(len(userInfo.EcPublicKey)) key.Len = &tmpLen // ClientSeqId tmpTime := int(time.Now().UnixNano() / 1000000000) tmpTimeStr := strconv.Itoa(tmpTime) var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr) // extSpamInfo var extSpamInfo wechat.SKBuiltinString_ extSpamInfo.Buffer = GetExtPBSpamInfoDataLogin(userInfo) extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen req := &wechat.AutoAuthRequest{ RsaReqData: &wechat.AutoAuthRsaReqData{ AesEncryptKey: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(autoAuthKey.EncryptKey.Buffer))), Buffer: autoAuthKey.EncryptKey.Buffer, }, PubEcdhKey: &wechat.ECDHKey{ Nid: proto.Uint32(tmpNid), Key: &key, }, }, AesReqData: &wechat.AutoAuthAesReqData{ BaseRequest: GetBaseRequest(userInfo), BaseReqInfo: &wechat.BaseAuthReqInfo{}, AutoAuthKey: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(userInfo.AutoAuthKey))), Buffer: userInfo.AutoAuthKey, }, Imei: &userInfo.DeviceInfo.Imei, SoftType: &userInfo.DeviceInfo.SoftTypeXML, BuiltinIpSeq: proto.Uint32(0), ClientSeqId: &strClientSeqID, DeviceName: proto.String(userInfo.DeviceInfo.DeviceName), SoftInfoXml: proto.String("iPad Mini 4"), Language: proto.String("zh_CN"), TimeZone: proto.String("8.00"), ExtSpamInfo: &extSpamInfo, }, } reqData, err := proto.Marshal(req) if err != nil { return nil, err } secKeyMgr := NewSecLoginKeyMgrByVer(146) //加密 encrypt, epKey, token, ecdhpairkey, err := clientsdk.HybridEncrypt(reqData, secKeyMgr.WeChatPubKey) if err != nil { return nil, err } /*ecdhPacket := &wechat.EcdhPacket{ Type: proto.Uint32(1), Key: &wechat.BufferT{ ILen: proto.Uint32(415), Buffer: ecdhpairkey.PubKey, }, Token: token, Url: proto.String(""), ProtobufData: encrypt, }*/ ecdhPacket := &wechat.HybridEcdhRequest{ Type: proto.Int32(1), SecECDHKey: &wechat.BufferT{ ILen: proto.Uint32(415), Buffer: ecdhpairkey.PubKey, }, Randomkeydata: token, Randomkeyextenddata: epKey, Encyptdata: encrypt, } secKeyMgr.PubKey = ecdhpairkey.PubKey secKeyMgr.PriKey = ecdhpairkey.PriKey secKeyMgr.SourceData = reqData secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, epKey[24:]...) secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, reqData...) ecdhDataPacket, err := proto.Marshal(ecdhPacket) if err != nil { return nil, err } packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, 763, ecdhDataPacket, ecdhDataPacket, uint32(len(ecdhDataPacket)), 12, uint32(0x4e)) //设置Hybrid 加密密钥版本 packHeader.HybridKeyVer = secKeyMgr.WeChatPubKeyVersion //开始组头 retData := PackHeaderSerialize(packHeader, false) //fmt.Println(hex.EncodeToString(retData)) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/secautoauth", retData) if err != nil { return nil, err } packHeader, err = DecodePackHeader(resp, nil) if err != nil { return nil, err } packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256) if err != nil { return nil, err } return packHeader, err /*hec :=&Client{} hec.Init("IOS") hecData := hec.HybridEcdhPackIosEn(763,userInfo.Uin,userInfo.Session,reqData) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/secautoauth", hecData) if err != nil { return nil, err } packHeader := hec.HybridEcdhPackIosUn(resp) packHeader, err = DecodePackHeader(resp, nil) if err != nil { return nil, err } packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256) if err != nil { return nil, err }*/ // return packHeader, err } // SendAutoAuthRequest 发送token登陆请求 func SendAutoAuthRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { userInfo.EcPublicKey, userInfo.EcPrivateKey = cecdh.GenerateEccKey() autoAuthKey := &wechat.AutoAuthKey{} err := proto.Unmarshal(userInfo.AutoAuthKey, autoAuthKey) if err != nil { return nil, err } userInfo.SessionKey = autoAuthKey.EncryptKey.Buffer // 获取AutoAuthRsaReqData rsaReqData := GetAutoAuthRsaReqDataMarshal(userInfo) aesReqData := GetAutoAuthAesReqDataMarshal(userInfo) // 开始打包数据 // 加密压缩 rsaReqData rsaEncodeData := baseutils.CompressAndRsaByVer(rsaReqData, userInfo.GetLoginRsaVer()) rsaAesEncodeData := baseutils.CompressAes(userInfo.SessionKey, rsaReqData) // 加密压缩 aesReqData aesEncodeData := baseutils.CompressAes(userInfo.SessionKey, aesReqData) body := make([]byte, 0) // rsaReqBuflen tmpBuf := baseutils.Int32ToBytes(uint32(len(rsaReqData))) body = append(body, tmpBuf[0:]...) // aesReqBuf len tmpBuf = baseutils.Int32ToBytes(uint32(len(aesReqData))) body = append(body, tmpBuf[0:]...) // rsaEncodeData len tmpBuf = baseutils.Int32ToBytes(uint32(len(rsaEncodeData))) body = append(body, tmpBuf[0:]...) // rsaAesEncodeData len tmpBuf = baseutils.Int32ToBytes(uint32(len(rsaAesEncodeData))) body = append(body, tmpBuf[0:]...) // rsaEncodeData body = append(body, rsaEncodeData[0:]...) body = append(body, rsaAesEncodeData[0:]...) body = append(body, aesEncodeData[0:]...) /*sendData,secKeyMgr:= Pack12(userInfo, body, baseinfo.MMRequestTypeAutoAuth, 12) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/autoauth",sendData) if err != nil { log.Error("mmtls error", err.Error()) } packHeader, err:= DecodePackHeader(resp, nil) if err != nil { log.Error("ecdhDataPacket error", err.Error()) } packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256) if err != nil { log.Error("HybridEcdhDecrypt error", err.Error()) } return packHeader,nil*/ // 发送请求 sendData := Pack(userInfo, body, baseinfo.MMRequestTypeAutoAuth, 9) MMInfo := userInfo.GetMMInfo() MMInfo.Dialer = userInfo.GetDialer() resp, err := mmtls.MMHTTPPostData(MMInfo, "/cgi-bin/micromsg-bin/autoauth", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetCheckLoginQRCodeRequest 长链接:获取检测二维码状态-请求数据包 func GetCheckLoginQRCodeRequest(userInfo *baseinfo.UserInfo, qrcodeUUID string, qrcodeKey []byte) ([]byte, error) { var request wechat.CheckLoginQRCodeRequest // 重新生成AesKey //userInfo.SessionKey = baseutils.RandomBytes(16) // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // AESKey var aesKey wechat.AESKey var tmpAesKeyLen = uint32(16) aesKey.Len = &tmpAesKeyLen aesKey.Key = []byte(userInfo.SessionKey) request.Aes = &aesKey // uuid request.Uuid = &qrcodeUUID // timeStamp 当前系统时间 timeStamp := (uint32)(time.Now().Unix()) request.TimeStamp = &timeStamp // OpCode var tmpOpcode = uint32(0) request.Opcode = &tmpOpcode // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeCheckLoginQRCode, 7) return sendData, nil } // SendPushQrLoginNotice 二维码二次登录 func SendPushQrLoginNotice(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.PushLoginURLRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request = wechat.PushLoginURLRequest{ BaseRequest: baseReq, UserName: proto.String(userInfo.GetUserName()), AutoAuthTicket: proto.String(""), ClientID: proto.String(fmt.Sprintf("iPad-Push-%s.110141", userInfo.DeviceInfo.DeviceID)), RandomEnCryptKey: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(userInfo.SessionKey))), Buffer: userInfo.SessionKey, }, OPCode: proto.Uint32(3), DeviceName: proto.String(userInfo.DeviceInfo.DeviceName), AutoAuthKey: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(userInfo.AutoAuthKey))), Buffer: userInfo.AutoAuthKey, }, } // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypePushQrLogin, 1) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/pushloginurl", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetHeartBeatShortRequest 短链接心跳 func GetHeartBeatShortRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { sendData, err := GetHeartBeatRequest(userInfo) if err != nil { return nil, err } MMInfo := userInfo.GetMMInfo() MMInfo.Dialer = userInfo.GetDialer() resp, err := mmtls.MMHTTPPostData(MMInfo, "/cgi-bin/micromsg-bin/heartbeat", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetHeartBeatRequest 长链接:获取心跳包-请求数据包 func GetHeartBeatRequest(userInfo *baseinfo.UserInfo) ([]byte, error) { var request wechat.HeartBeatRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // timeStamp 当前系统时间 timeStamp := (uint32)(time.Now().UnixNano() / 1000000000) request.TimeStamp = &timeStamp // Scene request.Scene = &tmpScene // KeyBuf request.KeyBuf = &wechat.SKBuiltinString_{} request.KeyBuf.Buffer = userInfo.SessionKey request.KeyBuf.Len = proto.Uint32(uint32(len(userInfo.SessionKey))) // 打包数据 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeHeartBeat, 5) return sendData, nil } // SendNewSyncRequest 发送同步信息请求 func SendNewSyncRequest(userInfo *baseinfo.UserInfo, scene uint32) (*baseinfo.PackHeader, error) { var request wechat.NewSyncRequest zeroValue32 := uint32(0) // Oplog var opLog wechat.CmdList opLog.Count = &zeroValue32 opLog.ItemList = make([]*wechat.CmdItem, 0) request.Oplog = &opLog // Selector tmpSelector := uint32(262151) request.Selector = &tmpSelector // keyBuf var keyBuf wechat.SKBuiltinString_ keyBuf.Buffer = userInfo.SyncKey tmpLen := uint32(len(keyBuf.Buffer)) keyBuf.Len = &tmpLen request.KeyBuf = &keyBuf // Scene request.Scene = &scene // DeviceType if userInfo.DeviceInfoA16 != nil { request.DeviceType = &baseinfo.AndroidDeviceType } else { request.DeviceType = &userInfo.DeviceInfo.OsType } // syncMsgDigest : 短链接同步 syncMsgDigest := baseinfo.MMSyncMsgDigestTypeShortLink request.SyncMsgDigest = &syncMsgDigest // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeNewSync, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newsync", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 同步消息 func SendWxSyncMsg(userInfo *baseinfo.UserInfo, key string) (*baseinfo.PackHeader, error) { zeroValue32 := uint32(0) // Oplog var opLog wechat.CmdList opLog.Count = &zeroValue32 opLog.ItemList = make([]*wechat.CmdItem, 0) // var keyBuf wechat.SKBuiltinString_ keyBuf.Buffer = userInfo.SyncKey if key != "" { keyBuf.Buffer = []byte(key) } tmpLen := uint32(len(keyBuf.Buffer)) keyBuf.Len = &tmpLen request := wechat.NewSyncRequest{ Oplog: &opLog, Selector: proto.Uint32(262151), Scene: proto.Uint32(4), DeviceType: proto.String(userInfo.DeviceInfo.OsType), SyncMsgDigest: proto.Uint32(baseinfo.MMSyncMsgDigestTypeShortLink), KeyBuf: &keyBuf, } // 发送请求 src, _ := proto.Marshal(&request) sendData := Pack(userInfo, src, baseinfo.MMRequestTypeNewSync, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newsync", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendGetProfileRequest 发送获取帐号所有信息请求 func SendGetProfileRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.GetProfileRequest baseReq := GetBaseRequest(userInfo) var tmpZero = uint32(0) baseReq.Scene = &tmpZero request.BaseRequest = baseReq // 发送请求 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetProfile, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getprofile", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 获取设备 func SendGetSafetyInfoRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) //baseRequest.Scene = proto.Uint32(1) var req = wechat.GetSafetyInfoRequest{ BaseRequest: baseRequest, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 850, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getsafetyinfo", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 删除设备 func SendDelSafeDeviceRequest(userInfo *baseinfo.UserInfo, uuid string) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) //baseRequest.Scene = proto.Uint32(1) var req = wechat.DelSafeDeviceRequest{ BaseRequest: baseRequest, Uuid: proto.String(uuid), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 362, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delsafedevice", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 检测微信登录环境 func SendCheckCanSetAliasRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) var req = wechat.CheckCanSetAliasReq{ BaseRequest: baseRequest, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 926, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/checkcansetalias", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendInitContactReq 初始化联系人列表 func SendInitContactReq(userInfo *baseinfo.UserInfo, contactSeq uint32) (*baseinfo.PackHeader, error) { var request wechat.InitContactReq // Username request.Username = &userInfo.WxId // CurrentWxcontactSeq request.CurrentWxcontactSeq = &contactSeq // CurrentChatRoomContactSeq roomContactSeq := uint32(0) request.CurrentChatRoomContactSeq = &roomContactSeq // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeInitContact, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/initcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } func GetContactListPageReq(userInfo *baseinfo.UserInfo, CurrentWxcontactSeq uint32, CurrentChatRoomContactSeq uint32) (*baseinfo.PackHeader, error) { var request wechat.InitContactReq // Username request.Username = &userInfo.WxId // CurrentWxcontactSeq request.CurrentWxcontactSeq = &CurrentWxcontactSeq request.CurrentChatRoomContactSeq = &CurrentChatRoomContactSeq // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeInitContact, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/initcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendBatchGetContactBriefInfoReq 批量获取联系人信息 func SendBatchGetContactBriefInfoReq(userInfo *baseinfo.UserInfo, userNameList []string) (*baseinfo.PackHeader, error) { var request wechat.BatchGetContactBriefInfoReq request.ContactUsernameList = userNameList // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeBatchGetContactBriefInfo, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/batchgetcontactbriefinfo", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } func SendGetFriendRelationReq(userInfo *baseinfo.UserInfo, userName string) (*baseinfo.PackHeader, error) { var request wechat.MMBizJsApiGetUserOpenIdRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(1) baseReq.Scene = &tmpScene request.BaseRequest = baseReq request.AppId = proto.String("wx7c8d593b2c3a7703") request.UserName = proto.String(userName) // 打包数据 发送 srcData, _ := proto.Marshal(&request) //获取好友关系状态 sendEncodeData := Pack(userInfo, srcData, 1177, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/usrmsg/mmbizjsapi_getuseropenid", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendGetContactRequest 获取指定微信号信息请求, userWxID:联系人ID roomWxID:群ID func SendGetContactRequest(userInfo *baseinfo.UserInfo, userWxIDList []string, antisPanTicketList []string, roomWxIDList []string) (*baseinfo.PackHeader, error) { var request wechat.GetContactRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // userCount var userCount = uint32(len(userWxIDList)) request.UserCount = &userCount // UserNameList userNameList := make([]*wechat.SKBuiltinString, userCount) // 遍历 for index := uint32(0); index < userCount; index++ { userNameItem := new(wechat.SKBuiltinString) userNameItem.Str = &userWxIDList[index] userNameList[index] = userNameItem } request.UserNameList = userNameList // AntispamTicketCount antispamTicketCount := uint32(len(antisPanTicketList)) request.AntispamTicketCount = &antispamTicketCount // AntispamTicket tmpAntispamTicketList := make([]*wechat.SKBuiltinString, antispamTicketCount) for index := uint32(0); index < antispamTicketCount; index++ { antispamTicket := new(wechat.SKBuiltinString) antispamTicket.Str = &antisPanTicketList[index] tmpAntispamTicketList[index] = antispamTicket } request.AntispamTicket = tmpAntispamTicketList // FromChatRoomCount fromChatRoomCount := uint32(len(roomWxIDList)) request.FromChatRoomCount = &fromChatRoomCount // FromChatRoom fromChatRoomList := make([]*wechat.SKBuiltinString, fromChatRoomCount) for index := uint32(0); index < fromChatRoomCount; index++ { fromChatRoom := new(wechat.SKBuiltinString) fromChatRoom.Str = &roomWxIDList[index] fromChatRoomList[index] = fromChatRoom } request.FromChatRoom = fromChatRoomList // GetContactScene var getContactScene = uint32(0) request.GetContactScene = &getContactScene // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetContact, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 创建红包 func SendWXCreateRedPacket(userInfo *baseinfo.UserInfo, hbItem *baseinfo.RedPacket) (*baseinfo.PackHeader, error) { var request wechat.HongBaoReq // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = proto.Uint32(0) // OutPutType request.OutPutType = proto.Uint32(0) // ReqText strReqText := string("") strReqText = strReqText + "city=Guangzhou&" strReqText = strReqText + "hbType=" + strconv.Itoa(int(hbItem.RedType)) + "&" strReqText = strReqText + "headImg=" + "&" strReqText = strReqText + "inWay=" + strconv.Itoa(int(hbItem.From)) + "&" strReqText = strReqText + "needSendToMySelf=0" + "&" strReqText = strReqText + "nickName=" + url.QueryEscape(userInfo.NickName) + "&" strReqText = strReqText + "perValue=" + strconv.Itoa(int(hbItem.Amount)) + "&" strReqText = strReqText + "province=Guangdong" + "&" strReqText = strReqText + "sendUserName=" + userInfo.WxId + "&" strReqText = strReqText + "totalAmount=" + strconv.Itoa(int(hbItem.Amount*hbItem.Count)) + "&" strReqText = strReqText + "totalNum=" + strconv.Itoa(int(hbItem.Count)) + "&" strReqText = strReqText + "username=" + hbItem.Username + "&" strReqText = strReqText + "wishing=" + url.QueryEscape(hbItem.Content) var reqText wechat.SKBuiltinString_ reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, 1575, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmpay-bin/requestwxhb", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendReceiveWxHB 发送接收红包请求 func SendReceiveWxHB(userInfo *baseinfo.UserInfo, hongBaoReceiverItem *baseinfo.HongBaoReceiverItem) (*baseinfo.PackHeader, error) { var request wechat.HongBaoReq // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &hongBaoReceiverItem.CgiCmd // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType /**agreeDuty=0 &channelId=1 &encrypt_key=T1LVNmOtXtStQDQwgZP81guupLsaO6meiWltwBFoSNL+WSIFmhqa1msSZ1J0HsRjE0V0u0k2qp2Yrqihjr8WXyV/okS+/4mJEl6whzupyQKYil69t/2kZ87agWyblo0A2SiozLrZSvs2HjFy9SH3IgXVECDSGKWVXcwJ3QqBmvY=& encrypt_userinfo=RU3cO5jg3eSTw+Kiwh14q3GhRM3Vk6ZNA5FD4BwmUxo+Bkr/JMItKC10pnNKUgsPfIpZ1/G1tk2MBtCwtQwo8A==&group_name=48593899189@chatroom &inWay=0 &msgType=1& nativeUrl=wxpay://c2cbizmessagehandler/hongbao/receivehongbao?msgtype=1&channelid=1&sendid=1800008896202411036324429265017&ver=2&sign=AARxHbYBAAABAAAAAAC07b6S00apLZ%2F7lz0nZyAAAAD5K3H1P3TTsgLxNwDzPyfEp2uvjYg0WGAGRbvB%2BrLW1PF0gCgzTvftYOhOXdBog8moWaYrvz7UoWuTijySa63rd0mAoTd3caJvpcvBzjUQcHvGUsYShwUN28KEUV6S6MOdl8QhdoPeRYZXwZC8kGaJCoLJ5t8zfDGgmdotHQ%3D%3D& sendId=1800008896202411036324429265017&union_source=0 */ // ReqText strReqText := string("") strReqText = strReqText + "agreeDuty=0&" strReqText = strReqText + "channelId=" + hongBaoReceiverItem.HongBaoURLItem.ChannelID + "&" // strReqText = strReqText + "city=" + hongBaoReceiverItem.City + "&" strReqText = strReqText + "encrypt_key=" + baseutils.EscapeURL(userInfo.HBAesKeyEncrypted) + "&" strReqText = strReqText + "encrypt_userinfo=" + baseutils.EscapeURL(GetEncryptUserInfo(userInfo)) + "&" strReqText = strReqText + "inWay=" + strconv.Itoa(int(hongBaoReceiverItem.InWay)) + "&" strReqText = strReqText + "msgType=" + hongBaoReceiverItem.HongBaoURLItem.MsgType + "&" strReqText = strReqText + "nativeUrl=" + baseutils.EscapeURL(hongBaoReceiverItem.NativeURL) + "&" // strReqText = strReqText + "province=" + hongBaoReceiverItem.Province + "&" strReqText = strReqText + "sendId=" + hongBaoReceiverItem.HongBaoURLItem.SendID // strReqText = strReqText + "union_source=0" var reqText wechat.SKBuiltinString_ reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText // 打包发送数据 RequestType := baseinfo.MMRequestTypeReceiveWxHB urlPath := "/cgi-bin/mmpay-bin/receivewxhb" if hongBaoReceiverItem.SceneID == uint32(1005) { // 企业外部群红包 timingIdentifier //RequestType = uint32(4536) strReqText = strReqText + "&union_source=0" strReqText = strReqText + "&group_name=" + baseutils.EscapeURL(hongBaoReceiverItem.HongBaoURLItem.SendUserName) //"encrypt_key" //"group_name" urlPath = "/cgi-bin/mmpay-bin/unionhb/receiveunionhb" CgiCmd := uint32(4536) request.CgiCmd = &CgiCmd reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText // fmt.Print("企业外部群红包 timingIdentifier") } srcData, _ := proto.Marshal(&request) // userInfo.ClientVersion = ClientVersion // fmt.Print("\nRequestType:", RequestType) // fmt.Print("\nurlPath:", urlPath) // fmt.Print("\n") sendEncodeData := Pack(userInfo, srcData, RequestType, 5) // byte[] 转 string // sendEncodeDataStr := string(srcData) // fmt.Println("srcData: ", sendEncodeDataStr) ///cgi-bin/mmpay-bin/unionhb 企业群红包 /// 打开红包 // 长链接发送 // fmt.Print("\n发送长连接接收红包请求\n") // err := mmtls.MMTCPSendReq(userInfo.MMInfo, mmtls.MMLongOperationRequest, sendEncodeData) // if err != nil { // return nil, err // } resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, urlPath, sendEncodeData) if err != nil { fmt.Println("err:", err) return nil, err } return DecodePackHeader(resp, nil) } // SendOpenWxHB 发送领取红包请求 func SendOpenWxHB(userInfo *baseinfo.UserInfo, hongBaoOpenItem *baseinfo.HongBaoOpenItem) (*baseinfo.PackHeader, error) { var request wechat.HongBaoReq // "channelId": "1", // "encrypt_key": "T1LVNmOtXtStQDQwgZP81guupLsaO6meiWltwBFoSNL+WSIFmhqa1msSZ1J0HsRjE0V0u0k2qp2Yrqihjr8WXyV/okS+/4mJEl6whzupyQKYil69t/2kZ87agWyblo0A2SiozLrZSvs2HjFy9SH3IgXVECDSGKWVXcwJ3QqBmvY=", // "encrypt_userinfo": "RU3cO5jg3eSTw+Kiwh14q3GhRM3Vk6ZNA5FD4BwmUxo+Bkr/JMItKC10pnNKUgsPfIpZ1/G1tk2MBtCwtQwo8A==", // "headImg": "https://wx.qlogo.cn/mmhead/ver_1/iaGwFC19C856VC76SkWmjlib40vgX6xtIQkbUM32rF45VDstSpH6KOdGoKaFCceXT04ia3NayIYspXPTpKcuw33UDcwasgaVkVgLttHCIUnMI0GjV8qd5es6lSUeWZwZry2/132", // "msgType": "1", // "nativeUrl": "wxpay://c2cbizmessagehandler/hongbao/receivehongbao?msgtype=1&channelid=1&sendid=1800008896202411036324429265017&ver=2&sign=AARxHbYBAAABAAAAAAC07b6S00apLZ%2F7lz0nZyAAAAD5K3H1P3TTsgLxNwDzPyfEp2uvjYg0WGAGRbvB%2BrLW1PF0gCgzTvftYOhOXdBog8moWaYrvz7UoWuTijySa63rd0mAoTd3caJvpcvBzjUQcHvGUsYShwUN28KEUV6S6MOdl8QhdoPeRYZXwZC8kGaJCoLJ5t8zfDGgmdotHQ%3D%3D", // "nickName": "琳琳", // "sendId": "1800008896202411036324429265017", // "sessionUserName": "48593899189@chatroom", // "timingIdentifier": "87a72ff1f1700e4dc289b712ff9bdfae", // "union_source": "0" ///402665260 // baserequest402665506 baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &hongBaoOpenItem.CgiCmd // // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText strReqText := string("") strReqText = strReqText + "channelId=" + hongBaoOpenItem.HongBaoURLItem.ChannelID + "&" strReqText = strReqText + "city=" + hongBaoOpenItem.City + "&" strReqText = strReqText + "encrypt_key=" + baseutils.EscapeURL(userInfo.HBAesKeyEncrypted) + "&" strReqText = strReqText + "encrypt_userinfo=" + baseutils.EscapeURL(GetEncryptUserInfo(userInfo)) + "&" strReqText = strReqText + "headImg=" + baseutils.EscapeURL(hongBaoOpenItem.HeadImg) + "&" strReqText = strReqText + "msgType=" + hongBaoOpenItem.HongBaoURLItem.MsgType + "&" strReqText = strReqText + "nativeUrl=" + baseutils.EscapeURL(hongBaoOpenItem.NativeURL) + "&" strReqText = strReqText + "nickName=" + baseutils.HongBaoStringToBytes(hongBaoOpenItem.NickName) + "&" strReqText = strReqText + "province=" + hongBaoOpenItem.Province + "&" strReqText = strReqText + "sendId=" + hongBaoOpenItem.HongBaoURLItem.SendID + "&" strReqText = strReqText + "sessionUserName=" + hongBaoOpenItem.HongBaoURLItem.SendUserName + "&" strReqText = strReqText + "timingIdentifier=" + hongBaoOpenItem.TimingIdentifier // strReqText = strReqText + "&union_source=0" // fmt.Println("strReqText: ") // fmt.Println(strReqText) var reqText wechat.SKBuiltinString_ reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText urlPath := "/cgi-bin/mmpay-bin/openwxhb" RequestType := baseinfo.MMRequestTypeReceiveWxHB // if hongBaoOpenItem.SceneID == uint32(1005) { // // 企业外部群红包 // RequestType = uint32(5148) // CgiCmd := uint32(0x141c) // request.CgiCmd = &CgiCmd // urlPath = "/cgi-bin/mmpay-bin/unionhb" // //打开 "4536", // //拆开 "5148", // // } // fmt.Println("\nurlPath: ") // fmt.Println(urlPath) // 打包发送数据 marshalStartMs := time.Now().UnixMilli() srcData, _ := proto.Marshal(&request) marshalEndMs := time.Now().UnixMilli() packStartMs := time.Now().UnixMilli() sendEncodeData := Pack(userInfo, srcData, RequestType, 5) packEndMs := time.Now().UnixMilli() httpStartMs := time.Now().UnixMilli() resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, urlPath, sendEncodeData) httpEndMs := time.Now().UnixMilli() if err != nil { return nil, err } decodeStartMs := time.Now().UnixMilli() ph, err := DecodePackHeader(resp, nil) decodeEndMs := time.Now().UnixMilli() fmt.Printf("OpenWxHB细分 marshal=%dms pack=%dms http=%dms decodePackHeader=%dms\n", marshalEndMs-marshalStartMs, packEndMs-packStartMs, httpEndMs-httpStartMs, decodeEndMs-decodeStartMs) return ph, err } func SendOpenUninoHB(userInfo *baseinfo.UserInfo, hongBaoOpenItem *baseinfo.HongBaoOpenItem) (*baseinfo.PackHeader, error) { var request wechat.HongBaoReq baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &hongBaoOpenItem.CgiCmd // // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText strReqText := string("") strReqText = strReqText + "channelId=" + hongBaoOpenItem.HongBaoURLItem.ChannelID + "&" //strReqText = strReqText + "city=" + hongBaoOpenItem.City + "&" strReqText = strReqText + "encrypt_key=" + baseutils.EscapeURL(userInfo.HBAesKeyEncrypted) + "&" strReqText = strReqText + "encrypt_userinfo=" + baseutils.EscapeURL(GetEncryptUserInfo(userInfo)) + "&" strReqText = strReqText + "headImg=" + baseutils.EscapeURL(hongBaoOpenItem.HeadImg) + "&" strReqText = strReqText + "msgType=" + hongBaoOpenItem.HongBaoURLItem.MsgType + "&" strReqText = strReqText + "nativeUrl=" + baseutils.EscapeURL(hongBaoOpenItem.NativeURL) + "&" strReqText = strReqText + "nickName=" + baseutils.HongBaoStringToBytes(hongBaoOpenItem.NickName) + "&" //strReqText = strReqText + "province=" + hongBaoOpenItem.Province + "&" strReqText = strReqText + "sendId=" + hongBaoOpenItem.HongBaoURLItem.SendID + "&" strReqText = strReqText + "sessionUserName=" + hongBaoOpenItem.HongBaoURLItem.SendUserName + "&" strReqText = strReqText + "timingIdentifier=" + hongBaoOpenItem.TimingIdentifier + "&" strReqText = strReqText + "union_source=0" // fmt.Println("strReqText: ") // fmt.Println(strReqText) var reqText wechat.SKBuiltinString_ reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText urlPath := "/cgi-bin/mmpay-bin/unionhb/openunionhb" RequestType := baseinfo.MMRequestTypeReceiveWxHB srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, RequestType, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, urlPath, sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendRedEnvelopeWxHB 发送查看红包详情请求 func SendRedEnvelopeWxHB(userInfo *baseinfo.UserInfo, hongBaoOpenItem *baseinfo.HongBaoOpenItem) (*baseinfo.PackHeader, error) { var request wechat.HongBaoReq // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &hongBaoOpenItem.CgiCmd // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText strReqText := string("") strReqText = strReqText + "agreeDuty=1" + "&" strReqText = strReqText + "inWay=1" + "&" strReqText = strReqText + "channelId=" + hongBaoOpenItem.HongBaoURLItem.ChannelID + "&" strReqText = strReqText + "msgType=" + hongBaoOpenItem.HongBaoURLItem.MsgType + "&" strReqText = strReqText + "nativeUrl=" + baseutils.EscapeURL(hongBaoOpenItem.NativeURL) + "&" strReqText = strReqText + "sendId=" + hongBaoOpenItem.HongBaoURLItem.SendID + "&" strReqText = strReqText + "sessionUserName=" + hongBaoOpenItem.HongBaoURLItem.SendUserName + "&" var reqText wechat.SKBuiltinString_ reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeQryDetailWxHB, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmpay-bin/qrydetailwxhb", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 查看红包领取列表 func SendGetRedPacketListRequest(userInfo *baseinfo.UserInfo, hongBaoOpenItem *baseinfo.GetRedPacketList) (*baseinfo.PackHeader, error) { var request wechat.HongBaoReq if hongBaoOpenItem.Limit == 0 { hongBaoOpenItem.Limit = 11 } // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = proto.Uint32(5) // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText strReqText := string("") strReqText = strReqText + "channelId=" + hongBaoOpenItem.HongBaoItem.ChannelID + "&" strReqText = strReqText + "msgType=" + hongBaoOpenItem.HongBaoItem.MsgType + "&" strReqText = strReqText + "nativeUrl=" + baseutils.EscapeURL(hongBaoOpenItem.NativeURL) + "&province=&" strReqText = strReqText + "sendId=" + hongBaoOpenItem.HongBaoItem.SendID + "&" strReqText = strReqText + "limit=" + strconv.FormatInt(hongBaoOpenItem.Limit, 10) + "&" strReqText = strReqText + "offset=" + strconv.FormatInt(hongBaoOpenItem.Offset, 10) var reqText wechat.SKBuiltinString_ reqText.Buffer = []byte(strReqText) tmpLen := uint32(len(reqText.Buffer)) reqText.Len = &tmpLen request.ReqText = &reqText // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeQryDetailWxHB, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmpay-bin/qrydetailwxhb", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendCreatePreTransferRequest 创建转账 func SendCreatePreTransferRequest(userInfo *baseinfo.UserInfo, transferItem *req.CreatePreTransfer) (*baseinfo.PackHeader, error) { description, fee, toUserName := transferItem.Description, transferItem.Fee, transferItem.ToUserName var req_text = "delay_confirm_flag=0&desc=" + description + "&fee=" + strconv.Itoa(int(fee)) + "&fee_type=CNY&pay_scene=31&receiver_name=" + toUserName + "&scene=31&transfer_scene=2" wcPaySign, err := TenPaySignDes3(req_text, "%^&*Tenpay!@#$") if err != nil { return nil, err } req_text += "&WCPaySign=" + wcPaySign tmpReqItem := &baseinfo.TenPayReqItem{} tmpReqItem.CgiCMD = 0x53 tmpReqItem.ReqText = req_text return SendWxPayTransferReq(userInfo, tmpReqItem) } // SendConfirmPreTransferRequest 确认转账 func SendConfirmPreTransferRequest(userInfo *baseinfo.UserInfo, transferItem *req.ConfirmPreTransfer) (*baseinfo.PackHeader, error) { bankType, bankSerial := transferItem.BankType, transferItem.BankSerial payPassword, reqKey := transferItem.PayPassword, transferItem.ReqKey var req_text = "auto_deduct_flag=0&bank_type=" + bankType + "&bind_serial=" + bankSerial + "&busi_sms_flag=0&flag=3&passwd=" + payPassword + "&pay_scene=37&req_key=" + reqKey + "&use_touch=0" wcPaySign, err := TenPaySignDes3(req_text, "%^&*Tenpay!@#$") if err != nil { return nil, err } req_text += "&WCPaySign=" + wcPaySign tmpReqItem := &baseinfo.TenPayReqItem{} tmpReqItem.CgiCMD = 0 tmpReqItem.ReqText = req_text return SendWxPayTransferReq(userInfo, tmpReqItem) } // SendWxPayTransferReq 发送微信支付之转账请求 func SendWxPayTransferReq(userInfo *baseinfo.UserInfo, reqItem *baseinfo.TenPayReqItem) (*baseinfo.PackHeader, error) { var request wechat.TenPayRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &reqItem.CgiCMD // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText var reqTextSKBuf wechat.SKBuiltinString_ tmpLen := uint32(len(reqItem.ReqText)) reqTextSKBuf.Len = &tmpLen reqTextSKBuf.Buffer = []byte(reqItem.ReqText) request.ReqText = &reqTextSKBuf // ReqTextWx var wxReqTextSKBuf wechat.SKBuiltinString_ wxReqTextSKBuf.Buffer = []byte(reqItem.ReqText) wxReqTextSKBuf.Len = &tmpLen request.ReqTextWx = &wxReqTextSKBuf // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, 385, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/tenpay", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendTextMsg 发送文本消息请求 toWxid:接受人微信id,content:消息内容,atWxIDList:@用户微信id列表(toWxid只能是群的wxid,content应为:@用户昵称 @用户昵称 消息内容) func SendTextMsg(userInfo *baseinfo.UserInfo, toWxid string, content string, atWxIDList []string, ContentType int) (*baseinfo.PackHeader, error) { // 构造请求 var request wechat.NewSendMsgRequest var count uint32 = 1 request.MsgCount = &count var msgRequestNewList []*wechat.MicroMsgRequestNew = make([]*wechat.MicroMsgRequestNew, count) var msgRequestNew wechat.MicroMsgRequestNew var recvierString wechat.SKBuiltinString recvierString.Str = &toWxid msgRequestNew.ToUserName = &recvierString // 设置接收人wxid msgRequestNew.Content = &content // 设置发送内容 if ContentType == 0 { ContentType = 1 } var tmpType uint32 = uint32(ContentType) msgRequestNew.Type = &tmpType // 发送的类型 currentTime := time.Now() misSecond := currentTime.UnixNano() / 1000000 var seconds = uint32(misSecond / 1000) msgRequestNew.CreateTime = &seconds // 设置时间 秒为单位 seqID := time.Now().UnixNano() / int64(time.Millisecond) var tmpCheckCode = WithSeqidCalcCheckCode(toWxid, seqID) msgRequestNew.ClientMsgId = &tmpCheckCode // 设置校验码 // atUserList var atUserStr = string("") size := len(atWxIDList) if size > 0 { atUserStr = atUserStr + "" for index := 0; index < size; index++ { atUserStr = atUserStr + atWxIDList[index] if index < size-1 { atUserStr = atUserStr + "," } } atUserStr = atUserStr + "" msgRequestNew.MsgSource = &atUserStr } msgRequestNewList[0] = &msgRequestNew request.ChatSendList = msgRequestNewList // 发送请求 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeNewSendMsg, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newsendmsg", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 发送图片v1.1 func SendUploadImageNewRequest(userInfo *baseinfo.UserInfo, imgData []byte, toUserName string) (*baseinfo.PackHeader, error) { // 构造请求 var protobufdata []byte imgStream := bytes.NewBuffer(imgData) Startpos := 0 datalen := 50000 datatotalength := imgStream.Len() ClientImgId := fmt.Sprintf("%v_%v", userInfo.WxId, time.Now().Unix()) I := 0 for { Startpos = I * datalen count := 0 if datatotalength-Startpos > datalen { count = datalen } else { count = datatotalength - Startpos } if count < 0 { break } Databuff := make([]byte, count) _, _ = imgStream.Read(Databuff) request := &wechat.UploadMsgImgRequest{ BaseRequest: GetBaseRequest(userInfo), ClientImgId: &wechat.SKBuiltinString{ Str: proto.String(ClientImgId), }, SenderWxid: &wechat.SKBuiltinString{ Str: proto.String(userInfo.WxId), }, RecvWxid: &wechat.SKBuiltinString{ Str: proto.String(toUserName), }, TotalLen: proto.Uint32(uint32(datatotalength)), StartPos: proto.Uint32(uint32(Startpos)), DataLen: proto.Uint32(uint32(len(Databuff))), Data: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(Databuff))), Buffer: Databuff, }, MsgType: proto.Uint32(3), EncryVer: proto.Uint32(0), ReqTime: proto.Uint32(uint32(time.Now().Unix())), MessageExt: proto.String("png"), } //序列化 srcData, _ := proto.Marshal(request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeForwardCdnImage, 5) // 发送请求 rsp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadmsgimg", sendData) if err != nil { break } protobufdata = rsp I++ } return DecodePackHeader(protobufdata, nil) } // 发送企业oplog func SendQWOpLogRequest(userInfo *baseinfo.UserInfo, cmdId int64, value []byte) (*baseinfo.PackHeader, error) { var request wechat.QYOpLogRequest request.Type = proto.Int64(cmdId) request.V = value // 发送请求 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, 806, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/openimoplog", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendOplogRequest 发送修改帐号信息请求 func SendOplogRequest(userInfo *baseinfo.UserInfo, modifyItems []*baseinfo.ModifyItem) (*baseinfo.PackHeader, error) { var request wechat.OplogRequest // CmdList var oplog wechat.CmdList count := uint32(len(modifyItems)) oplog.Count = &count // ItemList cmdItemList := make([]*wechat.CmdItem, count) var index = uint32(0) for ; index < count; index++ { //Item cmdItem := &wechat.CmdItem{} cmdItem.CmdId = &modifyItems[index].CmdID cmdBuf := &wechat.DATA{} cmdBuf.Len = &modifyItems[index].Len cmdBuf.Data = modifyItems[index].Data cmdItem.CmdBuf = cmdBuf cmdItemList[index] = cmdItem } oplog.ItemList = cmdItemList request.Oplog = &oplog // 发送请求 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeOplog, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/oplog", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendGetQRCodeRequest 获取二维码 func SendGetQRCodeRequest(userInfo *baseinfo.UserInfo, userName string) (*baseinfo.PackHeader, error) { var request wechat.GetQRCodeRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // opCode opcode := uint32(0) request.Opcode = &opcode // style style := uint32(0) request.Style = &style // UserName var userNameSKBuffer wechat.SKBuiltinString userNameSKBuffer.Str = &userName request.UserName = &userNameSKBuffer // 打包发送数据 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetQrCode, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getqrcode", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, []byte(userName)) } // SendLogOutRequest 发送登出请求 func SendLogOutRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.LogOutRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // 打包数据 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, 282, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/logout", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsPostRequest 发送朋友圈 func SendSnsPostRequest(userInfo *baseinfo.UserInfo, postItem *baseinfo.SnsPostItem) (*baseinfo.PackHeader, error) { var request wechat.SnsPostRequest zeroValue32 := uint32(0) zeroValue64 := uint64(0) // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // ObjectDesc objectDescData := CreateSnsPostItemXML(userInfo.WxId, postItem) if postItem.Xml { objectDescData = []byte(postItem.Content) } length := uint32(len(objectDescData)) var objectDesc wechat.SKBuiltinString_ objectDesc.Len = &length objectDesc.Buffer = objectDescData request.ObjectDesc = &objectDesc // WithUserListCount withUserListCount := uint32(len(postItem.WithUserList)) request.WithUserListCount = &withUserListCount // WithUserList request.WithUserList = make([]*wechat.SKBuiltinString, withUserListCount) index := uint32(0) for ; index < withUserListCount; index++ { withUser := &wechat.SKBuiltinString{} withUser.Str = &postItem.WithUserList[index] request.WithUserList[index] = withUser } // BlackListCount blackListCount := uint32(len(postItem.BlackList)) request.BlackListCount = &blackListCount // BlackList request.BlackList = make([]*wechat.SKBuiltinString, blackListCount) index = uint32(0) for ; index < blackListCount; index++ { blackUser := &wechat.SKBuiltinString{} blackUser.Str = &postItem.BlackList[index] request.BlackList[index] = blackUser } // GroupUserCount groupUserCount := uint32(len(postItem.GroupUserList)) request.GroupUserCount = &groupUserCount // GroupUser request.GroupUser = make([]*wechat.SKBuiltinString, groupUserCount) index = uint32(0) for ; index < groupUserCount; index++ { groupUser := &wechat.SKBuiltinString{} groupUser.Str = &postItem.GroupUserList[index] request.GroupUser[index] = groupUser } // otherFields bgImageType := uint32(1) request.PostBgimgType = &bgImageType request.ObjectSource = &zeroValue32 request.ReferId = &zeroValue64 request.Privacy = &postItem.Privacy request.SyncFlag = &zeroValue32 // ClientId tmpTime := int(time.Now().UnixNano() / 1000000000) tmpTimeStr := strconv.Itoa(tmpTime) clientID := string("sns_post_") clientID = clientID + userInfo.WxId + "_" + tmpTimeStr + "_0" request.ClientId = &clientID // groupCount request.GroupCount = &zeroValue32 request.GroupIds = make([]*wechat.SnsGroup, zeroValue32) // mediaInfoCount MediaInfo mediaInfoCount := uint32(len(postItem.MediaList)) request.MediaInfoCount = &mediaInfoCount request.MediaInfo = make([]*wechat.MediaInfo, mediaInfoCount) for index := uint32(0); index < mediaInfoCount; index++ { mediaInfo := &wechat.MediaInfo{} source := uint32(2) mediaInfo.Source = &source // MediaType mediaType := uint32(1) if postItem.MediaList[index].Type == baseinfo.MMSNSMediaTypeImage { mediaType = 1 } mediaInfo.MediaType = &mediaType // VideoPlayLength mediaInfo.VideoPlayLength = &zeroValue32 // SessionId currentTime := int(time.Now().UnixNano() / 1000000) sessionID := "memonts-" + strconv.Itoa(currentTime) mediaInfo.SessionId = &sessionID // startTime startTime := uint32(time.Now().UnixNano() / 1000000000) mediaInfo.StartTime = &startTime request.MediaInfo[index] = mediaInfo } // SnsPostOperationFields var postOperationFields wechat.SnsPostOperationFields postOperationFields.ContactTagCount = &zeroValue32 postOperationFields.TempUserCount = &zeroValue32 request.SnsPostOperationFields = &postOperationFields // clientcheckdata var extSpamInfo wechat.SKBuiltinString_ if userInfo.DeviceInfo != nil { extSpamInfo.Buffer = GetExtPBSpamInfoDataIpad(userInfo) } else { extSpamInfo.Buffer = GetExtPBSpamInfoDataA16(userInfo) } extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen request.ExtSpamInfo = &extSpamInfo // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsPost, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnspost", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsPostRequestByXML 通过XML的信息来发送朋友圈 func SendSnsPostRequestByXML(userInfo *baseinfo.UserInfo, timeLineObj *baseinfo.TimelineObject, blackList []string) (*baseinfo.PackHeader, error) { if timeLineObj.ContentObjectVideo != nil { return SendSnsPostRequestByXMLVideoNum(userInfo, timeLineObj, blackList) } var request wechat.SnsPostRequest zeroValue32 := uint32(0) zeroValue64 := uint64(0) // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // WithUserListCount withUserListCount := uint32(0) request.WithUserListCount = &withUserListCount // WithUserList request.WithUserList = make([]*wechat.SKBuiltinString, withUserListCount) // BlackListCount tmpCount := uint32(len(blackList)) request.BlackListCount = &tmpCount request.BlackList = make([]*wechat.SKBuiltinString, tmpCount) // BlackList for index := uint32(0); index < tmpCount; index++ { tmpSKBuiltinString := &wechat.SKBuiltinString{} tmpSKBuiltinString.Str = &blackList[index] request.BlackList[index] = tmpSKBuiltinString } // GroupUserCount groupUserCount := uint32(0) request.GroupUserCount = &groupUserCount // GroupUser request.GroupUser = make([]*wechat.SKBuiltinString, groupUserCount) // otherFields bgImageType := uint32(1) request.PostBgimgType = &bgImageType request.ObjectSource = &zeroValue32 request.ReferId = &zeroValue64 request.Privacy = &timeLineObj.Private request.SyncFlag = &zeroValue32 // ClientId tmpTime := int(time.Now().UnixNano() / 1000000000) tmpTimeStr := strconv.Itoa(tmpTime) clientID := string("sns_post_") clientID = clientID + userInfo.WxId + "_" + tmpTimeStr + "_0" request.ClientId = &clientID // groupCount request.GroupCount = &zeroValue32 request.GroupIds = make([]*wechat.SnsGroup, zeroValue32) // mediaInfoCount MediaInfo mediaInfoCount := uint32(len(timeLineObj.ContentObject.MediaList.Media)) request.MediaInfoCount = &mediaInfoCount request.MediaInfo = make([]*wechat.MediaInfo, mediaInfoCount) for index := uint32(0); index < mediaInfoCount; index++ { tmpMediaItem := timeLineObj.ContentObject.MediaList.Media[index] // 解析Source mediaInfo := &wechat.MediaInfo{} tmpSource := baseutils.ParseInt(tmpMediaItem.URL.Type) mediaInfo.Source = &tmpSource // MediaType mediaType := tmpMediaItem.Type - 1 mediaInfo.MediaType = &mediaType // VideoPlayLength playLength := uint32(tmpMediaItem.VideoDuration) mediaInfo.VideoPlayLength = &playLength // SessionId currentTime := int(time.Now().UnixNano() / 1000000) sessionID := "memonts-" + strconv.Itoa(currentTime) mediaInfo.SessionId = &sessionID // startTime startTime := uint32(time.Now().UnixNano() / 1000000000) mediaInfo.StartTime = &startTime request.MediaInfo[index] = mediaInfo } // ID和UserName置为0 timeLineObj.UserName = userInfo.WxId timeLineObj.CreateTime = uint32(int(time.Now().UnixNano() / 1000000000)) // ObjectDesc objectDescData, err := xml.Marshal(timeLineObj) if err != nil { return nil, err } str := string(objectDescData) str = strings.ReplaceAll(str, "token=\"\"", "") str = strings.ReplaceAll(str, "key=\"\"", "") str = strings.ReplaceAll(str, "enc_idx=\"\"", "") str = strings.ReplaceAll(str, "md5=\"\"", "") str = strings.ReplaceAll(str, "videomd5=\"\"", "") str = strings.ReplaceAll(str, "video", "") objectDescData = []byte(str) length := uint32(len(objectDescData)) var objectDesc wechat.SKBuiltinString_ objectDesc.Len = &length objectDesc.Buffer = objectDescData request.ObjectDesc = &objectDesc // SnsPostOperationFields var postOperationFields wechat.SnsPostOperationFields postOperationFields.ContactTagCount = &zeroValue32 postOperationFields.TempUserCount = &zeroValue32 request.SnsPostOperationFields = &postOperationFields // clientcheckdata var extSpamInfo wechat.SKBuiltinString_ if userInfo.DeviceInfo != nil { extSpamInfo.Buffer = GetExtPBSpamInfoDataIpad(userInfo) } else { extSpamInfo.Buffer = GetExtPBSpamInfoDataA16(userInfo) } extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen request.ExtSpamInfo = &extSpamInfo // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsPost, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnspost", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsPostRequestByXML 通过XML的信息来发送朋友圈(视频号) func SendSnsPostRequestByXMLVideoNum(userInfo *baseinfo.UserInfo, timeLineObj *baseinfo.TimelineObject, blackList []string) (*baseinfo.PackHeader, error) { var request wechat.SnsPostRequest zeroValue32 := uint32(0) zeroValue64 := uint64(0) fmt.Println("发布 视频号视频") newTimeLineObj := &baseinfo.TimelineObjectVideo{ ID: timeLineObj.ID, UserName: timeLineObj.UserName, CreateTime: timeLineObj.CreateTime, ContentDesc: timeLineObj.ContentDesc, ContentDescShowType: timeLineObj.ContentDescShowType, ContentDescScene: timeLineObj.ContentDescScene, Private: timeLineObj.Private, SightFolded: timeLineObj.SightFolded, ShowFlag: timeLineObj.ShowFlag, AppInfo: timeLineObj.AppInfo, SourceUserName: timeLineObj.SourceUserName, SourceNickName: timeLineObj.SourceNickName, StatisticsData: timeLineObj.StatisticsData, StatExtStr: timeLineObj.StatExtStr, ContentObject: *timeLineObj.ContentObjectVideo, ActionInfo: timeLineObj.ActionInfo, Location: timeLineObj.Location, PublicUserName: timeLineObj.PublicUserName, StreamVideo: timeLineObj.StreamVideo, } // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // WithUserListCount withUserListCount := uint32(0) request.WithUserListCount = &withUserListCount // WithUserList request.WithUserList = make([]*wechat.SKBuiltinString, withUserListCount) // BlackListCount tmpCount := uint32(len(blackList)) request.BlackListCount = &tmpCount request.BlackList = make([]*wechat.SKBuiltinString, tmpCount) // BlackList for index := uint32(0); index < tmpCount; index++ { tmpSKBuiltinString := &wechat.SKBuiltinString{} tmpSKBuiltinString.Str = &blackList[index] request.BlackList[index] = tmpSKBuiltinString } // GroupUserCount groupUserCount := uint32(0) request.GroupUserCount = &groupUserCount // GroupUser request.GroupUser = make([]*wechat.SKBuiltinString, groupUserCount) // otherFields bgImageType := uint32(1) request.PostBgimgType = &bgImageType request.ObjectSource = &zeroValue32 request.ReferId = &zeroValue64 request.Privacy = &newTimeLineObj.Private request.SyncFlag = &zeroValue32 // ClientId tmpTime := int(time.Now().UnixNano() / 1000000000) tmpTimeStr := strconv.Itoa(tmpTime) clientID := string("sns_post_") clientID = clientID + userInfo.WxId + "_" + tmpTimeStr + "_0" request.ClientId = &clientID // groupCount request.GroupCount = &zeroValue32 request.GroupIds = make([]*wechat.SnsGroup, zeroValue32) // mediaInfoCount MediaInfo mediaInfoCount := uint32(0) request.MediaInfoCount = &mediaInfoCount request.MediaInfo = make([]*wechat.MediaInfo, mediaInfoCount) // ID和UserName置为0 newTimeLineObj.UserName = userInfo.WxId newTimeLineObj.CreateTime = uint32(int(time.Now().UnixNano() / 1000000000)) // ObjectDesc // 定义 XML 模板 const xmlTemplate = ` {{.ID}} {{.UserName}} {{.CreateTime}} {{.ContentDesc}} {{.ContentDescShowType}} {{.ContentDescScene}} {{.Private}} {{.SightFolded}} {{.ShowFlag}} {{.AppInfo.ID}} {{.AppInfo.Version}} {{.AppInfo.AppName}} {{.AppInfo.InstallURL}} {{.AppInfo.FromURL}} {{.AppInfo.IsForceUpdate}} {{.SourceUserName}} {{.SourceNickName}} {{.StatisticsData}} {{.StatExtStr}} {{range .ContentObject.FinderFeed.MediaList.Media}} {{.MediaType}} {{.Height}} {{.Width}} {{.VideoPlayDuration}} {{end}} {{.StreamVideo.StreamVideoURL}} {{.StreamVideo.StreamVideoThumbURL}} {{.StreamVideo.StreamVideoWebURL}} ` // 创建模板 tmpl, err := template.New("xmlTemplate").Parse(xmlTemplate) if err != nil { fmt.Println("SendSnsPostRequestByXMLVideoNum Error parsing template:", err) return nil, err } // 执行模板并写入到 buffer var output bytes.Buffer err = tmpl.Execute(&output, newTimeLineObj) if err != nil { fmt.Println("SendSnsPostRequestByXMLVideoNum Error executing template:", err) return nil, err } // 正则表达式匹配 '><' 中间可能存在空白字符的情况 re := regexp.MustCompile(`>\s+<`) // 替换为没有空白字符的 '><' formattedXML := re.ReplaceAllString(strings.TrimSpace(output.String()), "><") fmt.Println("Formatted XML:", formattedXML) objectDescData := []byte(formattedXML) length := uint32(len(objectDescData)) var objectDesc wechat.SKBuiltinString_ objectDesc.Len = &length objectDesc.Buffer = objectDescData request.ObjectDesc = &objectDesc // SnsPostOperationFields var postOperationFields wechat.SnsPostOperationFields postOperationFields.ContactTagCount = &zeroValue32 postOperationFields.TempUserCount = &zeroValue32 request.SnsPostOperationFields = &postOperationFields // clientcheckdata var extSpamInfo wechat.SKBuiltinString_ if userInfo.DeviceInfo != nil { extSpamInfo.Buffer = GetExtPBSpamInfoDataIpad(userInfo) } else { extSpamInfo.Buffer = GetExtPBSpamInfoDataA16(userInfo) } extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen request.ExtSpamInfo = &extSpamInfo // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsPost, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnspost", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsObjectOpRequest 发送朋友圈操作 func SendSnsObjectOpRequest(userInfo *baseinfo.UserInfo, opItems []*baseinfo.SnsObjectOpItem) (*baseinfo.PackHeader, error) { var request wechat.SnsObjectOpRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // OpCount opCount := uint32(len(opItems)) request.OpCount = &opCount // OpList request.OpList = make([]*wechat.SnsObjectOp, opCount) index := uint32(0) for ; index < opCount; index++ { snsObject := &wechat.SnsObjectOp{} id, _ := strconv.ParseUint(opItems[index].SnsObjID, 0, 64) snsObject.Id = &id snsObject.OpType = &opItems[index].OpType if opItems[index].DataLen > 0 { skBuffer := &wechat.SKBuiltinString_{} skBuffer.Len = &opItems[index].DataLen skBuffer.Buffer = opItems[index].Data } if opItems[index].Ext != 0 { extInfo := &wechat.SnsObjectOpExt{ Id: &opItems[index].Ext, } CommnetId, _ := proto.Marshal(extInfo) snsObject.Ext = &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(CommnetId))), Buffer: CommnetId, } } request.OpList[index] = snsObject } // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsObjectOp, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnsobjectop", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } func Uint32ToBytes(n uint32) []byte { return []byte{ byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24), } } // SendSnsUserPageRequest 发送 获取朋友圈信息 请求 func SendSnsUserPageRequest(userInfo *baseinfo.UserInfo, userName string, firstPageMd5 string, maxID uint64) (*baseinfo.PackHeader, error) { var request wechat.SnsUserPageRequest var zeroValue64 = uint64(0) var zeroValue32 = uint32(0) // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // 其它参数 request.Username = &userName request.FirstPageMd5 = &firstPageMd5 request.MaxId = &maxID request.MinFilterId = &zeroValue64 request.LastRequestTime = &zeroValue32 request.FilterType = &zeroValue32 // 打包数据 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsUserPage, 5) // 发送请求 resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnsuserpage", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, srcData) } // SendSnsCommentRequest 发送评论/点赞请求 func SendSnsCommentRequest(userInfo *baseinfo.UserInfo, commentItem *baseinfo.SnsCommentItem) (*baseinfo.PackHeader, error) { request := wechat.SnsCommentRequest{ BaseRequest: GetBaseRequest(userInfo), Action: &wechat.SnsActionGroup{ Id: &commentItem.ItemID, ParentId: proto.Uint64(0), CurrentAction: &wechat.SnsAction{ FromUsername: &userInfo.WxId, ToUsername: &commentItem.ToUserName, Type: &commentItem.OpType, Source: proto.Uint32(6), ReplyCommentId: &commentItem.ReplyCommentID, Content: &commentItem.Content, }, }, } // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsComment, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnscomment", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 获取收藏lit func SendFavSyncListRequest(userInfo *baseinfo.UserInfo, keyBuf string) (*baseinfo.PackHeader, error) { var request wechat.FavSyncRequest selector := uint32(1) request.Selector = &selector var skBufferT wechat.SKBuiltinString_ skBufferT.Len = proto.Uint32(0) /*favSyncKeyLen := uint32(len(userInfo.FavSyncKey)) skBufferT.Len = &favSyncKeyLen skBufferT.Buffer = userInfo.FavSyncKey*/ if keyBuf != "" { key, _ := base64.StdEncoding.DecodeString(keyBuf) skBufferT.Buffer = key skBufferT.Len = proto.Uint32(uint32(len(key))) } request.KeyBuf = &skBufferT // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeFavSync, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/favsync", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendFavSyncRequest 同步收藏 func SendFavSyncRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.FavSyncRequest // selector selector := uint32(1) request.Selector = &selector var skBufferT wechat.SKBuiltinString_ favSyncKeyLen := uint32(len(userInfo.FavSyncKey)) skBufferT.Len = &favSyncKeyLen skBufferT.Buffer = userInfo.FavSyncKey request.KeyBuf = &skBufferT // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeFavSync, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/favsync", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendGetFavInfoRequest 获取 收藏信息 func SendGetFavInfoRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.GetFavInfoRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetFavInfo, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getfavinfo", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendBatchGetFavItemRequest 获取单条收藏 func SendBatchGetFavItemRequest(userInfo *baseinfo.UserInfo, favID uint32) (*baseinfo.PackHeader, error) { var request wechat.BatchGetFavItemRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // Count favIDCount := uint32(1) request.Count = &favIDCount // FavIdList request.FavIdList = make([]byte, 0) tmpBytes := baseutils.EncodeVByte32(favID) request.FavIdList = append(request.FavIdList, tmpBytes[0:]...) srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeBatchGetFavItem, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/batchgetfavitem", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendBatchDelFavItemRequest 删除收藏项 func SendBatchDelFavItemRequest(userInfo *baseinfo.UserInfo, favID uint32) (*baseinfo.PackHeader, error) { var request wechat.BatchDelFavItemRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // Count tmpCount := uint32(1) request.Count = &tmpCount // FavIdList request.FavIdList = make([]byte, 0) tmpBytes := baseutils.EncodeVByte32(favID) request.FavIdList = append(request.FavIdList, tmpBytes[0:]...) // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeBatchDelFavItem, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/batchdelfavitem", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendGetCDNDnsRequest 获取该帐号的CdnDns信息 func SendGetCDNDnsRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.GetCDNDnsRequest emptyString := string("") // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // ClientIp request.ClientIp = &emptyString // Scene scene := uint32(1) request.Scene = &scene // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetCdnDNS, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getcdndns", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsObjectDetailRequest SendSnsObjectDetailRequest func SendSnsObjectDetailRequest(userInfo *baseinfo.UserInfo, snsID uint64) (*baseinfo.PackHeader, error) { var request wechat.SnsObjectDetailRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq request.GroupDetail = proto.Uint32(0) // ID request.Id = &snsID // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsObjectDetail, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnsobjectdetail", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsSyncRequest 同步朋友圈 func SendSnsSyncRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.SnsSyncRequest // baseRequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // Selector tmpSelector := uint32(509) request.Selector = &tmpSelector // KeyBuf 第一次使用同步消息Key tmpKeyBuffer := userInfo.SnsSyncKey if len(tmpKeyBuffer) <= 0 { tmpKeyBuffer = userInfo.SyncKey } tmpLen := uint32(len(tmpKeyBuffer)) var tmpKeyBuf wechat.SKBuiltinString_ tmpKeyBuf.Buffer = tmpKeyBuffer tmpKeyBuf.Len = &tmpLen request.KeyBuf = &tmpKeyBuf // 打包数据 发送 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsSync, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnssync", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendGetContactLabelListRequest 获取设置好的联系人标签列表 func SendGetContactLabelListRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var request wechat.GetContactLabelListRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetContactLabelList, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getcontactlabellist", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendAddContactLabelRequest 发送添加标签请求 func SendAddContactLabelRequest(userInfo *baseinfo.UserInfo, newLabelList []string) (*baseinfo.PackHeader, error) { var request wechat.AddContactLabelRequest labelID := uint32(0) // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // LabelCount labelCount := uint32(len(newLabelList)) request.LabelCount = &labelCount // LabelPairList request.LabelPairList = make([]*wechat.LabelPair, labelCount) for index := uint32(0); index < labelCount; index++ { labelPair := &wechat.LabelPair{} labelPair.LabelName = &newLabelList[index] labelPair.LabelId = &labelID request.LabelPairList[index] = labelPair } // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeAddContactLabel, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/addcontactlabel", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendDelContactLabelRequest 删除标签 func SendDelContactLabelRequest(userInfo *baseinfo.UserInfo, labelId string) (*baseinfo.PackHeader, error) { req := wechat.DelContactLabelRequest{ BaseRequest: GetBaseRequest(userInfo), LabelIdlist: proto.String(labelId), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeDelContactLabel, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delcontactlabel", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendModifyLabelRequest 修改标签请求 func SendModifyLabelRequest(userInfo *baseinfo.UserInfo, userLabelList []baseinfo.UserLabelInfoItem) (*baseinfo.PackHeader, error) { _userLabelList := make([]*wechat.UserLabelInfo, 0) for _, item := range userLabelList { _userLabelList = append(_userLabelList, &wechat.UserLabelInfo{ UserName: proto.String(item.UserName), LabelIdlist: proto.String(item.LabelIDList), }) } req := wechat.ModifyContactLabelListRequest{ BaseRequest: GetBaseRequest(userInfo), UserCount: proto.Uint32(uint32(len(_userLabelList))), UserLabelInfoList: _userLabelList, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeModifyContactLabelList, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/modifycontactlabellist", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendBindQueryNewRequest SendBindQueryNewRequest func SendBindQueryNewRequest(userInfo *baseinfo.UserInfo, reqItem *baseinfo.TenPayReqItem) (*baseinfo.PackHeader, error) { var request wechat.TenPayRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &reqItem.CgiCMD // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText var reqTextSKBuf wechat.SKBuiltinString_ tmpLen := uint32(len(reqItem.ReqText)) reqTextSKBuf.Len = &tmpLen reqTextSKBuf.Buffer = []byte(reqItem.ReqText) request.ReqText = &reqTextSKBuf // ReqTextWx var wxReqTextSKBuf wechat.SKBuiltinString_ tmpText := "encrypt_key=" + userInfo.HBAesKeyEncrypted tmpText = tmpText + "&encrypt_userinfo=" + GetEncryptUserInfo(userInfo) tmpWXLen := uint32(len(tmpText)) wxReqTextSKBuf.Len = &tmpWXLen wxReqTextSKBuf.Buffer = []byte(tmpText) request.ReqTextWx = &wxReqTextSKBuf // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeBindQueryNew, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmpay-bin/tenpay/bindquerynew", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 确定收款 func SendTenPayRequest(userInfo *baseinfo.UserInfo, reqItem *baseinfo.TenPayReqItem) (*baseinfo.PackHeader, error) { var request wechat.TenPayRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // CgiCmd request.CgiCmd = &reqItem.CgiCMD // OutPutType outputType := baseinfo.MMTenPayReqOutputTypeJSON request.OutPutType = &outputType // ReqText var reqTextSKBuf wechat.SKBuiltinString_ tmpLen := uint32(len(reqItem.ReqText)) reqTextSKBuf.Len = &tmpLen reqTextSKBuf.Buffer = []byte(reqItem.ReqText) request.ReqText = &reqTextSKBuf // ReqTextWx var wxReqTextSKBuf wechat.SKBuiltinString_ wxReqTextSKBuf.Buffer = []byte(reqItem.ReqText) wxReqTextSKBuf.Len = &tmpLen request.ReqTextWx = &wxReqTextSKBuf // 打包发送数据 srcData, _ := proto.Marshal(&request) sendEncodeData := Pack(userInfo, srcData, 385, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/tenpay", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSnsTimeLineRequest 发送获取朋友圈请求 func SendSnsTimeLineRequest(userInfo *baseinfo.UserInfo, firstPageMD5 string, maxID uint64) (*baseinfo.PackHeader, error) { /*var request wechat.SnsTimeLineRequest // baserequest baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene request.BaseRequest = baseReq // ClientLatestId tmpLatestID := uint64(0) request.ClientLatestId = &tmpLatestID // FirstPageMd5 request.FirstPageMd5 = &firstPageMD5 // LastRequestTime lastRequestTime := uint32(0) request.LastRequestTime = &lastRequestTime // MAXID request.MaxId = &maxID // MinFilterId minFilterID := uint64(0) request.MinFilterId = &minFilterID // NetworkType netWorkType := uint32(1) request.NetworkType = &netWorkType*/ req := &wechat.SnsTimeLineRequest{ BaseRequest: GetBaseRequest(userInfo), ClientLatestId: proto.Uint64(0), FirstPageMd5: proto.String(firstPageMD5), LastRequestTime: proto.Uint32(0), MaxId: proto.Uint64(maxID), MinFilterId: proto.Uint64(0), NetworkType: proto.Uint32(1), } baseReq := GetBaseRequest(userInfo) var tmpScene = uint32(0) baseReq.Scene = &tmpScene req.BaseRequest = baseReq // 打包发送数据 srcData, _ := proto.Marshal(req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeMMSnsTimeLine, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mmsnstimeline", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // StatusNotify 发送状态通知 func StatusNotify(userInfo *baseinfo.UserInfo, toWxid string) (*baseinfo.PackHeader, error) { // 构造请求 request := wechat.StatusNotifyRequest{ BaseRequest: GetBaseRequest(userInfo), Code: proto.Uint32(2), FromUserName: proto.String(userInfo.GetUserName()), ToUserName: proto.String(toWxid), ClientMsgId: proto.String(fmt.Sprintf("%v_%v", toWxid, time.Now().Unix())), } // 发送请求 srcData, _ := proto.Marshal(&request) sendData := Pack(userInfo, srcData, baseinfo.MMRequestTypeStatusNotify, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/statusnotify", sendData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendAppMsgRequest 发送App消息 func SendAppMsgRequest(userInfo *baseinfo.UserInfo, contentType uint32, toUserName, xml string) (*baseinfo.PackHeader, error) { curTime := time.Now().Unix() req := wechat.SendAppMsgRequest{ BaseRequest: GetBaseRequest(userInfo), Msg: &wechat.AppMsg{ FromUserName: proto.String(userInfo.GetUserName()), AppId: proto.String(""), SdkVersion: proto.Uint32(0), ToUserName: proto.String(toUserName), Type: proto.Uint32(contentType), Content: proto.String(xml), CreateTime: proto.Uint32(uint32(curTime)), ClientMsgId: proto.String(fmt.Sprintf("%s_%v", toUserName, curTime)), Source: proto.Int32(0), RemindId: proto.Int32(0), MsgSource: proto.String(""), Thumb: &wechat.BufferT{ ILen: proto.Uint32(0), Buffer: []byte{}, }, }, FromSence: proto.String(""), DirectShare: proto.Int32(0), SendMsgTicket: proto.String(""), } // 打包发送数据 src, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, src, baseinfo.MMRequestTypeSendAppMsg, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/sendappmsg", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendEmojiRequest 发生表情 func SendEmojiRequest(userInfo *baseinfo.UserInfo, toUserName, Md5 string, length int32) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) //baseRequest.Scene = proto.Uint32(0) req := wechat.UploadEmojiRequest{ BaseRequest: baseRequest, EmojiItemCount: proto.Int32(1), EmojiItem: []*wechat.EmojiUploadInfoReq{ { MD5: proto.String(Md5), StartPos: proto.Int32(length), TotalLen: proto.Int32(length), EmojiBuffer: &wechat.BufferT{ ILen: proto.Uint32(0), Buffer: []byte{}, }, Type: proto.Int32(2), ToUserName: proto.String(toUserName), ClientMsgID: proto.String(fmt.Sprintf("%d", time.Now().UnixNano()/1000/1000)), }, }, } // 打包发送数据 src, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, src, baseinfo.MMRequestTypeSendEmoji, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/sendemoji", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 发送表情 new 包含动图 func ForwardEmojiRequest(userInfo *baseinfo.UserInfo, toUserName, Md5 string, length int32) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) //baseRequest.Scene = proto.Uint32(0) req := wechat.UploadEmojiRequest{ BaseRequest: baseRequest, EmojiItemCount: proto.Int32(1), EmojiItem: []*wechat.EmojiUploadInfoReq{ { MD5: proto.String(Md5), StartPos: proto.Int32(0), TotalLen: proto.Int32(length), EmojiBuffer: &wechat.BufferT{ ILen: proto.Uint32(0), Buffer: []byte{}, }, Type: proto.Int32(1), ToUserName: proto.String(toUserName), ClientMsgID: proto.String(strconv.FormatInt(time.Now().Unix(), 10)), }, }, } // 打包发送数据 src, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, src, baseinfo.MMRequestTypeSendEmoji, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/sendemoji", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 下载语音 func SendGetMsgVoiceRequest(userInfo *baseinfo.UserInfo, toUserName, NewMsgIds, Bufid string, Length int) (*vo.DownloadVoiceData, error) { I := 0 Startpos := 0 datalen := 50000 Databuff := make([]byte, Length+1000) var VoiceLength uint32 totalBytesDownloaded := 0 maxIterations := (Length + datalen - 1) / datalen NewMsgId, _ := strconv.ParseUint(NewMsgIds, 10, 64) MasterBufId, _ := strconv.ParseUint(Bufid, 10, 64) resp := new(wechat.DownloadVoiceResponse) for { if I >= maxIterations { return nil, fmt.Errorf("超过最大可下载tier(%d)", maxIterations) } Startpos = I * datalen count := 0 remainingBytes := Length - Startpos if remainingBytes <= 0 { break } if remainingBytes > datalen { count = datalen } else { count = remainingBytes } req := wechat.DownloadVoiceRequest{ BaseRequest: GetBaseRequest(userInfo), MsgId: proto.Uint32(0), Offset: proto.Uint32(uint32(Startpos)), Length: proto.Uint32(uint32(count)), NewMsgId: proto.Uint64(NewMsgId), ChatRoomName: proto.String(toUserName), MasterBufId: proto.Uint64(MasterBufId), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeDownloadVoice, 5) res, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/downloadvoice", sendEncodeData) if err != nil { return nil, fmt.Errorf("network error downloading voice chunk %d at offset %d: %w", I+1, Startpos, err) } header, err := DecodePackHeader(res, nil) if err != nil { return nil, fmt.Errorf("failed to decode response header for chunk %d at offset %d: %w", I+1, Startpos, err) } err = ParseResponseData(userInfo, header, resp) if err != nil { return nil, fmt.Errorf("failed to parse response data for chunk %d at offset %d: %w", I+1, Startpos, err) } if resp.GetBaseResponse().GetRet() != 0 { return nil, fmt.Errorf("server returned error %d for chunk %d at offset %d", resp.GetBaseResponse().GetRet(), I+1, Startpos) } // Fix: Write chunk data to correct buffer position instead of overwriting // Validate chunk response before processing if resp.GetData() == nil { return nil, fmt.Errorf("chunk %d at offset %d: response data is nil", I+1, Startpos) } chunkData := resp.GetData().GetBuffer() chunkSize := len(chunkData) // Validate that chunk data length matches expected size expectedChunkSize := count if chunkSize != expectedChunkSize { return nil, fmt.Errorf("chunk %d at offset %d: expected %d bytes, got %d bytes", I+1, Startpos, expectedChunkSize, chunkSize) } // Ensure proper handling of the last chunk which may be smaller if I > 0 && chunkSize > datalen { return nil, fmt.Errorf("chunk %d at offset %d: chunk size %d exceeds maximum chunk size %d", I+1, Startpos, chunkSize, datalen) } // Calculate the correct offset for this chunk bufferOffset := Startpos // Buffer bounds checking - prevent buffer overflow if bufferOffset+chunkSize > len(Databuff) { return nil, fmt.Errorf("buffer overflow: chunk at offset %d with size %d exceeds buffer capacity %d", bufferOffset, chunkSize, len(Databuff)) } // Validate that chunk data fits within allocated buffer space if bufferOffset < 0 || bufferOffset >= len(Databuff) { return nil, fmt.Errorf("invalid buffer offset: %d, buffer size: %d", bufferOffset, len(Databuff)) } // Copy chunk data to the correct position in the buffer copy(Databuff[bufferOffset:bufferOffset+chunkSize], chunkData) // Track bytes downloaded in this chunk totalBytesDownloaded += chunkSize // Progress tracking for validation and debugging progressPercent := float64(totalBytesDownloaded) / float64(Length) * 100 _ = progressPercent // Available for debugging if needed VoiceLength = resp.GetVoiceLength() I++ // Ensure loop exits when all expected data is downloaded if totalBytesDownloaded >= Length { break } } // Validate that downloaded length matches expected Length parameter if totalBytesDownloaded != Length { return nil, fmt.Errorf("download incomplete: expected %d bytes, but downloaded %d bytes", Length, totalBytesDownloaded) } return &vo.DownloadVoiceData{ Base64: Databuff, VoiceLength: VoiceLength, }, nil } // 群发图片 func SendGroupMassMsgImage(userInfo *baseinfo.UserInfo, toUSerName []string, ImageBase64 []byte) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) baseRequest.Scene = proto.Uint32(0) toList := strings.Join(toUSerName, ";") tolistmd5 := baseutils.MD5ToLower(toList) ClientImgId := fmt.Sprintf("%v_%v", time.Now().Unix(), tolistmd5) var protobufdata []byte imgStream := bytes.NewBuffer(ImageBase64) Startpos := 0 datalen := 50000 datatotalength := imgStream.Len() I := 0 for { Startpos = I * datalen count := 0 if datatotalength-Startpos > datalen { count = datalen } else { count = datatotalength - Startpos } if count < 0 { break } Databuff := make([]byte, count) _, _ = imgStream.Read(Databuff) req := wechat.MassSendRequest{ BaseRequest: baseRequest, ToList: proto.String(toList), ToListMd5: proto.String(tolistmd5), ClientId: proto.String(ClientImgId), MsgType: proto.Uint64(3), MediaTime: proto.Uint64(0), DataBuffer: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(Databuff))), Buffer: Databuff, }, DataStartPos: proto.Uint64(uint64(Startpos)), DataTotalLen: proto.Uint64(uint64(len(Databuff))), ThumbTotalLen: proto.Uint64(0), ThumbStartPos: proto.Uint64(0), ThumbData: &wechat.SKBuiltinString_{ Len: proto.Uint32(0), Buffer: []byte{}, }, CameraType: proto.Uint64(2), VideoSource: proto.Uint64(0), ToListCount: proto.Uint64(uint64(len(toUSerName))), IsSendAgain: proto.Uint64(0), CompressType: proto.Uint64(1), VoiceFormat: proto.Uint64(0), } // 打包发送数据 src, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, src, 193, 5) rsp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/masssend", sendEncodeData) if err != nil { return nil, err } protobufdata = rsp I++ } return DecodePackHeader(protobufdata, nil) } func SendGroupMassMsgText(userInfo *baseinfo.UserInfo, toUSerName []string, content string) (*baseinfo.PackHeader, error) { baseRequest := GetBaseRequest(userInfo) // baseRequest.Scene = proto.Uint32(0) toList := strings.Join(toUSerName, ";") tolistmd5 := baseutils.MD5ToLower(toList) Databuff := []byte(content) ClientImgId := fmt.Sprintf("%v_%v", time.Now().Unix(), tolistmd5) fmt.Println("toList:", toList, "tolistmd5:", tolistmd5) req := wechat.MassSendRequest{ BaseRequest: baseRequest, ToList: proto.String(toList), ToListMd5: proto.String(tolistmd5), ClientId: proto.String(ClientImgId), MsgType: proto.Uint64(1), MediaTime: proto.Uint64(0), DataBuffer: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(Databuff))), Buffer: Databuff, }, DataStartPos: proto.Uint64(0), DataTotalLen: proto.Uint64(uint64(len(Databuff))), ThumbTotalLen: proto.Uint64(0), ThumbStartPos: proto.Uint64(0), ThumbData: &wechat.SKBuiltinString_{ Len: proto.Uint32(0), Buffer: []byte{}, }, CameraType: proto.Uint64(2), VideoSource: proto.Uint64(0), ToListCount: proto.Uint64(uint64(len(toUSerName))), IsSendAgain: proto.Uint64(1), CompressType: proto.Uint64(0), VoiceFormat: proto.Uint64(0), } // 打包发送数据 src, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, src, 193, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/masssend", sendEncodeData) fmt.Println("resp:", string(resp)) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetChatroomMemberDetailRequest 获取群成员详细 func GetChatroomMemberDetailRequest(userInfo *baseinfo.UserInfo, roomId string) (*baseinfo.PackHeader, error) { req := wechat.GetChatroomMemberDetailRequest{ BaseRequest: GetBaseRequest(userInfo), ChatroomWxid: proto.String(roomId), ClientVersion: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetChatRoomMemberDetail, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getchatroommemberdetail", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 群拍一拍 func SendSendPatRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName string, scene int64) (*baseinfo.PackHeader, error) { ClientImgId := fmt.Sprintf("%v_%v_%v", userInfo.WxId, toUserName, time.Now().Unix()) req := wechat.SendPatRequest{ BaseRequest: GetBaseRequest(userInfo), FromUsername: proto.String(userInfo.WxId), ChatUsername: proto.String(chatRoomName), PattedUsername: proto.String(toUserName), ClientMsgId: proto.String(ClientImgId), Scene: proto.Int64(scene), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 849, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/sendpat", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SetChatRoomAnnouncementRequest 设置群公告 func SetChatRoomAnnouncementRequest(userInfo *baseinfo.UserInfo, roomId, content string) (*baseinfo.PackHeader, error) { req := wechat.SetChatRoomAnnouncementRequest{ BaseRequest: GetBaseRequest(userInfo), ChatRoomName: proto.String(roomId), Announcement: proto.String(content), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeSetChatRoomAnnouncement, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/setchatroomannouncement", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 同意入群 func JoinGroupRequest(fullUrl string) (*wechat.JoinChatRoomResponse, error) { client := &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, } req, err := http.NewRequest("POST", fullUrl, strings.NewReader("s=1")) if err != nil { return nil, errors.New(fmt.Sprintf("异常:%v", err.Error())) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := client.Do(req) if err != nil { return nil, errors.New(fmt.Sprintf("异常:%v", err.Error())) } defer resp.Body.Close() if resp.StatusCode == 302 { QID := strings.Replace(resp.Header.Get("Location"), "weixin://jump/mainframe/", "", -1) response := wechat.JoinChatRoomResponse{} response.QID = QID response.Msg = "入群成功" return &response, nil } str, _ := ioutil.ReadAll(resp.Body) return nil, errors.New(fmt.Sprintf("异常:%v", string(str))) } // 获取群详细 func SetGetChatRoomInfoDetailRequest(userInfo *baseinfo.UserInfo, roomId string) (*baseinfo.PackHeader, error) { req := wechat.GetChatRoomInfoDetailRequest{ BaseRequest: GetBaseRequest(userInfo), ChatRoomName: proto.String(roomId), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetChatRoomInfoDetail, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getchatroominfodetail", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } //保存群聊操作 /*func SetMoveToContractRequest(userInfo *baseinfo.UserInfo, ChatRoomName string, Val uint32) (*baseinfo.PackHeader, error) { UserNameListSplit := strings.Split(ChatRoomName, ",") req := wechat.GetChatRoomInfoDetailRequest{ BaseRequest: GetBaseRequest(userInfo), ChatRoomName: proto.String(roomId), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetChatRoomInfoDetail, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getchatroominfodetail", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) }*/ // GetCreateChatRoomEntity 创建群 func GetCreateChatRoomEntity(userInfo *baseinfo.UserInfo, topIc string, userList []string) (*baseinfo.PackHeader, error) { userList = append([]string{userInfo.GetUserName()}, userList...) memberList := make([]*wechat.MemberReq, 0) for _, user := range userList { memberList = append(memberList, &wechat.MemberReq{ MemberName: &wechat.SKBuiltinString{ Str: proto.String(user), }, }) } req := wechat.CreateChatRoomRequest{ BaseRequest: GetBaseRequest(userInfo), Topic: &wechat.SKBuiltinString{ Str: proto.String(topIc), }, MemberCount: proto.Uint32(uint32(len(memberList))), MemberList: memberList, Scene: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeCreateChatRoom, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/createchatroom", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 添加群管理 func SendAddChatroomAdmin(userInfo *baseinfo.UserInfo, chatRoomName string, userList []string) (*baseinfo.PackHeader, error) { req := wechat.AddChatRoomAdminRequest{ BaseRequest: GetBaseRequest(userInfo), ChatRoomName: proto.String(chatRoomName), UserNameList: userList, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 889, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/addchatroomadmin", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetQrCodeRequest 获取(群聊/个人)二维码 func GetQrCodeRequest(userInfo *baseinfo.UserInfo, id string, style uint32) (*baseinfo.PackHeader, error) { req := wechat.GetQRCodeRequest{ BaseRequest: GetBaseRequest(userInfo), UserName: &wechat.SKBuiltinString{ Str: proto.String(id), }, Style: proto.Uint32(style), Opcode: proto.Uint32(1), // 安卓 0(群二维码) 1(个人二维码) } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetQrCode, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getqrcode", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 删除群管理 func SendDelChatroomAdminRequest(userInfo *baseinfo.UserInfo, chatRoomName string, userList []string) (*baseinfo.PackHeader, error) { req := wechat.DelChatRoomAdminRequest{ BaseRequest: GetBaseRequest(userInfo), ChatRoomName: proto.String(chatRoomName), UserNameList: userList, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 259, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delchatroomadmin", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 获取群列表 func SendWXSyncContactRequest(userInfo *baseinfo.UserInfo, key []byte) (*baseinfo.PackHeader, error) { keyBuf := userInfo.SyncKey if key != nil { keyBuf = key } osType := "" if userInfo.DeviceInfoA16 != nil { osType = baseinfo.AndroidDeviceType } else { osType = userInfo.DeviceInfo.OsType } req := wechat.NewSyncRequest{ Oplog: &wechat.CmdList{ Count: proto.Uint32(0), }, DeviceType: proto.String(osType), Scene: proto.Uint32(3), //有时候03,有时候01 Selector: proto.Uint32(7), // 7 SyncMsgDigest: proto.Uint32(baseinfo.MMSyncMsgDigestTypeShortLink), KeyBuf: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(keyBuf))), Buffer: keyBuf, }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 138, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newsync", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 搜手机或企业对外名片链接提取验证 func SendQWSearchContactRequest(userInfo *baseinfo.UserInfo, tg string, fromScene uint64, userName string) (*baseinfo.PackHeader, error) { req := wechat.SearchQYContactRequest{} if utils.IsMobile(tg) { req.Tg = proto.String(tg) req.FromScene = proto.Uint64(1) } else { req.UserName = proto.String(tg) } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 372, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/searchopenimcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetAddChatRoomMemberRequest 拉人 func GetAddChatRoomMemberRequest(userInfo *baseinfo.UserInfo, chatRoomName string, userList []string) (*baseinfo.PackHeader, error) { memberList := make([]*wechat.MemberReq, 0) for _, user := range userList { memberList = append(memberList, &wechat.MemberReq{ MemberName: &wechat.SKBuiltinString{ Str: proto.String(user), }, }) } req := wechat.AddChatRoomMemberRequest{ BaseRequest: GetBaseRequest(userInfo), MemberCount: proto.Uint32(uint32(len(memberList))), MemberList: memberList, ChatRoomName: &wechat.SKBuiltinString{ Str: proto.String(chatRoomName), }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeAddChatRoomMember, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/addchatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // DelDelChatRoomMember 删除群成员 func DelDelChatRoomMemberRequest(userInfo *baseinfo.UserInfo, chatRoomName string, delUserList []string) (*baseinfo.PackHeader, error) { memberList := make([]*wechat.DelMemberReq, 0) for _, user := range delUserList { memberList = append(memberList, &wechat.DelMemberReq{ MemberName: &wechat.SKBuiltinString{ Str: proto.String(user), }, }) } req := wechat.DelChatRoomMemberRequest{ BaseRequest: GetBaseRequest(userInfo), MemberCount: proto.Uint32(uint32(len(memberList))), MemberList: memberList, ChatRoomName: proto.String(chatRoomName), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeDelChatRoomMember, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delchatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetTransferGroupOwnerRequest 转让群 func GetTransferGroupOwnerRequest(userInfo *baseinfo.UserInfo, chatRoomName, newOwnerUserName string) (*baseinfo.PackHeader, error) { req := wechat.TransferChatRoomOwnerRequest{ BaseRequest: GetBaseRequest(userInfo), ChatRoomName: proto.String(chatRoomName), NewOwnerUserName: proto.String(newOwnerUserName), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeTransferChatRoomOwnerRequest, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/transferchatroomowner", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetInviteChatroomMembersEntity 邀请群成员 func GetInviteChatroomMembersRequest(userInfo *baseinfo.UserInfo, chatRoomName string, userList []string) (*baseinfo.PackHeader, error) { memberList := make([]*wechat.MemberReq, 0) for _, user := range userList { memberList = append(memberList, &wechat.MemberReq{ MemberName: &wechat.SKBuiltinString{ Str: proto.String(user), }, }) } req := wechat.InviteChatRoomMemberRequest{ BaseRequest: GetBaseRequest(userInfo), MemberCount: proto.Uint32(uint32(len(memberList))), MemberList: memberList, ChatRoomName: &wechat.SKBuiltinString{ Str: proto.String(chatRoomName), }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeInviteChatRoomMember, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/invitechatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 查看附近的人 func SendGetPeopleNearbyResultRequest(userInfo *baseinfo.UserInfo, longitude float32, latitude float32) (*baseinfo.PackHeader, error) { req := &wechat.LbsRequest{ BaseRequest: GetBaseRequest(userInfo), GPSSource: proto.Int64(0), Latitude: proto.Float32(latitude), Longitude: proto.Float32(longitude), OpCode: proto.Uint64(1), Precision: proto.Int64(65), } // 打包发送数据 srcData, _ := proto.Marshal(req) sendEncodeData := Pack(userInfo, srcData, 148, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/lbsfind", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetA8KeyRequest 授权链接 // @opCode : // // enum GetA8KeyOpCode // { // MMGETA8KEY_OPENAPI = 1, // MMGETA8KEY_QZONE = 3, // MMGETA8KEY_REDIRECT = 2 // } // // @scene : // // enum GetA8KeyScene // { // MMGETA8KEY_SCENE_UNKNOW, // MMGETA8KEY_SCENE_MSG, // MMGETA8KEY_SCENE_TIMELINE, // MMGETA8KEY_SCENE_PROFILE, // MMGETA8KEY_SCENE_QRCODE, // MMGETA8KEY_SCENE_QZONE, // MMGETA8KEY_SCENE_OAUTH, // MMGETA8KEY_SCENE_OPEN, // MMGETA8KEY_SCENE_PLUGIN, // MMGETA8KEY_SCENE_JUMPURL, // MMGETA8KEY_SCENE_SHAKETV, // MMGETA8KEY_SCENE_SCANBARCODE, // MMGETA8KEY_SCENE_SCANIMAGE, // MMGETA8KEY_SCENE_SCANSTREETVIEW, // MMGETA8KEY_SCENE_FAV, // MMGETA8KEY_SCENE_MMBIZ, // MMGETA8KEY_SCENE_QQMAIL, // MMGETA8KEY_SCENE_LINKEDIN, // MMGETA8KEY_SCENE_SHAKETV_DETAIL, // MMGETA8KEY_SCENE_BIZHOMEPAGE, // MMGETA8KEY_SCENE_USBCONNECT, // MMGETA8KEY_SCENE_SHORT_URL, // MMGETA8KEY_SCENE_WIFI, // MMGETA8KEY_SCENE_OUTSIDE_DEEPLINK, // MMGETA8KEY_SCENE_PUSH_LOGIN_URL // } func GetA8KeyRequest(userInfo *baseinfo.UserInfo, opCode, scene uint32, reqUrl string, getType baseinfo.GetA8KeyType) (*baseinfo.PackHeader, error) { req := wechat.GetA8KeyRequest{ BaseRequest: GetBaseRequest(userInfo), OpCode: proto.Uint32(opCode), //2 ReqUrl: &wechat.SKBuiltinString{ Str: proto.String(reqUrl), }, Scene: proto.Uint32(scene), //4 UserName: proto.String(userInfo.GetUserName()), BundleID: proto.String(""), NetType: proto.String("WiFi"), FontScale: proto.Uint32(100), RequestId: proto.Uint64(uint64(time.Now().Unix())), CodeType: proto.Uint32(19), //CodeType: proto.Uint32(15), //CodeVersion: proto.Uint32(5), OuterUrl: proto.String(""), SubScene: proto.Uint32(1), } cgi := uint32(0) cgiUrl := "" switch getType { case baseinfo.ThrIdGetA8Key: cgi = baseinfo.MMRequestTypeThrIdGetA8Key cgiUrl = "/cgi-bin/micromsg-bin/3rd-geta8key" default: cgi = baseinfo.MMRequestTypeGetA8Key cgiUrl = "/cgi-bin/micromsg-bin/geta8key" } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, uint32(cgi), 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, cgiUrl, sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // JSLoginRequest 授权小程序 返回Code // @appId :要授权wxappid func JSLoginRequest(userInfo *baseinfo.UserInfo, appId string) (*baseinfo.PackHeader, error) { req := wechat.JSLoginRequest{ BaseRequest: GetBaseRequest(userInfo), AppId: proto.String(appId), LoginType: proto.Int32(1), VersionType: proto.Int32(0), WxaExternalInfo: &wechat.WxaExternalInfo{ Scene: proto.Int32(1001), SourceEnv: proto.Int32(1), }, } /*req := wechat.JSLoginRequest{ BaseRequest: GetBaseRequest(userInfo), AppId: proto.String(appId), Scope: proto.String("snsapi_login"), LoginType: proto.Int32(4), Url: proto.String("https://open.weixin.qq.com/connect/confirm?uuid=021extwqXdPRRlbJ"), VersionType: proto.Int32(0), WxaExternalInfo: &wechat.WxaExternalInfo{ Scene: proto.Int32(1001), SourceEnv: proto.Int32(1), }, }*/ /*req := wechat.JSLoginRequest{ BaseRequest: GetBaseRequest(userInfo), AppId: proto.String(appId), LoginType: proto.Int32(1), VersionType: proto.Int32(0), WxaExternalInfo: &wechat.WxaExternalInfo{ Scene: proto.Int32(1066), SourceEnv: proto.Int32(1), }, }*/ srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeJSLogin, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/js-login", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // JSOperateWxDataRequest 小程序云函数操作; 授权小程序后返回 encryptedData,iv等信息 func JSOperateWxDataRequest(userInfo *baseinfo.UserInfo, appId string, opt int32, data string) (*baseinfo.PackHeader, error) { req := wechat.JSOperateWxDataRequest{ BaseRequest: GetBaseRequest(userInfo), AppId: proto.String(appId), Data: []byte(data), GrantScope: proto.String("scope.userInfo"), Opt: proto.Int32(opt), // 默认为 1 VersionType: proto.Int32(0), WxaExternalInfo: &wechat.WxaExternalInfo{ Scene: proto.Int32(1001), SourceEnv: proto.Int32(2), }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeJSOperateWxData, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/js-operatewxdata", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SdkOauthAuthorizeRequest 授权app应用 func SdkOauthAuthorizeRequest(userInfo *baseinfo.UserInfo, appId string, sdkName string, packageName string) (*baseinfo.PackHeader, error) { req := wechat.SdkOauthAuthorizeReq{ BaseRequest: GetBaseRequest(userInfo), AppId: proto.String(appId), Tag3: proto.String("snsapi_userinfo"), Tag4: proto.String(sdkName), //wechat_sdk_demo_test Tag5: proto.String(packageName), //"com.yimu.renwuxiongObject" Tag8: proto.String(""), Tag9: proto.String(""), Tag10: proto.String(""), Tag11: proto.String(""), Tag12: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeSdkOauthAuthorize, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/sdk_oauth_authorize", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendSearchContactRequest 搜索联系人 func SendSearchContactRequest(userInfo *baseinfo.UserInfo, opCode, fromScene, searchScene uint32, userName string) (*baseinfo.PackHeader, error) { req := wechat.SearchContactRequest{ BaseRequest: GetBaseRequest(userInfo), UserName: &wechat.SKBuiltinString{ Str: proto.String(userName), }, OpCode: proto.Uint32(opCode), FromScene: proto.Uint32(fromScene), SearchScene: proto.Uint32(searchScene), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeSearchContact, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/searchcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // VerifyUserRequest 好友验证 func VerifyUserRequest(userInfo *baseinfo.UserInfo, opCode uint32, verifyContent string, scene int, V3, V4, ChatRoomUserName string) (*baseinfo.PackHeader, error) { // clientcheckdata var extSpamInfo wechat.SKBuiltinString_ if userInfo.DeviceInfo != nil { extSpamInfo.Buffer = GetExtPBSpamInfoDataIPhone(userInfo) } else { extSpamInfo.Buffer = GetExtPBSpamInfoDataA16(userInfo) } extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen userTicket := V4 if ChatRoomUserName != "" { userTicket = "" } req := wechat.VerifyUserRequest{ BaseRequest: GetBaseRequest(userInfo), OpCode: proto.Uint32(opCode), VerifyUserListSize: proto.Uint32(1), VerifyUserList: []*wechat.VerifyUser{{ Value: proto.String(V3), VerifyUserTicket: proto.String(userTicket), AntispamTicket: proto.String(V4), FriendFlag: proto.Uint32(0), ChatRoomUserName: proto.String(ChatRoomUserName), SourceUserName: proto.String(""), SourceNickName: proto.String(""), ScanQrcodeFromScene: proto.Uint32(0), ReportInfo: proto.String(""), OuterUrl: proto.String(""), SubScene: proto.Uint32(0), }}, VerifyContent: proto.String(verifyContent), SceneListCount: proto.Uint32(1), SceneList: []byte{byte(scene)}, ExtSpamInfo: &extSpamInfo, //NeedConfirm: proto.Uint32(1), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeVerifyUser, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/verifyuser", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // UploadMContact 上传通讯录 func UploadMContactRequest(userInfo *baseinfo.UserInfo, mobile string, mobiles []string, opcdoe int32) (*baseinfo.PackHeader, error) { mobileList := make([]*wechat.Mobile, 0) for _, mobile := range mobiles { mobileList = append(mobileList, &wechat.Mobile{ V: proto.String(mobile), }) } req := wechat.UploadMContactRequest{ BaseRequest: GetBaseRequest(userInfo), UserName: proto.String(userInfo.WxId), Opcode: &opcdoe, Mobile: proto.String(mobile), MobileListSize: proto.Int32(int32(len(mobileList))), MobileList: mobileList, EmailListSize: proto.Int32(0), EmailList: []*wechat.MEmail{}, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeUploadMContact, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadmcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetMFriendRequest 获取通讯录 func GetMFriendRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { req := wechat.GetMFriendRequest{ BaseRequest: GetBaseRequest(userInfo), OpType: proto.Uint32(0), MD5: proto.String(uuid.New().String()), Scene: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetMFriend, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getmfriend", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetCertRequest 获取证书 func GetCertRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { //userInfo.SessionKey = baseutils.RandomBytes(16) req := wechat.GetCertRequest{ BaseRequest: GetBaseRequest(userInfo), AesEncryptKey: &wechat.SKBuiltinString_{ Len: proto.Uint32(16), Buffer: userInfo.SessionKey[:16], }, Version: proto.Uint32(135), } srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 381, 7) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getcert", sendEncodeData) // fmt.Println(hex.EncodeToString(resp)) // fmt.Println(hex.EncodeToString(userInfo.SessionKey)) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetSdkOauthAuthorizeConfirmRequest func GetSdkOauthAuthorizeConfirmRequest(userInfo *baseinfo.UserInfo, AppId, appName, appNamePack string) (*baseinfo.PackHeader, error) { req := wechat.SdkOauthAuthorizeConfirmNewReq{ BaseRequest: GetBaseRequest(userInfo), Opt: proto.Uint32(1), Scope: []string{"snsapi_userinfo"}, AppId: proto.String(AppId), State: proto.String(appName), BundleId: proto.String(appNamePack), AvatarId: proto.Uint32(0), UniversalLink: proto.String(""), OpenSdkVersion: proto.String(""), SdkToken: proto.String(""), OpenSdkBundleId: proto.String(""), SdkTokenChk: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 1346, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/sdk_oauth_authorize_confirm", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetQRConnectAuthorizeRequest 获取授权二维码链接组包 func GetQRConnectAuthorizeRequest(userInfo *baseinfo.UserInfo, url string) (*baseinfo.PackHeader, error) { req := wechat.QRConnectAuthorizeReq{ BaseRequest: GetBaseRequest(userInfo), OAuthUrl: proto.String(url), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 2543, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/qrconnect_authorize", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetQRConnectAuthorizeConfirmRequest 授权二维码链接确认组包 func GetQRConnectAuthorizeConfirmRequest(userInfo *baseinfo.UserInfo, url string) (*baseinfo.PackHeader, error) { req := wechat.QRConnectAuthorizeConfirmReq{ BaseRequest: GetBaseRequest(userInfo), OAuthUrl: proto.String(url), Opt: proto.Uint32(1), Scope: []string{"snsapi_login"}, AvatarId: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 1137, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/qrconnect_authorize_confirm", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 授权链接 func SendGetMpA8Request(userInfo *baseinfo.UserInfo, url string, opcode uint32) (*baseinfo.PackHeader, error) { req := wechat.GetA8KeyRequest{ BaseRequest: GetBaseRequest(userInfo), CodeType: proto.Uint32(19), CodeVersion: proto.Uint32(10), Flag: proto.Uint32(0), FontScale: proto.Uint32(118), NetType: proto.String("WIFI"), OpCode: proto.Uint32(opcode), UserName: proto.String(userInfo.WxId), ReqUrl: &wechat.SKBuiltinString{ Str: proto.String(url), }, FriendQq: proto.Uint32(0), Scene: proto.Uint32(4), SubScene: proto.Uint32(1), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 233, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/mp-geta8key", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetOnlineInfoRequest 获取登录信息组包 func GetOnlineInfoRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { req := wechat.GetOnlineInfoRequest{ BaseRequest: GetBaseRequest(userInfo), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeGetOnlineInfo, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getonlineinfo", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // GetRevokeMsgRequest 撤销消息 func GetRevokeMsgRequest(userInfo *baseinfo.UserInfo, newMsgId string, clientMsgId uint64, toUserName string) (*baseinfo.PackHeader, error) { msgId, _ := strconv.ParseUint(newMsgId, 10, 64) reqData := wechat.RevokeMsgRequest{ BaseRequest: GetBaseRequest(userInfo), ClientMsgId: proto.String(fmt.Sprintf("%v_%v", time.Now().Unix(), newMsgId)), NewClientMsgId: proto.Uint32(uint32(time.Now().Unix())), CreateTime: proto.Uint32(uint32(time.Now().Unix())), SvrMsgId: proto.Uint64(clientMsgId), FromUserName: proto.String(userInfo.GetUserName()), ToUserName: proto.String(toUserName), IndexOfRequest: proto.Uint32(26), SvrNewMsgId: proto.Uint64(msgId), } // 打包发送数据 srcData, _ := proto.Marshal(&reqData) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeRevokeMsg, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/revokemsg", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // RevokeMsgRequestNew 撤回消息New func RevokeMsgRequestNew(userInfo *baseinfo.UserInfo, m req.RevokeMsgModel) (*baseinfo.PackHeader, error) { newMsgId, _ := strconv.ParseUint(m.NewMsgId, 10, 64) reqData := wechat.RevokeMsgRequestNew{ BaseRequest: GetBaseRequest(userInfo), FromUserName: proto.String(userInfo.GetUserName()), ToUserName: proto.String(m.ToUserName), CreateTime: proto.Uint64(m.CreateTime), IndexOfRequest: proto.Uint64(0), NewMsgId: proto.Uint64(newMsgId), } if m.IsImage { // 图片消息撤回 if m.ClientImgIdStr != "" { reqData.ClientMsgId = proto.String(m.ClientImgIdStr) // 使用原始clientImgId字符串 } else { // 如果未提供,尝试构造一个 reqData.ClientMsgId = proto.String(fmt.Sprintf("%s_%d", userInfo.GetUserName(), m.CreateTime)) } reqData.MsgId = proto.Uint64(m.ClientMsgId) // 对图片消息,使用msgId值 reqData.NewClientMsgId = proto.Uint64(m.CreateTime) // 尝试使用createTime } else { // 文本消息撤回,保持原来的逻辑 reqData.ClientMsgId = proto.String("") reqData.MsgId = proto.Uint64(0) reqData.NewClientMsgId = proto.Uint64(m.ClientMsgId) } // 打包发送数据 srcData, _ := proto.Marshal(&reqData) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeRevokeMsg, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/revokemsg", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // UploadHeadImage 修改头像 func UploadHeadImage(userInfo *baseinfo.UserInfo, base64Image string) (*baseinfo.PackHeader, error) { ImgData := strings.Split(base64Image, ",") var ImgBase64 []byte if len(ImgData) > 1 { ImgBase64, _ = base64.StdEncoding.DecodeString(ImgData[1]) } else { ImgBase64, _ = base64.StdEncoding.DecodeString(base64Image) } ImgStream := bytes.NewBuffer(ImgBase64) Startpos := 0 datalen := 30000 datatotalength := ImgStream.Len() ImgHash := GetFileMD5Hash(ImgBase64) I := 0 resps := make([]byte, 0) for { Startpos = I * datalen count := 0 if datatotalength-Startpos > datalen { count = datalen } else { count = datatotalength - Startpos } if count < 0 { break } Databuff := make([]byte, count) _, _ = ImgStream.Read(Databuff) req := wechat.UploadHDHeadImgRequest{ BaseRequest: GetBaseRequest(userInfo), TotalLen: proto.Uint32(uint32(datatotalength)), StartPos: proto.Uint32(uint32(Startpos)), HeadImgType: proto.Uint32(1), Data: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(Databuff))), Buffer: Databuff, }, ImgHash: proto.String(ImgHash), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeUploadHDHeadImg, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadhdheadimg", sendEncodeData) if err != nil { return nil, err } resps = resp I++ } // 打包发送数据 return DecodePackHeader(resps, nil) } func GetFileMD5Hash(Data []byte) string { hash := md5.New() hash.Write(Data) retVal := hash.Sum(nil) return hex.EncodeToString(retVal) } // GetVerifyPwdRequest 验证密码 func GetVerifyPwdRequest(userInfo *baseinfo.UserInfo, pwd string) (*baseinfo.PackHeader, error) { req := wechat.VerifyPwdRequest{ BaseRequest: GetBaseRequest(userInfo), OpCode: proto.Uint32(1), Pwd1: proto.String(baseutils.Md5Value(pwd)), Pwd2: proto.String(baseutils.Md5Value(pwd)), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeVerifyPassword, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newverifypasswd", sendEncodeData) if err != nil { return nil, err } // 转 字符串 return DecodePackHeader(resp, nil) } // SendSetPwdRequest 修改密码 func SendSetPwdRequest(userInfo *baseinfo.UserInfo, ticket, newPwd string, OpCode uint32) (*baseinfo.PackHeader, error) { log.Println("SendSetPwdRequest:", newPwd) log.Println("SendSetPwdRequest:", ticket) req := &wechat.SetPwdRequest{ BaseRequest: GetBaseRequest(userInfo), Password: proto.String(baseutils.Md5Value(newPwd)), Ticket: proto.String(ticket), AutoAuthKey: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(userInfo.AutoAuthKey))), Buffer: userInfo.AutoAuthKey, }, } // 打包发送数据 srcData, _ := proto.Marshal(req) S2801, _ := hex.DecodeString("2801") reqdataA := new(bytes.Buffer) reqdataA.Write(srcData) if len(userInfo.DeviceInfo.DeviceID) <= 16 { reqdataA.Write(S2801) } sendEncodeData := Pack(userInfo, reqdataA.Bytes(), baseinfo.MMRequestTypeSetPassword, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newsetpasswd", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendUploadVoiceRequest 发送语音 func SendUploadVoiceNewRequest(userInfo *baseinfo.UserInfo, ToWxId string, Startpos int, Databuff []byte, ClientImgId string, VoiceTime int32, Type int32, endFlag int) (*baseinfo.PackHeader, error) { var req = wechat.UploadVoiceRequest{ BaseRequest: GetBaseRequest(userInfo), FromUserName: proto.String(userInfo.WxId), ToUserName: proto.String(ToWxId), Offset: proto.Uint32(uint32(Startpos)), Length: proto.Uint32(uint32(len(Databuff))), ClientMsgId: proto.String(ClientImgId), MsgId: proto.Uint32(0), VoiceLength: proto.Int32(VoiceTime * 1000), VoiceFormat: proto.Int32(Type), Data: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(Databuff))), Buffer: Databuff, }, EndFlag: proto.Uint32(uint32(endFlag)), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeUploadVoiceNew, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadvoice", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendUploadVoiceRequest 发送语音 /*func SendUploadVoiceRequest(userInfo *baseinfo.UserInfo, toUserName string, data []byte, totalLen, startPos uint32, clientImgId string, voiceLen uint32, voiceFormat uint32) (*baseinfo.PackHeader, error) { endFlag := uint32(0) if startPos+uint32(len(data)) >= totalLen { endFlag = 1 } var req = wechat.UploadVoiceRequest{ BaseRequest: GetBaseRequest(userInfo), FromUserName: proto.String(userInfo.GetUserName()), ToUserName: proto.String(toUserName), ClientMsgId: proto.String(clientImgId), VoiceFormat: proto.Uint32(voiceFormat), VoiceLength: proto.Uint32(voiceLen), Length: proto.Uint32(uint32(len(data))), Data: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(data))), Buffer: data, }, Offset: proto.Uint32(startPos), EndFlag: proto.Uint32(endFlag), MsgId: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeUploadVoice, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadvoice", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) }*/ // SendNewInitSyncRequest 首次登录初始化 func SendNewInitSyncRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { mgr := userInfo.SyncKeyMgr() if mgr.CurKey() == nil { mgr.SetCurKey(&wechat.BufferT{ ILen: proto.Uint32(0), Buffer: make([]byte, 0), }) } if mgr.MaxKey() == nil { mgr.SetMaxKey(&wechat.BufferT{ ILen: proto.Uint32(0), Buffer: make([]byte, 0), }) } req := &wechat.NewInitRequest{} req.BaseRequest = GetBaseRequest(userInfo) //req.BaseRequest.Scene = proto.Uint32(0) req.UserName = proto.String(userInfo.GetUserName()) req.CurrentSynckey = mgr.CurKey() req.MaxSynckey = mgr.MaxKey() req.Language = proto.String("zh_CN") // 打包发送数据 srcData, _ := proto.Marshal(req) sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeNewInit, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/newinit", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 设置微信号 func SetWechatRequest(userInfo *baseinfo.UserInfo, alisa string) (*baseinfo.PackHeader, error) { var req = wechat.GeneralSetRequest{ BaseRequest: GetBaseRequest(userInfo), SetType: proto.Int32(1), SetValue: proto.String(alisa), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 177, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/generalset", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 获取设备 func GetBoundHardDeviceRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { var req = wechat.GetBoundHardDevicesRequest{ BaseRequest: GetBaseRequest(userInfo), Version: proto.Uint32(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 539, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getboundharddevices", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 获取步数列表 func SendGetUserRankLikeCountRequest(userInfo *baseinfo.UserInfo, rankId string) (*baseinfo.PackHeader, error) { var req = wechat.GetUserRankLikeCountRequest{ BaseRequest: GetBaseRequest(userInfo), Username: proto.String(userInfo.WxId), LatestRank: proto.Bool(true), RankId: proto.String(rankId), AppUsername: proto.String("wx7fa037cc7dfabad5"), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 1042, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmbiz-bin/rank/getuserranklike", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 上传步数 func UploadStepSetRequestRequest(userInfo *baseinfo.UserInfo, deviceID string, deviceType string, number uint64) (*baseinfo.PackHeader, error) { currentTime := time.Now() startTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, currentTime.Location()).Unix() endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location()).Unix() var req = wechat.UploadDeviceStepRequest{ BaseRequest: GetBaseRequest(userInfo), DeviceID: proto.String(deviceID), DeviceType: proto.String(deviceType), FromTime: proto.Uint32(uint32(startTime)), ToTime: proto.Uint32(uint32(endTime)), StepCount: proto.Uint32(uint32(number)), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 1261, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/mmoc-bin/hardware/uploaddevicestep", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 提取企业 wx 详情 func SendQWContactRequest(userInfo *baseinfo.UserInfo, openIm, chatRoom, t string) (*baseinfo.PackHeader, error) { req := wechat.GetQYContactRequest{} req.Wxid = proto.String(openIm) if chatRoom != "" { req.Room = proto.String(chatRoom) } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 881, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getopenimcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 提取全部的企业通寻录 func SendQWSyncContactRequest(userInfo *baseinfo.UserInfo) (*baseinfo.PackHeader, error) { ck := make([]*wechat.SyncKey_, 0) ck = append(ck, &wechat.SyncKey_{ SyncKey: proto.Int64(0), Type: proto.Uint32(400), }) key := wechat.SyncMsgKey{ Len: proto.Uint32(1), MsgKey: &wechat.SyncKey{ Size: proto.Uint32(1), Type: ck, }, } keyMar, _ := proto.Marshal(&key) var req = wechat.QYSyncRequest{ BaseRequest: GetBaseRequest(userInfo), Selector: proto.Int64(0x200000), Key: keyMar, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 810, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/openimsync", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 创建企业群 func SendQWCreateChatRoomRequest(userInfo *baseinfo.UserInfo, userList []string) (*baseinfo.PackHeader, error) { memberlist := make([]*wechat.Openimcontact, 0) for _, val := range userList { memberlist = append(memberlist, &wechat.Openimcontact{ UserName: proto.String(val), }) } var req = wechat.CreateQYChatRoomRequest{ MemberList: memberlist, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 371, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/createopenimchatroom", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 向企业微信打招呼 func SendQWApplyAddContactRequest(userInfo *baseinfo.UserInfo, toUserName, v1, Content string) (*baseinfo.PackHeader, error) { var req = wechat.QYVerifyUserRequest{ Wxid: proto.String(toUserName), V1: proto.String(v1), Content: proto.String(Content), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 0xF3, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/sendopenimverifyrequest", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 单向加企业微信 func SendQWAddContactRequest(userInfo *baseinfo.UserInfo, toUserName, v1, Content string) (*baseinfo.PackHeader, error) { var req = wechat.QYVAddUserRequest{ Wxid: proto.String(toUserName), V1: proto.String(v1), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 667, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/addopenimcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 提取所有企业群 func SendQWSyncChatRoomRequest(userInfo *baseinfo.UserInfo, key string) (*baseinfo.PackHeader, error) { ck := make([]*wechat.SyncKey_, 0) ck = append(ck, &wechat.SyncKey_{ SyncKey: proto.Int64(0), Type: proto.Uint32(0), }) keys := wechat.SyncMsgKey{ Len: proto.Uint32(1), MsgKey: &wechat.SyncKey{ Size: proto.Uint32(1), Type: ck, }, } keyMar, _ := proto.Marshal(&keys) var req = wechat.QYSyncRequest{ BaseRequest: GetBaseRequest(userInfo), Selector: proto.Int64(2097152), //0x200000 2097152 Key: keyMar, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 810, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/openimsync", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 转让企业微信群 func SendQWChatRoomTransferOwnerRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName string) (*baseinfo.PackHeader, error) { var req = wechat.QWTransferChatRoomOwnerRequest{ Username: proto.String(chatRoomName), Owner: &wechat.Openimcontact{ UserName: proto.String(toUserName), }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 811, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/modopenimchatroomowner", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 直接拉好友进群 func SendQWAddChatRoomMemberRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName []string) (*baseinfo.PackHeader, error) { list := make([]*wechat.Openimcontact, 0) for _, val := range toUserName { list = append(list, &wechat.Openimcontact{ UserName: proto.String(val), }) } var req = wechat.QYAddChatRoomRequest{ ChatRoomName: proto.String(chatRoomName), MemberList: list, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 0x32E, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/addopenimchatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 发送群邀请链接 func SendQWInviteChatRoomMemberRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName []string) (*baseinfo.PackHeader, error) { list := make([]*wechat.Openimcontact, 0) for _, val := range toUserName { list = append(list, &wechat.Openimcontact{ UserName: proto.String(val), }) } var req = wechat.InviteQYChatRoomRequest{ ChatRoomName: proto.String(chatRoomName), MemberList: list, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 887, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/inviteopenimchatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 删除企业群群成员 func SendQWDelChatRoomMemberRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName []string) (*baseinfo.PackHeader, error) { list := make([]*wechat.Openimcontact, 0) for _, val := range toUserName { list = append(list, &wechat.Openimcontact{ UserName: proto.String(val), }) } var req = wechat.QYDelChatRoomMemberRequest{ Username: proto.String(chatRoomName), MemberList: list, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 0x3AF, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delopenimchatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 提取企业群全部成员 func SendQWGetChatRoomMemberRequest(userInfo *baseinfo.UserInfo, chatRoomName string) (*baseinfo.PackHeader, error) { var req = wechat.GetQYChatroomMemberDetailRequest{ ChatroomUserName: proto.String(chatRoomName), ClientVersion: proto.Uint64(0), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 942, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getopenimchatroommemberdetail", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 提取企业群名称公告设定等信息 func SendQWGetChatroomInfoRequest(userInfo *baseinfo.UserInfo, chatRoomName string) (*baseinfo.PackHeader, error) { var req = wechat.Openimcontact{ UserName: proto.String(chatRoomName), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 407, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getopenimchatroomcontact", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 提取企业群二维码 func SendQWGetChatRoomQRRequest(userInfo *baseinfo.UserInfo, chatRoomName string) (*baseinfo.PackHeader, error) { var req = wechat.Openimcontact{ UserName: proto.String(chatRoomName), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 890, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getopenimchatroomqrcode", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 增加企业管理员 func SendQWAppointChatRoomAdminRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName []string) (*baseinfo.PackHeader, error) { var req = wechat.QYChatRoomAdminRequest{ ChatRoomName: proto.String(chatRoomName), MemberList: toUserName, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 776, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/addopenimchatroomadmin", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 移除企业群管理员 func SendQWDelChatRoomAdminRequest(userInfo *baseinfo.UserInfo, chatRoomName string, toUserName []string) (*baseinfo.PackHeader, error) { var req = wechat.QYChatRoomAdminRequest{ ChatRoomName: proto.String(chatRoomName), MemberList: toUserName, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 3677, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delopenimchatroomadmin", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 同意进企业群 func SendQWAcceptChatRoomRequest(userInfo *baseinfo.UserInfo, link string, opcode uint32) (*baseinfo.PackHeader, error) { var req = wechat.GetA8KeyRequest{} req.BaseRequest = GetBaseRequest(userInfo) req.CodeType = proto.Uint32(0) req.CodeVersion = proto.Uint32(8) req.Flag = proto.Uint32(0) req.FontScale = proto.Uint32(100) req.NetType = proto.String("WIFI") req.OpCode = proto.Uint32(opcode) req.UserName = proto.String(userInfo.WxId) req.ReqUrl = &wechat.SKBuiltinString{ Str: proto.String(link), } req.FriendQq = proto.Uint32(0) req.Scene = proto.Uint32(37) // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 233, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/geta8key", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 设定企业群管理审核进群 func SendQWAdminAcceptJoinChatRoomSetRequest(userInfo *baseinfo.UserInfo, link string, url string) (*baseinfo.PackHeader, error) { var req = wechat.QYChatRoomAdminRequest{} // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 3677, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/delopenimchatroomadmin", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 群管理批准进企业群 func SendQWAdminAcceptJoinChatRoomRequest(userInfo *baseinfo.UserInfo, chatRoomName, key, toUserName string, toUserNames []string) (*baseinfo.PackHeader, error) { list := make([]*wechat.Openimcontact, 0) for _, val := range toUserNames { list = append(list, &wechat.Openimcontact{ UserName: proto.String(val), }) } var req = wechat.QYAdminAddRequest{ Room: proto.String(chatRoomName), Key: proto.String(key), Username: &wechat.Openimcontact{ UserName: proto.String(toUserName), }, Usernamelist: list, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 0x3AD, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/approveaddopenimchatroommember", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 视频号搜索 func SendGetFinderSearchRequest(userInfo *baseinfo.UserInfo, Index uint32, Userver int32, UserKey string, Uuid string) (*baseinfo.PackHeader, error) { var req = wechat.FinderSearchRequest{ BaseRequest: GetBaseRequest(userInfo), UserKey: proto.String(UserKey), Offset: proto.Uint32(Index), Scene: proto.Uint32(0), Uuid: proto.String(Uuid), FinderTxRequest: &wechat.FinderTxRequest{ Userver: proto.Int32(Userver), }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 3820, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/findersearch", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 视频号个人中心 func SendFinderUserPrepareRequest(userInfo *baseinfo.UserInfo, Userver int32) (*baseinfo.PackHeader, error) { var req = wechat.FinderUserPrepareRequest{ BaseRequest: GetBaseRequest(userInfo), Scene: proto.Int32(0), FinderTxRequest: &wechat.FinderTxRequest{ Userver: proto.Int32(Userver), }, } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 3761, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/finderuserprepare", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 视频号关注or取消关注 func SendFinderFollowRequest(userInfo *baseinfo.UserInfo, FinderUserName string, OpType int32, RefObjectId string, Cook string, Userver int32, PosterUsername string) (*baseinfo.PackHeader, error) { //refId, err := strconv.ParseUint(RefObjectId, 10, 64) T := time.Now().Unix() var req = wechat.FinderFollowRequest{ FinderUsername: proto.String(FinderUserName), OpType: proto.Int32(OpType), RefObjectId: proto.Uint64(0), PosterUsername: proto.String(""), FinderReq: &wechat.FinderTxRequest{ Userver: proto.Int32(Userver), Scene: proto.Int32(6), T: proto.Int32(1), G: &wechat.FinderZd{ G1: proto.String(fmt.Sprintf("Finder_Enter%v", T)), G2: proto.String(fmt.Sprintf("4-%v", T)), G3: proto.String(fmt.Sprintf(`{"sessionId":"109_%v#$0_%v#"}`, T, T)), }, Tg: proto.Int64(time.Now().Unix()), }, Cook: proto.String(Cook), EnterType: proto.Int32(7), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 3867, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/finderfollow", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // 获取验证码 func SendWxBindOpMobileForRegRequest(userInfo *baseinfo.UserInfo, opcode int64, mobile, verifycode string) (*baseinfo.PackHeader, error) { tmpTime := int(time.Now().UnixNano() / 1000000000) tmpTimeStr := strconv.Itoa(tmpTime) var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr) var req = wechat.BindOpMobileForRegRequest{ BaseRequest: GetBaseRequest(userInfo), Mobile: proto.String(mobile), Opcode: proto.Int64(opcode), Verifycode: proto.String(verifycode), SafeDeviceName: proto.String("iPad"), SafeDeviceType: proto.String("iPad"), RandomEncryKey: &wechat.SKBuiltinString_{ Len: proto.Uint32(uint32(len(userInfo.SessionKey))), Buffer: userInfo.SessionKey, }, Language: proto.String("zh_CN"), InputMobileReTrYs: proto.Uint32(0), AdjustRet: proto.Uint32(0), ClientSeqID: proto.String(strClientSeqID), DialLang: proto.String(""), } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 145, 7) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/bindopmobileforreg", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendUploadAppAttach 上传文件 func SendUploadAppAttach(userInfo *baseinfo.UserInfo, fileData []byte) (*baseinfo.PackHeader, error) { Stream := bytes.NewBuffer(fileData) datalen := 50000 datatotalength := Stream.Len() FileMD5 := lib.GetFileMD5Hash(fileData) ClientAppDataId := fmt.Sprintf("%v_%v_UploadFile", userInfo.WxId, time.Now().Unix()) Startpos := 0 I := 0 var protobufdata []byte for { Startpos = I * datalen count := 0 if datatotalength-Startpos > datalen { count = datalen } else { count = datatotalength - Startpos } if count <= 0 { break } Databuff := make([]byte, count) _, _ = Stream.Read(Databuff) req := &wechat.UploadAppAttachRequest{ BaseRequest: GetBaseRequest(userInfo), AppId: proto.String(""), SdkVersion: proto.Uint32(0), ClientAppDataId: proto.String(ClientAppDataId), UserName: proto.String(userInfo.WxId), TotalLen: proto.Uint32(uint32(datatotalength)), StartPos: proto.Uint32(uint32(Startpos)), DataLen: proto.Uint32(uint32(len(Databuff))), Data: &wechat.SKBuiltinBufferT{ ILen: proto.Uint32(uint32(len(Databuff))), Buffer: Databuff, }, Type: proto.Uint32(6), Md5: proto.String(FileMD5), } // 序列化请求数据 reqdata, err := proto.Marshal(req) if err != nil { return nil, err } // 发送请求 sendEncodeData := Pack(userInfo, reqdata, 220, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadappattach", sendEncodeData) if err != nil { return nil, err } protobufdata = resp I++ } return DecodePackHeader(protobufdata, nil) } // SendScanQrcodeEventReportRequest 扫码事件上报 (CGI ID: 8887) // 模拟用户扫码行为 func SendScanQrcodeEventReportRequest(userInfo *baseinfo.UserInfo, loginUrl string) (*baseinfo.PackHeader, error) { baseReq := GetBaseRequest(userInfo) var req = wechat.ScanQrcodeEventReportRequest{ A: &wechat.ScanQrcodeBaseInfo{ A1: proto.String(""), A2: proto.Int32(int32(*baseReq.Uin)), A3: proto.String(string(baseReq.DeviceId)), A4: proto.Int32(int32(*baseReq.ClientVersion)), A5: proto.String(*baseReq.OsType), A6: proto.Int32(0), }, D: proto.Int32(19), // 事件类型 (字段2) E: proto.Int32(4), // Scene (字段3) F: proto.Int32(102462105), // 时间戳 (字段4) // 字段5不存在,跳过 H: proto.String(strings.Trim(strings.TrimSpace(loginUrl), " `\"'")), // 登录URL (字段6) I: proto.String(""), // 空字符串 (字段7) M: proto.Int32(0), // 标志 (字段8) N: []byte("0.964844"), // 版本号二进制 (字段9) O: proto.Int32(1), // 标志 (字段10) P: []byte("0.992188"), // 版本号二进制 (字段11) } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 8887, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/scan_qrcode_event_report_cgi", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } // SendExtDeviceLoginConfirmGetRequest 微信小店获取确认信息 (CGI ID: 971) func SendExtDeviceLoginConfirmGetRequest(userInfo *baseinfo.UserInfo, loginUrl string) (*baseinfo.PackHeader, error) { if userInfo == nil || len(userInfo.SessionKey) == 0 { return nil, fmt.Errorf("session 未初始化") } extra := load971Extra() // 替换时间戳为当前时间 extra = replaceTimestampIn971Extra(extra) srcData := build971Raw(loginUrl, extra) sendEncodeData := Pack(userInfo, srcData, 971, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/extdeviceloginconfirmget", sendEncodeData) if err != nil { return nil, err } return DecodePackHeader(resp, nil) } func encodeVarint(n int) []byte { b := make([]byte, 0, 10) u := uint64(n) for u >= 0x80 { b = append(b, byte(u)|0x80) u >>= 7 } b = append(b, byte(u)) return b } func build971Raw(url string, extra []byte) []byte { b := make([]byte, 0, len(url)+len(extra)+16) // Field 1: URL (string) b = append(b, 0x0a) // field 1, wire type 2 (length-delimited) b = append(b, encodeVarint(len(url))...) b = append(b, []byte(url)...) // Field 3: Extra data (nested message) if len(extra) > 0 { b = append(b, 0x1a) // field 3, wire type 2 (length-delimited) b = append(b, encodeVarint(len(extra))...) b = append(b, extra...) } return b } // load971Extra 从扫码.txt文件中提取field 3的嵌套消息数据 // 文件结构: field1(url) + field3(nested message) // 我们需要提取field3中的嵌套消息内容 func load971Extra() []byte { p := "protobuf/扫码.txt" d, err := ioutil.ReadFile(p) if err != nil { return nil } s := strings.TrimSpace(string(d)) s = strings.TrimPrefix(s, "0x") s = strings.ReplaceAll(s, " ", "") s = strings.ReplaceAll(s, "\n", "") raw, err := hex.DecodeString(s) if err != nil { return nil } // 解析protobuf结构 // 跳过field 1 (URL) if len(raw) < 3 || raw[0] != 0x0a { return nil } i := 1 // 读取URL长度 urlLen := 0 shift := 0 for { if i >= len(raw) { return nil } b := raw[i] i++ urlLen |= int(b&0x7f) << shift if b < 0x80 { break } shift += 7 } // 跳过URL内容 i += urlLen // 现在应该在field 3的位置 if i >= len(raw) || raw[i] != 0x1a { return nil } i++ // 跳过field tag // 读取field 3的长度 field3Len := 0 shift = 0 for { if i >= len(raw) { return nil } b := raw[i] i++ field3Len |= int(b&0x7f) << shift if b < 0x80 { break } shift += 7 } // 提取field 3的内容 if i+field3Len > len(raw) { return nil } return raw[i : i+field3Len] } // replaceTimestampIn971Extra 替换 field 3 中的时间戳为当前时间 // 已知时间戳: 1765334020 (2025-12-10 10:33:40),以 varint 编码存储 func replaceTimestampIn971Extra(data []byte) []byte { if data == nil || len(data) < 100 { return data } // 旧时间戳: 1765334020 -> varint: 84b8e3c906 (5字节) oldTimestamp := int64(1765334020) oldVarint := encodeVarint64(oldTimestamp) // 新时间戳: 当前时间 newTimestamp := time.Now().Unix() newVarint := encodeVarint64(newTimestamp) // 在 data 中搜索并替换旧时间戳 result := make([]byte, len(data)) copy(result, data) // 搜索旧时间戳的位置 for i := 0; i <= len(result)-len(oldVarint); i++ { match := true for j := 0; j < len(oldVarint); j++ { if result[i+j] != oldVarint[j] { match = false break } } if match { // 找到了,替换 if len(newVarint) == len(oldVarint) { // 长度相同,直接替换 copy(result[i:], newVarint) } else { // 长度不同,需要重新构建整个数组 newResult := make([]byte, 0, len(data)-len(oldVarint)+len(newVarint)) newResult = append(newResult, result[:i]...) newResult = append(newResult, newVarint...) newResult = append(newResult, result[i+len(oldVarint):]...) return newResult } break } } return result } func encodeVarint64(n int64) []byte { b := make([]byte, 0, 10) u := uint64(n) for u >= 0x80 { b = append(b, byte(u)|0x80) u >>= 7 } b = append(b, byte(u)) return b } // SendExtDeviceLoginConfirmOkRequest 微信小店确认登录 (CGI ID: 972) func SendExtDeviceLoginConfirmOkRequest(userInfo *baseinfo.UserInfo, loginUrl string) (*baseinfo.PackHeader, error) { // 自动拼接deviceId: wxid,newsapp,wxid,weixin wxid := userInfo.GetUserName() deviceId := fmt.Sprintf("%s,newsapp,%s,weixin", wxid, wxid) fmt.Println(deviceId) var req = wechat.ExtDeviceLoginConfirmOkRequest{ D: proto.String(strings.Trim(strings.TrimSpace(strings.Replace(loginUrl, "https", "http", -1)), " `\"'")), E: proto.String(deviceId), // 字段2: 设备ID H: proto.Int32(0), // 字段4 J: proto.Int32(0), // 字段5 M: proto.Int32(0), // 字段7 } // 打包发送数据 srcData, _ := proto.Marshal(&req) sendEncodeData := Pack(userInfo, srcData, 972, 5) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/extdeviceloginconfirmok", sendEncodeData) if err != nil { return nil, err } if len(resp) <= 32 { return nil, fmt.Errorf("请求被拒绝: %d", len(resp)) } return DecodePackHeader(resp, nil) }