yuqian 7 vuotta sitten
vanhempi
commit
06885b84c8

+ 143 - 0
ServiceWechat/ServiceWechat.Utility/HttpHelper.cs

@@ -0,0 +1,143 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Net.Http;
4
+using System.Net.Http.Headers;
5
+using System.Text;
6
+using System.Threading.Tasks;
7
+
8
+namespace ServiceWechat.Utility
9
+{
10
+    public static class HttpHelper
11
+    {
12
+        /// <summary>
13
+        /// 异步请求get(UTF-8)
14
+        /// </summary>
15
+        /// <param name="url">链接地址</param>   
16
+        /// <param name="formData">写在header中的内容</param>
17
+        /// <returns></returns>
18
+        public static async Task<string> HttpGetAsync(string url, List<KeyValuePair<string, string>> formData = null)
19
+        {
20
+            HttpClient httpClient = new HttpClient();
21
+            HttpContent content = new FormUrlEncodedContent(formData);
22
+            if (formData != null)
23
+            {
24
+                content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
25
+                content.Headers.ContentType.CharSet = "UTF-8";
26
+                for (int i = 0; i < formData.Count; i++)
27
+                {
28
+                    content.Headers.Add(formData[i].Key, formData[i].Value);
29
+                }
30
+            }
31
+            var request = new HttpRequestMessage()
32
+            {
33
+                RequestUri = new Uri(url),
34
+                Method = HttpMethod.Get,
35
+            };
36
+            for (int i = 0; i < formData.Count; i++)
37
+            {
38
+                request.Headers.Add(formData[i].Key, formData[i].Value);
39
+            }
40
+            var resp = await httpClient.SendAsync(request);
41
+            resp.EnsureSuccessStatusCode();
42
+            string token = await resp.Content.ReadAsStringAsync();
43
+
44
+            return token;
45
+        }
46
+
47
+        /// <summary>
48
+        /// 异步请求post(键值对形式,可等待的)
49
+        /// </summary>
50
+        /// <param name="uri">网络基址("http://localhost:59315")</param>
51
+        /// <param name="url">网络的地址("/api/UMeng")</param>
52
+        /// <param name="formData">键值对List<KeyValuePair<string, string>> formData = new List<KeyValuePair<string, string>>();formData.Add(new KeyValuePair<string, string>("userid", "29122"));formData.Add(new KeyValuePair<string, string>("umengids", "29122"));</param>
53
+        /// <param name="charset">编码格式</param>
54
+        /// <param name="mediaType">头媒体类型</param>
55
+        /// <returns></returns>
56
+        public static async Task<string> HttpPostAsync(string uri, string url, List<KeyValuePair<string, string>> formData = null, string charset = "UTF-8", string mediaType = "application/x-www-form-urlencoded")
57
+        {
58
+
59
+            string tokenUri = url;
60
+            var client = new HttpClient();
61
+            client.BaseAddress = new Uri(uri);
62
+            HttpContent content = new FormUrlEncodedContent(formData);
63
+            content.Headers.ContentType = new MediaTypeHeaderValue(mediaType);
64
+            content.Headers.ContentType.CharSet = charset;
65
+            for (int i = 0; i < formData.Count; i++)
66
+            {
67
+                content.Headers.Add(formData[i].Key, formData[i].Value);
68
+            }
69
+
70
+            HttpResponseMessage resp = await client.PostAsync(tokenUri, content);
71
+            resp.EnsureSuccessStatusCode();
72
+            string token = await resp.Content.ReadAsStringAsync();
73
+            return token;
74
+        }
75
+
76
+        ///// <summary>
77
+        ///// 
78
+        ///// </summary>
79
+        ///// <param name="url"></param>
80
+        ///// <param name="data"></param>
81
+        ///// <param name="encoding"></param>
82
+        ///// <param name="type"></param>
83
+        ///// <returns></returns>
84
+        //public string Post(string url, string data, Encoding encoding, int type)
85
+        //{
86
+        //    try
87
+        //    {
88
+        //        HttpWebRequest req = WebRequest.CreateHttp(new Uri(url));
89
+        //        if (type == 1)
90
+        //        {
91
+        //            req.ContentType = "application/json;charset=utf-8";
92
+        //        }
93
+        //        else if (type == 2)
94
+        //        {
95
+        //            req.ContentType = "application/xml;charset=utf-8";
96
+        //        }
97
+        //        else
98
+        //        {
99
+        //            req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
100
+        //        }
101
+
102
+        //        req.Method = "POST";
103
+        //        //req.Accept = "text/xml,text/javascript";
104
+        //        req.ContinueTimeout = 60000;
105
+
106
+        //        byte[] postData = encoding.GetBytes(data);
107
+        //        Stream reqStream = req.GetRequestStreamAsync().Result;
108
+        //        reqStream.Write(postData, 0, postData.Length);
109
+        //        reqStream.Dispose();
110
+
111
+        //        var rsp = (HttpWebResponse)req.GetResponseAsync().Result;
112
+        //        var result = GetResponseAsString(rsp, encoding);
113
+        //        return result;
114
+
115
+        //    }
116
+        //    catch (Exception ex)
117
+        //    {
118
+        //        throw;
119
+        //    }
120
+        //}
121
+
122
+        //private string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
123
+        //{
124
+        //    Stream stream = null;
125
+        //    StreamReader reader = null;
126
+
127
+        //    try
128
+        //    {
129
+        //        // 以字符流的方式读取HTTP响应
130
+        //        stream = rsp.GetResponseStream();
131
+        //        reader = new StreamReader(stream, encoding);
132
+        //        return reader.ReadToEnd();
133
+        //    }
134
+        //    finally
135
+        //    {
136
+        //        // 释放资源
137
+        //        if (reader != null) reader.Dispose();
138
+        //        if (stream != null) stream.Dispose();
139
+        //        if (rsp != null) rsp.Dispose();
140
+        //    }
141
+        //}
142
+    }
143
+}

