using MAX.Core.DependencyInjection; using MAX.Core.Helpers; using Store.Client.HttpExtension; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Store.Framework; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Store.Management.Framework.Apis; public class WXApi : ITransientDependency { private const string Host = "https://store.weixin.qq.com"; private const string WxUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"; private const string E57UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"; private const string JsonAccept = "application/json, text/plain, */*"; private const string HtmlAccept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"; private const string JsonContentType = "application/json"; private const string WxAcceptLanguage = "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"; private const string E57AcceptLanguage = "zh-CN,zh;q=0.9"; /// /// 执行底层 HTTP 请求。 /// protected HttpResult Send(HttpItem item) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (string.IsNullOrWhiteSpace(item.URL)) { throw new ArgumentException("请求地址不能为空。", nameof(item)); } #if RELEASE item.WebProxy = null; #endif if (!item.URL.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { item.URL = Host + "/" + item.URL.TrimStart('/'); } item.Encoding = Encoding.UTF8; if (item.PostEncoding == null) { item.PostEncoding = Encoding.UTF8; } HttpResult result = HttpHelper.Request(item); return result; } public HttpResult WeiXinAssistantPostResponse(string cookie, string url, string data, string referer) { HttpItem item = CreateWxItem(cookie, url, referer); AddCommonWxHeaders(item, string.Empty, GetCookieValue(cookie, "talent_magic")); PrepareJsonPost(item, data); return Send(item); } public HttpResult WeiXinPostResponse(string cookie, string url, string data, string referer) { HttpItem item = CreateWxItem(cookie, url, referer); AddCommonWxHeaders(item, GetCookieValue(cookie, "biz_magic"), string.Empty); PrepareJsonPost(item, data); return Send(item); } public HttpResult WeiXinTalentOpenKfPostResponse(string cookie, string url, string data, string referer) { HttpItem item = CreateWxItem(cookie, url, referer); AddCommonWxHeaders(item, GetCookieValue(cookie, "biz_magic"), string.Empty); item.Header["user_scene"] = "1002"; item.Header["kf_scene"] = "6"; item.Header["logistics_magic"] = string.Empty; PrepareJsonPost(item, data); return Send(item); } public HttpResult WeiXinImgPostResponse(string cookie, string url, string data, string disK, long disT, string ext, string openid, string referer = "https://store.weixin.qq.com/") { HttpItem item = CreateWxItem(cookie, url, referer); item.Header["sec-ch-ua-platform"] = "\"Windows\""; item.Header["sec-ch-ua"] = "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\""; item.Header["sec-ch-ua-mobile"] = "?0"; item.Header["X-Requested-With"] = "XMLHttpRequest"; item.Header["X-Arguments"] = "dis_k=" + disK + "&dis_t=" + disT.ToString(CultureInfo.InvariantCulture) + "&ext=" + ext + "&apptype=160&filetype=20304&openid=" + openid + "&groupid=0&taskid=" + Guid.NewGuid().ToString(); item.Header["Origin"] = Host; item.Header["Sec-Fetch-Site"] = "same-site"; item.Header["Sec-Fetch-Mode"] = "cors"; item.Header["Sec-Fetch-Dest"] = "empty"; item.Header["Accept-Encoding"] = "gzip"; item.Header["Accept-Language"] = "zh-CN,zh;q=0.9"; item.Method = MethodType.Post; item.ContentType = JsonContentType; item.PostDataType = PostDataType.Byte; item.PostdataByte = System.Convert.FromBase64String(data ?? string.Empty); return Send(item); } public HttpResult WeiXinUploadResponse(string cookie, string url, string body, string boundaryStr, string referer) { HttpItem item = CreateWxItem(GetBizCookies(cookie), url, referer); AddCommonWxHeaders(item, GetCookieValue(cookie, "biz_magic"), string.Empty, includeMobileHeader: false); item.ContentType = "multipart/form-data; boundary=" + boundaryStr; item.Method = MethodType.Post; item.PostDataType = PostDataType.Byte; item.PostdataByte = BuildMultipartBody(body); return Send(item); } public HttpResult WeiXinGetResponse(string cookie, string url, string referer = "", bool isGetDocument = false) { string cookies = GetBizCookies(cookie); HttpItem item = CreateWxItem(cookies, url, isGetDocument ? string.Empty : referer, isGetDocument ? HtmlAccept : JsonAccept); if (isGetDocument) { item.Header["sec-ch-ua"] = "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\""; item.Header["sec-ch-ua-mobile"] = "?0"; item.Header["sec-ch-ua-platform"] = "\"Windows\""; item.Header["Upgrade-Insecure-Requests"] = "1"; item.Header["Sec-Fetch-Site"] = "none"; item.Header["Sec-Fetch-Mode"] = "navigate"; item.Header["Sec-Fetch-User"] = "?1"; item.Header["Sec-Fetch-Dest"] = "document"; } else { AddCommonWxHeaders(item, GetCookieValue(cookie, "biz_magic"), string.Empty); } return Send(item); } public HttpResult kdniaoPostResponse(string url, string data, string referer, Dictionary reqDic, string kdnAuth = null, string kdnAuthKey = "Auth") { HttpItem item = CreateWxItem(string.Empty, url, referer, "application/json, text/javascript, */*; q=0.01"); item.Header["sec-ch-ua-platform"] = "\"Windows\""; item.Header["sec-ch-ua"] = "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\""; item.Header["sec-ch-ua-mobile"] = "?0"; item.Header["Origin"] = "https://56.kdniao.com"; item.Header["Accept-Language"] = "zh-CN,zh;q=0.9"; item.Header["Sec-Fetch-Site"] = "same-site"; item.Header["Sec-Fetch-Mode"] = "cors"; item.Header["Sec-Fetch-Dest"] = "empty"; if (reqDic != null) { foreach (string key in reqDic.Keys) { if (item.Header.AllKeys.Contains(key, StringComparer.OrdinalIgnoreCase)) { continue; } item.Header[key] = reqDic[key]?.ToString() ?? string.Empty; } } item.Header["Accept-Encoding"] = "gzip"; item.Method = MethodType.Post; item.ContentType = "application/x-www-form-urlencoded"; item.Postdata = data ?? string.Empty; item.WebProxy = null; return Send(item); } public HttpResult e57PostResponse(string cookie, string url, string data, string referer, string authorization = null) { string token = ResolveAuthorization(cookie, authorization); HttpItem item = CreateE57Item(cookie, token, url, referer); item.Method = MethodType.Post; item.ContentType = JsonContentType; item.Postdata = data ?? string.Empty; return Send(item); } public HttpResult e57GetResponse(string cookie, string url, string referer) { string token = ResolveAuthorization(cookie, null); HttpItem item = CreateE57Item(cookie, token, url, referer); return Send(item); } #region WXUpload 业务接口 public HttpResult searchProduct(string cookie, string extCode, string extCode2 = "") { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/searchProduct?" + "token=&lang=zh_CN&pageSize=20&productStatus[]=-1&productSource=[1,16,32]&searchSource=1&useNew=true&pageNum=1&status[]=5&spuCode=" + extCode; if (!string.IsNullOrEmpty(extCode2)) { url += "," + extCode2; } return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/list?currentTab=PRODUCT_STATUS_ON"); } public HttpResult searchProductWithSpuId(string cookie, string spuId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/searchProduct?" + "token=&lang=zh_CN&pageSize=20&productStatus[]=-1&productSource=[1,16,32]&searchSource=1&useNew=true&pageNum=1&status[]=-1&spuId=" + spuId; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/list"); } public HttpResult searchProductWithTitle(string cookie, string urlEncodeTitle) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/searchProduct?" + "token=&lang=zh_CN&pageSize=20&productStatus[]=-1&productSource=[1,16,32]&searchSource=1&useNew=true&pageNum=1&status[]=-1&title=" + urlEncodeTitle; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/list"); } public HttpResult getUploadTempImgAuth(string cookie, int uploadScene = 3) { string url = "https://store.weixin.qq.com/shop-faas/mmecchannelspicture/cgi/getUploadTempImgAuth?token=&lang=zh_CN&uploadScene=" + uploadScene; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult adtimageupload(string cookie, string openid, string imgBase64, string disK, long disT, string ext) { return WeiXinImgPostResponse(cookie, "https://westorealpha.video.qq.com/adtimageupload", imgBase64, disK, disT, ext, openid, "https://store.weixin.qq.com/"); } public HttpResult getProductClassify(string cookie, string goodsName, List goodImgUrlsLst) { string boundaryStr = CreateBoundary(); string url = "https://store.weixin.qq.com/shop-faas/cgi/common/productClassify?from=B&title=" + WebUtility.UrlEncode(goodsName) + "&token=&lang=zh_CN"; string referer = "https://store.weixin.qq.com/shop/goods/entry"; string body = "--" + boundaryStr + "\r\n"; foreach (string imgFullPath in goodImgUrlsLst ?? new List()) { string fileName = Path.GetFileName(imgFullPath); body += "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n" + "Content-Type: image/jpeg\r\n\r\n" + "" + imgFullPath + "\r\n--" + boundaryStr; } body += "--\r\n"; return WeiXinUploadResponse(cookie, url, body, boundaryStr, referer); } public HttpResult getCategoryOnShelf(string cookie, List catIdLst, string brandId = "2100000000") { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/product/getCategoryOnShelfV2?token=&lang=zh_CN"; string body = "{\"catIdList\":[" + string.Join(",", catIdLst) + "],\"brandId\":" + brandId + "}"; return WeiXinPostResponse(cookie, url, body, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult getMixBrand(string cookie, string catId = "547591") { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/getMixBrand?token=&lang=zh_CN"; string body = "{\"categoryId\":\"" + catId + "\"}"; return WeiXinPostResponse(cookie, url, body, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult batchCheckCategoryRelation(string cookie, long catId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/product/batchCheckCategoryRelation?token=&lang=zh_CN"; string body = "{\"categoryIdList\":[" + catId + "]}"; return WeiXinPostResponse(cookie, url, body, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult addFinderCategoryV2(string cookie, long catId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/addFinderCategoryV2?token=&lang=zh_CN"; string body = "{\"categoryInfo\":{\"categories\":[{\"id\":\"" + catId + "\"}]},\"brandIdList\":[],\"leafCategoryId\":\"" + catId + "\",\"reuse\":0,\"applyType\":1}"; return WeiXinPostResponse(cookie, url, body, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult getSingleCategoryData(string cookie, long catId, List catIdLst) { string catIds = BuildQuotedArray(catIdLst); string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/getSingleCategoryData?token=&lang=zh_CN&categoryId=" + catId; string referer = "https://store.weixin.qq.com/shop/brandAndCat/category/apply?defaultCategoryIds=" + WebUtility.UrlEncode(catIds) + "&source=goods&type=apply"; return WeiXinGetResponse(cookie, url, referer); } public HttpResult wxCateAuth(string cookie, List catIdLst, string requestJson) { string catIds = BuildQuotedArray(catIdLst); string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/addFinderCategoryV2?token=&lang=zh_CN"; string referer = "https://store.weixin.qq.com/shop/brandAndCat/category/apply?defaultCategoryIds=" + WebUtility.UrlEncode(catIds) + "&source=goods&type=apply"; return WeiXinPostResponse(cookie, url, requestJson, referer); } public HttpResult genProductShortTitle(string cookie, string requestJson) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/common/cgi/goods/genProductShortTitle?token=&lang=zh_CN"; return WeiXinPostResponse(cookie, url, requestJson, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult getFreightTemplate(string cookie) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/express/cgi/goods/getFreightTemplate?token=&lang=zh_CN"; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult getAddress(string cookie, string searchText = "") { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeexpress/cgi/getAddress?token=&lang=zh_CN"; if (!string.IsNullOrEmpty(searchText)) { url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeexpress/cgi/getAddress?searchStr=" + WebUtility.UrlEncode(searchText) + "&token=&lang=zh_CN"; } return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult getAddressById(string cookie, string addressId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeexpress/cgi/getAddress?offset=0&limit=20&includeBlock=1&addressId=" + addressId + "&token=&lang=zh_CN"; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/address/expressAddressMgmt"); } public HttpResult uploadProductDraft(string cookie, string productJson) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/common/cgi/goods/uploadProductDraft?token=&lang=zh_CN"; productJson = SetJsonProperty(productJson, "type", 1); return WeiXinPostResponse(cookie, url, WrapData(productJson), "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult upProductV2(string cookie, string productJson) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/upProductV2?token=&lang=zh_CN"; return WeiXinPostResponse(cookie, url, WrapData(productJson), "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult checkProductUpload(string cookie, string productId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/checkUploadProductDraftStatus?token=&lang=zh_CN&productKey=%7B%22productId%22:" + productId + "%7D&preview=false"; string referer = "https://store.weixin.qq.com/shop/goods/entry?productId=" + productId + "&isUpdateAuditFree=0&source=list_edit&continueEditInfo=" + "{%22isEditingContinued%22:false,%22lastEditDraftTime%22:0,%22listingTime%22:0}"; return WeiXinGetResponse(cookie, url, referer); } public HttpResult SearchProductUpload(string cookie, string productId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/searchProduct?token=&lang=zh_CN&pageSize=20&productStatus[]=-1" + "&productSource=[1,16,32]&searchSource=1&useNew=true&fromProductManager=1&pageNum=1&status[]=2&spuId=" + productId; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/goods/list?currentTab=PRODUCT_STATUS_EDIT"); } public HttpResult upProductJObjectV2(string cookie, string prodStr) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/upProductV2?token=&lang=zh_CN"; return WeiXinPostResponse(cookie, url, WrapData(prodStr), "https://store.weixin.qq.com/shop/goods/entry"); } public HttpResult getEditProductV2(string cookie, string productId) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/getEditProductV2?token=&lang=zh_CN&productKey=%7B%22productId%22:" + productId + "%7D&needRealStock=true&preview=false&release=false"; string referer = "https://store.weixin.qq.com/shop/goods/entry?productId=" + productId + "&isUpdateAuditFree=0&source=list_edit&continueEditInfo={%22isEditingContinued%22:false,%22lastEditDraftTime%22:0,%22listingTime%22:0}"; return WeiXinGetResponse(cookie, url, referer); } public HttpResult initUploadPart(string cookie, string submitJson, string prodId, int time1, int time2) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodefiletransfer/filecos/initUploadPart?token=&lang=zh_CN"; string referer = BuildAuditFreeReferer(prodId, time1, time2); return WeiXinPostResponse(cookie, url, submitJson, referer); } public HttpResult listingAuditFree(string cookie, string productJson, string prodId, int time1, int time2) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/listingAuditFree?token=&lang=zh_CN"; string referer = BuildAuditFreeReferer(prodId, time1, time2); return WeiXinPostResponse(cookie, url, WrapData(productJson), referer); } public HttpResult uploadPartBinary(string cookie, string initFileName, string blobPath, string uploadId, string prodId, int time1, int time2) { string boundaryStr = CreateBoundary(); string url = "https://store.weixin.qq.com/shop-faas/mmecnodefiletransfer/filecos/uploadPartBinary?token=&lang=zh_CN"; string referer = BuildAuditFreeReferer(prodId, time1, time2); string body = "--" + boundaryStr + "\r\n" + "Content-Disposition: form-data; name=\"name\"\r\n\r\n" + initFileName + "\r\n" + "--" + boundaryStr + "\r\n" + "Content-Disposition: form-data; name=\"uploadId\"\r\n\r\n" + uploadId + "\r\n" + "--" + boundaryStr + "\r\n" + "Content-Disposition: form-data; name=\"partSeq\"\r\n\r\n1\r\n" + "--" + boundaryStr + "\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"blob\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n" + "" + blobPath + "\r\n--" + boundaryStr + "--\r\n"; return WeiXinUploadResponse(cookie, url, body, boundaryStr, referer); } public HttpResult completeUploadPart(string cookie, string completeJson, string prodId, int time1, int time2) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodefiletransfer/filecos/completeUploadPart?token=&lang=zh_CN"; string referer = BuildAuditFreeReferer(prodId, time1, time2); return WeiXinPostResponse(cookie, url, completeJson, referer); } public HttpResult addAddress(string cookie, string provinceName, string cityName, string countyName, string detailInfo, string userName, string telNumber) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeexpress/address/addAddress?token=&lang=zh_CN"; string address = JsonConvert.SerializeObject(new { addressInfo = new { provinceName, cityName, countyName, detailInfo, userName, telNumber, location = new JObject() }, defaultSend = 0, defaultRecv = 0 }); return WeiXinPostResponse(cookie, url, WrapData(address), "https://store.weixin.qq.com/shop/address/expressAddressMgmt"); } public HttpResult GetApiServiceList(string cookie) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodeservicemarket/service/GetMyServiceList?offset=0&limit=20&status=2&token=&lang=zh_CN"; return WeiXinGetResponse(cookie, url, "https://store.weixin.qq.com/shop/servicemarket/myServices?status=2"); } public HttpResult GetAndUpdateWebStatus(string cookie) { string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradehome/home/getAndUpdateWebStatus?token=&lang=zh_CN"; long startMs = ToTimestampMilliseconds(DateTime.Now.Date.AddDays(-1)); long endMs = ToTimestampMilliseconds(DateTime.Now.Date.AddSeconds(-1)); string body = "{\"timeQuery\":{\"startMs\":" + startMs + ",\"endMs\":" + endMs + "}}"; return WeiXinPostResponse(cookie, url, body, "https://store.weixin.qq.com/shop/home"); } public HttpResult addLeagueItemForUpdatingProduct(string cookie, int itemSwitch, int itemRatio, int headSupplierItemSwitch, int headSupplierItemRatio, long prodId, int updType = 2) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/common/cgi/goods/addLeagueItemForUpdatingProduct?token=&lang=zh_CN"; string body = "{\"itemSwitch\":" + itemSwitch + ",\"itemRatio\":" + itemRatio + ",\"headSupplierPublicItemSwitch\":" + headSupplierItemSwitch + ",\"headSupplierPublicItemServiceRatio\":" + headSupplierItemRatio + ",\"productId\":" + prodId + ",\"scene\":2,\"updType\":" + updType + "}"; return WeiXinPostResponse(cookie, url, body, "https://store.weixin.qq.com/shop/home"); } public HttpResult generalProductInfoRecommend(string cookie, string productId, string requestJson) { string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/aiRecommendCompat/cgi/goods/generalProductInfoRecommend?token=&lang=zh_CN"; string referer = "https://store.weixin.qq.com/shop/goods/entry?productId=" + productId + "&isUpdateAuditFree=0&source=list_edit&continueEditInfo={%22isEditingContinued%22:false,%22lastEditDraftTime%22:0,%22listingTime%22:0}"; return WeiXinPostResponse(cookie, url, requestJson, referer); } public HttpResult wxGetAssistant(string cookie, string prodId, string pageContext = null, string spu_id = null) { var NULL = (object)null; string url = "https://store.weixin.qq.com/shop-faas/mmeckolpoolnode/ecSearchSelectionSpuItems?token=&lang=zh_CN"; string referer = "https://store.weixin.qq.com/talent/pool/home"; if (!string.IsNullOrEmpty(prodId)) { referer += "?keyword=" + prodId; } object data = new { filter = new { spuFilter = new { monthlySalesRange = NULL, goodEvaluationRatioRange = NULL, shopScoreRange = NULL }, spuSort = new { sortOrder = 0, sortType = 0 }, category = NULL }, pageContext = new { pageContext = pageContext, limit = 15 }, requestContext = new { sessionId = DateHelper.GetUnixTimestampInMilliseconds(DateTime.Now.AddSeconds(-RandomHelper.GetRandomNumber(10, 100))), requestId = DateHelper.GetUnixTimestampInMilliseconds(DateTime.Now), parentSearchId = 53, displayedSpus = string.IsNullOrEmpty(spu_id) ? NULL : new { spuId = spu_id, } }, keyword = prodId }; string body = JsonConvert.SerializeObject(data); var result = WeiXinAssistantPostResponse(cookie, url, body, referer); return result; } #endregion private static HttpItem CreateWxItem(string cookie, string url, string referer, string accept = JsonAccept) { return new HttpItem { URL = url, Cookie = cookie ?? string.Empty, Referer = referer ?? string.Empty, KeepAlive = true, Expect100Continue = false, UserAgent = WxUserAgent, Accept = accept, PostEncoding = Encoding.UTF8 }; } private static HttpItem CreateE57Item(string cookie, string token, string url, string referer) { HttpItem item = new HttpItem { URL = url, Cookie = BuildAuthorizationCookie(cookie, token), KeepAlive = true, Expect100Continue = false, UserAgent = E57UserAgent, Accept = HtmlAccept, PostEncoding = Encoding.UTF8, WebProxy = null }; if (url != null && url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { item.ProtocolVersion = HttpVersion.Version10; } item.Header["sec-ch-ua"] = "\"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"144\", \"Google Chrome\";v=\"144\""; item.Header["sec-ch-ua-mobile"] = "?0"; item.Header["sec-ch-ua-platform"] = "\"Windows\""; item.Header["Upgrade-Insecure-Requests"] = "1"; item.Header["Authorization"] = "Bearer " + token; item.Header["Sec-Fetch-Site"] = "none"; item.Header["Sec-Fetch-Mode"] = "navigate"; item.Header["Sec-Fetch-User"] = "?1"; item.Header["Sec-Fetch-Dest"] = "document"; item.Header["Accept-Encoding"] = "gzip"; item.Header["Accept-Language"] = E57AcceptLanguage; return item; } private static void AddCommonWxHeaders(HttpItem item, string bizMagic, string talentMagic, bool includeMobileHeader = true) { item.Header["wecom_magic"] = string.Empty; item.Header["sec-ch-ua-platform"] = "\"Windows\""; item.Header["supplier_magic"] = string.Empty; item.Header["sec-ch-ua"] = "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\""; if (includeMobileHeader) { item.Header["sec-ch-ua-mobile"] = "?0"; } item.Header["potter-scene"] = "weixinShop"; item.Header["biz_magic"] = bizMagic ?? string.Empty; item.Header["talent_magic"] = talentMagic ?? string.Empty; item.Header["mcn_magic"] = string.Empty; item.Header["Origin"] = Host; item.Header["Sec-Fetch-Site"] = "same-origin"; item.Header["Sec-Fetch-Mode"] = "cors"; item.Header["Sec-Fetch-Dest"] = "empty"; item.Header["Accept-Encoding"] = "gzip"; item.Header["Accept-Language"] = WxAcceptLanguage; } private static void PrepareJsonPost(HttpItem item, string data) { item.Method = MethodType.Post; item.ContentType = JsonContentType; item.Postdata = data ?? string.Empty; } private static string CreateBoundary() { return "----WebKitFormBoundary" + Guid.NewGuid().ToString("N").Substring(0, 16); } private static string BuildQuotedArray(List values) { return "[\"" + string.Join("\",\"", values ?? new List()) + "\"]"; } private static string WrapData(string data) { return JsonConvert.SerializeObject(new { data = data ?? string.Empty }); } private static string SetJsonProperty(string json, string propertyName, JToken value) { if (string.IsNullOrWhiteSpace(json)) { return json; } try { JObject obj = JObject.Parse(json); obj[propertyName] = value; return obj.ToString(Formatting.None); } catch { return json; } } private static string BuildAuditFreeReferer(string prodId, int time1, int time2) { return "https://store.weixin.qq.com/shop/goods/entry?productId=" + prodId + "&isUpdateAuditFree=1&source=list_audit_free&continueEditInfo=" + "{%22isEditingContinued%22:true,%22lastEditDraftTime%22:" + time1 + "," + "%22listingTime%22:" + time2 + "}"; } private static long ToTimestampMilliseconds(DateTime time) { DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); return (long)(time - startTime).TotalMilliseconds; } private static string GetCookieValue(string cookie, string name) { if (string.IsNullOrWhiteSpace(cookie)) { return string.Empty; } foreach (string part in cookie.Split(';')) { string value = part.Trim(); int index = value.IndexOf('='); if (index <= 0) { continue; } string key = value.Substring(0, index).Trim(); if (key.Equals(name, StringComparison.OrdinalIgnoreCase)) { return value.Substring(index + 1).Trim(); } } return string.Empty; } private static string GetBizCookies(string cookie) { if (string.IsNullOrWhiteSpace(cookie)) { return string.Empty; } return string.Join(";", cookie .Split(';') .Select(part => part.Trim()) .Where(part => { int index = part.IndexOf('='); return index > 0 && part.Substring(0, index).Trim().StartsWith("biz", StringComparison.OrdinalIgnoreCase); })); } private static string ResolveAuthorization(string cookie, string authorization) { if (!string.IsNullOrWhiteSpace(authorization)) { string value = authorization.Trim(); return value.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase) ? value.Substring("Bearer ".Length).Trim() : value; } string token = GetCookieValue(cookie, "Admin-Token"); if (!string.IsNullOrWhiteSpace(token)) { return token; } return string.IsNullOrWhiteSpace(cookie) ? string.Empty : cookie.Trim(); } private static string BuildAuthorizationCookie(string cookie, string token) { if (!string.IsNullOrWhiteSpace(cookie) && cookie.IndexOf('=') >= 0) { return cookie; } return string.IsNullOrWhiteSpace(token) ? string.Empty : "Admin-Token=" + token; } private static byte[] BuildMultipartBody(string body) { if (string.IsNullOrEmpty(body)) { return Array.Empty(); } using (MemoryStream stream = new MemoryStream()) { foreach (string part in Regex.Split(body, @"")) { byte[] bytes = File.Exists(part) ? File.ReadAllBytes(part) : Encoding.UTF8.GetBytes(part.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n")); stream.Write(bytes, 0, bytes.Length); } return stream.ToArray(); } } }