Пример #1
0
        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(""));
            }
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        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}"));
        }
Пример #4
0
        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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
 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"));
 }
Пример #7
0
        /// <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);
        }
Пример #8
0
        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;
            }
        }
Пример #9
0
        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"));
        }
Пример #10
0
        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));
            }
        }
Пример #12
0
        /// <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);
        }
Пример #13
0
        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)));
        }
Пример #14
0
        /// <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();
            }
        }
Пример #15
0
        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));
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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一致。"));
            }
        }
Пример #19
0
        // 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");
        }
Пример #20
0
        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));
        }
Пример #21
0
        // 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
        }
Пример #22
0
        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(""));
            }
        }
Пример #23
0
        /// <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);
        }
Пример #24
0
        /// <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;
            }
        }
Пример #25
0
        /// <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;
            }
        }
Пример #26
0
 private string GetDatabaseFilePath()
 {
     return(ServerUtility.ContentRootMapPath("~/App_Data/Document/Config.xml"));
 }
Пример #27
0
 /// <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);
 }
Пример #28
0
        /// <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;
            }
        }
Пример #29
0
        /// <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)
            //            };
        }