using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using CsharpHttpHelper; using CsharpHttpHelper.Enum; using Microsoft.ClearScript.V8; using Newtonsoft.Json.Linq; namespace Api.Framework.Tools { /// /// 快手解析助手 /// public class KSHelper { /// /// 解析商品内容获取Id /// /// /// public static string GetItemId(string str, out string title) { #region 解析链接 if (Regex.IsMatch(str, @"((?:https://a6chq\.ogwormb\.com)|(?:(https://ac31\.suvmothq\.com)))", RegexOptions.IgnoreCase)) { var url = HttpExtend.RegexMatchUrl(str); str = CsharpHttpHelper.HttpExtend.GetLocationUrl(url); } var reg = Regex.Match(str, @"https:\/\/cps\.kwaixiaodian\.com\/page\/kwaimoney\/promotion\/goods\/detail\/(?<商品ID>\d+)", RegexOptions.ExplicitCapture); if (!reg.Success) reg = Regex.Match(str, @"package-shop/pages/goods/main.*?[\?&]id=(?<商品ID>\d+)", RegexOptions.IgnoreCase | RegexOptions.Multiline); if (!reg.Success) reg = Regex.Match(str, @"page/kwaishop-buyer-goods-detail.*?[\?&]id=(?<商品ID>\d+)", RegexOptions.IgnoreCase | RegexOptions.Multiline); if (reg.Success) { title = string.Empty; return reg.Groups["商品ID"].Value; } #endregion #region 解析解析口令 //##X7poMxtqkJLk21g## reg = Regex.Match(str, @"((?:##)|(?:[^a-zA-Z0-9-]))(?<口令>X[a-zA-Z0-9-]{13,15})((?:##)|(?:[^a-zA-Z0-9-]))", RegexOptions.IgnoreCase); if (reg.Success) { var result = AnalysisKl(reg.Groups["口令"].Value); //....解析操作 #region 数据结构 //{"result":1,"hostName":"zt-zl-rs296.idczw.hb1.kwaidc.com","cache-scope":"nocache","error_msg":null,"showDialog":{"originKpn":"KUAISHOU","originSubBiz":"GOODS_DETAILS_OF_NATIVE","kpn":"KUAISHOU","subBiz":"share","kwaiUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareToken=X7WKCOoS0M6bgoi&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","dialog":{"subTitle":"来快手看看这个商品吧","footerText":"来自好友的分享,查看他","actionButtonTargetUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","shareId":"16956809344990","footerTargetUrl":"kwai://profile/2430851481?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","shareObjectId":"4035974256190","iconUrl":"https://p3.eckwai.com/bs2/image-kwaishop-product/item-2763666190-185a99e1c95847b39e39ad59f34c94cf.jpg","iconTargetUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","title":"1元 快乐旺哥草莓蛋糕【拼满19.9包邮发货】","actionButtonText":"去看看"},"oldShowType":0,"newShowTypes":["bigHeadDialog"],"extParams":{"kwaiUrl":"kwai://home","shareUrl":"/package-shop/pages/goods/main?id=4035974256190&layoutType=4&carrierType=24","iconUrl":"https://p3.eckwai.com/bs2/image-kwaishop-product/item-2763666190-185a99e1c95847b39e39ad59f34c94cf.jpg","title":"1元 快乐旺哥草莓蛋糕【拼满19.9包邮发货】","carrierId":"5","jumpUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?id=4035974256190&layoutType=4&carrierType=24"}},"max-age":0} #endregion var jObj = JObject.Parse(result); var jumpUrl = jObj?["showDialog"]?["dialog"]?["shareObjectId"]?.ToString(); if (!string.IsNullOrWhiteSpace(jumpUrl)) { title = jObj?["showDialog"]?["dialog"]?["title"]?.ToString(); return jumpUrl; } } #endregion title = string.Empty; return string.Empty; } #region 快手口令解析 /// /// Post参数 /// static string postParam = $"kpf=ANDROID_PHONE&shareMessage=内容&kpn=KUAISHOU&sdkVersion=1.14.0.0&theme=light&sessionId=8a19a62f-fa3c-4097-aae4-cdf0ec11c59d&extTransientParams={{\"source\":\"autoDetectPasteboard\"}}&launchState=firstColdLaunchToday"; /// /// 参数2 /// static string getParam = "kpf=ANDROID_PHONE&ver=9.7&gid=&mod=HUAWEI%28HWI-AL00%29&c=OPPO&oDid=TEST_ANDROID_dd6f96475163fa32&android_os=0&os=android&appver=9.7.30.21320&boardPlatform=hi3660&ftt=&kpn=KUAISHOU&subBiz=share&androidApiLevel=28&language=zh-cn&sys=ANDROID_9&mcc=46007&userId=0&memoryTotalSize=5725&did_tag=0&countryCode=CN&rdid=&net=WIFI&did="; /// /// 解析快手口令 /// /// /// public static string AnalysisKl(string content) { content = $"##{content}##"; var sign = GetKlSign(content); var param = postParam.Replace("内容", content) + $"&sig={sign}"; var url = $"https://api.kuaishouzt.com/rest/zt/share/show/any?{getParam}"; HttpHelper http = new HttpHelper(); HttpItem item = new HttpItem() { URL = url, Method = "post", IsToLower = false, Cookie = "", Referer = "", Postdata = param, Timeout = 100000, ReadWriteTimeout = 30000, UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", ContentType = "application/x-www-form-urlencoded", Allowautoredirect = false, ResultType = ResultType.String }; HttpResult result = http.GetHtml(item); string html = result.Html; //EventClient.OnEvent("", "口令解析:" + html); return html; } private static string GetKlSign(string content) { var paramC = $"{postParam.Replace("内容", content)}&{getParam}"; var deContent = System.Web.HttpUtility.UrlDecode(paramC); //var splits = deContent.Split('&').ToList(); //splits.Sort(); //var sortContent = string.Join("", splits); byte[] deContentAAscii = Encoding.ASCII.GetBytes(deContent); string deContentUtf8 = Encoding.UTF8.GetString(deContentAAscii); var sortContent = JsStrSort(deContentUtf8); var result = $"{sortContent}382700b563f4"; MD5 md5 = MD5.Create(); var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(result)); // 第五步:把二进制转化为大写的十六进制 StringBuilder strb = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { strb.Append(bytes[i].ToString("x2")); } return strb.ToString(); } private static string JsStrSort(string content) { return V8Method(JsSort, $"'{content}'", "getString"); } /// /// 使用V8引擎执行JS代码 /// /// JS代码 /// 当前方法需要的参数 /// 执行的JS方法名 /// private static string V8Method(string JsCode, string JsParam, string JsMethodName) { string result = string.Empty; try { using (var engine = new V8ScriptEngine()) { V8Script script = engine.Compile(JsCode); engine.Execute(script); result = engine.ExecuteCommand(string.Format("{0}({1})", JsMethodName, JsParam)); //其他写法 } } catch (Exception ex) { //result = ex.Message.ToString(); } return result; } private static string JsSort { get { return @"function getString(str){ var array; array = str.split('&'); array.sort(); return array.join(''); }"; } } #endregion } }