public ActionResult Post(PostModel postModel) { var maxRecordCount = 10; postModel.Token = Token; postModel.EncodingAESKey = EncodingAESKey; postModel.CorpId = CorpId; #region 用于生产环境测试原始数据 //var ms = new MemoryStream(); //Request.InputStream.CopyTo(ms); //ms.Seek(0, SeekOrigin.Begin); //var sr = new StreamReader(ms); //var xml = sr.ReadToEnd(); //var doc = XDocument.Parse(xml); //doc.Save(ServerUtility.ContentRootMapPath("~/App_Data/TestWork.log")); //return null; #endregion //自定义MessageHandler,对微信请求的详细判断操作都在这里面。 var messageHandler = new WorkCustomMessageHandler(Request.InputStream, postModel, maxRecordCount); if (messageHandler.RequestMessage == null) { //验证不通过或接受信息有错误 } try { //测试时可开启此记录,帮助跟踪数据,使用前请确保App_Data文件夹存在,且有读写权限。 messageHandler.SaveRequestMessageLog(); //记录 Request 日志(可选) messageHandler.Execute(); //执行微信处理过程(关键) messageHandler.SaveResponseMessageLog(); //记录 Response 日志(可选) //自动返回加密后结果 return(new FixWeixinBugWeixinResult(messageHandler));//为了解决官方微信5.0软件换行bug暂时添加的方法,平时用下面一个方法即可 } catch (Exception ex) { using (TextWriter tw = new StreamWriter(ServerUtility.ContentRootMapPath("~/App_Data/Work_Error_" + SystemTime.Now.Ticks + ".txt"))) { tw.WriteLine("ExecptionMessage:" + ex.Message); tw.WriteLine(ex.Source); tw.WriteLine(ex.StackTrace); //tw.WriteLine("InnerExecptionMessage:" + ex.InnerException.Message); if (messageHandler.FinalResponseDocument != null && messageHandler.FinalResponseDocument.Root != null) { tw.WriteLine(messageHandler.FinalResponseDocument.ToString()); } tw.Flush(); tw.Close(); } return(Content("")); } }
/// <summary> /// 微信MessageHandler事件处理,此代码的简化MessageHandler方法已由/CustomerMessageHandler/CustomerMessageHandler_Event.cs完成, /// 此方法不再更新 /// </summary> /// <param name="requestMessage"></param> /// <returns></returns> public ResponseMessageBase GetResponseMessage(RequestMessageEventBase requestMessage) { ResponseMessageBase responseMessage = null; switch (requestMessage.Event) { case Event.ENTER: { var strongResponseMessage = requestMessage.CreateResponseMessage <ResponseMessageText>(); strongResponseMessage.Content = "您刚才发送了ENTER事件请求。"; responseMessage = strongResponseMessage; break; } case Event.LOCATION: throw new Exception("暂不可用"); //break; case Event.subscribe: //订阅 { var strongResponseMessage = requestMessage.CreateResponseMessage <ResponseMessageText>(); //获取Senparc.Weixin.MP.dll版本信息 #if NET45 var dllPath = HttpContext.Current.Server.MapPath("~/bin/Senparc.Weixin.MP.dll"); #else //var dllPath = ServerUtility.ContentRootMapPath("~/bin/Release/netcoreapp2.2/Senparc.Weixin.MP.dll");//本地测试路径 var dllPath = ServerUtility.ContentRootMapPath("~/Senparc.Weixin.MP.dll"); //发布路径 #endif var fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath); var version = fileVersionInfo.FileVersion; strongResponseMessage.Content = string.Format( "欢迎关注【Senparc.Weixin.MP 微信公众平台SDK】,当前运行版本:v{0}。\r\n您还可以发送【位置】【图片】【语音】信息,查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com", version); responseMessage = strongResponseMessage; break; } case Event.unsubscribe: //退订 { //实际上用户无法收到非订阅账号的消息,所以这里可以随便写。 //unsubscribe事件的意义在于及时删除网站应用中已经记录的OpenID绑定,消除冗余数据。 var strongResponseMessage = requestMessage.CreateResponseMessage <ResponseMessageText>(); strongResponseMessage.Content = "有空再来"; responseMessage = strongResponseMessage; break; } case Event.CLICK: //菜单点击事件,根据自己需要修改 //这里的CLICK在此DEMO中不会被执行到,因为已经重写了OnEvent_ClickRequest break; default: throw new ArgumentOutOfRangeException(); } return(responseMessage); }
public ActionResult TestUploadMediaFile(string token, UploadMediaFileType type, int contentLength /*, HttpPostedFileBase postedFile*/) { var inputStream = Request.InputStream; if (contentLength != inputStream.Length) { return(Content("ContentLength不正确,可能接收错误!")); } if (token != "TOKEN") { return(Content("TOKEN不正确!")); } if (type != UploadMediaFileType.image) { return(Content("UploadMediaFileType不正确!")); } //储存文件,对比是否上传成功 using (FileStream ms = new FileStream(ServerUtility.ContentRootMapPath("~/TestUploadMediaFile.jpg"), FileMode.OpenOrCreate)) { inputStream.CopyTo(ms, 256); } return(Content("{\"type\":\"image\",\"media_id\":\"MEDIA_ID\",\"created_at\":123456789}")); }
public static string GetOpenTicket(string componentAppId) { //实际开发过程不一定要用文件记录,也可以用数据库。 var openTicketPath = ServerUtility.ContentRootMapPath("~/App_Data/OpenTicket"); string openTicket = null; var filePath = Path.Combine(openTicketPath, string.Format("{0}.txt", componentAppId)); if (File.Exists(filePath)) { using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { using (TextReader tr = new StreamReader(fs)) { openTicket = tr.ReadToEnd(); } } } else { throw new WeixinException("OpenTicket不存在!"); } //其他逻辑 return(openTicket); }
/// <summary> /// 处理视频请求 /// </summary> /// <param name="requestMessage"></param> /// <returns></returns> public override IResponseMessageBase OnVideoRequest(RequestMessageVideo requestMessage) { var responseMessage = CreateResponseMessage <ResponseMessageText>(); responseMessage.Content = "您发送了一条视频信息,ID:" + requestMessage.MediaId; #region 材并推送到客户端 Task.Factory.StartNew(async() => { //上传素材 var dir = ServerUtility.ContentRootMapPath("~/App_Data/TempVideo/"); var file = await MediaApi.GetAsync(appId, requestMessage.MediaId, dir); var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, UploadMediaFileType.video, file, 50000); await CustomApi.SendVideoAsync(appId, base.OpenId, uploadResult.media_id, "这是您刚才发送的视频", "这是一条视频消息"); }).ContinueWith(async task => { if (task.Exception != null) { WeixinTrace.Log("OnVideoRequest()储存Video过程发生错误:", task.Exception.Message); var msg = string.Format("上传素材出错:{0}\r\n{1}", task.Exception.Message, task.Exception.InnerException != null ? task.Exception.InnerException.Message : null); await CustomApi.SendTextAsync(appId, base.OpenId, msg); } }); #endregion return(responseMessage); }
public async Task <IActionResult> Basic(BasicEdit from, IFormFile file) { try { if (!ModelState.IsValid) { SetMessager(MessageType.success, ModelState.FirstErrorMessage()); return(RedirectToAction("Index")); } string headImg = null; if (file != null) { headImg = $"/headImgs/headImg_{DateTime.Now.Ticks.ToString()}.{Path.GetExtension(file.FileName)}"; await FileExtension.Upload(file, ServerUtility.ContentRootMapPath(headImg)); } _accountService.ChangeBasic(FullAccount.Id, from.RealName, from.Email, headImg); SetMessager(MessageType.success, "修改基本信息成功"); } catch (System.Exception ex) { LogUtility.Account.Error(ex.Message, ex); SetMessager(MessageType.success, "修改基本信息失败"); } return(RedirectToAction("Index")); }
/// <summary> /// 处理语音请求 /// </summary> /// <param name="requestMessage"></param> /// <returns></returns> public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage) { var responseMessage = CreateResponseMessage <ResponseMessageMusic>(); //上传缩略图 //var accessToken = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret); var uploadResult = MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.image, ServerUtility.ContentRootMapPath("~/Images/Logo.jpg")); //设置音乐信息 responseMessage.Music.Title = "天籁之音"; responseMessage.Music.Description = "播放您上传的语音"; responseMessage.Music.MusicUrl = "https://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId; responseMessage.Music.HQMusicUrl = "https://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId; responseMessage.Music.ThumbMediaId = uploadResult.media_id; //推送一条客服消息 try { CustomApi.SendText(appId, OpenId, "本次上传的音频MediaId:" + requestMessage.MediaId); } catch { } return(responseMessage); }
public ActionResult PayNotifyUrl() { try { ResponseHandler resHandler = new ResponseHandler(HttpContext); string return_code = resHandler.GetParameter("return_code"); string return_msg = resHandler.GetParameter("return_msg"); string res = null; resHandler.SetKey(TenPyConfigRead.Key); //验证请求是否从微信发过来(安全) if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS") { res = "success";//正确的订单处理 //直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息! } else { res = "wrong";//错误的订单处理 } #region 记录日志 var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd"))); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8))); using (var fileStream = System.IO.File.OpenWrite(logPath)) { var notifyXml = resHandler.ParseXML(); //fileStream.Write(Encoding.Default.GetBytes(res), 0, Encoding.Default.GetByteCount(res)); fileStream.Write(Encoding.Default.GetBytes(notifyXml), 0, Encoding.Default.GetByteCount(notifyXml)); fileStream.Close(); } #endregion string xml = string.Format(@"<xml> <return_code><![CDATA[{0}]]></return_code> <return_msg><![CDATA[{1}]]></return_msg> </xml>", return_code, return_msg); return(Content(xml, "text/xml")); } catch (Exception ex) { WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex)); throw; } }
public void ContentRootMapPathTest() { var path = "~/App_Data/log.log"; var result = ServerUtility.ContentRootMapPath(path); Console.WriteLine(result); Assert.IsTrue(result.EndsWith(@"src\Senparc.CO2NET.Tests\App_Data\log.log")); }
private string GetWelcomeInfo() { //获取Senparc.Weixin.MP.dll版本信息 var filePath = ServerUtility.ContentRootMapPath("~/Senparc.Weixin.MP.dll");//发布路径 var fileVersionInfo = FileVersionInfo.GetVersionInfo(filePath); string version = fileVersionInfo == null ? "-" : string.Format("{0}.{1}.{2}", fileVersionInfo.FileMajorPart, fileVersionInfo.FileMinorPart, fileVersionInfo.FileBuildPart); return(string.Format( @"欢迎关注【Senparc.Weixin 微信公众平台SDK】,当前运行版本:v{0}。 您可以发送【文字】【位置】【图片】【语音】【文件】等不同类型的信息,查看不同格式的回复。 您也可以直接点击菜单查看各种类型的回复。 还可以点击菜单体验微信支付。 SDK官方地址:https://weixin.senparc.com SDK Demo:https://sdk.weixin.senparc.com 源代码及Demo下载地址:https://github.com/JeffreySu/WeiXinMPSDK Nuget地址:https://www.nuget.org/packages/Senparc.Weixin.MP QQ群:289181996 =============== 更多: 1、JSSDK测试:https://sdk.weixin.senparc.com/WeixinJSSDK 2、开放平台测试(建议PC上打开):https://sdk.weixin.senparc.com/OpenOAuth/JumpToMpOAuth 3、回复关键字: 【open】 进入第三方开放平台(Senparc.Weixin.Open)测试 【tm】 测试异步模板消息 【openid】 获取OpenId等用户信息 【约束】 测试微信浏览器约束 【AsyncTest】 异步并发测试 【错误】 体验发生错误无法返回正确信息 【容错】 体验去重容错 【ex】 体验错误日志推送提醒 【mute】 不返回任何消息,也无出错信息 【jssdk】 测试JSSDK图文转发接口 格式:【数字#数字】,如2010#0102,调用正则表达式匹配 【订阅】 测试“一次性订阅消息”接口 ", version)); }
public ActionResult Notice(PostModel postModel) { var logPath = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/Open/{0}/", SystemTime.Now.ToString("yyyy-MM-dd"))); if (!Directory.Exists(logPath)) { Directory.CreateDirectory(logPath); } //using (TextWriter tw = new StreamWriter(Path.Combine(logPath, string.Format("{0}_RequestStream.txt", SystemTime.Now.Ticks)))) //{ // using (var sr = new StreamReader(Request.InputStream)) // { // tw.WriteLine(sr.ReadToEnd()); // tw.Flush(); // } //} //Request.InputStream.Seek(0, SeekOrigin.Begin); try { postModel.Token = component_Token; postModel.EncodingAESKey = component_EncodingAESKey; //根据自己后台的设置保持一致 postModel.AppId = component_AppId; //根据自己后台的设置保持一致 var messageHandler = new CustomThirdPartyMessageHandler(Request.GetRequestMemoryStream(), postModel);//初始化 //注意:在进行“全网发布”时使用上面的CustomThirdPartyMessageHandler,发布完成之后使用正常的自定义的MessageHandler,例如下面一行。 //var messageHandler = new CommonService.CustomMessageHandler.CustomMessageHandler(Request.GetRequestMemoryStream(), // postModel, 10); //记录RequestMessage日志(可选) //messageHandler.EcryptRequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request.txt", SystemTime.Now.Ticks))); messageHandler.RequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_{1}.txt", SystemTime.Now.Ticks, messageHandler.RequestMessage.AppId))); messageHandler.Execute();//执行 //记录ResponseMessage日志(可选) using (TextWriter tw = new StreamWriter(Path.Combine(logPath, string.Format("{0}_Response_{1}.txt", SystemTime.Now.Ticks, messageHandler.RequestMessage.AppId)))) { tw.WriteLine(messageHandler.ResponseMessageText); tw.Flush(); tw.Close(); } return(Content(messageHandler.ResponseMessageText)); } catch (Exception ex) { throw; return(Content("error:" + ex.Message)); } }
/// <summary> /// 获取日志保存地址 /// </summary> /// <returns></returns> public string GetLogPath() { var logPath = ServerUtility.ContentRootMapPath($"~/App_Data/{this.MessageEntityEnlightener?.PlatformType.ToString()}/{ SystemTime.Now.ToString("yyyy-MM-dd")}/"); if (!Directory.Exists(logPath)) { Directory.CreateDirectory(logPath); } return(logPath); }
public string Download(string version, bool isWebVersion) { lock (Lock) { var config = GetConfig(); config.DownloadCount++; Save(config); } //打包下载文件 //FileStream fs = new FileStream(_context.ServerUtility.ContentRootMapPath(string.Format("~/App_Data/Document/Files/Senparc.Weixin-v{0}.rar", version)), FileMode.Open); //return fs; return(ServerUtility.ContentRootMapPath(string.Format("~/App_Data/Document/Files/Senparc.Weixin{0}-v{1}.rar", isWebVersion ? "-Web" : "", version))); }
/// <summary> /// 日志记录 /// </summary> /// <param name="msg"></param> private static void Log(string msg) { var logDir = ServerUtility.ContentRootMapPath($"~/App_Data/PayNotifyUrl/{SystemTime.Now:yyyyMMdd}"); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } var logPath = Path.Combine(logDir, $"{SystemTime.Now:yyyyMMdd}-{SystemTime.Now:HHmmss}-{Guid.NewGuid().ToString("n").Substring(0, 8)}.txt"); using (var fileStream = System.IO.File.OpenWrite(logPath)) { fileStream.Write(Encoding.Default.GetBytes(msg), 0, Encoding.Default.GetByteCount(msg)); fileStream.Close(); } }
public ActionResult WebLogList([DefaultValue(1)] int pageIndex) { int pageCount = 31; int skipRecord = Senparc.Scf.Core.Utility.Extensions.GetSkipRecord(pageIndex, pageCount); string logFileDir = ServerUtility.ContentRootMapPath("~/App_Data/Log/"); var dateDirs = Directory.GetDirectories(logFileDir, "Logs_*", SearchOption.TopDirectoryOnly); Log_WebLogListVD vd = new Log_WebLogListVD() { DateList = new PagedList <string>( dateDirs.OrderByDescending(z => z) .Select(z => Path.GetFileName(z).Split('_')[1]) .Skip(skipRecord) .Take(pageCount).ToList(), pageIndex, pageCount, dateDirs.Length, skipRecord) }; return(View(vd)); }
public VideoMediaIdResult GetVideoMediaIdResultTest() { var videoFilePath = ServerUtility.ContentRootMapPath("video-test.mp4"); Console.WriteLine("Video Path:" + videoFilePath); //上传视频 var uploadResult = MediaApi.UploadTemporaryMedia(_appId, UploadMediaFileType.video, videoFilePath); Console.WriteLine("Video Upload Result:" + uploadResult); string mediaId = uploadResult.media_id;//也可以通过对公众号发送视频获得 var result = GroupMessageApi.GetVideoMediaIdResult(_appId, mediaId, "test", "test"); Assert.IsNotNull(result); Console.WriteLine("GetVideoMediaIdResult" + result.ToJson()); Assert.IsNotNull(result.media_id); Assert.IsTrue(result.media_id.Length > 0); return(result); }
public string Download(string version, bool isWebVersion) { lock (Lock) { var config = GetConfig(); config.DownloadCount++; Save(config); } //打包下载文件 //FileStream fs = new FileStream(_context.ServerUtility.ContentRootMapPath(string.Format("~/App_Data/Document/Files/Senparc.Weixin-v{0}.rar", version)), FileMode.Open); //return fs; var filePath = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/Document/Files/Senparc.Weixin{0}-v{1}.rar", isWebVersion ? "-Web" : "", version)); if (!File.Exists(filePath)) { //使用.zip文件 filePath = filePath.Replace(".rar", ".zip"); } return(filePath); }
public ActionResult Get(string msg_signature = "", string timestamp = "", string nonce = "", string echostr = "") { //return Content(echostr); //返回随机字符串则表示验证通过 var verifyUrl = Work.Signature.VerifyURL(Token, EncodingAESKey, SuiteId, msg_signature, timestamp, nonce, echostr); if (verifyUrl != null) { var fileStream = System.IO.File.OpenWrite(ServerUtility.ContentRootMapPath("~/1.txt")); fileStream.Write(Encoding.Default.GetBytes(verifyUrl), 0, Encoding.Default.GetByteCount(verifyUrl)); fileStream.Close(); //return Content(verifyUrl); //返回解密后的随机字符串则表示验证通过 return(Content("Success")); } else { var fileStream = System.IO.File.OpenWrite(ServerUtility.ContentRootMapPath("~/1.txt")); fileStream.Write(Encoding.Default.GetBytes("asd"), 0, Encoding.Default.GetByteCount("asd")); fileStream.Close(); return(Content("如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。")); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSession();//使用Session(实践证明需要在配置 Mvc 之前) var builder = services.AddControllersWithViews() .AddNewtonsoftJson(); // 支持 NewtonsoftJson //.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_3_0); // Add CookieTempDataProvider after AddMvc and include ViewFeatures. services.AddSingleton <ITempDataProvider, CookieTempDataProvider>(); //如果部署在linux系统上,需要加上下面的配置: //services.Configure<KestrelServerOptions>(options => options.AllowSynchronousIO = true); //如果部署在IIS上,需要加上下面的配置: services.Configure <IISServerOptions>(options => options.AllowSynchronousIO = true); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddMemoryCache(); //使用本地缓存必须添加 services.AddSignalR(); //使用 SignalR -- DPBMARK WebSocket DPBMARK_END /* * CO2NET 是从 Senparc.Weixin 分离的底层公共基础模块,经过了长达 6 年的迭代优化,稳定可靠。 * 关于 CO2NET 在所有项目中的通用设置可参考 CO2NET 的 Sample: * https://github.com/Senparc/Senparc.CO2NET/blob/master/Sample/Senparc.CO2NET.Sample.netcore/Startup.cs */ services.AddSenparcWeixinServices(Configuration) //Senparc.Weixin 注册(必须) .AddSenparcWebSocket <CustomNetCoreWebSocketMessageHandler>() //Senparc.WebSocket 注册(按需) -- DPBMARK WebSocket DPBMARK_END ; //启用 WebApi(可选) services.AddAndInitDynamicApi(builder, options => options.DocXmlPath = ServerUtility.ContentRootMapPath("~/App_Data")); //此处可以添加更多 Cert 证书 //services.AddCertHttpClient("name", "pwd", "path"); }
public override string OnComponentVerifyTicketRequest(RequestMessageComponentVerifyTicket requestMessage) { var openTicketPath = ServerUtility.ContentRootMapPath("~/App_Data/OpenTicket"); if (!Directory.Exists(openTicketPath)) { Directory.CreateDirectory(openTicketPath); } //RequestDocument.Save(Path.Combine(openTicketPath, string.Format("{0}_Doc.txt", SystemTime.Now.Ticks))); //记录ComponentVerifyTicket(也可以存入数据库或其他可以持久化的地方) using (FileStream fs = new FileStream(Path.Combine(openTicketPath, string.Format("{0}.txt", RequestMessage.AppId)), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { using (TextWriter tw = new StreamWriter(fs)) { tw.Write(requestMessage.ComponentVerifyTicket); tw.Flush(); //tw.Close(); } } return(base.OnComponentVerifyTicketRequest(requestMessage)); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions <SenparcSetting> senparcSetting, IOptions <SenparcWeixinSetting> senparcWeixinSetting, IHubContext <ReloadPageHub> hubContext) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"node_modules")), RequestPath = new PathString("/node_modules") }); app.UseCookiePolicy(); app.UseMvc(); #region CO2NET // 启动 CO2NET 全局注册,必须! IRegisterService register = RegisterService.Start(env, senparcSetting.Value) //关于 UseSenparcGlobal() 的更多用法见 CO2NET Demo:https://github.com/Senparc/Senparc.CO2NET/blob/master/Sample/Senparc.CO2NET.Sample.netcore/Startup.cs .UseSenparcGlobal(); #region 全局缓存配置(按需) //当同一个分布式缓存同时服务于多个网站(应用程序池)时,可以使用命名空间将其隔离(非必须) register.ChangeDefaultCacheNamespace("SCFCache"); #region 配置和使用 Redis //配置全局使用Redis缓存(按需,独立) var redisConfigurationStr = senparcSetting.Value.Cache_Redis_Configuration; var useRedis = !string.IsNullOrEmpty(redisConfigurationStr) && redisConfigurationStr != "Redis配置"; if (useRedis) //这里为了方便不同环境的开发者进行配置,做成了判断的方式,实际开发环境一般是确定的,这里的if条件可以忽略 { /* 说明: * 1、Redis 的连接字符串信息会从 Config.SenparcSetting.Cache_Redis_Configuration 自动获取并注册,如不需要修改,下方方法可以忽略 * /* 2、如需手动修改,可以通过下方 SetConfigurationOption 方法手动设置 Redis 链接信息(仅修改配置,不立即启用) */ Senparc.CO2NET.Cache.Redis.Register.SetConfigurationOption(redisConfigurationStr); //以下会立即将全局缓存设置为 Redis Senparc.CO2NET.Cache.Redis.Register.UseKeyValueRedisNow(); //键值对缓存策略(推荐) //Senparc.CO2NET.Cache.Redis.Register.UseHashRedisNow();//HashSet储存格式的缓存策略 //也可以通过以下方式自定义当前需要启用的缓存策略 //CacheStrategyFactory.RegisterObjectCacheStrategy(() => RedisObjectCacheStrategy.Instance);//键值对 //CacheStrategyFactory.RegisterObjectCacheStrategy(() => RedisHashSetObjectCacheStrategy.Instance);//HashSet } //如果这里不进行Redis缓存启用,则目前还是默认使用内存缓存 #endregion #region 注册日志(按需,建议) register.RegisterTraceLog(ConfigTraceLog); //配置TraceLog #endregion #endregion #endregion #region Weixin 设置 /* 微信配置开始 * * 建议按照以下顺序进行注册,尤其须将缓存放在第一位! */ //注册开始 #region 微信缓存(按需,必须在 register.UseSenparcWeixin () 之前) //微信的 Redis 缓存,如果不使用则注释掉(开启前必须保证配置有效,否则会抛错) if (useRedis) { app.UseSenparcWeixinCacheRedis(); } #endregion //开始注册微信信息,必须! register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value) //注意:上一行没有 ; 下面可接着写 .RegisterXX() #region 注册公众号或小程序(按需) //注册公众号(可注册多个) .RegisterMpAccount(senparcWeixinSetting.Value, "SCF") .RegisterMpAccount("", "", "Senparc_Template") //注册多个公众号或小程序(可注册多个) //.RegisterWxOpenAccount(senparcWeixinSetting.Value, "【盛派网络小助手】小程序") //注册第三方平台(可注册多个) #region 注册第三方平台 .RegisterOpenComponent(senparcWeixinSetting.Value, //getComponentVerifyTicketFunc async componentAppId => { var dir = Path.Combine(ServerUtility.ContentRootMapPath("~/App_Data/OpenTicket")); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var file = Path.Combine(dir, string.Format("{0}.txt", componentAppId)); using (var fs = new FileStream(file, FileMode.Open)) { using (var sr = new StreamReader(fs)) { var ticket = await sr.ReadToEndAsync(); return(ticket); } } }, //getAuthorizerRefreshTokenFunc async(componentAppId, auhtorizerId) => { var dir = Path.Combine(ServerUtility.ContentRootMapPath("~/App_Data/AuthorizerInfo/" + componentAppId)); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var file = Path.Combine(dir, string.Format("{0}.bin", auhtorizerId)); if (!System.IO.File.Exists(file)) { return(null); } using (Stream fs = new FileStream(file, FileMode.Open)) { var binFormat = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); var result = (RefreshAuthorizerTokenResult)binFormat.Deserialize(fs); return(result.authorizer_refresh_token); } }, //authorizerTokenRefreshedFunc (componentAppId, auhtorizerId, refreshResult) => { var dir = Path.Combine(ServerUtility.ContentRootMapPath("~/App_Data/AuthorizerInfo/" + componentAppId)); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var file = Path.Combine(dir, string.Format("{0}.bin", auhtorizerId)); using (Stream fs = new FileStream(file, FileMode.Create)) { var binFormat = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); binFormat.Serialize(fs, refreshResult); fs.Flush(); } }, "【盛派网络】开放平台") #endregion //除此以外,仍然可以在程序任意地方注册公众号或小程序: //AccessTokenContainer.Register(appId, appSecret, name);//命名空间:Senparc.Weixin.MP.Containers #endregion #region 注册微信支付(按需) //注册最新微信支付版本(V3)(可注册多个) .RegisterTenpayV3(senparcWeixinSetting.Value, "SCF") //记录到同一个 SenparcWeixinSettingItem 对象中 #endregion ; #endregion #region .NET Core默认不支持GB2312 //http://www.mamicode.com/info-detail-2225481.html Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); #endregion #region Senparc.Core 设置 //用于解决HttpContext.Connection.RemoteIpAddress为null的问题 //https://stackoverflow.com/questions/35441521/remoteipaddress-is-always-null app.UseHttpMethodOverride(new HttpMethodOverrideOptions { //FormFieldName = "X-Http-Method-Override"//此为默认值 }); app.UseSenparcMvcDI(); //Senparc.Scf.Core.Config.SiteConfig.SenparcCoreSetting = senparcCoreSetting.Value;//网站设置 //提供网站根目录 if (env.ContentRootPath != null) { Senparc.Scf.Core.Config.SiteConfig.ApplicationPath = env.ContentRootPath; Senparc.Scf.Core.Config.SiteConfig.WebRootPath = env.WebRootPath; } #endregion #region 异步线程 { ////APM Ending 数据统计 //var utility = new APMNeuralDataThreadUtility(); //Thread thread = new Thread(utility.Run) { Name = "APMNeuralDataThread" }; //SiteConfig.AsynThread.Add(thread.Name, thread); } SiteConfig.AsynThread.Values.ToList().ForEach(z => { z.IsBackground = true; z.Start(); }); //全部运行 #endregion }
public ActionResult Post(PostModel postModel) { if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token)) { return(Content("参数错误!")); } postModel.Token = Token; //根据自己后台的设置保持一致 postModel.EncodingAESKey = EncodingAESKey; //根据自己后台的设置保持一致 postModel.AppId = WxOpenAppId; //根据自己后台的设置保持一致(必须提供) //v4.2.2之后的版本,可以设置每个人上下文消息储存的最大数量,防止内存占用过多,如果该参数小于等于0,则不限制 var maxRecordCount = 10; var logPath = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/WxOpen/{0}/", SystemTime.Now.ToString("yyyy-MM-dd"))); if (!Directory.Exists(logPath)) { Directory.CreateDirectory(logPath); } //自定义MessageHandler,对微信请求的详细判断操作都在这里面。 var messageHandler = new CustomWxOpenMessageHandler(Request.GetRequestMemoryStream(), postModel, maxRecordCount); try { /* 如果需要添加消息去重功能,只需打开OmitRepeatedMessage功能,SDK会自动处理。 * 收到重复消息通常是因为微信服务器没有及时收到响应,会持续发送2-5条不等的相同内容的RequestMessage*/ messageHandler.OmitRepeatedMessage = true; //测试时可开启此记录,帮助跟踪数据,使用前请确保App_Data文件夹存在,且有读写权限。 messageHandler.SaveRequestMessageLog(); //记录 Request 日志(可选) messageHandler.Execute(); //执行微信处理过程(关键) messageHandler.SaveResponseMessageLog(); //记录 Response 日志(可选) //return Content(messageHandler.ResponseDocument.ToString());//v0.7- return(new FixWeixinBugWeixinResult(messageHandler)); //为了解决官方微信5.0软件换行bug暂时添加的方法,平时用下面一个方法即可 //return new WeixinResult(messageHandler);//v0.8+ } catch (Exception ex) { using (TextWriter tw = new StreamWriter(ServerUtility.ContentRootMapPath("~/App_Data/Error_WxOpen_" + _getRandomFileName() + ".txt"))) { tw.WriteLine("ExecptionMessage:" + ex.Message); tw.WriteLine(ex.Source); tw.WriteLine(ex.StackTrace); //tw.WriteLine("InnerExecptionMessage:" + ex.InnerException.Message); if (messageHandler.ResponseDocument != null) { tw.WriteLine(messageHandler.ResponseDocument.ToString()); } if (ex.InnerException != null) { tw.WriteLine("========= InnerException ========="); tw.WriteLine(ex.InnerException.Message); tw.WriteLine(ex.InnerException.Source); tw.WriteLine(ex.InnerException.StackTrace); } tw.Flush(); tw.Close(); } return(Content("")); } }
/// <summary> /// NeuChar 请求 /// </summary> public virtual async Task <IResponseMessageBase> OnNeuCharRequestAsync(RequestMessageNeuChar requestMessage) { try { var path = ServerUtility.ContentRootMapPath("~/App_Data/NeuChar"); //SenparcTrace.SendCustomLog("OnNeuCharRequest path", path); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var file = Path.Combine(path, "NeuCharRoot.config"); bool success = true; string result = null; var configFileExisted = File.Exists(file); if (!configFileExisted) { using (var fs = new FileStream(file, FileMode.CreateNew)) { using (var sw = new StreamWriter(fs)) { await sw.WriteLineAsync(NeuralSystem.DEFAULT_CONFIG_FILE_CONENT).ConfigureAwait(false); } await fs.FlushAsync().ConfigureAwait(false); } } switch (requestMessage.NeuCharMessageType) { case NeuCharActionType.GetConfig: { if (configFileExisted) { //文件刚创建,但不再读取,此时读取可能会发生“无法访问已关闭文件”的错误 using (var fs = FileHelper.GetFileStream(file)) { using (var sr = new StreamReader(fs, Encoding.UTF8)) { var json = await sr.ReadToEndAsync().ConfigureAwait(false); result = json; } } } else { result = NeuralSystem.DEFAULT_CONFIG_FILE_CONENT; //TODO:初始化一个对象 } } break; case NeuCharActionType.SaveConfig: { var configRootJson = requestMessage.ConfigRoot; SenparcTrace.SendCustomLog("收到NeuCharRequest", "字符串长度:" + configRootJson.Length.ToString()); var configRoot = SerializerHelper.GetObject <ConfigRoot>(configRootJson); //这里只做序列化校验 //TODO:进行验证 if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var fileTemp = Path.Combine(path, $"NeuCharRoot.temp.{SystemTime.Now.ToString("yyyyMMdd-HHmmss")}.config"); //TODO:后期也可以考虑把不同模块分离到不同的文件中 using (var fs = new FileStream(fileTemp, FileMode.Create)) { using (var sw = new StreamWriter(fs)) { await sw.WriteAsync(configRootJson).ConfigureAwait(false); await sw.FlushAsync().ConfigureAwait(false); } } //历史文件备份,并替换临时文件 File.Move(file, file.Replace(".config", $".bak.{SystemTime.Now.ToString("yyyyMMdd-HHmmss")}.config")); File.Move(fileTemp, file); //刷新数据 var neuralSystem = NeuralSystem.Instance; neuralSystem.ReloadNode(); } break; case NeuCharActionType.CheckNeuChar: { //TODO:进行有效性检验 var configRoot = requestMessage.ConfigRoot?.GetObject <APMDomainConfig>(); if (configRoot == null || configRoot.Domain.IsNullOrWhiteSpace()) { success = false; result = "未指定 Domain!"; break; } var co2netDataOperation = new DataOperation(configRoot.Domain); //获取所有数据 var dataItems = await co2netDataOperation.ReadAndCleanDataItemsAsync(configRoot.RemoveData, true).ConfigureAwait(false); result = dataItems.ToJson(); } break; case NeuCharActionType.PushNeuCharAppConfig: //推送 NeuChar App 配置 { var configFileDir = Path.Combine(path, "AppConfig"); if (!Directory.Exists(configFileDir)) { Directory.CreateDirectory(configFileDir); //这里也可以不创建,除非是为了推送 } //还原一次,为了统一格式,并未后续处理提供能力(例如调整缩进格式) var requestData = requestMessage.RequestData.GetObject <PushConfigRequestData>(); var mainVersion = requestData.Version.Split('.')[0]; //主版本号 //配置文件路径:~/App_Data/NeuChar/AppConfig/123-v1.config var configFilePath = Path.Combine(configFileDir, $"{requestData.AppId}-v{mainVersion}.config"); using (var fs = new FileStream(configFilePath, FileMode.Create)) { using (var sw = new StreamWriter(fs, Encoding.UTF8)) { var json = requestData.Config.ToJson(true); //带缩进格式的 JSON 字符串 await sw.WriteAsync(json).ConfigureAwait(false); //写入 Json 文件 await sw.FlushAsync().ConfigureAwait(false); } } result = "OK"; } break; case NeuCharActionType.PullNeuCharAppConfig: //拉取 NeuCharApp 配置 { var requestData = requestMessage.RequestData.GetObject <PullConfigRequestData>(); var mainVersion = requestData.Version.Split('.')[0]; //主版本号 var configFileDir = Path.Combine(path, "AppConfig"); //配置文件路径:~/App_Data/NeuChar/AppConfig/123-v1.config var configFilePath = Path.Combine(configFileDir, $"{requestData.AppId}-v{mainVersion}.config"); if (!File.Exists(configFilePath)) { //文件不存在 result = $"配置文件不存在,请先推送或设置配置文件,地址:{configFilePath}"; success = false; } else { //读取内容 using (var fs = FileHelper.GetFileStream(configFilePath)) { using (var sr = new StreamReader(fs, Encoding.UTF8)) { var json = await sr.ReadToEndAsync().ConfigureAwait(false); //带缩进格式的 JSON 字符串(文件中的原样) result = json; } } } } break; default: break; } var successMsg = new { success = success, result = result }; TextResponseMessage = successMsg.ToJson(); } catch (Exception ex) { var errMsg = new { success = false, result = ex.Message }; TextResponseMessage = errMsg.ToJson(); } return(null); }
/// <summary> /// JS-SDK支付回调地址(在统一下单接口中设置notify_url) /// </summary> /// <returns></returns> public ActionResult PayNotifyUrl() { try { ResponseHandler resHandler = new ResponseHandler(HttpContext); string return_code = resHandler.GetParameter("return_code"); string return_msg = resHandler.GetParameter("return_msg"); string res = null; resHandler.SetKey(TenPayV3Info.Key); //验证请求是否从微信发过来(安全) if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS") { res = "success";//正确的订单处理 //直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息! } else { res = "wrong";//错误的订单处理 } /* 这里可以进行订单处理的逻辑 */ //发送支付成功的模板消息 try { string appId = Config.SenparcWeixinSetting.TenPayV3_AppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。 string openId = resHandler.GetParameter("openid"); var templateData = new WeixinTemplate_PaySuccess("https://weixin.senparc.com", "购买商品", "状态:" + return_code); Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数", appId + " , " + openId); var result = AdvancedAPIs.TemplateApi.SendTemplateMessage(appId, openId, templateData); } catch (Exception ex) { Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString()); } #region 记录日志 var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd"))); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8))); using (var fileStream = System.IO.File.OpenWrite(logPath)) { var notifyXml = resHandler.ParseXML(); //fileStream.Write(Encoding.Default.GetBytes(res), 0, Encoding.Default.GetByteCount(res)); fileStream.Write(Encoding.Default.GetBytes(notifyXml), 0, Encoding.Default.GetByteCount(notifyXml)); fileStream.Close(); } #endregion string xml = string.Format(@"<xml> <return_code><![CDATA[{0}]]></return_code> <return_msg><![CDATA[{1}]]></return_msg> </xml>", return_code, return_msg); return(Content(xml, "text/xml")); } catch (Exception ex) { WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex)); throw; } }
/// <summary> /// JS-SDK支付回调地址(在下单接口中设置的 notify_url) /// </summary> /// <returns></returns> public async Task <IActionResult> PayNotifyUrl() { try { //获取微信服务器异步发送的支付通知信息 var resHandler = new TenPayNotifyHandler(HttpContext); var orderReturnJson = await resHandler.AesGcmDecryptGetObjectAsync <OrderReturnJson>(); //记录日志 Senparc.Weixin.WeixinTrace.SendCustomLog("PayNotifyUrl 接收到消息", orderReturnJson.ToJson(true)); //演示记录 transaction_id,实际开发中需要记录到数据库,以便退款和后续跟踪 TradeNumberToTransactionId[orderReturnJson.out_trade_no] = orderReturnJson.transaction_id; //获取支付状态 string trade_state = orderReturnJson.trade_state; //验证请求是否从微信发过来(安全) NotifyReturnData returnData = new(); //验证可靠的支付状态 if (orderReturnJson.VerifySignSuccess == true && trade_state == "SUCCESS") { returnData.code = "SUCCESS";//正确的订单处理 /* 提示: * 1、直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息! * 2、上述判断已经具有比较高的安全性以外,还可以对访问 IP 进行判断进一步加强安全性。 * 3、下面演示的是发送支付成功的模板消息提示,非必须。 */ #region 发送支付成功模板消息提醒 try { string appId = Config.SenparcWeixinSetting.TenPayV3_AppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。 string openId = orderReturnJson.payer.openid; var templateData = new WeixinTemplate_PaySuccess("https://weixin.senparc.com", "微信支付 V3 购买商品", "状态:" + trade_state); Senparc.Weixin.WeixinTrace.SendCustomLog("TenPayV3 支付成功模板消息参数", "AppId:" + appId + " ,openId: " + openId); var result = await MP.AdvancedAPIs.TemplateApi.SendTemplateMessageAsync(appId, openId, templateData); } catch (Exception ex) { Senparc.Weixin.WeixinTrace.SendCustomLog("TenPayV3 支付成功模板消息", ex.ToString()); } #endregion } else { returnData.code = "FAILD";//错误的订单处理 returnData.message = "验证失败"; //此处可以给用户发送支付失败提示等 } #region 记录日志(也可以记录到数据库审计日志中) var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd"))); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8))); using (var fileStream = System.IO.File.OpenWrite(logPath)) { var notifyJson = orderReturnJson.ToString(); await fileStream.WriteAsync(Encoding.Default.GetBytes(notifyJson), 0, Encoding.Default.GetByteCount(notifyJson)); fileStream.Close(); } #endregion //https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml return(Json(returnData)); } catch (Exception ex) { WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex)); throw; } }
private string GetDatabaseFilePath() { return(ServerUtility.ContentRootMapPath("~/App_Data/Document/Config.xml")); }
/// <summary> /// 获取文件路径 /// </summary> /// <param name="path"></param> /// <returns></returns> private string GetMapPath(string path) { return(ServerUtility.ContentRootMapPath(path));//path.Replace("~/", HttpRuntime.AppDomainAppPath);// _context.Server.MapPath(path); }
/// <summary> /// JS-SDK支付回调地址(在统一下单接口中设置notify_url) /// </summary> /// <returns></returns> public ActionResult PayNotifyUrl(bool isWxOpenPay = false)//注意:统一下单接口中不能带参数! { WeixinTrace.SendCustomLog("微信支付回调", "来源:" + (isWxOpenPay ? "微信支付" : "小程序支付")); try { ResponseHandler resHandler = new ResponseHandler(null); string return_code = resHandler.GetParameter("return_code"); string return_msg = resHandler.GetParameter("return_msg"); bool paySuccess = false; resHandler.SetKey(TenPayV3Info.Key); //验证请求是否从微信发过来(安全) if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS") { paySuccess = true;//正确的订单处理 //直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息! } else { paySuccess = false;//错误的订单处理 } if (paySuccess) { /* 这里可以进行订单处理的逻辑 */ //发送支付成功的模板消息 try { string appId = Config.SenparcWeixinSetting.WeixinAppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。 string openId = resHandler.GetParameter("openid"); if (isWxOpenPay) { //DPBMARK MiniProgram var cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance(); var unifiedorderRequestData = cacheStrategy.Get <TenPayV3UnifiedorderRequestData>($"WxOpenUnifiedorderRequestData-{openId}"); //获取订单请求信息缓存 var unifedorderResult = cacheStrategy.Get <UnifiedorderResult>($"WxOpenUnifiedorderResultData-{openId}"); //获取订单信息缓存 if (unifedorderResult != null || !string.IsNullOrEmpty(unifedorderResult.prepay_id)) { Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数(小程序)", appId + " , " + openId); //小程序支付,发送小程序模板消息 var templateData = new WxOpenTemplateMessage_PaySuccessNotice( "在线购买(小程序支付)测试", SystemTime.Now, "小程序支付 | 注意:这条消息来自微信服务器异步回调,官方证明支付成功! | prepay_id:" + unifedorderResult.prepay_id, unifiedorderRequestData.OutTradeNo, unifiedorderRequestData.TotalFee, "400-031-8816", "https://weixin.senparc.com"); //微信官方已停用此接口 //Senparc.Weixin.WxOpen.AdvancedAPIs // .Template.TemplateApi // .SendTemplateMessage( // Config.SenparcWeixinSetting.WxOpenAppId, openId, templateData.TemplateId, templateData, unifedorderResult.prepay_id, "pages/index/index", "图书", "#fff00"); } else { Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数(小程序)", "prepayId未记录:" + appId + " , " + openId); } //DPBMARK_END } else { //微信公众号支付 var templateData = new WeixinTemplate_PaySuccess("https://weixin.senparc.com", "购买商品", "状态:" + return_code); Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数(公众号)", appId + " , " + openId); var result = AdvancedAPIs.TemplateApi.SendTemplateMessage(appId, openId, templateData); } } catch (Exception ex) { WeixinTrace.WeixinExceptionLog(new WeixinException("支付成功模板消息异常", ex)); //WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString()); } WeixinTrace.SendCustomLog("PayNotifyUrl回调", "支付成功"); } else { Senparc.Weixin.WeixinTrace.SendCustomLog("PayNotifyUrl回调", "支付失败"); } #region 记录日志 var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd"))); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8))); using (var fileStream = System.IO.File.OpenWrite(logPath)) { var notifyXml = resHandler.ParseXML(); //fileStream.Write(Encoding.Default.GetBytes(res), 0, Encoding.Default.GetByteCount(res)); fileStream.Write(Encoding.Default.GetBytes(notifyXml), 0, Encoding.Default.GetByteCount(notifyXml)); fileStream.Close(); } #endregion string xml = string.Format(@"<xml> <return_code><![CDATA[{0}]]></return_code> <return_msg><![CDATA[{1}]]></return_msg> </xml>", return_code, return_msg); return(Content(xml, "text/xml")); } catch (Exception ex) { WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex)); throw; } }
/// <summary> /// NeuChar 请求 /// </summary> public virtual IResponseMessageBase OnNeuCharRequest(RequestMessageNeuChar requestMessage) { try { var path = ServerUtility.ContentRootMapPath("~/App_Data/NeuChar"); var file = Path.Combine(path, "NeuCharRoot.config"); string result = null; switch (requestMessage.NeuCharMessageType) { case NeuCharMessageType.GetConfig: { if (File.Exists(file)) { using (var fs = FileHelper.GetFileStream(file)) { using (var sr = new StreamReader(fs, Encoding.UTF8)) { var json = sr.ReadToEnd(); result = json; } } } else { result = "{}"; //TODO:初始化一个对象 } } break; case NeuCharMessageType.SaveConfig: { var configRootJson = requestMessage.ConfigRoot; SenparcTrace.SendCustomLog("收到NeuCharRequest", configRootJson); var configRoot = SerializerHelper.GetObject <ConfigRoot>(configRootJson); //这里只做序列化校验 //TODO:进行验证 if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var fileBak = Path.Combine(path, "NeuCharRoot.bak.config"); //TODO:后期也可以考虑把不同模块分离到不同的文件中 File.Delete(fileBak); using (var fs = new FileStream(fileBak, FileMode.CreateNew)) { using (var sw = new StreamWriter(fs)) { sw.Write(configRootJson); sw.Flush(); } } //替换备份文件 File.Delete(file); File.Move(fileBak, file); //刷新数据 var neuralSystem = NeuralSystem.Instance; neuralSystem.ReloadNode(); } break; default: break; } var successMsg = new { success = true, result = result }; TextResponseMessage = successMsg.ToJson(); } catch (Exception ex) { var errMsg = new { success = false, result = ex.Message }; TextResponseMessage = errMsg.ToJson(); } return(null); }
/// <summary> /// 处理文字请求 /// </summary> /// <returns></returns> public override async Task <IResponseMessageBase> OnTextRequestAsync(RequestMessageText requestMessage) { //TODO:这里的逻辑可以交给Service处理具体信息,参考OnLocationRequest方法或/Service/LocationSercice.cs //这里可以进行数据库记录或处理 //发送一条客服消息回复用户 var contentUpper = requestMessage.Content.ToUpper(); if (contentUpper == "LINK") { //发送客服消息 await Senparc.Weixin.WxOpen.AdvancedAPIs.CustomApi.SendLinkAsync(appId, OpenId, "欢迎使用 Senparc.Weixin SDK", "感谢大家的支持!\r\n\r\n盛派永远在你身边!", "https://weixin.senparc.com", "https://sdk.weixin.senparc.com/images/book-cover-front-small-3d-transparent.png"); } else if (contentUpper == "CARD") { //上传封面临时素材 var uploadResult = await MP.AdvancedAPIs.MediaApi.UploadTemporaryMediaAsync(appId, UploadMediaFileType.image, ServerUtility.ContentRootMapPath("~/Images/Logo.thumb.jpg")); //发送客服消息 await Senparc.Weixin.WxOpen.AdvancedAPIs.CustomApi.SendMiniProgramPageAsync(appId, OpenId, "欢迎使用 Senparc.Weixin SDK", "pages/websocket/websocket", uploadResult.media_id); } else if (contentUpper == "客服") { await Senparc.Weixin.WxOpen.AdvancedAPIs.CustomApi.SendTextAsync(appId, OpenId, "您即将进入客服"); var responseMessage = base.CreateResponseMessage <ResponseMessageTransfer_Customer_Service>(); return(responseMessage); } else { var result = new StringBuilder(); result.AppendFormat("您刚才发送了文字信息:{0}\r\n\r\n", requestMessage.Content); var messageContext = await GetCurrentMessageContext().ConfigureAwait(false); if (messageContext.RequestMessages.Count > 1) { result.AppendFormat("您刚才还发送了如下消息({0}/{1}):\r\n", messageContext.RequestMessages.Count, messageContext.StorageData); for (int i = messageContext.RequestMessages.Count - 2; i >= 0; i--) { var historyMessage = messageContext.RequestMessages[i]; string content = null; if (historyMessage is RequestMessageText) { content = (historyMessage as RequestMessageText).Content; } else if (historyMessage is RequestMessageEvent_UserEnterTempSession) { content = "[进入客服]"; } else { content = string.Format("[非文字信息:{0}]", historyMessage.GetType().Name); } result.AppendFormat("{0} 【{1}】{2}\r\n", historyMessage.CreateTime.ToString("HH:mm:ss"), historyMessage.MsgType.ToString(), content ); } result.AppendLine("\r\n"); } //处理微信换行符识别问题 var msg = result.ToString().Replace("\r\n", "\n"); //发送客服消息 await Senparc.Weixin.WxOpen.AdvancedAPIs.CustomApi.SendTextAsync(appId, OpenId, msg); //也可以使用微信公众号的接口,完美兼容: //Senparc.Weixin.MP.AdvancedAPIs.CustomApi.SendText(appId, WeixinOpenId, msg); } return(new SuccessResponseMessage()); //和公众号一样回复XML是无效的: // return new SuccessResponseMessage() // { // ReturnText = string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?> //<xml> // <ToUserName><![CDATA[{0}]]></ToUserName> // <FromUserName><![CDATA[{1}]]></FromUserName> // <CreateTime>1357986928</CreateTime> // <MsgType><![CDATA[text]]></MsgType> // <Content><![CDATA[TNT2]]></Content> //</xml>",requestMessage.FromUserName,requestMessage.ToUserName) // }; }