+ 1 - 1
ServiceWechat/ServiceWechat.sln

@@ -1,7 +1,7 @@
1 1
 
2 2
 Microsoft Visual Studio Solution File, Format Version 12.00
3 3
 # Visual Studio 15
4
-VisualStudioVersion = 15.0.26730.16
4
+VisualStudioVersion = 15.0.27130.2024
5 5
 MinimumVisualStudioVersion = 10.0.40219.1
6 6
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceWechat.Api", "ServiceWechat\ServiceWechat.Api.csproj", "{4EA25C0F-1647-48DD-92F1-DE70D3D79465}"
7 7
 EndProject

+ 26 - 54
ServiceWechat/ServiceWechat/Controllers/WechatApis/HomeController.cs

@@ -17,21 +17,25 @@ using System.Xml;
17 17
 using System.Xml.Linq;
18 18
 using ServiceWechat.Api.MessageHandlers;
19 19
 using Senparc.Weixin.MP.MvcExtension;
20
+using Microsoft.AspNetCore.Hosting;
20 21
 
21 22
 namespace ServiceWechat.Api.Controllers.WechatApis
22 23
 {
23 24
     [Route("wechatapi/Home/[action]")]
24
-    public class HomeController : BaseController
25
+    public class HomeController : Controller
25 26
     {
27
+        readonly Func<string> _getRandomFileName = () => DateTime.Now.ToString("yyyyMMdd-HHmmss") + Guid.NewGuid().ToString("n").Substring(0, 6);
26 28
         private readonly string Token;
27 29
         private readonly string AppId;
28 30
         private readonly string EncodingAESKey;
29 31
         static Logger Logger = LogManager.GetCurrentClassLogger();
30
-        public HomeController(IConfiguration configuration)
32
+        private IHostingEnvironment _host;
33
+        public HomeController(IConfiguration configuration, IHostingEnvironment host)
31 34
         {
32 35
             Token = configuration["WechatStatic:Token"];
33 36
             AppId = configuration["WechatStatic:AppId"];
34 37
             EncodingAESKey = configuration["WechatStatic:EncodingAESKey"];
38
+            _host = host;
35 39
         }
36 40
 
37 41
         /// <summary>
@@ -58,77 +62,45 @@ namespace ServiceWechat.Api.Controllers.WechatApis
58 62
         /// 用户发送消息后,微信平台自动Post一个请求到这里,并等待响应XML。
59 63
         /// </summary>
60 64
         [HttpPost]
61
-        public WeixinResult Verify(PostModel postModel)
65
+        [Produces("text/xml")]
66
+        public ActionResult Verify(PostModel postModel)
62 67
         {
63 68
             if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
64 69
             {
65
-                Logger.Info($"参数错误");
66 70
                 return new WeixinResult("参数错误");
67 71
             }
68
-
69 72
             postModel.Token = Token;//根据自己后台的设置保持一致
70 73
             postModel.EncodingAESKey = EncodingAESKey;//根据自己后台的设置保持一致
71 74
             postModel.AppId = AppId;//根据自己后台的设置保持一致
72 75
 
73
-            //var memoryStream = new MemoryStream();
74
-            //Request.Body.CopyTo(memoryStream);
76
+            string body = new StreamReader(Request.Body).ReadToEnd();
77
+            byte[] requestData = Encoding.UTF8.GetBytes(body);
78
+            Stream inputStream = new MemoryStream(requestData);
75 79
 
76
-            //byte[] requestByte = new byte[memoryStream.Length];
77
-            //memoryStream.Read(requestByte, 0, (int)memoryStream.Length);
78
-            //string dataEncrypt = Encoding.UTF8.GetString(requestByte);
79 80
 
81
+            CustomMessageHandler messageHandler = new CustomMessageHandler(inputStream, postModel);//接收消息
82
+            messageHandler.Execute();//执行微信处理过程
80 83
 
81
-            var maxRecordCount = 10;
82
-            var inputStream = Request.Body;
83
-            byte[] buffer = new byte[Request.ContentLength ?? 0];
84
-            inputStream.Read(buffer, 0, buffer.Length);
85
-            var requestXmlStream = new MemoryStream(buffer);
86
-            var requestXml = Encoding.UTF8.GetString(buffer);
84
+            var responseDocumentFileName = Path.Combine(_host.ContentRootPath, string.Format("{0}_Response_{1}.txt", _getRandomFileName(), messageHandler.RequestMessage.FromUserName));
85
+            var ecryptResponseDocumentFileName = Path.Combine(_host.ContentRootPath, string.Format("{0}_Response_Final_{1}.txt", _getRandomFileName(), messageHandler.RequestMessage.FromUserName));
87 86
 
88
-            if (inputStream.Position > 0)
87
+            if (messageHandler.ResponseDocument != null)
89 88
             {
90
-                inputStream.Position = 0;
89
+                using (FileStream fs = new FileStream(responseDocumentFileName, FileMode.CreateNew, FileAccess.ReadWrite))
90
+                {
91
+                    messageHandler.ResponseDocument.Save(fs);
92
+                }
91 93
             }
92 94
 
93
-
94
-            //StreamReader reader = new StreamReader(inputStream, Encoding.UTF8);
95
-            string dataEncrypt = requestXml;
96
-            string dataDecrypt = "";
97
-            int ret = 0;
98
-            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(Token, EncodingAESKey, AppId);
99
-            Logger.Info($"data ={dataEncrypt}");
100
-            ret = wxcpt.DecryptMsg(postModel.Msg_Signature, postModel.Timestamp, postModel.Nonce, dataEncrypt, ref dataDecrypt);
101
-            if (ret != 0)
95
+            if (messageHandler.UsingEcryptMessage && messageHandler.FinalResponseDocument != null)
102 96
             {
103
-                Logger.Error($"微信消息推送解密失败,错误代码:{ret}");
97
+                using (FileStream fs = new FileStream(ecryptResponseDocumentFileName, FileMode.CreateNew, FileAccess.ReadWrite))
98
+                {
99
+                    //记录加密后的响应信息
100
+                    messageHandler.FinalResponseDocument.Save(fs);
101
+                }
104 102
             }
105
-            Logger.Info($"接收用户消息调用RecieveMsg =【{  dataDecrypt }】");
106
-            //自定义MessageHandler,对微信请求的详细判断操作都在这里面。
107
-
108
-
109
-
110
-            //if (Request.Body.Position > 0)
111
-            //{
112
-            //    Request.Body.Position = 0;
113
-            //}
114
-
115
-            //XDocument xml = null;
116
-            //using (XmlReader xr = XmlReader.Create(Request.Body))
117
-            //{
118
-            //    xml = XDocument.Load(xr);
119
-            //}
120
-            CustomMessageHandler messageHandler = null;
121
-            try
122
-            {
123
-                messageHandler = new CustomMessageHandler(inputStream, postModel);//接收消息
124
-            }
125
-            catch (Exception ex)
126
-            {
127
-                Logger.Error(ex, $"{ex.StackTrace}");
128
-            }
129
-            messageHandler.Execute();//执行微信处理过程
130 103
             return new WeixinResult(messageHandler);//返回结果
131
-
132 104
         }
133 105
 
134 106
         public string Test()

+ 93 - 0
ServiceWechat/ServiceWechat/Controllers/WechatApis/PaymentController.cs

@@ -0,0 +1,93 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Linq;
4
+using System.Threading.Tasks;
5
+using Microsoft.AspNetCore.Mvc;
6
+using Microsoft.Extensions.Configuration;
7
+using Microsoft.Extensions.Logging;
8
+using NLog;
9
+using Senparc.Weixin.MP.TenPayLibV3;
10
+
11
+// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
12
+
13
+namespace ServiceWechat.Api.Controllers.WechatApis
14
+{
15
+
16
+    [Route("wechatapi/payment/[action]")]
17
+    public class PaymentController : Controller
18
+    {
19
+        private readonly string AppId;
20
+        private readonly string MchId;
21
+        private readonly string TenPayV3Notify;
22
+        private readonly string Key;
23
+
24
+        static Logger Logger = LogManager.GetCurrentClassLogger();
25
+
26
+        public PaymentController(IConfiguration configuration)
27
+        {
28
+            AppId = configuration["WechatStatic:AppId"];
29
+            MchId = configuration["WechatStatic:MchId"];
30
+            TenPayV3Notify = configuration["WechatStatic:TenPayV3Notify"];
31
+            Key = configuration["Key"];
32
+        }
33
+        public string MakeOrder()
34
+        {
35
+            #region 生成商户订单(系统内订单)TODO
36
+
37
+            #endregion 
38
+
39
+
40
+            #region 调用微信统一下单API,生成预付单,获取预付单信息
41
+
42
+            var attach = "efg";
43
+            var body = "abc";
44
+            var openId = "oKOqcv_4HD3qeuf6aL5gaD--z4Xs";
45
+            var orderNum = DateTime.Now.ToString("yyyyMMddHHmmss");
46
+            var total_fee = "1";
47
+
48
+            RequestHandler requestHandler = new RequestHandler(HttpContext);
49
+            requestHandler.SetParameter("appid", this.AppId);                       //公众账号ID
50
+            requestHandler.SetParameter("mch_id", this.MchId);                      //商户号
51
+            //requestHandler.SetParameterWhenNotNull("sub_appid", this.SubAppId);     //子商户公众账号ID
52
+            //requestHandler.SetParameterWhenNotNull("sub_mch_id", this.SubMchId);    //子商户号
53
+            //requestHandler.SetParameterWhenNotNull("device_info", this.DeviceInfo); //自定义参数
54
+            requestHandler.SetParameter("nonce_str", TenPayV3Util.GetNoncestr());                //随机字符串
55
+            requestHandler.SetParameterWhenNotNull("sign_type", "MD5");     //签名类型,默认为MD5
56
+            requestHandler.SetParameter("body", body);                         //商品信息
57
+            //requestHandler.SetParameterWhenNotNull("detail", this.Detail);          //商品详细列表
58
+            requestHandler.SetParameterWhenNotNull("attach", attach);          //附加数据
59
+            requestHandler.SetParameter("out_trade_no", orderNum);           //商家订单号
60
+            requestHandler.SetParameterWhenNotNull("fee_type", "CNY");       //符合ISO 4217标准的三位字母代码,默认人民币:CNY
61
+            requestHandler.SetParameter("total_fee", total_fee);     //商品金额,以分为单位(money * 100).ToString()
62
+            requestHandler.SetParameter("spbill_create_ip", "");   //用户的公网ip,不是商户服务器IP
63
+            requestHandler.SetParameterWhenNotNull("time_start", DateTime.Now.ToString());   //订单生成时间
64
+            requestHandler.SetParameterWhenNotNull("time_expire", DateTime.Now.AddDays(1).ToString());  //订单失效时间
65
+            //requestHandler.SetParameterWhenNotNull("goods_tag", this.GoodsTag);     //商品标记
66
+            requestHandler.SetParameter("notify_url", TenPayV3Notify);              //接收财付通通知的URL
67
+            requestHandler.SetParameter("trade_type", "JSAPI");   //交易类型
68
+            //requestHandler.SetParameterWhenNotNull("product_id", this.ProductId);   //trade_type=NATIVE时(即扫码支付),此参数必传。
69
+            //requestHandler.SetParameterWhenNotNull("limit_pay", this.LimitPay);     //上传此参数no_credit--可限制用户不能使用信用卡支付
70
+            requestHandler.SetParameterWhenNotNull("openid", openId);                     //用户的openId,trade_type=JSAPI时(即公众号支付),此参数必传
71
+            //requestHandler.SetParameterWhenNotNull("sub_openid", this.SubOpenid);              //用户子标识
72
+            //if (SceneInfo != null)
73
+            //{
74
+            //    requestHandler.SetParameter("scene_info", SceneInfo.ToString());   //场景信息
75
+            //}
76
+
77
+            var sign = requestHandler.CreateMd5Sign("key", this.Key);
78
+
79
+            requestHandler.SetParameter("sign", sign);                              //签名
80
+
81
+            var xml = requestHandler.ParseXML();
82
+            var result = TenPayV3.Unifiedorder(xml);
83
+            //获取并返回预支付XML信息
84
+            return $"xml= {xml} ||||||  result={TenPayV3.Unifiedorder(result)}";
85
+            #endregion
86
+        }
87
+
88
+        public void callback()
89
+        {
90
+
91
+        }
92
+    }
93
+}

+ 128 - 43
ServiceWechat/ServiceWechat/MessageHandlers/CustomMessageHandler.cs

@@ -1,9 +1,11 @@
1 1
 using Microsoft.Extensions.Logging;
2 2
 using NLog;
3 3
 using Senparc.Weixin.Context;
4
+using Senparc.Weixin.MP;
4 5
 using Senparc.Weixin.MP.Entities;
5 6
 using Senparc.Weixin.MP.Entities.Request;
6 7
 using Senparc.Weixin.MP.MessageHandlers;
8
+using ServiceWechat.Api.CryptCode;
7 9
 using System;
8 10
 using System.Collections.Generic;
9 11
 using System.IO;
@@ -13,22 +15,116 @@ using System.Xml.Linq;
13 15
 
14 16
 namespace ServiceWechat.Api.MessageHandlers
15 17
 {
16
-    public partial class CustomMessageHandler : MessageHandler<MessageContext<IRequestMessageBase, IResponseMessageBase>>
18
+    public partial class CustomMessageHandler : MessageHandler<CustomMessageContext>
17 19
     {
18 20
         static Logger Logger = LogManager.GetCurrentClassLogger();
19 21
 
22
+        private PostModel _postModel;
20 23
         public CustomMessageHandler(Stream inputStream, PostModel postModel)
21 24
             : base(inputStream, postModel)
22 25
         {
23 26
             Logger.Info($"实例化CustomMessageHandler");
27
+            _postModel = postModel;
24 28
         }
25
-
26
-        public CustomMessageHandler(XDocument inputStream, PostModel postModel)
27
-          : base(inputStream, postModel)
29
+        /// <summary>
30
+        /// 初始化时【解密】
31
+        /// </summary>
32
+        /// <param name="postDataDocument"></param>
33
+        /// <param name="postData"></param>
34
+        /// <returns></returns>
35
+        public override XDocument Init(XDocument postDataDocument, object postData = null)
28 36
         {
29
-            Logger.Info($"实例化CustomMessageHandler");
37
+
38
+            //进行加密判断并处理
39
+            _postModel = postData as PostModel;
40
+            var postDataStr = postDataDocument.ToString();
41
+            Logger.Info($"Init  postDataStr={postDataStr}");
42
+
43
+
44
+            XDocument decryptDoc = postDataDocument;
45
+
46
+            if (_postModel != null && postDataDocument.Root.Element("Encrypt") != null && !string.IsNullOrEmpty(postDataDocument.Root.Element("Encrypt").Value))
47
+            {
48
+                //使用了加密
49
+                UsingEcryptMessage = true;
50
+                EcryptRequestDocument = postDataDocument;
51
+
52
+                WXBizMsgCrypt msgCrype = new WXBizMsgCrypt(_postModel.Token, _postModel.EncodingAESKey, _postModel.AppId);
53
+                string msgXml = null;
54
+                var result = msgCrype.DecryptMsg(_postModel.Msg_Signature, _postModel.Timestamp, _postModel.Nonce, postDataStr, ref msgXml);
55
+
56
+                //判断result类型
57
+                if (result != 0)
58
+                {
59
+                    //验证没有通过,取消执行
60
+                    CancelExcute = true;
61
+                    return null;
62
+                }
63
+
64
+                if (postDataDocument.Root.Element("FromUserName") != null && !string.IsNullOrEmpty(postDataDocument.Root.Element("FromUserName").Value))
65
+                {
66
+                    //TODO:使用了兼容模式,进行验证即可
67
+                    UsingCompatibilityModelEcryptMessage = true;
68
+                }
69
+
70
+                decryptDoc = XDocument.Parse(msgXml);//完成解密
71
+            }
72
+
73
+            RequestMessage = RequestMessageFactory.GetRequestEntity(decryptDoc);
74
+            if (UsingEcryptMessage)
75
+            {
76
+                RequestMessage.Encrypt = postDataDocument.Root.Element("Encrypt").Value;
77
+            }
78
+
79
+
80
+            //TODO:分布式系统中本地的上下文会有同步问题,需要同步使用远程的储存
81
+            if (WeixinContextGlobal.UseWeixinContext)
82
+            {
83
+
84
+                var omit = OmitRepeatedMessageFunc == null || OmitRepeatedMessageFunc(RequestMessage);
85
+
86
+                lock (WeixinContextGlobal.OmitRepeatLock)//TODO:使用分布式锁
87
+                {
88
+                    #region 消息去重
89
+
90
+                    if (omit &&
91
+                        OmitRepeatedMessage &&
92
+                        CurrentMessageContext.RequestMessages.Count > 0
93
+                         //&& !(RequestMessage is RequestMessageEvent_Merchant_Order)批量订单的MsgId可能会相同
94
+                         )
95
+                    {
96
+                        //lastMessage必定有值(除非极端小的过期时间条件下,几乎不可能发生)
97
+                        var lastMessage = CurrentMessageContext.RequestMessages[CurrentMessageContext.RequestMessages.Count - 1];
98
+
99
+                        if (
100
+                            //使用MsgId去重
101
+                            (lastMessage.MsgId != 0 && lastMessage.MsgId == RequestMessage.MsgId)
102
+                            //使用CreateTime去重(OpenId对象已经是同一个)
103
+                            || (lastMessage.MsgId == RequestMessage.MsgId
104
+                                && lastMessage.CreateTime == RequestMessage.CreateTime
105
+                                && lastMessage.MsgType == RequestMessage.MsgType)
106
+                            )
107
+                        {
108
+                            CancelExcute = true;//重复消息,取消执行
109
+                            MessageIsRepeated = true;
110
+                        }
111
+                    }
112
+
113
+                    #endregion
114
+
115
+                    //在消息没有被去重的情况下记录上下文
116
+                    if (!MessageIsRepeated)
117
+                    {
118
+                        WeixinContext.InsertMessage(RequestMessage);
119
+                    }
120
+                }
121
+            }
122
+
123
+            Logger.Info($"接收用户消息调用RecieveMsg =【{  decryptDoc }】");
124
+            return decryptDoc;
30 125
         }
31 126
 
127
+
32 128
         /// <summary>
33 129
         /// 默认回复
34 130
         /// </summary>
@@ -36,49 +132,13 @@ namespace ServiceWechat.Api.MessageHandlers
36 132
         /// <returns></returns>
37 133
         public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
38 134
         {
39
-            var responseMessage = this.CreateResponseMessage<ResponseMessageText>(); //ResponseMessageText也可以是News等其他类型
135
+            var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(RequestMessage);
40 136
             Logger.Info($"我是默认的自动回复 么么哒~~~。");
41 137
             responseMessage.Content = "我是默认的自动回复 么么哒~~~。";
42 138
             return responseMessage;
43 139
         }
44 140
 
45 141
 
46
-        public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
47
-        {
48
-            var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
49
-            //responseMessage.Content = "您的OpenID是:" + responseMessage.FromUserName+".\r\n您发送的文字是:"+requestMessage.Content;  
50
-            if (requestMessage.Content == "ID")
51
-                responseMessage.Content = "您的OpenID是:" + responseMessage.FromUserName;
52
-            if (requestMessage.Content == "天气")
53
-                responseMessage.Content = "抱歉,还未开通此功能!";
54
-            return responseMessage;
55
-        }
56
-
57
-
58
-        /// <summary>
59
-        /// 处理用户发来的文本信息
60
-        /// </summary>
61
-        /// <param name="requestMessage"></param>
62
-        /// <returns></returns>
63
-        //public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
64
-        //{
65
-
66
-        //    //requestMessage.FromUserName也可以直接写成base.WeixinOpenId
67
-        //    var openId = base.WeixinOpenId;
68
-        //    //客户发来的文本信息
69
-        //    var content = requestMessage.Content;
70
-
71
-        //    Logger.Info($"您的OpenID是{openId}。\r\n您发送了文字信息:{content}, requestMessage.MsgId={requestMessage.MsgId},requestMessage.MsgId={requestMessage.CreateTime}");
72
-        //    //【TODO:查询已配置的文本回复信息】
73
-
74
-        //    var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
75
-        //    responseMessage.Content = $"您的OpenID是{openId}。\r\n您发送了文字信息:{content}, requestMessage.MsgId={requestMessage.MsgId},requestMessage.MsgId={requestMessage.CreateTime}";
76
-        //    Logger.Info($"responseMessage.FromUserName = {responseMessage.FromUserName}   responseMessage.MsgType={responseMessage.MsgType},responseMessage.ToUserName={responseMessage.ToUserName}");
77
-        //    return responseMessage;
78
-
79
-
80
-        //}
81
-
82 142
 
83 143
         public override void OnExecuting()
84 144
         {
@@ -98,5 +158,30 @@ namespace ServiceWechat.Api.MessageHandlers
98 158
             base.OnExecuted();
99 159
             CurrentMessageContext.StorageData = ((int)CurrentMessageContext.StorageData) + 1;
100 160
         }
161
+
162
+        public override XDocument FinalResponseDocument
163
+        {
164
+            get
165
+            {
166
+                Logger.Info($"ResponseDocument");
167
+                if (ResponseDocument == null)
168
+                {
169
+                    Logger.Info($"ResponseDocument=null");
170
+                    return null;
171
+                }
172
+
173
+                var timeStamp = _postModel.Timestamp;
174
+                var nonce = _postModel.Nonce;
175
+
176
+                WXBizMsgCrypt msgCrype = new WXBizMsgCrypt(_postModel.Token, _postModel.EncodingAESKey, _postModel.AppId);
177
+                string finalResponseXml = null;
178
+                msgCrype.EncryptMsg(ResponseDocument.ToString(), timeStamp, nonce, ref finalResponseXml);//TODO:这里官方的方法已经把EncryptResponseMessage对应的XML输出出来了
179
+                Logger.Info($"ResponseDocument.ToString() =【{  ResponseDocument.ToString() }】");
180
+                Logger.Info($"finalResponseXml =【{  finalResponseXml }】");
181
+                return XDocument.Parse(finalResponseXml);
182
+
183
+            }
184
+
185
+        }
101 186
     }
102
-}
187
+}

+ 3 - 1
ServiceWechat/ServiceWechat/Program.cs

@@ -20,7 +20,9 @@ namespace ServiceWechat.Api
20 20
         public static IWebHost BuildWebHost(string[] args) =>
21 21
             WebHost.CreateDefaultBuilder(args)
22 22
                 .UseStartup<Startup>()
23
-                .UseIISIntegration()
23
+                .UseKestrel()
24
+                .UseUrls("http://meiwang.800100.net:80")
25
+                //.UseIISIntegration()
24 26
                 .Build();
25 27
     }
