using MAX.Core.Autofac; using MAX.Core.Cryptography; using MAX.Core.DependencyInjection; using MAX.Core.Helpers; using MAX.Core.Logger; using Store.Client.Agent; using Store.Framework; using Store.Framework.Inerterfaces; using Store.Framework.Models; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; namespace Store.Client.HttpExtension { /// /// Store 基础 API 请求基类。 /// 项目 API 可以继承该基类并重写 ServiceConfigKey,使用项目自己的服务配置。 /// public class AppApiRequestBase { /// /// 日志。 /// [Autowired] protected ILoggerFacade _logger => LazyServiceProvider.Instance.LazyGetService(); protected IApiServerConfig _config => LazyServiceProvider.Instance.LazyGetService(); protected ICurrentUser CurrentUser => LazyServiceProvider.Instance.LazyGetService(); /// /// 默认服务请求。 /// protected HttpResult Post(string urlpath, string postdata = "") { return Request(BuildServiceUrl(urlpath), postdata); } /// /// 公共签名服务请求。 /// protected HttpResult PostPublic(string urlpath, string postdata = "") { return Request(BuildServiceUrl(urlpath), postdata, isUserSign: false); } /// /// 拼多多服务请求。 /// protected HttpResult PostPdd(string urlpath, string postdata = "") { return Request(BuildServiceUrl("bxx_" + urlpath), postdata); } /// /// 微信服务请求。 /// protected HttpResult PostWx(string urlpath, string postdata = "") { return Request(BuildServiceUrl("wxxd_" + urlpath), postdata); } /// /// 微信图片服务请求。 /// protected HttpResult PostWxImg(string urlpath, string postdata = "") { return Request(BuildServiceUrl("wxxd_" + urlpath), postdata); } /// /// 默认兼容服务请求。 /// protected HttpResult PostDefault(string urlpath, string postdata = "") { return Request(BuildServiceUrl(urlpath), postdata); } /// /// 使用当前 Key 构建服务请求地址。 /// protected string BuildServiceUrl(string urlPath) { return $"{_config.Host}/wxxd_{urlPath}?obj={Config.MainPath}/wxxd_{urlPath}"; } /// /// 创建并执行服务端请求,默认使用当前用户签名。 /// protected HttpResult Request(string url, string postdata = "", MethodType method = MethodType.Post, bool isUserSign = true) { HttpItem item = new HttpItem { URL = url, Method = method, Postdata = postdata ?? string.Empty }; ApplySign(item, isUserSign); return Send(item); } /// /// 服务器请求。 /// public HttpResult ServerRequest(HttpItem item) { if (item == null) { throw new ArgumentNullException(nameof(item)); } #if RELEASE item.WebProxy = null; #endif ApplySign(item, false); return Send(item); } /// /// 执行底层 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 (!item.URL.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { item.URL = _config.Host + "/" + item.URL.TrimStart('/'); } item.Encoding = Encoding.UTF8; HttpResult result = HttpHelper.Request(item); if (result.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(result.Html) && result.Html[0] == 65279) { result.Html = result.Html.Remove(0, 1); } return result; } /// /// 为请求添加公共签名或用户签名。 /// private void ApplySign(HttpItem item, bool isUserSign) { string sign = isUserSign ? GetUserSign("", "") : GetSign(); SetSign(item, sign); } /// /// 获取公共签名。 /// private static string GetSign() { long time = GetReviseUnix(); string code = Encryption(time); return "time=" + time + "&code=" + code + "&NbCodeVersion=1"; } /// /// 获取当前用户签名。 /// private string GetUserSign(string shopId, string shopName) { UserInfo user = CurrentUser.User; if (user == null) { throw new InvalidOperationException("当前用户未登录,无法生成用户签名。"); } long time = GetReviseUnix(); string code = Encryption(time); var dict = new Dictionary { { "time", time.ToString() }, { "code", code }, { "code_version", "1" }, { "version", Config.Version }, { "user_name", user.UserName }, { "path", Config.MainPath } }; if (!string.IsNullOrEmpty(AgentConfig.AgentCode)) { dict.Add("agent_code", AgentConfig.AgentCode); dict.Add("agent_name", AgentConfig.AgentName); } return string.Join("&", dict.Select(kv => $"{kv.Key}={kv.Value}")); } /// /// 获取校正后的时间戳。 /// protected static long GetReviseUnix() { return DateHelper.GetCurrentUnixTimestampInSeconds() + ServerConfig.TimeDifferent; } /// /// 签名算法。 /// /// 随机数 /// 加密签名结果 protected static string Encryption(long s) { string value = $"{s}sdhewu*/fhAAue48485ew5+5%@3485esGFFHFD"; return MD5Helper.Md5_32(value); } /// /// 将签名参数拼接到请求。 /// private static void SetSign(HttpItem item, string sign) { if (item.Method == MethodType.Get) { item.URL += item.URL.Contains("?") ? "&" : "?"; item.URL += sign; } else { item.Postdata = item.Postdata ?? string.Empty; if (item.Postdata.Length > 0) { item.Postdata += "&"; } item.Postdata += sign; } } } }