1203 lines
39 KiB
Go
1203 lines
39 KiB
Go
package clientsdk
|
||
|
||
import (
|
||
"encoding/hex"
|
||
"errors"
|
||
"fmt"
|
||
"log"
|
||
"math/rand"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
"xiawan/wx/api/req"
|
||
"xiawan/wx/clientsdk/mmtls"
|
||
|
||
"github.com/gogo/protobuf/proto"
|
||
|
||
"xiawan/wx/clientsdk/baseinfo"
|
||
"xiawan/wx/clientsdk/baseutils"
|
||
"xiawan/wx/protobuf/wechat"
|
||
)
|
||
|
||
// ---------------------创建请求---------------------------------------------------------------
|
||
|
||
// CreateCDNDownloadRequest 创建Cdn资源下载请求
|
||
func CreateCDNDownloadRequest(userInfo *baseinfo.UserInfo, dnsInfo *wechat.CDNDnsInfo, aesKeyBytes []byte, imageURL string, fileType uint32) *baseinfo.CdnImageDownloadRequest {
|
||
request := &baseinfo.CdnImageDownloadRequest{}
|
||
request.Ver = 1
|
||
request.WeiXinNum = dnsInfo.GetUin()
|
||
request.Seq = 1
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
|
||
if userInfo.DeviceInfo == nil {
|
||
request.ClientOsType = baseinfo.AndroidDeviceType
|
||
} else {
|
||
request.ClientOsType = userInfo.DeviceInfo.OsType
|
||
}
|
||
// authkey
|
||
authKey := dnsInfo.GetAuthKey().GetBuffer()
|
||
request.AuthKey = authKey
|
||
request.NetType = 1
|
||
request.AcceptDupack = 1
|
||
request.RsaVer = 1
|
||
rsaBytes, _ := baseutils.CdnRsaEncrypt(aesKeyBytes)
|
||
request.RsaValue = rsaBytes
|
||
request.FileType = fileType
|
||
request.WxChatType = 0
|
||
request.FileID = imageURL
|
||
request.LastRetCode = 0
|
||
request.IPSeq = 0
|
||
request.CliQuicFlag = 0
|
||
request.WxMsgFlag = nil
|
||
request.WxAutoStart = 1
|
||
request.DownPicFormat = 1
|
||
request.Offset = 0
|
||
request.LargesVideo = 0
|
||
request.SourceFlag = 0
|
||
return request
|
||
}
|
||
|
||
// CreateVideoUploadRequest 创建视频上传请求
|
||
func CreateVideoUploadRequest(userInfo *baseinfo.UserInfo, videoItem *baseinfo.UploadVideoItem) (*baseinfo.CdnVideoUploadRequest, error) {
|
||
request := &baseinfo.CdnVideoUploadRequest{}
|
||
request.Ver = 1
|
||
request.WeiXinNum = videoItem.CDNDns.GetUin()
|
||
request.Seq = videoItem.Seq
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
if userInfo.DeviceInfo == nil {
|
||
request.ClientOSType = baseinfo.AndroidDeviceType
|
||
} else {
|
||
request.ClientOSType = userInfo.DeviceInfo.OsType
|
||
}
|
||
request.AutoKey = videoItem.CDNDns.AuthKey.GetBuffer()
|
||
request.NetType = 1
|
||
request.AcceptDuPack = 1
|
||
request.SafeProto = 1
|
||
request.FileType = 4
|
||
request.WeChatType = 0
|
||
request.LastRetCode = 0
|
||
request.IpSeq = 0
|
||
request.HastHumb = 1
|
||
// ToUser
|
||
retBytes := baseutils.AesEncrypt([]byte(videoItem.ToUser), []byte("wxusrname2016cdn"))
|
||
request.ToUSerName = "@cdn2_" + baseutils.BytesToHexString(retBytes, false)
|
||
request.CompressType = 0
|
||
request.NoCheckAesKey = 1
|
||
request.EnaBleHit = 1
|
||
request.ExistAnceCheck = 0
|
||
request.AppType = 0
|
||
|
||
// 加密视频
|
||
videoEncodeData := baseutils.AesEncryptECB(videoItem.VideoData, videoItem.AesKey)
|
||
// 加密微缩图
|
||
thumbEncodeData := baseutils.AesEncryptECB(videoItem.ThumbData, videoItem.AesKey)
|
||
|
||
userMd5 := baseutils.Md5ValueByte([]byte(userInfo.GetUserName()+"-"+videoItem.ToUser), false)
|
||
timeStamp := fmt.Sprintf("%d", time.Now().UnixNano()/1000/1000)
|
||
videoKey := timeStamp + "baed6285091"
|
||
fileKey := fmt.Sprintf("aupvideo_%s_%s_%s", userMd5, timeStamp, videoKey) // guid
|
||
request.FileKey = fileKey
|
||
request.LocalName = baseutils.Md5ValueByte(videoItem.VideoData, false) + ".jpg"
|
||
request.Offset = 0
|
||
request.LargesVideo = 1
|
||
request.SourceFlag = 0
|
||
request.DropRateFlag = 1
|
||
request.ClientRsaVer = 1
|
||
//rsaValue, _ := baseutils.RsaEncryptByVer(videoItem.AesKey, userInfo.GetLoginRsaVer())
|
||
rsaValue, _ := baseutils.CdnRsaEncrypt(videoItem.AesKey)
|
||
request.ClientRsaVal = rsaValue
|
||
request.AdVideoFlag = 0
|
||
|
||
request.FileMd5 = baseutils.Md5ValueByte(videoItem.VideoData, false)
|
||
request.RawFileMd5 = baseutils.Md5ValueByte(videoItem.VideoData, false)
|
||
request.DataCheckSum = baseutils.Adler32(0, videoEncodeData)
|
||
request.EncThumbCrc = baseutils.Adler32(0, thumbEncodeData)
|
||
request.ThumbData = thumbEncodeData
|
||
request.RawThumbMd5 = baseutils.Md5ValueByte(videoItem.ThumbData, false)
|
||
|
||
request.TotalSize = uint32(len(videoEncodeData))
|
||
request.RawTotalSize = uint32(len(videoItem.VideoData))
|
||
request.ThumbTotalSize = uint32(len(thumbEncodeData))
|
||
request.RawThumbSize = uint32(len(videoItem.ThumbData))
|
||
request.FileCrc = baseutils.Adler32(0, videoItem.VideoData)
|
||
request.FileData = videoEncodeData
|
||
request.Mp4identify = "a79c98ca478c707db3c80d28766f89e0"
|
||
|
||
return request, nil
|
||
}
|
||
|
||
// CreateImageUploadRequest 创建上传高清图请求
|
||
func CreateImageUploadRequest(userInfo *baseinfo.UserInfo, imgItem *baseinfo.UploadImgItem) (*baseinfo.CdnImageUploadRequest, error) {
|
||
request := &baseinfo.CdnImageUploadRequest{}
|
||
request.Ver = 1
|
||
request.WeiXinNum = uint32(imgItem.CDNDns.GetUin())
|
||
request.Seq = imgItem.Seq
|
||
if !strings.HasPrefix(userInfo.LoginDataInfo.LoginData, "A") && userInfo.DeviceInfo != nil {
|
||
request.ClientOsType = userInfo.DeviceInfo.OsType
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
} else {
|
||
request.ClientOsType = baseinfo.AndroidDeviceType
|
||
request.ClientVersion = baseinfo.AndroidClientVersion
|
||
}
|
||
request.AuthKey = imgItem.CDNDns.AuthKey.GetBuffer()
|
||
request.NetType = 1
|
||
request.AcceptDupack = 1
|
||
request.SafeProto = 1
|
||
request.FileType = 2
|
||
request.WxChatType = 0
|
||
request.LastRetCode = 0
|
||
request.IPSeq = 0
|
||
request.CliQuicFlag = 0
|
||
request.CompressType = 0
|
||
request.NoCheckAesKey = 1
|
||
request.EnableHit = 1
|
||
request.ExistAnceCheck = 0
|
||
request.AppType = 1
|
||
request.LocalName = imgItem.LocalName + imgItem.ExtName
|
||
request.Offset = 0
|
||
request.LargesVideo = 0
|
||
request.SourceFlag = 0
|
||
request.AdVideoFlag = 0
|
||
|
||
// ToUser
|
||
retBytes := baseutils.AesEncrypt([]byte(imgItem.ToUser), []byte("wxusrname2016cdn"))
|
||
request.ToUser = "@cdn2_" + baseutils.BytesToHexString(retBytes, false)
|
||
|
||
// ThumbData
|
||
thumbItem := CreateThumbImage(imgItem.ImageData)
|
||
if thumbItem == nil {
|
||
return nil, errors.New("生成缩略图失败")
|
||
}
|
||
thumbEncodeData := baseutils.AesEncryptECB(thumbItem.Data, []byte(imgItem.AesKey))
|
||
request.HasThumb = 1
|
||
request.ThumbTotalSize = uint32(len(thumbEncodeData))
|
||
request.RawThumbSize = uint32(len(thumbItem.Data))
|
||
request.RawThumbMD5 = baseutils.Md5ValueByte(thumbItem.Data, false)
|
||
request.EncThumbCRC = baseutils.Adler32(0, thumbEncodeData)
|
||
request.ThumbData = thumbEncodeData
|
||
|
||
// FileKey
|
||
request.FileKey = "wxupload_" + imgItem.ToUser + imgItem.LocalName + "_" + strconv.Itoa(int(imgItem.CreateTime))
|
||
|
||
// FileData
|
||
fileEncodeData := baseutils.AesEncryptECB(imgItem.ImageData, []byte(imgItem.AesKey))
|
||
request.TotalSize = uint32(len(fileEncodeData))
|
||
request.RawTotalSize = uint32(len(imgItem.ImageData))
|
||
request.FileMD5 = baseutils.Md5ValueByte(fileEncodeData, false)
|
||
request.RawFileMD5 = baseutils.Md5ValueByte(imgItem.ImageData, false)
|
||
request.FileCRC = baseutils.Adler32(0, imgItem.ImageData)
|
||
request.DataCheckSum = baseutils.Adler32(0, fileEncodeData)
|
||
request.FileData = fileEncodeData
|
||
request.SetOfPicFormat = "011000"
|
||
|
||
// prepareRequestItem
|
||
var prepareRequestItem baseinfo.CDNUploadMsgImgPrepareRequestItem
|
||
prepareRequestItem.ToUser = imgItem.ToUser
|
||
prepareRequestItem.LocalName = imgItem.LocalName
|
||
prepareRequestItem.CreateTime = imgItem.CreateTime
|
||
prepareRequestItem.ThumbWidth = thumbItem.Width
|
||
prepareRequestItem.ThumbHeight = thumbItem.Height
|
||
prepareRequestItem.AesKey = imgItem.AesKey
|
||
prepareRequestItem.Crc32 = request.FileCRC
|
||
|
||
// SessionBuf
|
||
request.SessionBuf = CreateCDNUploadMsgImgPrepareRequest(userInfo, &prepareRequestItem)
|
||
return request, nil
|
||
}
|
||
|
||
// CreateSnsImageUploadRequest 创建Cdn上传朋友圈高清图请求
|
||
func CreateSnsImageUploadRequest(userInfo *baseinfo.UserInfo, snsImgItem *baseinfo.SnsUploadImgItem) (*baseinfo.CdnSnsImageUploadRequest, error) {
|
||
request := &baseinfo.CdnSnsImageUploadRequest{}
|
||
request.Ver = 1
|
||
request.WeiXinNum = uint32(snsImgItem.CDNDns.GetUin())
|
||
request.Seq = snsImgItem.Seq
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
if userInfo.DeviceInfo == nil {
|
||
request.ClientOsType = baseinfo.AndroidDeviceType
|
||
} else {
|
||
request.ClientOsType = userInfo.DeviceInfo.OsType
|
||
}
|
||
request.AuthKey = snsImgItem.CDNDns.AuthKey.GetBuffer()
|
||
request.NetType = 1
|
||
request.AcceptDupack = 1
|
||
request.RsaVer = 1
|
||
rsaValue, _ := baseutils.CdnRsaEncrypt(snsImgItem.AesKey)
|
||
request.RsaValue = rsaValue
|
||
request.FileType = 20201
|
||
request.WxChatType = 0
|
||
request.LastRetCode = 0
|
||
request.IPSeq = 0
|
||
request.CliQuicFlag = 0
|
||
request.HasThumb = 0
|
||
request.ToUser = ""
|
||
request.CompressType = 1
|
||
request.NoCheckAesKey = 1
|
||
request.EnableHit = 1
|
||
request.ExistAnceCheck = 0
|
||
request.AppType = 108
|
||
request.LocalName = "[TEMP]" + strconv.Itoa(int(snsImgItem.ImageID)) + "_" + strconv.Itoa(int(snsImgItem.CreateTime))
|
||
request.FileKey = request.LocalName + "_" + strconv.Itoa(int(snsImgItem.CreateTime)+rand.Intn(1000))
|
||
request.Offset = 0
|
||
request.ThumbTotalSize = 0
|
||
request.RawThumbSize = 0
|
||
request.RawThumbMD5 = ""
|
||
request.ThumbCRC = 0
|
||
request.LargesVideo = 0
|
||
request.SourceFlag = 0
|
||
request.AdVideoFlag = 0
|
||
|
||
// FileData
|
||
fileEncodeData := baseutils.AesEncryptECB(snsImgItem.ImageData, []byte(snsImgItem.AesKey))
|
||
request.TotalSize = uint32(len(snsImgItem.ImageData))
|
||
request.RawTotalSize = request.TotalSize
|
||
request.FileMD5 = baseutils.Md5ValueByte(snsImgItem.ImageData, false)
|
||
request.RawFileMD5 = request.FileMD5
|
||
request.FileCRC = baseutils.Adler32(0, snsImgItem.ImageData)
|
||
request.DataCheckSum = baseutils.Adler32(0, fileEncodeData)
|
||
request.FileData = snsImgItem.ImageData
|
||
return request, nil
|
||
}
|
||
|
||
// CreateSnsVideoDownloadRequest 创建Cdn下载朋友圈视频请求
|
||
func CreateSnsVideoDownloadRequest(userInfo *baseinfo.UserInfo, snsVideoItem *baseinfo.SnsVideoDownloadItem) (*baseinfo.CdnSnsVideoDownloadRequest, error) {
|
||
request := &baseinfo.CdnSnsVideoDownloadRequest{}
|
||
request.Ver = 1
|
||
request.WeiXinNum = uint32(snsVideoItem.CDNDns.GetUin())
|
||
request.Seq = snsVideoItem.Seq
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
if userInfo.DeviceInfo == nil {
|
||
request.ClientOsType = baseinfo.AndroidDeviceType
|
||
} else {
|
||
request.ClientOsType = userInfo.DeviceInfo.OsType
|
||
}
|
||
request.AuthKey = snsVideoItem.CDNDns.AuthKey.GetBuffer()
|
||
request.NetType = 1
|
||
request.AcceptDupack = 1
|
||
request.Signal = ""
|
||
request.Scene = ""
|
||
request.URL = snsVideoItem.URL
|
||
request.RangeStart = snsVideoItem.RangeStart
|
||
request.RangeEnd = snsVideoItem.RangeEnd
|
||
request.LastRetCode = 0
|
||
request.IPSeq = 0
|
||
request.RedirectType = 0
|
||
request.LastVideoFormat = 0
|
||
request.VideoFormat = 2
|
||
request.XSnsVideoFlag = snsVideoItem.XSnsVideoFlag
|
||
return request, nil
|
||
}
|
||
|
||
// CreateCdnSnsVideoUploadRequest 上传朋友圈视频
|
||
func CreateCdnSnsVideoUploadRequest(userInfo *baseinfo.UserInfo, videoUploadItem *baseinfo.SnsVideoUploadItem) (*baseinfo.CdnSnsVideoUploadRequest, error) {
|
||
request := &baseinfo.CdnSnsVideoUploadRequest{}
|
||
filekey := fmt.Sprintf("aupimg_%s_%d", userInfo.GetUserName(), time.Now().UnixNano()/1000/1000)
|
||
request.Ver = 1
|
||
request.WeiXinNum = uint32(videoUploadItem.CDNDns.GetUin())
|
||
request.Seq = videoUploadItem.Seq
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
if userInfo.DeviceInfo == nil {
|
||
request.ClientOsType = baseinfo.AndroidDeviceType
|
||
} else {
|
||
request.ClientOsType = userInfo.DeviceInfo.OsType
|
||
}
|
||
request.AuthKey = videoUploadItem.CDNDns.AuthKey.GetBuffer()
|
||
request.NetType = 1
|
||
request.AcceptDupack = 1
|
||
request.RsaVer = 1
|
||
fileAESKey := "42807213a18c421db34bad77219f5172"
|
||
bFileAESKey, _ := hex.DecodeString(fileAESKey)
|
||
rsaValue, _ := baseutils.CdnRsaEncrypt(bFileAESKey)
|
||
request.RsaValue = rsaValue
|
||
request.FileType = 20202 //20202
|
||
request.WxChatType = 0
|
||
request.LastRetCode = 0
|
||
request.IPSeq = 0
|
||
request.CliQuicFlag = 0
|
||
request.IsStoreVideo = 0
|
||
request.NoCheckAesKey = 1
|
||
request.EnableHit = 1
|
||
request.ExistAnceCheck = 0
|
||
request.AppType = 102
|
||
totalSize := uint32(len(videoUploadItem.VideoData))
|
||
request.TotalSize = totalSize
|
||
request.RawTotalSize = totalSize
|
||
// tmpLocalNameNoExt := "[TEMP]" + strconv.Itoa(int(videoUploadItem.VideoID)) + "_" + strconv.Itoa(int(videoUploadItem.CreateTime))
|
||
request.LocalName = "sns_tmps_Locall_path4"
|
||
request.FileKey = filekey
|
||
request.Offset = 0
|
||
|
||
// 暂时不设置Thumb数据
|
||
thumbDataLen := uint32(len(videoUploadItem.ThumbData))
|
||
request.HasThumb = 1
|
||
request.ThumbTotalSize = thumbDataLen
|
||
request.RawThumbSize = thumbDataLen
|
||
request.RawThumbMD5 = baseutils.Md5ValueByte(videoUploadItem.ThumbData, false)
|
||
request.ThumbCRC = baseutils.Adler32(0, videoUploadItem.ThumbData)
|
||
request.ThumbData = videoUploadItem.ThumbData
|
||
|
||
request.LargesVideo = 80
|
||
request.SourceFlag = 0
|
||
request.AdVideoFlag = 0
|
||
fileEncodeData := baseutils.AesEncryptECB(videoUploadItem.VideoData, videoUploadItem.AesKey)
|
||
request.Mp4Identify = baseutils.Md5ValueByte(fileEncodeData, false)
|
||
md5Value := baseutils.Md5ValueByte(videoUploadItem.VideoData, false)
|
||
request.FileMD5 = md5Value
|
||
request.RawFileMD5 = md5Value
|
||
request.FileCRC = baseutils.Adler32(0, videoUploadItem.VideoData)
|
||
request.DataCheckSum = baseutils.Adler32(0, fileEncodeData)
|
||
request.FileData = videoUploadItem.VideoData
|
||
//request.UserLargeFileApi=true
|
||
return request, nil
|
||
}
|
||
|
||
// ---------------------发送请求---------------------------------------------------------------
|
||
|
||
// SendCdnDownloadReuqest 发送CDN下载请求
|
||
func SendCdnDownloadReuqest(userInfo *baseinfo.UserInfo, downItem *baseinfo.DownMediaItem) (*baseinfo.CdnDownloadResponse, error) {
|
||
dnsInfo := userInfo.DNSInfo
|
||
aesKeyBytes := baseutils.HexStringToBytes(downItem.AesKey)
|
||
request := CreateCDNDownloadRequest(userInfo, dnsInfo, aesKeyBytes, downItem.FileURL, downItem.FileType)
|
||
sendData := PackCdnImageDownloadRequest(request)
|
||
|
||
// 连接Cdn服务器
|
||
serverIP := dnsInfo.FrontIplist[0].GetStr()
|
||
serverPort := dnsInfo.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer conn.Close()
|
||
|
||
// 发送请求数据
|
||
conn.Write(sendData)
|
||
retData := CDNRecvData(conn)
|
||
|
||
// 返回解密图片数据
|
||
response, err := DecodeImageDownloadResponse(retData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
response.FileData = baseutils.AesDecryptECB(response.FileData, aesKeyBytes)
|
||
return response, nil
|
||
}
|
||
|
||
// 获取图片
|
||
func GetMsgBigImg(userInfo *baseinfo.UserInfo, m req.DownloadParam) (*baseinfo.PackHeader, error) {
|
||
if m.Section.DataLen > 65535 {
|
||
m.Section.DataLen = 65535
|
||
}
|
||
|
||
reqData := wechat.GetMsgImgRequest{
|
||
BaseRequest: GetBaseRequest(userInfo),
|
||
MsgId: proto.Uint32(m.MsgId),
|
||
FromUserName: &wechat.SKBuiltinString{
|
||
Str: proto.String(m.FromUserName),
|
||
},
|
||
ToUserName: &wechat.SKBuiltinString{
|
||
Str: proto.String(m.ToUserName),
|
||
//Str: proto.String(userInfo.WxId), // 别人发送给 "我" 的图片数据
|
||
},
|
||
TotalLen: proto.Uint32(uint32(m.TotalLen)),
|
||
StartPos: proto.Uint32(m.Section.StartPos),
|
||
DataLen: proto.Uint32(m.Section.DataLen),
|
||
CompressType: proto.Uint32(uint32(m.CompressType)),
|
||
}
|
||
|
||
// 打包发送数据
|
||
srcData, _ := proto.Marshal(&reqData)
|
||
sendEncodeData := Pack(userInfo, srcData, 109, 5)
|
||
resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/getmsgimg", sendEncodeData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return DecodePackHeader(resp, nil)
|
||
}
|
||
|
||
// GetMsgCdnVideo 获取视频(下载视频数据)
|
||
func GetMsgCdnVideo(userInfo *baseinfo.UserInfo, m req.DownloadParam) (*baseinfo.PackHeader, error) {
|
||
req := wechat.DownloadVideoRequest{
|
||
BaseRequest: GetBaseRequest(userInfo),
|
||
MsgId: proto.Uint32(m.MsgId),
|
||
TotalLen: proto.Uint32(uint32(m.TotalLen)),
|
||
StartPos: proto.Uint32(m.Section.StartPos),
|
||
NetworkEnv: proto.Uint32(1),
|
||
MxPackSize: proto.Uint32(m.Section.DataLen),
|
||
}
|
||
|
||
// 打包发送数据
|
||
srcData, _ := proto.Marshal(&req)
|
||
sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeForwardCdnVideo, 5)
|
||
resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/downloadvideo", sendEncodeData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return DecodePackHeader(resp, nil)
|
||
}
|
||
|
||
func SendCdnUploadVideoRequest(userInfo *baseinfo.UserInfo, toUser string, imgData []byte, videoData []byte) (*baseinfo.CdnMsgVideoUploadResponse, error) {
|
||
videoItem := &baseinfo.UploadVideoItem{}
|
||
videoItem.ThumbData = imgData
|
||
videoItem.VideoData = videoData
|
||
videoItem.ToUser = toUser
|
||
videoItem.CDNDns = userInfo.DNSInfo
|
||
videoItem.Seq = uint32(rand.Intn(10))
|
||
videoItem.AesKey, _ = hex.DecodeString("1f22e78fd07d46a68b889aa222e93563")
|
||
request, err := CreateVideoUploadRequest(userInfo, videoItem)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
sendData := PackCdnVideoUploadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := videoItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := videoItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
retryCount := uint32(0)
|
||
// 接收响应信息
|
||
for {
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeVideoUploadResponse(retData)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, errors.New("上传视频失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
|
||
// 判断 服务器是否接收完毕
|
||
if response.FileID != "" {
|
||
response.FileAesKey = "1f22e78fd07d46a68b889aa222e93563"
|
||
response.ThumbDataSize = uint32(len(videoItem.ThumbData))
|
||
response.VideoDataSize = uint32(len(videoItem.VideoData))
|
||
response.Mp4identify = "a79c98ca478c707db3c80d28766f89e0"
|
||
response.VideoDataMD5 = request.RawFileMd5
|
||
response.ThumbWidth = 200
|
||
response.ThumbHeight = 200
|
||
return response, nil
|
||
}
|
||
|
||
// 设置请求数据
|
||
//response.ReqData = request
|
||
}
|
||
}
|
||
|
||
// SendCdnUploadImageReuqest 发送CDN上传图片请求
|
||
func SendCdnUploadImageReuqest(userInfo *baseinfo.UserInfo, toUser string, imgData []byte) (bool, error) {
|
||
imgItem := &baseinfo.UploadImgItem{}
|
||
imgItem.ToUser = toUser
|
||
imgItem.Seq = uint32(rand.Intn(10))
|
||
imgItem.LocalName = strconv.Itoa(rand.Intn(100))
|
||
imgItem.ExtName = ".pic"
|
||
// 随机生成AesKey
|
||
imgItem.AesKey = []byte(baseutils.RandomStringByLength(16))
|
||
imgItem.ImageData = imgData
|
||
imgItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
||
// 设置Dns路由信息
|
||
imgItem.CDNDns = userInfo.FAKEDnsInfo
|
||
|
||
// 创建上传图片请求
|
||
request, err := CreateImageUploadRequest(userInfo, imgItem)
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
|
||
// 打包请求
|
||
sendData := PackCdnImageUploadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := imgItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := imgItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
retryCount := uint32(0)
|
||
// 接收响应信息
|
||
sendImgLen := uint32(len(request.FileData))
|
||
for {
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeImageUploadResponse(retData)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return false, err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return false, errors.New("发送图片失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
|
||
// 判断 服务器是否接收完毕
|
||
if response.RecvLen < sendImgLen {
|
||
continue
|
||
}
|
||
|
||
// SKeyResp CDNUploadMsgImgPrepareResponse的错误码
|
||
if response.SKeyResp != 0 {
|
||
return false, errors.New("发送图片失败: SKeyResp = " + strconv.Itoa(int(response.SKeyResp)))
|
||
}
|
||
|
||
// SKeyBuf
|
||
skbufLen := len(response.SKeyBuf)
|
||
if skbufLen <= 0 {
|
||
continue
|
||
}
|
||
break
|
||
}
|
||
|
||
return true, nil
|
||
}
|
||
|
||
// SendCdnUploadImageReuqestWithDetails 发送CDN上传图片请求并返回详细信息
|
||
func SendCdnUploadImageReuqestWithDetails(userInfo *baseinfo.UserInfo, toUser string, imgData []byte) (*baseinfo.CdnImageUploadResponse, string, error) {
|
||
imgItem := &baseinfo.UploadImgItem{}
|
||
imgItem.ToUser = toUser
|
||
imgItem.Seq = uint32(rand.Intn(10))
|
||
imgItem.LocalName = strconv.Itoa(rand.Intn(100))
|
||
imgItem.ExtName = ".pic"
|
||
// 随机生成AesKey
|
||
imgItem.AesKey = []byte(baseutils.RandomStringByLength(16))
|
||
aesKeyHex := hex.EncodeToString(imgItem.AesKey)
|
||
imgItem.ImageData = imgData
|
||
imgItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
||
// 设置Dns路由信息
|
||
imgItem.CDNDns = userInfo.FAKEDnsInfo
|
||
|
||
// 创建上传图片请求
|
||
request, err := CreateImageUploadRequest(userInfo, imgItem)
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
// 打包请求
|
||
sendData := PackCdnImageUploadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := imgItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := imgItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
retryCount := uint32(0)
|
||
// 接收响应信息
|
||
sendImgLen := uint32(len(request.FileData))
|
||
var finalResponse *baseinfo.CdnImageUploadResponse
|
||
for {
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeImageUploadResponse(retData)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return nil, "", err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, "", errors.New("发送图片失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
|
||
// 判断 服务器是否接收完毕
|
||
if response.RecvLen < sendImgLen {
|
||
continue
|
||
}
|
||
|
||
// SKeyResp CDNUploadMsgImgPrepareResponse的错误码
|
||
if response.SKeyResp != 0 {
|
||
return nil, "", errors.New("发送图片失败: SKeyResp = " + strconv.Itoa(int(response.SKeyResp)))
|
||
}
|
||
|
||
// SKeyBuf
|
||
skbufLen := len(response.SKeyBuf)
|
||
if skbufLen <= 0 {
|
||
continue
|
||
}
|
||
finalResponse = response
|
||
break
|
||
}
|
||
|
||
log.Printf("CDN上传图片响应: Ver=%d, Seq=%d, RetCode=%d, FileKey=%s, RecvLen=%d, FileID=%s",
|
||
finalResponse.Ver, finalResponse.Seq, finalResponse.RetCode, finalResponse.FileKey,
|
||
finalResponse.RecvLen, finalResponse.FileID)
|
||
|
||
// 解析SKeyBuf获取FileID
|
||
log.Printf("SKeyBuf 长度: %d, SKeyResp: %d", len(finalResponse.SKeyBuf), finalResponse.SKeyResp)
|
||
|
||
// 如果 CDN 响应中已经有 FileID,直接使用
|
||
if finalResponse.FileID == "" && len(finalResponse.SKeyBuf) > 0 {
|
||
var cdnPrepareResp wechat.CDNUploadMsgImgPrepareResponse
|
||
// SKeyBuf 可能是加密的,尝试解密
|
||
decryptedSKeyBuf, err := baseutils.AesDecrypt(finalResponse.SKeyBuf, userInfo.SessionKey)
|
||
if err != nil {
|
||
// 尝试直接解析(可能不需要解密)
|
||
err = proto.Unmarshal(finalResponse.SKeyBuf, &cdnPrepareResp)
|
||
if err == nil && cdnPrepareResp.FileId != nil {
|
||
finalResponse.FileID = cdnPrepareResp.GetFileId()
|
||
}
|
||
} else {
|
||
// 尝试解析 protobuf
|
||
err = proto.Unmarshal(decryptedSKeyBuf, &cdnPrepareResp)
|
||
if err == nil && cdnPrepareResp.FileId != nil {
|
||
finalResponse.FileID = cdnPrepareResp.GetFileId()
|
||
}
|
||
}
|
||
} else if finalResponse.FileID != "" {
|
||
log.Printf("响应中已包含 FileID: %s", finalResponse.FileID)
|
||
}
|
||
|
||
// 设置 CDN URL
|
||
finalResponse.CdnBigImgUrl = finalResponse.FileID
|
||
finalResponse.CdnMidImgUrl = finalResponse.FileID
|
||
finalResponse.CdnThumbImgUrl = finalResponse.FileID
|
||
|
||
return finalResponse, aesKeyHex, nil
|
||
}
|
||
|
||
// SendCdnSnsUploadImageReuqest 发送CDN朋友圈上传图片请求
|
||
func SendCdnSnsUploadImageReuqest(userInfo *baseinfo.UserInfo, imgData []byte) (*baseinfo.CdnSnsImageUploadResponse, error) {
|
||
// 生产SnsImgItem
|
||
snsImgItem := &baseinfo.SnsUploadImgItem{}
|
||
snsImgItem.Seq = uint32(rand.Intn(50))
|
||
snsImgItem.AesKey = []byte(baseutils.RandomStringByLength(16))
|
||
snsImgItem.ImageData = imgData
|
||
snsImgItem.ImageID = CreateID(imgData)
|
||
snsImgItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
||
if userInfo.SNSDnsInfo == nil {
|
||
return nil, errors.New("SendCdnSnsUploadImageReuqest err:userInfo.SNSDnsInfo == nil")
|
||
}
|
||
snsImgItem.CDNDns = userInfo.SNSDnsInfo
|
||
|
||
// 创建上传图片请求
|
||
request, err := CreateSnsImageUploadRequest(userInfo, snsImgItem)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 打包请求
|
||
sendData := PackCdnSnsImageUploadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := snsImgItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := snsImgItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
retryCount := uint32(0)
|
||
// 接收响应信息
|
||
sendImgLen := uint32(len(request.FileData))
|
||
for {
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeSnsImageUploadResponse(retData)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, errors.New("发送图片失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
|
||
// 判断 服务器是否接收完毕
|
||
if response.RecvLen < sendImgLen {
|
||
continue
|
||
}
|
||
|
||
response.ImageMD5 = request.FileMD5
|
||
width, height := GetImageBounds(request.FileData)
|
||
response.ImageWidth = width
|
||
response.ImageHeight = height
|
||
return response, nil
|
||
}
|
||
}
|
||
|
||
// SendCdnSnsVideoUploadReuqest 发送CDN朋友圈上传视频请求
|
||
func SendCdnSnsVideoUploadReuqest(userInfo *baseinfo.UserInfo, videoData []byte, thumbData []byte) (*baseinfo.CdnSnsVideoUploadResponse, error) {
|
||
// 生产SnsImgItem
|
||
snsVideoItem := &baseinfo.SnsVideoUploadItem{}
|
||
snsVideoItem.Seq = uint32(rand.Intn(10))
|
||
snsVideoItem.AesKey = []byte(baseutils.RandomStringByLength(16))
|
||
snsVideoItem.VideoData = videoData
|
||
snsVideoItem.ThumbData = thumbData
|
||
snsVideoItem.VideoID = CreateID(videoData)
|
||
snsVideoItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
||
snsVideoItem.CDNDns = userInfo.SNSDnsInfo
|
||
|
||
// 创建上传朋友圈视频请求
|
||
request, err := CreateCdnSnsVideoUploadRequest(userInfo, snsVideoItem)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 打包请求
|
||
sendData := PackCdnSnsVideoUploadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := snsVideoItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := snsVideoItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
retryCount := uint32(0)
|
||
// 接收响应信息
|
||
for {
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeSnsVideoUploadResponse(retData)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, errors.New("上传朋友圈视频失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
|
||
// 判断 服务器是否接收完毕
|
||
if response.RecvLen < request.TotalSize {
|
||
continue
|
||
}
|
||
|
||
// 设置请求数据
|
||
response.ReqData = request
|
||
return response, nil
|
||
}
|
||
}
|
||
|
||
// SendCdnSnsVideoDownloadReuqestPiece 分片下载
|
||
func SendCdnSnsVideoDownloadReuqestPiece(userInfo *baseinfo.UserInfo, snsVideoItem *baseinfo.SnsVideoDownloadItem) (*baseinfo.CdnSnsVideoDownloadResponse, error) {
|
||
// 创建朋友圈视频下载请求
|
||
request, err := CreateSnsVideoDownloadRequest(userInfo, snsVideoItem)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 打包请求
|
||
sendData := PackCdnSnsVideoDownloadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := snsVideoItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := snsVideoItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
// 接收响应信息
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeSnsVideoDownloadResponse(retData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, errors.New("下载朋友圈视频失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
return response, nil
|
||
}
|
||
|
||
// SendCdnSnsVideoDownloadReuqest 发送CDN朋友圈视频下载请求
|
||
func SendCdnSnsVideoDownloadReuqest(userInfo *baseinfo.UserInfo, encKey uint64, tmpURL string) ([]byte, error) {
|
||
retFileData := []byte{}
|
||
lessLength := uint32(2000000)
|
||
encLen := uint32(0)
|
||
videoFlag := string("V2")
|
||
|
||
retryCount := uint32(0)
|
||
|
||
for {
|
||
// 生产SnsImgItem
|
||
var snsVideoItem baseinfo.SnsVideoDownloadItem
|
||
snsVideoItem.Seq = uint32(rand.Intn(10))
|
||
snsVideoItem.URL = tmpURL
|
||
snsVideoItem.RangeStart = uint32(len(retFileData))
|
||
snsVideoItem.RangeEnd = snsVideoItem.RangeStart + lessLength
|
||
snsVideoItem.XSnsVideoFlag = videoFlag
|
||
snsVideoItem.CDNDns = userInfo.SNSDnsInfo
|
||
|
||
// 发送分片下载请求
|
||
response, err := SendCdnSnsVideoDownloadReuqestPiece(userInfo, &snsVideoItem)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, errors.New("SendCdnSnsVideoDownloadReuqest err: response.RetCode != 0")
|
||
}
|
||
|
||
// 设置加密的字节数
|
||
if encLen == 0 {
|
||
encLen = response.XEncLen
|
||
}
|
||
|
||
// 合并数据
|
||
retFileData = append(retFileData, response.FileData[0:]...)
|
||
currentLen := uint32(len(retFileData))
|
||
if currentLen >= response.TotalSize {
|
||
break
|
||
}
|
||
|
||
// 如果没有读取完
|
||
lessLength = response.TotalSize - currentLen
|
||
videoFlag = response.XSnsVideoFlag
|
||
}
|
||
if encKey != 0 {
|
||
retFileData = baseutils.DecryptSnsVideoData(retFileData, encLen, encKey)
|
||
}
|
||
// ioutil.WriteFile("log/1.mp4", retFileData, 0777)
|
||
// 解密数据
|
||
return retFileData, nil
|
||
}
|
||
|
||
// ForwardCdnImageRequest 转发Cdn图片
|
||
func ForwardCdnImageRequest(userInfo *baseinfo.UserInfo, item baseinfo.ForwardImageItem) (*baseinfo.PackHeader, error) {
|
||
req := &wechat.UploadMsgImgRequest{
|
||
BaseRequest: GetBaseRequest(userInfo),
|
||
AesKey: proto.String(item.AesKey),
|
||
CdnThumbAesKey: proto.String(item.AesKey),
|
||
|
||
CdnMidImgSize: proto.Uint32(uint32(item.CdnMidImgSize)),
|
||
CdnThumbImgSize: proto.Uint32(uint32(item.CdnThumbImgSize)),
|
||
|
||
CdnSmallImgUrl: proto.String(item.CdnMidImgUrl),
|
||
CdnThumbImgUrl: proto.String(item.CdnMidImgUrl),
|
||
|
||
TotalLen: proto.Uint32(uint32(item.CdnMidImgSize)),
|
||
DataLen: proto.Uint32(uint32(item.CdnMidImgSize)),
|
||
|
||
ClientImgId: &wechat.SKBuiltinString{
|
||
Str: proto.String(func() string {
|
||
//logger.Println(cli.GetAcctSect().GetUserName())
|
||
userMd5 := strings.ToLower(baseutils.Md5Value(userInfo.GetUserName() + "-" + item.ToUserName)[:16])
|
||
filekey := fmt.Sprintf("aupimg_%s_%d", userMd5, time.Now().UnixNano()/10000)
|
||
return filekey
|
||
}()),
|
||
},
|
||
RecvWxid: &wechat.SKBuiltinString{
|
||
Str: proto.String(item.ToUserName),
|
||
},
|
||
MsgType: proto.Uint32(3),
|
||
SenderWxid: &wechat.SKBuiltinString{
|
||
Str: proto.String(userInfo.GetUserName()),
|
||
},
|
||
StartPos: proto.Uint32(0),
|
||
ReqTime: proto.Uint32(uint32(time.Now().Unix())),
|
||
EncryVer: proto.Uint32(1),
|
||
Data: &wechat.SKBuiltinString_{
|
||
Len: proto.Uint32(0),
|
||
Buffer: []byte{},
|
||
},
|
||
MessageExt: proto.String("png"),
|
||
}
|
||
|
||
// 打包发送数据
|
||
srcData, _ := proto.Marshal(req)
|
||
sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeForwardCdnImage, 5)
|
||
resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadmsgimg", sendEncodeData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return DecodePackHeader(resp, nil)
|
||
}
|
||
|
||
// ForwardCdnVideoRequest 转发Cdn视频
|
||
func ForwardCdnVideoRequest(userInfo *baseinfo.UserInfo, item baseinfo.ForwardVideoItem) (*baseinfo.PackHeader, error) {
|
||
req := &wechat.UploadVideoRequest{
|
||
BaseRequest: GetBaseRequest(userInfo),
|
||
ClientMsgId: proto.String(func() string {
|
||
userMd5 := strings.ToLower(baseutils.Md5Value(userInfo.GetUserName() + "-" + item.ToUserName)[:16])
|
||
videokey := strconv.FormatInt(time.Now().UnixNano()/10000, 10) + "baed6285091"
|
||
filekey := fmt.Sprintf("aupvideo_%s_%d_%s", userMd5, time.Now().UnixNano()/10000, videokey)
|
||
return filekey
|
||
}()),
|
||
FromUserName: proto.String(userInfo.GetUserName()),
|
||
ToUserName: proto.String(item.ToUserName),
|
||
|
||
AESKey: proto.String(item.AesKey),
|
||
CDNThumbAESKey: proto.String(item.AesKey),
|
||
CDNThumbImgHeight: proto.Int32(120),
|
||
CDNThumbImgWidth: proto.Int32(120),
|
||
CDNThumbUrl: proto.String(item.CdnVideoUrl),
|
||
CDNVideoUrl: proto.String(item.CdnVideoUrl),
|
||
EncryVer: proto.Int32(1),
|
||
ThumbData: &wechat.BufferT{
|
||
ILen: proto.Uint32(0),
|
||
Buffer: []byte{},
|
||
},
|
||
VideoData: &wechat.BufferT{
|
||
ILen: proto.Uint32(0),
|
||
Buffer: []byte{},
|
||
},
|
||
MsgForwardType: proto.Uint32(1),
|
||
CameraType: proto.Uint32(2),
|
||
MsgSource: proto.String(""),
|
||
FuncFlag: proto.Uint32(0),
|
||
ThumbTotalLen: proto.Uint32(uint32(item.CdnThumbLength)),
|
||
VideoTotalLen: proto.Uint32(uint32(item.Length)),
|
||
VideoStartPos: proto.Uint32(0),
|
||
ThumbStartPos: proto.Uint32(0),
|
||
PlayLength: proto.Uint32(uint32(item.PlayLength)),
|
||
VideoFrom: proto.Int32(0),
|
||
NetworkEnv: proto.Uint32(1),
|
||
ReqTime: proto.Uint32(uint32(time.Now().Unix())),
|
||
}
|
||
// 打包发送数据
|
||
srcData, _ := proto.Marshal(req)
|
||
sendEncodeData := Pack(userInfo, srcData, baseinfo.MMRequestTypeForwardCdnVideo, 5)
|
||
resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/uploadvideo", sendEncodeData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return DecodePackHeader(resp, nil)
|
||
}
|
||
|
||
// SendCdnUploadImageReuqestWithSource 发送CDN上传图片请求
|
||
func SendCdnUploadImageReuqestWithSource(userInfo *baseinfo.UserInfo, toUser string, imgData []byte, sourceValue uint32) (*baseinfo.CdnImageUploadResponse, string, error) {
|
||
imgItem := &baseinfo.UploadImgItem{}
|
||
imgItem.ToUser = toUser
|
||
imgItem.Seq = uint32(rand.Intn(10))
|
||
imgItem.LocalName = strconv.Itoa(rand.Intn(100))
|
||
imgItem.ExtName = ".pic"
|
||
// 随机生成AesKey
|
||
imgItem.AesKey = []byte(baseutils.RandomStringByLength(16))
|
||
aesKeyHex := hex.EncodeToString(imgItem.AesKey)
|
||
imgItem.ImageData = imgData
|
||
imgItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
|
||
// 设置Dns路由信息
|
||
imgItem.CDNDns = userInfo.FAKEDnsInfo
|
||
|
||
// 创建上传图片请求
|
||
request := &baseinfo.CdnImageUploadRequest{}
|
||
request.Ver = 1
|
||
request.WeiXinNum = uint32(imgItem.CDNDns.GetUin())
|
||
request.Seq = imgItem.Seq
|
||
if !strings.HasPrefix(userInfo.LoginDataInfo.LoginData, "A") && userInfo.DeviceInfo != nil {
|
||
request.ClientOsType = userInfo.DeviceInfo.OsType
|
||
request.ClientVersion = userInfo.ClientVersion
|
||
if !(int(request.ClientVersion) > 0) {
|
||
request.ClientVersion = baseinfo.ClientVersion
|
||
}
|
||
} else {
|
||
request.ClientOsType = baseinfo.AndroidDeviceType
|
||
request.ClientVersion = baseinfo.AndroidClientVersion
|
||
}
|
||
request.AuthKey = imgItem.CDNDns.AuthKey.GetBuffer()
|
||
request.NetType = 1
|
||
request.AcceptDupack = 1
|
||
request.SafeProto = 1
|
||
request.FileType = 2
|
||
request.WxChatType = 0
|
||
request.LastRetCode = 0
|
||
request.IPSeq = 0
|
||
request.CliQuicFlag = 0
|
||
request.CompressType = 0
|
||
request.NoCheckAesKey = 1
|
||
request.EnableHit = 1
|
||
request.ExistAnceCheck = 0
|
||
request.AppType = 1
|
||
request.LocalName = imgItem.LocalName + imgItem.ExtName
|
||
request.Offset = 0
|
||
request.LargesVideo = 0
|
||
request.SourceFlag = 0
|
||
request.AdVideoFlag = 0
|
||
|
||
// ToUser
|
||
retBytes := baseutils.AesEncrypt([]byte(imgItem.ToUser), []byte("wxusrname2016cdn"))
|
||
request.ToUser = "@cdn2_" + baseutils.BytesToHexString(retBytes, false)
|
||
|
||
// request.HasThumb = 0
|
||
// request.ThumbData = nil
|
||
// ThumbData
|
||
thumbItem := CreateThumbImage(imgItem.ImageData)
|
||
if thumbItem == nil {
|
||
return nil, "", errors.New("生成缩略图失败")
|
||
}
|
||
thumbEncodeData := baseutils.AesEncryptECB(imgItem.ImageData, []byte(imgItem.AesKey))
|
||
request.HasThumb = 1
|
||
request.ThumbTotalSize = uint32(len(thumbEncodeData))
|
||
request.RawThumbSize = uint32(len(imgItem.ImageData))
|
||
request.RawThumbMD5 = baseutils.Md5ValueByte(imgItem.ImageData, false)
|
||
request.EncThumbCRC = baseutils.Adler32(0, thumbEncodeData)
|
||
request.ThumbData = thumbEncodeData
|
||
|
||
// FileKey
|
||
request.FileKey = "wxupload_" + imgItem.ToUser + imgItem.LocalName + "_" + strconv.Itoa(int(imgItem.CreateTime))
|
||
|
||
// FileData
|
||
fileEncodeData := baseutils.AesEncryptECB(imgItem.ImageData, []byte(imgItem.AesKey))
|
||
request.TotalSize = uint32(len(fileEncodeData))
|
||
request.RawTotalSize = uint32(len(imgItem.ImageData))
|
||
request.FileMD5 = baseutils.Md5ValueByte(fileEncodeData, false)
|
||
request.RawFileMD5 = baseutils.Md5ValueByte(imgItem.ImageData, false)
|
||
request.FileCRC = baseutils.Adler32(0, imgItem.ImageData)
|
||
request.DataCheckSum = baseutils.Adler32(0, fileEncodeData)
|
||
request.FileData = fileEncodeData
|
||
request.SetOfPicFormat = "111000"
|
||
|
||
// prepareRequestItem
|
||
var prepareRequestItem baseinfo.CDNUploadMsgImgPrepareRequestItem
|
||
prepareRequestItem.ToUser = imgItem.ToUser
|
||
prepareRequestItem.LocalName = imgItem.LocalName
|
||
prepareRequestItem.CreateTime = imgItem.CreateTime
|
||
prepareRequestItem.ThumbWidth = thumbItem.Width
|
||
prepareRequestItem.ThumbHeight = thumbItem.Height
|
||
prepareRequestItem.AesKey = imgItem.AesKey
|
||
prepareRequestItem.Crc32 = request.FileCRC
|
||
|
||
// SessionBuf - 使用自定义 source 值
|
||
request.SessionBuf = CreateCDNUploadMsgImgPrepareRequestWithSource(userInfo, &prepareRequestItem, sourceValue)
|
||
|
||
// 打包请求
|
||
sendData := PackCdnImageUploadRequest(request)
|
||
// 连接Cdn服务器
|
||
serverIP := imgItem.CDNDns.FrontIplist[0].GetStr()
|
||
serverPort := imgItem.CDNDns.FrontIpportList[0].PortList[0]
|
||
conn, err := ConnectCdnServer(serverIP, serverPort)
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
// 发送数据
|
||
conn.Write(sendData)
|
||
defer conn.Close()
|
||
|
||
retryCount := uint32(0)
|
||
// 接收响应信息
|
||
sendImgLen := uint32(len(request.FileData))
|
||
var finalResponse *baseinfo.CdnImageUploadResponse
|
||
for {
|
||
// 接收响应信息,解析
|
||
retData := CDNRecvData(conn)
|
||
response, err := DecodeImageUploadResponse(retData)
|
||
if err != nil {
|
||
if retryCount < 3 {
|
||
retryCount++
|
||
continue
|
||
}
|
||
return nil, "", err
|
||
}
|
||
|
||
retryCount = 0
|
||
// 判断错误码
|
||
if response.RetCode != 0 {
|
||
return nil, "", errors.New("发送图片失败: ErrCode = " + GetErrStringByRetCode(response.RetCode))
|
||
}
|
||
|
||
// 判断 服务器是否接收完毕
|
||
if response.RecvLen < sendImgLen {
|
||
continue
|
||
}
|
||
|
||
// SKeyResp CDNUploadMsgImgPrepareResponse的错误码
|
||
if response.SKeyResp != 0 {
|
||
return nil, "", errors.New("发送图片失败: SKeyResp = " + strconv.Itoa(int(response.SKeyResp)))
|
||
}
|
||
|
||
// SKeyBuf
|
||
skbufLen := len(response.SKeyBuf)
|
||
if skbufLen <= 0 {
|
||
continue
|
||
}
|
||
finalResponse = response
|
||
break
|
||
}
|
||
|
||
log.Printf("CDN上传图片响应 (source=%d): Ver=%d, Seq=%d, RetCode=%d, FileKey=%s, RecvLen=%d, FileID=%s",
|
||
sourceValue, finalResponse.Ver, finalResponse.Seq, finalResponse.RetCode, finalResponse.FileKey,
|
||
finalResponse.RecvLen, finalResponse.FileID)
|
||
|
||
// 设置 CDN URL
|
||
finalResponse.CdnBigImgUrl = finalResponse.FileID
|
||
finalResponse.CdnMidImgUrl = finalResponse.FileID
|
||
finalResponse.CdnThumbImgUrl = finalResponse.FileID
|
||
|
||
return finalResponse, aesKeyHex, nil
|
||
}
|