26 28
 }

+ 7 - 2
ServiceWechat/ServiceWechat/ServiceWechat.Api.csproj

@@ -6,7 +6,12 @@
6 6
   </PropertyGroup>
7 7
 
8 8
   <ItemGroup>
9
+    <None Remove="Properties\PublishProfiles\FolderProfile.pubxml" />
10
+  </ItemGroup>
11
+
12
+  <ItemGroup>
9 13
     <Folder Include="Controllers\ManageApis\" />
14
+    <Folder Include="Properties\PublishProfiles\" />
10 15
     <Folder Include="wwwroot\" />
11 16
   </ItemGroup>
12 17
 
@@ -14,8 +19,8 @@
14 19
     <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
15 20
     <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.2" />
16 21
     <PackageReference Include="NLog.Web.AspNetCore" Version="4.4.1" />
17
-    <PackageReference Include="Senparc.Weixin" Version="4.20.0" />
18
-    <PackageReference Include="Senparc.Weixin.MP" Version="14.10.0" />
22
+    <PackageReference Include="Senparc.Weixin" Version="4.20.2" />
23
+    <PackageReference Include="Senparc.Weixin.MP" Version="14.10.3" />
19 24
     <PackageReference Include="Senparc.Weixin.MP.MVC" Version="5.2.0" />
