897 lines
28 KiB
Go
897 lines
28 KiB
Go
|
|
package clientsdk
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"encoding/hex"
|
|||
|
|
"errors"
|
|||
|
|
"fmt"
|
|||
|
|
"hash/crc32"
|
|||
|
|
"net/url"
|
|||
|
|
"strconv"
|
|||
|
|
"strings"
|
|||
|
|
"time"
|
|||
|
|
"xiawan/wx/clientsdk/android"
|
|||
|
|
"xiawan/wx/clientsdk/android/mmproto"
|
|||
|
|
"xiawan/wx/clientsdk/baseinfo"
|
|||
|
|
"xiawan/wx/clientsdk/baseutils"
|
|||
|
|
"xiawan/wx/clientsdk/extinfo"
|
|||
|
|
"xiawan/wx/protobuf/wechat"
|
|||
|
|
|
|||
|
|
"github.com/golang/protobuf/proto"
|
|||
|
|
"github.com/micro/go-micro/util/log"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// GetClientCheckData 获取ClientCheckData
|
|||
|
|
// func GetClientCheckData(userInfo *baseinfo.UserInfo) []byte {
|
|||
|
|
// retData, err := ccdata.CreateClientCheckData(userInfo.DeviceInfo.ClientCheckDataXML)
|
|||
|
|
// if err != nil {
|
|||
|
|
// log.Info(err)
|
|||
|
|
// return retData
|
|||
|
|
// }
|
|||
|
|
// // DeviceRunningInfo
|
|||
|
|
// deviceRuntimInfo := &wechat.DeviceRunningInfo{}
|
|||
|
|
// mode := uint32(1)
|
|||
|
|
// deviceRuntimInfo.Mode = &mode
|
|||
|
|
// deviceRuntimInfo.Type = []byte("00000003")
|
|||
|
|
// deviceRuntimInfo.Data = retData
|
|||
|
|
|
|||
|
|
// // 序列化
|
|||
|
|
// finalData, err := proto.Marshal(deviceRuntimInfo)
|
|||
|
|
// if err != nil {
|
|||
|
|
// log.Info(err)
|
|||
|
|
// }
|
|||
|
|
// return finalData
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// GetExtSpamInfoData 获取ExtSpamInfo
|
|||
|
|
// func GetExtSpamInfoData(userInfo *baseinfo.UserInfo) []byte {
|
|||
|
|
// ccdata := GetClientCheckData(userInfo)
|
|||
|
|
|
|||
|
|
// // WCExtInfoLod
|
|||
|
|
// extInfo := &wechat.WCExtInfo{}
|
|||
|
|
// // ccDataBuffer
|
|||
|
|
// var ccDataBuffer wechat.SKBuiltinString_
|
|||
|
|
// tmpLen := uint32(len(ccdata))
|
|||
|
|
// ccDataBuffer.Len = &tmpLen
|
|||
|
|
// ccDataBuffer.Buffer = ccdata
|
|||
|
|
// extInfo.CcData = &ccDataBuffer
|
|||
|
|
|
|||
|
|
// // 序列化
|
|||
|
|
// retData, err := proto.Marshal(extInfo)
|
|||
|
|
// if err != nil {
|
|||
|
|
// log.Info(err)
|
|||
|
|
// }
|
|||
|
|
// return retData
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
func GetExtPBSpamInfoDataA16(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
|
|||
|
|
wxId_ := ""
|
|||
|
|
if len(wxId) == 0 {
|
|||
|
|
wxId_ = userInfo.GetUserName()
|
|||
|
|
} else {
|
|||
|
|
wxId_ = wxId[0]
|
|||
|
|
}
|
|||
|
|
ccd1 := GetCCD1(wxId_)
|
|||
|
|
ccd1PB, _ := proto.Marshal(ccd1)
|
|||
|
|
ccd2 := GetCCD2()
|
|||
|
|
ccd2PB, _ := proto.Marshal(ccd2)
|
|||
|
|
ccd3 := GetCCD3(*userInfo.DeviceInfoA16)
|
|||
|
|
ccd3PB, _ := proto.Marshal(ccd3)
|
|||
|
|
|
|||
|
|
devicetoken := GetDeviceToken(userInfo.DeviceInfoA16.DeviceIdStr)
|
|||
|
|
dtPB, _ := proto.Marshal(devicetoken)
|
|||
|
|
spamdatabody := &mmproto.SpamDataBody{
|
|||
|
|
Ccd1: &mmproto.SpamDataSubBody{
|
|||
|
|
Ilen: proto.Uint32(uint32(len(ccd1PB))),
|
|||
|
|
Ztdata: ccd1,
|
|||
|
|
},
|
|||
|
|
Ccd2: &mmproto.SpamDataSubBody{
|
|||
|
|
Ilen: proto.Uint32(uint32(len(ccd2PB))),
|
|||
|
|
Ztdata: ccd2,
|
|||
|
|
},
|
|||
|
|
Ccd3: &mmproto.SpamDataSubBody{
|
|||
|
|
Ilen: proto.Uint32(uint32(len(ccd3PB))),
|
|||
|
|
Ztdata: ccd3,
|
|||
|
|
},
|
|||
|
|
Dt: &mmproto.DeviceTokenBody{
|
|||
|
|
Ilen: proto.Uint32(uint32(len(dtPB))),
|
|||
|
|
DeviceToken: devicetoken,
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
retData, err := proto.Marshal(spamdatabody)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info(err)
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetCCD1(UserName string) *mmproto.ZTData {
|
|||
|
|
return android.AndroidWcstf(UserName)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetCCD2() *mmproto.ZTData {
|
|||
|
|
// return android.AndroidWcste(384214787666497617, 384002236977512448)
|
|||
|
|
return android.AndroidWcste(0, 0)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 算法
|
|||
|
|
func GetCCD3(accoutInfo baseinfo.AndroidDeviceInfo) *mmproto.ZTData {
|
|||
|
|
|
|||
|
|
curtime := uint32(time.Now().Unix())
|
|||
|
|
|
|||
|
|
ccd3body := &mmproto.Ccd3Body{
|
|||
|
|
KernelReleaseNumber: proto.String(accoutInfo.KernelReleaseNumber),
|
|||
|
|
UsbState: proto.Uint32(0),
|
|||
|
|
Sign: proto.String(accoutInfo.PackageSign),
|
|||
|
|
PackageFlag: proto.Uint32(14),
|
|||
|
|
AccessFlag: proto.Uint32(364604),
|
|||
|
|
Unkonwn: proto.Uint32(3),
|
|||
|
|
TbVersionCrc: proto.Uint32(553983350),
|
|||
|
|
SfMD5: proto.String("d001b450158a85142c953011c66d531d"),
|
|||
|
|
SfArmMD5: proto.String("bf7f84d081f1dffd587803c233d4e235"),
|
|||
|
|
SfArm64MD5: proto.String("85801b3939f277ad31c9f89edd9dd008"),
|
|||
|
|
SbMD5: proto.String("683e7beb7a44017ca2e686e3acedfb9f"),
|
|||
|
|
SoterId2: proto.String(""),
|
|||
|
|
TimeCheck: proto.Uint32(0),
|
|||
|
|
NanoTime: proto.Uint32(455583),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pb, _ := proto.Marshal(ccd3body)
|
|||
|
|
|
|||
|
|
crc := crc32.ChecksumIEEE(pb)
|
|||
|
|
|
|||
|
|
ccd3 := &mmproto.Ccd3{
|
|||
|
|
Crc: &crc,
|
|||
|
|
TimeStamp: &curtime,
|
|||
|
|
Body: nil,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pb, _ = proto.Marshal(ccd3)
|
|||
|
|
|
|||
|
|
// var b bytes.Buffer
|
|||
|
|
// w := zlib.NewWriter(&b)
|
|||
|
|
// w.Write(pb)
|
|||
|
|
// w.Close()
|
|||
|
|
|
|||
|
|
// zt := new(android.ZT)
|
|||
|
|
// zt.Init()
|
|||
|
|
// encData := zt.Encrypt(b.Bytes())
|
|||
|
|
compressData := android.DoZlibCompress(pb)
|
|||
|
|
encData := android.SaeEncrypt07(compressData)
|
|||
|
|
|
|||
|
|
Ztdata := &mmproto.ZTData{
|
|||
|
|
Version: proto.String("00000007\x00"),
|
|||
|
|
Encrypted: proto.Uint32(1),
|
|||
|
|
Data: encData,
|
|||
|
|
TimeStamp: &curtime,
|
|||
|
|
Optype: proto.Uint32(5),
|
|||
|
|
Uin: proto.Uint32(0),
|
|||
|
|
}
|
|||
|
|
// MS, _ := proto.Marshal(Ztdata)
|
|||
|
|
// return MS
|
|||
|
|
return Ztdata
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetDeviceToken(devicetoken string) *mmproto.DeviceToken {
|
|||
|
|
curtime := uint32(time.Now().Unix())
|
|||
|
|
return &mmproto.DeviceToken{
|
|||
|
|
Version: proto.String(""),
|
|||
|
|
Encrypted: proto.Uint32(1),
|
|||
|
|
Data: &mmproto.SKBuiltinStringt{
|
|||
|
|
String_: &devicetoken,
|
|||
|
|
},
|
|||
|
|
TimeStamp: &curtime,
|
|||
|
|
Optype: proto.Uint32(2),
|
|||
|
|
Uin: proto.Uint32(0),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetExtPBSpamInfoDataIpad(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
|
|||
|
|
wxId_ := ""
|
|||
|
|
if len(wxId) == 0 {
|
|||
|
|
wxId_ = userInfo.GetUserName()
|
|||
|
|
} else {
|
|||
|
|
wxId_ = wxId[0]
|
|||
|
|
}
|
|||
|
|
retData, err := extinfo.GetCCDPbLib(
|
|||
|
|
userInfo.DeviceInfo.OsTypeNumber,
|
|||
|
|
userInfo.DeviceInfo.OsType,
|
|||
|
|
userInfo.DeviceInfo.UUIDTwo,
|
|||
|
|
userInfo.DeviceInfo.UUIDTwo,
|
|||
|
|
userInfo.DeviceInfo.DeviceName,
|
|||
|
|
userInfo.DeviceInfo.DeviceToken,
|
|||
|
|
hex.EncodeToString(userInfo.DeviceInfo.DeviceID),
|
|||
|
|
wxId_,
|
|||
|
|
userInfo.DeviceInfo.GUID2,
|
|||
|
|
)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info(err)
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetExtPBSpamInfoDataLogin(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
|
|||
|
|
wxId_ := ""
|
|||
|
|
if len(wxId) == 0 {
|
|||
|
|
wxId_ = userInfo.GetUserName()
|
|||
|
|
} else {
|
|||
|
|
wxId_ = wxId[0]
|
|||
|
|
}
|
|||
|
|
retData, err := extinfo.GetCCDPbLibLogin(
|
|||
|
|
userInfo.DeviceInfo.OsTypeNumber,
|
|||
|
|
userInfo.DeviceInfo.OsType,
|
|||
|
|
userInfo.DeviceInfo.UUIDTwo,
|
|||
|
|
userInfo.DeviceInfo.UUIDTwo,
|
|||
|
|
userInfo.DeviceInfo.DeviceName,
|
|||
|
|
userInfo.DeviceInfo.DeviceToken,
|
|||
|
|
hex.EncodeToString(userInfo.DeviceInfo.DeviceID),
|
|||
|
|
wxId_,
|
|||
|
|
userInfo.DeviceInfo.GUID2,
|
|||
|
|
)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info(err)
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetExtPBSpamInfoDataIPhone(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
|
|||
|
|
wxId_ := ""
|
|||
|
|
if len(wxId) == 0 {
|
|||
|
|
wxId_ = userInfo.GetUserName()
|
|||
|
|
} else {
|
|||
|
|
wxId_ = wxId[0]
|
|||
|
|
}
|
|||
|
|
retData, err := extinfo.GetCCDPbLibIPhone(
|
|||
|
|
userInfo.DeviceInfo.OsTypeNumber,
|
|||
|
|
userInfo.DeviceInfo.OsType,
|
|||
|
|
userInfo.DeviceInfo.UUIDTwo,
|
|||
|
|
userInfo.DeviceInfo.UUIDTwo,
|
|||
|
|
userInfo.DeviceInfo.DeviceName,
|
|||
|
|
userInfo.DeviceInfo.DeviceToken,
|
|||
|
|
hex.EncodeToString(userInfo.DeviceInfo.DeviceID),
|
|||
|
|
wxId_,
|
|||
|
|
userInfo.DeviceInfo.GUID2,
|
|||
|
|
)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info(err)
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetAutoAuthRsaReqDataMarshal 生成自动登陆rsareq项
|
|||
|
|
func GetAutoAuthRsaReqDataMarshal(userInfo *baseinfo.UserInfo) []byte {
|
|||
|
|
var rsaReqData wechat.AutoAuthRsaReqData
|
|||
|
|
|
|||
|
|
// AesEncyptKey
|
|||
|
|
var aesEncryptKey wechat.SKBuiltinString_
|
|||
|
|
aesEncryptKey.Buffer = []byte(userInfo.SessionKey)
|
|||
|
|
var aesKeyLen = uint32(len(userInfo.SessionKey))
|
|||
|
|
aesEncryptKey.Len = &aesKeyLen
|
|||
|
|
rsaReqData.AesEncryptKey = &aesEncryptKey
|
|||
|
|
|
|||
|
|
// ecdh
|
|||
|
|
var ecdhKey wechat.ECDHKey
|
|||
|
|
var tmpNid = uint32(713)
|
|||
|
|
ecdhKey.Nid = &tmpNid
|
|||
|
|
// ecdhKey
|
|||
|
|
var ecdhKeyBuffer wechat.SKBuiltinString_
|
|||
|
|
var ecdhKeyLen = uint32(len(userInfo.EcPublicKey))
|
|||
|
|
ecdhKeyBuffer.Len = &ecdhKeyLen
|
|||
|
|
ecdhKeyBuffer.Buffer = userInfo.EcPublicKey
|
|||
|
|
ecdhKey.Key = &ecdhKeyBuffer
|
|||
|
|
rsaReqData.PubEcdhKey = &ecdhKey
|
|||
|
|
|
|||
|
|
retData, err := proto.Marshal(&rsaReqData)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info("proto.Marshal AutoAuthRsaReqData failed: ", err)
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetAutoAuthAesReqDataMarshal 生成自动登陆aesreq项
|
|||
|
|
func GetAutoAuthAesReqDataMarshal(userInfo *baseinfo.UserInfo) []byte {
|
|||
|
|
var zeroUint32 = uint32(0)
|
|||
|
|
var emptyString = string("")
|
|||
|
|
var aesReqData wechat.AutoAuthAesReqData
|
|||
|
|
baseReq := GetBaseRequest(userInfo)
|
|||
|
|
var tmpScene uint32 = 2
|
|||
|
|
baseReq.Scene = &tmpScene
|
|||
|
|
baseReq.SessionKey = []byte{}
|
|||
|
|
aesReqData.BaseRequest = baseReq
|
|||
|
|
|
|||
|
|
// autoauthkey
|
|||
|
|
tmpAuthKeyLen := uint32(len(userInfo.AutoAuthKey))
|
|||
|
|
var tmpAutoAuthKey wechat.SKBuiltinString_
|
|||
|
|
tmpAutoAuthKey.Buffer = userInfo.AutoAuthKey
|
|||
|
|
tmpAutoAuthKey.Len = &tmpAuthKeyLen
|
|||
|
|
aesReqData.AutoAuthKey = &tmpAutoAuthKey
|
|||
|
|
|
|||
|
|
// BaseAuthReqInfo
|
|||
|
|
var baseReqInfo wechat.BaseAuthReqInfo
|
|||
|
|
baseReqInfo.AuthReqFlag = &zeroUint32
|
|||
|
|
baseReqInfo.AuthTicket = &emptyString
|
|||
|
|
aesReqData.BaseReqInfo = &baseReqInfo
|
|||
|
|
|
|||
|
|
if userInfo.DeviceInfo == nil {
|
|||
|
|
//return GetManualAuthAesReqDataA16Protobuf(userInfo)
|
|||
|
|
aesReqData.Imei = proto.String(userInfo.DeviceInfoA16.AndriodImei(userInfo.DeviceInfoA16.DeviceIdStr))
|
|||
|
|
aesReqData.SoftType = proto.String(userInfo.DeviceInfoA16.AndriodGetSoftType(userInfo.DeviceInfoA16.DeviceIdStr))
|
|||
|
|
aesReqData.ClientSeqId = proto.String(fmt.Sprintf("%s_%d", userInfo.DeviceInfoA16.DeviceIdStr, (time.Now().UnixNano() / 1e6)))
|
|||
|
|
aesReqData.DeviceName = proto.String(userInfo.DeviceInfoA16.AndroidManufacturer(userInfo.DeviceInfoA16.DeviceIdStr) + "-" + userInfo.DeviceInfoA16.AndroidPhoneModel(userInfo.DeviceInfoA16.DeviceIdStr))
|
|||
|
|
aesReqData.Language = proto.String("Zh")
|
|||
|
|
aesReqData.TimeZone = proto.String("8.0")
|
|||
|
|
aesReqData.Channel = &zeroUint32
|
|||
|
|
// TimeStamp
|
|||
|
|
aesReqData.Signature = proto.String(userInfo.DeviceInfoA16.AndriodPackageSign(userInfo.DeviceInfoA16.DeviceIdStr))
|
|||
|
|
aesReqData.BuiltinIpSeq = &zeroUint32
|
|||
|
|
ext, err := GetExtSpamInfoAndroid(userInfo)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("Android extSpam err", err.Error())
|
|||
|
|
}
|
|||
|
|
// extSpamInfo
|
|||
|
|
var extSpamInfo wechat.SKBuiltinString_
|
|||
|
|
extSpamInfo.Buffer = ext
|
|||
|
|
extSpamInfoLen := uint32(len(extSpamInfo.Buffer))
|
|||
|
|
extSpamInfo.Len = &extSpamInfoLen
|
|||
|
|
aesReqData.ExtSpamInfo = &extSpamInfo
|
|||
|
|
reqData, _ := proto.Marshal(&aesReqData)
|
|||
|
|
return reqData
|
|||
|
|
} else {
|
|||
|
|
// imei
|
|||
|
|
aesReqData.Imei = &userInfo.DeviceInfo.Imei
|
|||
|
|
aesReqData.TimeZone = &userInfo.DeviceInfo.TimeZone
|
|||
|
|
aesReqData.DeviceName = &userInfo.DeviceInfo.DeviceName
|
|||
|
|
aesReqData.Language = &userInfo.DeviceInfo.Language
|
|||
|
|
aesReqData.BuiltinIpSeq = &zeroUint32
|
|||
|
|
aesReqData.Signature = &emptyString
|
|||
|
|
aesReqData.SoftType = &userInfo.DeviceInfo.SoftTypeXML
|
|||
|
|
|
|||
|
|
tmpTime := int(time.Now().UnixNano() / 1000000000)
|
|||
|
|
tmpTimeStr := strconv.Itoa(tmpTime)
|
|||
|
|
var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr)
|
|||
|
|
aesReqData.ClientSeqId = &strClientSeqID
|
|||
|
|
aesReqData.Channel = &zeroUint32
|
|||
|
|
|
|||
|
|
// extSpamInfo
|
|||
|
|
var extSpamInfo wechat.SKBuiltinString_
|
|||
|
|
extSpamInfo.Buffer = GetExtPBSpamInfoDataLogin(userInfo)
|
|||
|
|
extSpamInfoLen := uint32(len(extSpamInfo.Buffer))
|
|||
|
|
extSpamInfo.Len = &extSpamInfoLen
|
|||
|
|
aesReqData.ExtSpamInfo = &extSpamInfo
|
|||
|
|
|
|||
|
|
retData, err := proto.Marshal(&aesReqData)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info("proto.Marshal AutoAuthAesReqData failed: ", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetManualAuthAesReqDataMarshal 生成自动登陆aesreq项
|
|||
|
|
func GetManualAuthAesReqDataMarshal(userInfo *baseinfo.UserInfo) []byte {
|
|||
|
|
zeroUint32 := uint32(0)
|
|||
|
|
zeroInt32 := int32(0)
|
|||
|
|
emptyString := string("")
|
|||
|
|
|
|||
|
|
var aesRequest wechat.ManualAuthAesReqData
|
|||
|
|
// BaseRequest
|
|||
|
|
baseReq := GetBaseRequest(userInfo)
|
|||
|
|
var tmpScene uint32 = 1
|
|||
|
|
baseReq.Scene = &tmpScene
|
|||
|
|
baseReq.SessionKey = []byte{}
|
|||
|
|
aesRequest.BaseRequest = baseReq
|
|||
|
|
|
|||
|
|
// imei
|
|||
|
|
aesRequest.Imei = &userInfo.DeviceInfo.Imei
|
|||
|
|
aesRequest.TimeZone = &userInfo.DeviceInfo.TimeZone
|
|||
|
|
aesRequest.DeviceName = &userInfo.DeviceInfo.DeviceName
|
|||
|
|
aesRequest.DeviceType = &userInfo.DeviceInfo.DeviceName
|
|||
|
|
aesRequest.Channel = &zeroInt32
|
|||
|
|
aesRequest.Language = &userInfo.DeviceInfo.Language
|
|||
|
|
aesRequest.BuiltinIpseq = &zeroUint32
|
|||
|
|
aesRequest.Signature = &emptyString
|
|||
|
|
aesRequest.SoftType = &userInfo.DeviceInfo.SoftTypeXML
|
|||
|
|
aesRequest.DeviceBrand = &userInfo.DeviceInfo.DeviceBrand
|
|||
|
|
aesRequest.RealCountry = &userInfo.DeviceInfo.RealCountry
|
|||
|
|
aesRequest.BundleId = &userInfo.DeviceInfo.BundleID
|
|||
|
|
aesRequest.AdSource = &userInfo.DeviceInfo.AdSource
|
|||
|
|
inputType := uint32(2)
|
|||
|
|
aesRequest.InputType = &inputType
|
|||
|
|
|
|||
|
|
// ClientSeqId
|
|||
|
|
tmpTime := int(time.Now().UnixNano() / 1000000000)
|
|||
|
|
tmpTimeStr := strconv.Itoa(tmpTime)
|
|||
|
|
var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr)
|
|||
|
|
aesRequest.ClientSeqId = &strClientSeqID
|
|||
|
|
|
|||
|
|
// TimeStamp
|
|||
|
|
tmpTime2 := uint32(time.Now().UnixNano() / 1000000000)
|
|||
|
|
aesRequest.TimeStamp = &tmpTime2
|
|||
|
|
|
|||
|
|
// extSpamInfo
|
|||
|
|
var extSpamInfo wechat.SKBuiltinString_
|
|||
|
|
extSpamInfo.Buffer = GetExtPBSpamInfoDataLogin(userInfo)
|
|||
|
|
extSpamInfoLen := uint32(len(extSpamInfo.Buffer))
|
|||
|
|
extSpamInfo.Len = &extSpamInfoLen
|
|||
|
|
aesRequest.ExtSpamInfo = &extSpamInfo
|
|||
|
|
|
|||
|
|
retData, err := proto.Marshal(&aesRequest)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Info("proto.Marshal AutoAuthAesReqData failed: ", err)
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ParseHongBaoURL 解析红包URL
|
|||
|
|
func ParseHongBaoURL(hongBaoURL string, senderUserName string) (*baseinfo.HongBaoURLItem, error) {
|
|||
|
|
// 捕获错误返回 nil
|
|||
|
|
if len(hongBaoURL) == 0 {
|
|||
|
|
return nil, errors.New("ParseHongBaoURL hongbao url is empty")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retURL, err := url.Parse(hongBaoURL)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retMaps, err := url.ParseQuery(retURL.RawQuery)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//retMaps 下面可能不存在 数据,所以需要判断
|
|||
|
|
if len(retMaps["msgtype"]) == 0 || len(retMaps["channelid"]) == 0 || len(retMaps["sendid"]) == 0 || len(retMaps["ver"]) == 0 || len(retMaps["sign"]) == 0 {
|
|||
|
|
return nil, errors.New("ParseHongBaoURL hongbao url is invalid")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retItem := &baseinfo.HongBaoURLItem{}
|
|||
|
|
retItem.MsgType = retMaps["msgtype"][0]
|
|||
|
|
retItem.ChannelID = retMaps["channelid"][0]
|
|||
|
|
retItem.SendID = retMaps["sendid"][0]
|
|||
|
|
retItem.Ver = retMaps["ver"][0]
|
|||
|
|
retItem.Sign = retMaps["sign"][0]
|
|||
|
|
retItem.SendUserName = senderUserName
|
|||
|
|
return retItem, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateMediaItemXML 将mediaItem转换成XML
|
|||
|
|
func CreateMediaItemXML(mediaItem *baseinfo.SnsMediaItem) string {
|
|||
|
|
retString := string("<media>")
|
|||
|
|
if mediaItem.EncKey != "" {
|
|||
|
|
retString = retString + "<enc key=\"" + mediaItem.EncKey + "\">" + strconv.Itoa(int(mediaItem.EncValue)) + "</enc>"
|
|||
|
|
}
|
|||
|
|
retString = retString + "<id>" + strconv.Itoa(int(mediaItem.ID)) + "</id>"
|
|||
|
|
retString = retString + "<type>" + strconv.Itoa(int(mediaItem.Type)) + "</type>"
|
|||
|
|
|
|||
|
|
// title
|
|||
|
|
titleString := "<title/>"
|
|||
|
|
if len(mediaItem.Title) > 0 {
|
|||
|
|
titleString = "<title>" + mediaItem.Title + "</title>"
|
|||
|
|
}
|
|||
|
|
retString = retString + titleString
|
|||
|
|
|
|||
|
|
// description
|
|||
|
|
descriptionString := "<description/>"
|
|||
|
|
if len(mediaItem.Description) > 0 {
|
|||
|
|
descriptionString = "<description>" + mediaItem.Description + "</description>"
|
|||
|
|
}
|
|||
|
|
retString = retString + descriptionString
|
|||
|
|
|
|||
|
|
// private
|
|||
|
|
retString = retString + "<private>" + strconv.Itoa(int(mediaItem.Private)) + "</private>"
|
|||
|
|
|
|||
|
|
// userData
|
|||
|
|
userDataString := "<userData/>"
|
|||
|
|
if len(mediaItem.UserData) > 0 {
|
|||
|
|
userDataString = "<userData>" + mediaItem.UserData + "</userData>"
|
|||
|
|
}
|
|||
|
|
retString = retString + userDataString
|
|||
|
|
|
|||
|
|
// subType
|
|||
|
|
retString = retString + "<subType>" + strconv.Itoa(int(mediaItem.SubType)) + "</subType>"
|
|||
|
|
|
|||
|
|
// videoSize
|
|||
|
|
retString = retString + "<videoSize width=\"" + mediaItem.VideoWidth + "\" height=\"" + mediaItem.VideoHeight + "\"/>"
|
|||
|
|
|
|||
|
|
// url
|
|||
|
|
retString = retString + "<url type=\"" + mediaItem.URLType + "\" md5=\"" + mediaItem.MD5 + "\" videomd5=\"" + mediaItem.VideoMD5 + "\">"
|
|||
|
|
retString = retString + mediaItem.URL + "</url>"
|
|||
|
|
|
|||
|
|
// thumb
|
|||
|
|
retString = retString + "<thumb type=\"" + mediaItem.ThumType + "\">"
|
|||
|
|
retString = retString + mediaItem.Thumb + "</thumb>"
|
|||
|
|
|
|||
|
|
// size
|
|||
|
|
retString = retString + "<size width=\"" + mediaItem.SizeWidth + "\" height=\"" + mediaItem.SizeHeight + "\" totalSize=\"" + mediaItem.TotalSize + "\"/>"
|
|||
|
|
|
|||
|
|
// videoDuration 如果是视频
|
|||
|
|
if mediaItem.Type == baseinfo.MMSNSMediaTypeVideo {
|
|||
|
|
// 格式化
|
|||
|
|
tmpValue := strconv.FormatFloat(mediaItem.VideoDuration, 'f', 6, 64)
|
|||
|
|
retString = retString + "<videoDuration>" + tmpValue + "</videoDuration>"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retString = retString + "</media>"
|
|||
|
|
return retString
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSnsPostItemXML 转成xml字符串,字节数组
|
|||
|
|
func CreateSnsPostItemXML(userName string, postItem *baseinfo.SnsPostItem) []byte {
|
|||
|
|
// createTime
|
|||
|
|
tmpTime := int(time.Now().UnixNano() / 1000000000)
|
|||
|
|
tmpTimeStr := strconv.Itoa(tmpTime)
|
|||
|
|
|
|||
|
|
// start
|
|||
|
|
retString := string("<TimelineObject>")
|
|||
|
|
retString = retString + "<id><![CDATA[0]]></id>"
|
|||
|
|
retString = retString + "<username><![CDATA[" + userName + "]]></username>"
|
|||
|
|
retString = retString + "<createTime><![CDATA[" + tmpTimeStr + "]]></createTime>"
|
|||
|
|
retString = retString + "<contentDesc><![CDATA[" + postItem.Content + "]]></contentDesc>"
|
|||
|
|
retString = retString + "<contentDescShowType><![CDATA[0]]></contentDescShowType>"
|
|||
|
|
retString = retString + "<contentDescScene><![CDATA[" + strconv.Itoa(0) + "]]></contentDescScene>"
|
|||
|
|
retString = retString + "<private>" + strconv.Itoa(int(postItem.Privacy)) + "</private>"
|
|||
|
|
retString = retString + "<sightFolded>" + strconv.Itoa(0) + "</sightFolded>"
|
|||
|
|
retString = retString + "<showFlag>" + strconv.Itoa(0) + "</showFlag>"
|
|||
|
|
// location
|
|||
|
|
|
|||
|
|
// appInfo
|
|||
|
|
retString = retString + "<appInfo>"
|
|||
|
|
retString = retString + "<id/>"
|
|||
|
|
retString = retString + "<version/>"
|
|||
|
|
retString = retString + "<appName/>"
|
|||
|
|
retString = retString + "<installUrl/>"
|
|||
|
|
retString = retString + "<fromUrl/>"
|
|||
|
|
retString = retString + "<isForceUpdate>" + strconv.Itoa(0) + "</isForceUpdate>"
|
|||
|
|
retString = retString + "</appInfo>"
|
|||
|
|
|
|||
|
|
retString = retString + "<sourceUserName/>"
|
|||
|
|
retString = retString + "<sourceNickName/>"
|
|||
|
|
retString = retString + "<statisticsData/>"
|
|||
|
|
retString = retString + "<statExtStr/>"
|
|||
|
|
// ContentObject
|
|||
|
|
/*retString = retString + "<ContentObject>"
|
|||
|
|
retString = retString + "<contentStyle>" + strconv.Itoa(int(postItem.ContentStyle)) + "</contentStyle>"
|
|||
|
|
retString = retString + "<title>


习近平<title/>"
|
|||
|
|
retString = retString + "<description/>"*/
|
|||
|
|
|
|||
|
|
// location
|
|||
|
|
if postItem.LocationInfo != nil {
|
|||
|
|
// float, int 转成string
|
|||
|
|
longitudeStr := postItem.LocationInfo.Longitude
|
|||
|
|
latitudeStr := postItem.LocationInfo.Latitude
|
|||
|
|
poiScaleStr := strconv.Itoa(int(postItem.LocationInfo.PoiScale))
|
|||
|
|
poiClassfyTypeStr := strconv.Itoa(int(postItem.LocationInfo.PoiClassifyType))
|
|||
|
|
poiClickableStatusStr := strconv.Itoa(int(postItem.LocationInfo.PoiClickableStatus))
|
|||
|
|
// 增加 LocationXml
|
|||
|
|
retString = retString + "<location "
|
|||
|
|
retString = retString + "city = \"" + postItem.LocationInfo.City + "\" "
|
|||
|
|
retString = retString + "longitude = \"" + longitudeStr + "\" "
|
|||
|
|
retString = retString + "latitude = \"" + latitudeStr + "\" "
|
|||
|
|
retString = retString + "poiName = \"" + postItem.LocationInfo.PoiName + "\" "
|
|||
|
|
retString = retString + "poiAddress = \"" + postItem.LocationInfo.PoiAddress + "\" "
|
|||
|
|
retString = retString + "poiScale = \"" + poiScaleStr + "\" "
|
|||
|
|
retString = retString + "poiInfoUrl = \"" + postItem.LocationInfo.PoiInfoURL + "\" "
|
|||
|
|
retString = retString + "poiClassifyId = \"" + postItem.LocationInfo.PoiClassifyID + "\" "
|
|||
|
|
retString = retString + "poiClassifyType = \"" + poiClassfyTypeStr + "\" "
|
|||
|
|
retString = retString + "poiClickableStatus = \"" + poiClickableStatusStr + "\" "
|
|||
|
|
retString = retString + "></location>"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retString = retString + "<ContentObject>"
|
|||
|
|
if postItem.ContentUrl != "" {
|
|||
|
|
retString = retString + "<contentUrl><![CDATA[" + postItem.ContentUrl + "]]></contentUrl>"
|
|||
|
|
}
|
|||
|
|
retString = retString + "<contentStyle><![CDATA[" + strconv.Itoa(int(postItem.ContentStyle)) + "]]></contentStyle>"
|
|||
|
|
if len(postItem.MediaList) > 0 && postItem.ContentUrl != "" {
|
|||
|
|
retString = retString + "<title><![CDATA[" + postItem.MediaList[0].Title + "]]>


习近平--习大大</title>" //习近平
|
|||
|
|
} else {
|
|||
|
|
retString = retString + "<title>


习近平;习大大</title>" //习近平
|
|||
|
|
}
|
|||
|
|
if postItem.Description != "" {
|
|||
|
|
retString = retString + "<description>![CDATA[" + postItem.Description + "]]></description>"
|
|||
|
|
} else {
|
|||
|
|
retString = retString + "<description></description>"
|
|||
|
|
}
|
|||
|
|
// mediaList
|
|||
|
|
mediaListString := "<mediaList/>"
|
|||
|
|
mediaCount := len(postItem.MediaList)
|
|||
|
|
if mediaCount > 0 {
|
|||
|
|
mediaListString = "<mediaList>"
|
|||
|
|
for index := 0; index < mediaCount; index++ {
|
|||
|
|
mediaListString = mediaListString + CreateMediaItemXML(postItem.MediaList[index])
|
|||
|
|
}
|
|||
|
|
mediaListString = mediaListString + "</mediaList>"
|
|||
|
|
}
|
|||
|
|
retString = retString + mediaListString
|
|||
|
|
retString = retString + "</ContentObject>"
|
|||
|
|
// end
|
|||
|
|
retString = retString + "</TimelineObject>"
|
|||
|
|
// fmt.Println(retString)
|
|||
|
|
return []byte(retString)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSnsMediaItem 创建媒体项
|
|||
|
|
// privacy:公开/不公开
|
|||
|
|
// description:描述
|
|||
|
|
func CreateSnsMediaItem(snsImgResponse *baseinfo.CdnSnsImageUploadResponse, privacy uint32, description string) *baseinfo.SnsMediaItem {
|
|||
|
|
mediaItem := &baseinfo.SnsMediaItem{}
|
|||
|
|
mediaItem.ID = 0
|
|||
|
|
mediaItem.Type = baseinfo.MMSNSMediaTypeImage
|
|||
|
|
mediaItem.Title = ""
|
|||
|
|
mediaItem.Description = description
|
|||
|
|
mediaItem.Private = privacy
|
|||
|
|
mediaItem.UserData = ""
|
|||
|
|
mediaItem.SubType = 0
|
|||
|
|
mediaItem.URL = snsImgResponse.FileURL
|
|||
|
|
mediaItem.URLType = "1"
|
|||
|
|
mediaItem.Thumb = snsImgResponse.ThumbURL
|
|||
|
|
mediaItem.ThumType = "1"
|
|||
|
|
mediaItem.MD5 = snsImgResponse.ImageMD5
|
|||
|
|
mediaItem.VideoMD5 = ""
|
|||
|
|
mediaItem.VideoWidth = strconv.Itoa(int(snsImgResponse.ImageWidth))
|
|||
|
|
mediaItem.VideoHeight = strconv.Itoa(int(snsImgResponse.ImageHeight))
|
|||
|
|
tmpWidth := float64(snsImgResponse.ImageWidth)
|
|||
|
|
tmpHeight := float64(snsImgResponse.ImageHeight)
|
|||
|
|
mediaItem.SizeWidth = strconv.FormatFloat(tmpWidth, 'f', 6, 64)
|
|||
|
|
mediaItem.SizeHeight = strconv.FormatFloat(tmpHeight, 'f', 6, 64)
|
|||
|
|
mediaItem.TotalSize = "0"
|
|||
|
|
|
|||
|
|
return mediaItem
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSnsCommentLikeItem 创建评论项:朋友圈点赞
|
|||
|
|
func CreateSnsCommentLikeItem(itemID uint64, toUserName string) *baseinfo.SnsCommentItem {
|
|||
|
|
retItem := &baseinfo.SnsCommentItem{}
|
|||
|
|
retItem.OpType = baseinfo.MMSnsCommentTypeLike
|
|||
|
|
retItem.ItemID = itemID
|
|||
|
|
retItem.ToUserName = toUserName
|
|||
|
|
retItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
|||
|
|
retItem.Content = ""
|
|||
|
|
retItem.ReplyCommentID = 0
|
|||
|
|
retItem.ReplyItem = nil
|
|||
|
|
|
|||
|
|
return retItem
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSnsCommentItem 创建评论项:朋友圈评论
|
|||
|
|
func CreateSnsCommentItem(itemID uint64, toUserName string, content string, replyComment *wechat.SnsCommentInfo) *baseinfo.SnsCommentItem {
|
|||
|
|
retItem := &baseinfo.SnsCommentItem{}
|
|||
|
|
retItem.OpType = baseinfo.MMSnsCommentTypeComment
|
|||
|
|
retItem.ItemID = itemID
|
|||
|
|
retItem.ToUserName = toUserName
|
|||
|
|
retItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
|||
|
|
retItem.Content = content
|
|||
|
|
retItem.ReplyCommentID = 0
|
|||
|
|
retItem.ReplyItem = nil
|
|||
|
|
|
|||
|
|
// 回复
|
|||
|
|
if replyComment != nil {
|
|||
|
|
retItem.ReplyItem = &baseinfo.ReplyCommentItem{}
|
|||
|
|
retItem.ReplyItem.UserName = replyComment.GetUsername()
|
|||
|
|
retItem.ReplyItem.NickName = replyComment.GetNickname()
|
|||
|
|
retItem.ReplyCommentID = replyComment.GetCommentId()
|
|||
|
|
retItem.ReplyItem.OpType = replyComment.GetType()
|
|||
|
|
retItem.ReplyItem.Source = replyComment.GetSource()
|
|||
|
|
}
|
|||
|
|
return retItem
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSnsLocationInfo 创建朋友圈项: 发送朋友圈地址
|
|||
|
|
func CreateSnsLocationInfo(lbsLife *wechat.LbsLife, cityName string, longitude string, latitude string) *baseinfo.SnsLocationInfo {
|
|||
|
|
retLocationInfo := &baseinfo.SnsLocationInfo{}
|
|||
|
|
|
|||
|
|
retLocationInfo.City = cityName
|
|||
|
|
retLocationInfo.Longitude = longitude
|
|||
|
|
retLocationInfo.Latitude = latitude
|
|||
|
|
retLocationInfo.PoiName = lbsLife.GetTitle()
|
|||
|
|
retLocationInfo.PoiAddress = ""
|
|||
|
|
retLocationInfo.PoiScale = 11.0
|
|||
|
|
retLocationInfo.PoiInfoURL = lbsLife.GetPoiUrl()
|
|||
|
|
retLocationInfo.PoiClassifyID = lbsLife.GetBid()
|
|||
|
|
retLocationInfo.PoiClassifyType = 1
|
|||
|
|
if lbsLife.GetType() == 1 {
|
|||
|
|
retLocationInfo.PoiClassifyType = 2
|
|||
|
|
}
|
|||
|
|
retLocationInfo.PoiClickableStatus = 0
|
|||
|
|
return retLocationInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateGetLbsLifeListItem 创建GetLbsLifeListItem项
|
|||
|
|
func CreateGetLbsLifeListItem(longitude float64, latitude float64, buff []byte, keyWord string) *baseinfo.GetLbsLifeListItem {
|
|||
|
|
// 获取Lbs地址列表
|
|||
|
|
lbsLifeListItem := &baseinfo.GetLbsLifeListItem{}
|
|||
|
|
lbsLifeListItem.Opcode = baseinfo.MMLbsLifeOpcodeNormal
|
|||
|
|
lbsLifeListItem.Buffer = buff
|
|||
|
|
lbsLifeListItem.Longitude = float32(longitude)
|
|||
|
|
lbsLifeListItem.Latitude = float32(latitude)
|
|||
|
|
lbsLifeListItem.KeyWord = keyWord
|
|||
|
|
|
|||
|
|
return lbsLifeListItem
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateCDNUploadMsgImgPrepareRequest 创建 CreateCDNUploadMsgImgPrepareRequest请求
|
|||
|
|
// prepareRequestItem: 请求项
|
|||
|
|
func CreateCDNUploadMsgImgPrepareRequest(userInfo *baseinfo.UserInfo, prepareRequestItem *baseinfo.CDNUploadMsgImgPrepareRequestItem) []byte {
|
|||
|
|
var request wechat.CDNUploadMsgImgPrepareRequest
|
|||
|
|
var emptyString = string("")
|
|||
|
|
var zeroValue32 = int32(0)
|
|||
|
|
|
|||
|
|
// FromUserName
|
|||
|
|
request.FromUserName = &userInfo.WxId
|
|||
|
|
|
|||
|
|
// ToUserName
|
|||
|
|
request.ToUserName = &prepareRequestItem.ToUser
|
|||
|
|
|
|||
|
|
// ClientImgId
|
|||
|
|
clientImgID := prepareRequestItem.ToUser + prepareRequestItem.LocalName + "_" + strconv.Itoa(int(prepareRequestItem.CreateTime))
|
|||
|
|
request.ClientImgId = &clientImgID
|
|||
|
|
|
|||
|
|
// ThumbWidth
|
|||
|
|
request.ThumbWidth = &prepareRequestItem.ThumbWidth
|
|||
|
|
|
|||
|
|
// ThumbHeight
|
|||
|
|
request.ThumbHeight = &prepareRequestItem.ThumbHeight
|
|||
|
|
|
|||
|
|
// encryVer
|
|||
|
|
request.EncryVer = &zeroValue32
|
|||
|
|
|
|||
|
|
// Scene
|
|||
|
|
request.Scene = &zeroValue32
|
|||
|
|
|
|||
|
|
// Crc32
|
|||
|
|
request.Crc32 = &prepareRequestItem.Crc32
|
|||
|
|
|
|||
|
|
// Aeskey
|
|||
|
|
aesKey := baseutils.BytesToHexString(prepareRequestItem.AesKey, false)
|
|||
|
|
request.Aeskey = &aesKey
|
|||
|
|
|
|||
|
|
// MsgForwardType
|
|||
|
|
msgForwardType := uint32(1)
|
|||
|
|
request.MsgForwardType = &msgForwardType
|
|||
|
|
|
|||
|
|
// AttachedContent
|
|||
|
|
request.AttachedContent = &emptyString
|
|||
|
|
|
|||
|
|
// Longitude
|
|||
|
|
longitude := float32(0.0)
|
|||
|
|
request.Longitude = &longitude
|
|||
|
|
// Latitude
|
|||
|
|
request.Latitude = &longitude
|
|||
|
|
|
|||
|
|
// Source
|
|||
|
|
source := uint32(2)
|
|||
|
|
request.Source = &source
|
|||
|
|
|
|||
|
|
// Appid
|
|||
|
|
request.Appid = &emptyString
|
|||
|
|
|
|||
|
|
// MessageAction
|
|||
|
|
request.MessageAction = &emptyString
|
|||
|
|
|
|||
|
|
// MessageExt
|
|||
|
|
request.MeesageExt = &emptyString
|
|||
|
|
|
|||
|
|
// MediaTagName
|
|||
|
|
request.MediaTagName = &emptyString
|
|||
|
|
|
|||
|
|
// 打包
|
|||
|
|
srcData, _ := proto.Marshal(&request)
|
|||
|
|
retData := Pack(userInfo, srcData, 625, 5)
|
|||
|
|
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSendEmojiMsgXMl 生成表情xml
|
|||
|
|
func CreateSendEmojiMsgXMl(md5 string, totallen int32) string {
|
|||
|
|
retString := strings.Builder{}
|
|||
|
|
retString.WriteString("<appmsg appid=\"\" sdkver=\"0\">")
|
|||
|
|
retString.WriteString("<title></title>")
|
|||
|
|
retString.WriteString("<des></des>")
|
|||
|
|
retString.WriteString("<action></action>")
|
|||
|
|
retString.WriteString("<type>8</type>") // 发送表情 type:8
|
|||
|
|
retString.WriteString("<showtype>0</showtype>")
|
|||
|
|
retString.WriteString("<soundtype>0</soundtype>")
|
|||
|
|
retString.WriteString("<mediatagname></mediatagname>")
|
|||
|
|
retString.WriteString("<messageext></messageext>")
|
|||
|
|
retString.WriteString("<messageaction></messageaction>")
|
|||
|
|
retString.WriteString("<content></content>")
|
|||
|
|
retString.WriteString("<contentattr>0</contentattr>")
|
|||
|
|
retString.WriteString("<url></url>")
|
|||
|
|
retString.WriteString("<lowurl></lowurl>")
|
|||
|
|
retString.WriteString("<dataurl></dataurl>")
|
|||
|
|
retString.WriteString("<lowdataurl></lowdataurl>")
|
|||
|
|
retString.WriteString("<songalbumurl></songalbumurl>")
|
|||
|
|
retString.WriteString("<songlyric></songlyric>")
|
|||
|
|
retString.WriteString("<appattach>")
|
|||
|
|
retString.WriteString(fmt.Sprintf("<totallen>%d</totallen>", totallen))
|
|||
|
|
retString.WriteString(fmt.Sprintf("<attachid>0:0:%s</attachid>", md5))
|
|||
|
|
retString.WriteString(fmt.Sprintf("<emoticonmd5>%s</emoticonmd5>", md5))
|
|||
|
|
retString.WriteString("<fileext>pic</fileext>")
|
|||
|
|
retString.WriteString("<cdnthumbaeskey></cdnthumbaeskey>" +
|
|||
|
|
"<aeskey></aeskey>" +
|
|||
|
|
"</appattach>" +
|
|||
|
|
"<extinfo></extinfo>" +
|
|||
|
|
"<sourceusername></sourceusername>" +
|
|||
|
|
"<sourcedisplayname></sourcedisplayname>" +
|
|||
|
|
"<thumburl></thumburl>" +
|
|||
|
|
"<md5></md5>" +
|
|||
|
|
"<statextstr></statextstr>" +
|
|||
|
|
"<directshare>0</directshare>" +
|
|||
|
|
"</appmsg>" +
|
|||
|
|
"<fromusername></fromusername>")
|
|||
|
|
return retString.String()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateCDNUploadMsgImgPrepareRequestWithSource 创建 CDN 上传图片准备请求
|
|||
|
|
func CreateCDNUploadMsgImgPrepareRequestWithSource(userInfo *baseinfo.UserInfo, prepareRequestItem *baseinfo.CDNUploadMsgImgPrepareRequestItem, sourceValue uint32) []byte {
|
|||
|
|
var request wechat.CDNUploadMsgImgPrepareRequest
|
|||
|
|
var emptyString = string("")
|
|||
|
|
var zeroValue32 = int32(0)
|
|||
|
|
|
|||
|
|
// FromUserName
|
|||
|
|
request.FromUserName = &userInfo.WxId
|
|||
|
|
|
|||
|
|
toUserName := prepareRequestItem.ToUser
|
|||
|
|
if toUserName == "" || toUserName == "filehelper" {
|
|||
|
|
toUserName = userInfo.WxId
|
|||
|
|
}
|
|||
|
|
request.ToUserName = &toUserName
|
|||
|
|
|
|||
|
|
// ClientImgId
|
|||
|
|
clientImgID := toUserName + prepareRequestItem.LocalName + "_" + strconv.Itoa(int(prepareRequestItem.CreateTime))
|
|||
|
|
request.ClientImgId = &clientImgID
|
|||
|
|
|
|||
|
|
// ThumbWidth
|
|||
|
|
request.ThumbWidth = &prepareRequestItem.ThumbWidth
|
|||
|
|
|
|||
|
|
// ThumbHeight
|
|||
|
|
request.ThumbHeight = &prepareRequestItem.ThumbHeight
|
|||
|
|
|
|||
|
|
// encryVer
|
|||
|
|
request.EncryVer = &zeroValue32
|
|||
|
|
|
|||
|
|
// Scene
|
|||
|
|
request.Scene = &zeroValue32
|
|||
|
|
|
|||
|
|
// Crc32
|
|||
|
|
request.Crc32 = &prepareRequestItem.Crc32
|
|||
|
|
|
|||
|
|
// Aeskey
|
|||
|
|
aesKey := baseutils.BytesToHexString(prepareRequestItem.AesKey, false)
|
|||
|
|
request.Aeskey = &aesKey
|
|||
|
|
|
|||
|
|
// MsgForwardType
|
|||
|
|
msgForwardType := uint32(1)
|
|||
|
|
request.MsgForwardType = &msgForwardType
|
|||
|
|
|
|||
|
|
// AttachedContent
|
|||
|
|
request.AttachedContent = &emptyString
|
|||
|
|
|
|||
|
|
// Longitude
|
|||
|
|
longitude := float32(0.0)
|
|||
|
|
request.Longitude = &longitude
|
|||
|
|
// Latitude
|
|||
|
|
request.Latitude = &longitude
|
|||
|
|
|
|||
|
|
// Source - 使用传入的值
|
|||
|
|
request.Source = &sourceValue
|
|||
|
|
|
|||
|
|
// Appid
|
|||
|
|
request.Appid = &emptyString
|
|||
|
|
|
|||
|
|
// MessageAction
|
|||
|
|
request.MessageAction = &emptyString
|
|||
|
|
|
|||
|
|
// MessageExt
|
|||
|
|
request.MeesageExt = &emptyString
|
|||
|
|
|
|||
|
|
// MediaTagName
|
|||
|
|
request.MediaTagName = &emptyString
|
|||
|
|
|
|||
|
|
// 打包
|
|||
|
|
srcData, _ := proto.Marshal(&request)
|
|||
|
|
retData := Pack(userInfo, srcData, 625, 5)
|
|||
|
|
|
|||
|
|
return retData
|
|||
|
|
}
|