20 25
   </ItemGroup>
21 26
 

+ 1 - 0
ServiceWechat/ServiceWechat/ServiceWechat.Api.csproj.user

@@ -15,5 +15,6 @@
15 15
     <WebStackScaffolding_IsReferencingScriptLibrariesSelected>True</WebStackScaffolding_IsReferencingScriptLibrariesSelected>
16 16
     <WebStackScaffolding_LayoutPageFile />
17 17
     <WebStackScaffolding_IsAsyncSelected>False</WebStackScaffolding_IsAsyncSelected>
18
+    <ShowAllFiles>true</ShowAllFiles>
18 19
   </PropertyGroup>
19 20
 </Project>

+ 2 - 1
ServiceWechat/ServiceWechat/Startup.cs

@@ -31,6 +31,7 @@ namespace ServiceWechat.Api
31 31
         public void ConfigureServices(IServiceCollection services)
32 32
         {
33 33
             services.AddMvc();
34
+
34 35
         }
35 36
 
36 37
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -42,12 +43,12 @@ namespace ServiceWechat.Api
42 43
             }
43 44
 
44 45
             app.UseMvc();
46
+            app.UseStaticFiles(); // For the wwwroot folder
45 47
 
46 48
             #region NLog
47 49
             loggerFactory.AddNLog();//添加NLog
48 50
             env.ConfigureNLog("StaticConfig/nlog.config");//读取Nlog配置文件
49 51
             #endregion
50
-
51 52
             AccessTokenContainer.Register(AppId, AppSecret);
52 53
         }
53 54
     }

+ 5 - 1
ServiceWechat/ServiceWechat/appsettings.json

@@ -16,9 +16,13 @@
16 16
     "AppId": "wxe03366d8c63d9b09",
17 17
     "AppSecret": "3e42313935a4d6dc8b450172b8be2765",
18 18
     "Token": "72E4E2C7EC8BBF6AF535F53A213E8EBB",
19
-    "EncodingAESKey": "bOs7gmWm6FaqAViH9ZngbfhZS47pvzOucCrGO7tkMlD"
19
+    "EncodingAESKey": "bOs7gmWm6FaqAViH9ZngbfhZS47pvzOucCrGO7tkMlD",
20
+    "MchId": "1493808312", //商户号
21
+    "TenPayV3Notify": "http://meiwang.800100.net/wechatapi/payment/callback/", //回调地址
22
+    "Key": "u92kcvielwoc045kigdslwod937ckw9c" //api秘钥
20 23
   }
21 24
 
22 25
 
23 26
 
27
+
24 28
 }

+ 25 - 0
ServiceWechat/ServiceWechat/wwwroot/makeorder.html

@@ -0,0 +1,25 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+    <meta charset="utf-8">
5
+    <title>订单页面</title>
6
+</head>
7
+<body>
8
+    <h1>订单页面</h1>
9
+    <input id="btn" type="button" value="点击下订单" />
10
+    <script type="text/javascript" src="script/jquery.min.js"></script>
11
+    <script>
12
+        $(function () {
13
+            $("#btn").click(function () {
14
+                $.ajax({
15
+                    "url": "/wechatapi/payment/makeorder",
16
+                    "type": "json",
17
+                    "success": function (res) {
18
+                        alert(res);
19
+                    }
20
+                });
21
+            });
22
+        });
23
+    </script>
24
+</body>
25
+</html>

+ 34 - 0
ServiceWechat/ServiceWechat/wwwroot/payment.html

@@ -0,0 +1,34 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+    <meta charset="utf-8">
5
+    <title>支付页面</title>
6
+</head>
7
+<body>
8
+    <h1>这是支付测试页面</h1>
9
+    <input id="btn" type="button" value="点击调用微信公众号的支付api" />
10
+    <script>
11
+        function onBridgeReady() {
12
+            WeixinJSBridge.invoke(
13
+                'getBrandWCPayRequest', {
14
+                    "appId": $('#APPID').val(),     //公众号名称,由商户传入
15
+                    "timeStamp": $('#Timestamp').val(),         //时间戳,自1970年以来的秒数
16
+                    "nonceStr": $('#Noncestr').val(), //随机串
17
+                    "package": $('#package').val(),
18
+                    "signType": "MD5",         //微信签名方式:
19
+                    "paySign": $('#paySign').val() //微信签名
20
+                },
21
+                function (res) {
22
+                    if (res.err_msg == "get_brand_wcpay_request:ok") {
23
+                        //支付成功,后续自行处理
24
+
25
+                    }
26
+                    else {
27
+                        //支付取消,或者其他错误,自行处理
28
+                    }
29
+                }
30
+            );
31
+        }
32
+    </script>
33
+</body>
34
+</html>

File diff suppressed because it is too large
+ 4 - 0
ServiceWechat/ServiceWechat/wwwroot/script/jquery.min.js