1 using House.IService.Common;
2 using House.IService.Common.Sign;
3 using House.IService.Model;
4 using Microsoft.AspNetCore.Http;
5 using Newtonsoft.Json;
6 using System;
7 using System.Collections.Generic;
8 using System.Data;
9 using System.IO;
10 using System.Linq;
11 using System.Net;
12 using System.Security.Cryptography;
13 using System.Text;
14 using System.Threading.Tasks;
15 using Config = Data.MSSQL.Common;
16
17 namespace House.Service.Common
18 {
19 /// <summary>
20 /// 后续常量规范化,待修改[标记]
21 /// </summary>
22 public class WinXinSingle : IWeiXinSingle
23 {
24 private IHttpContextAccessor _httpContext = null;
25 private ISignSingle _sign = null;
26 private string AppId => CommonFiled.appID;
27 private string AppSecret => CommonFiled.appSecret;
28
29 public WinXinSingle(IHttpContextAccessor http, ISignSingle sign)
30 {
31 this._httpContext = http;
32 this._sign = sign;
33 }
34
35 #region Private
36 private Microsoft.AspNetCore.Http.HttpContext Current
37 {
38 get
39 {
40 return _httpContext.HttpContext;
41 }
42 }
43
44 private string ParamsQuery(string param)
45 {
46 return this._httpContext.HttpContext.Request.Query[param].FirstOrDefault();
47 }
48
49 #region Session 操作
50 public string GetSession(string key)
51 {
52 byte[] value = null;
53 if (this._httpContext.HttpContext.Session.TryGetValue(key, out value))
54 {
55 return System.Text.Encoding.Default.GetString(value);
56 }
57 return null;
58 }
59
60 /// <summary>
61 /// 已经修改其他的授权方式,Session已经不需要了。暂时弃用
62 /// </summary>
63 /// <param name="key"></param>
64 /// <param name="val"></param>
65 [Obsolete]
66 public void SetSession(string key, string val)
67 {
68 byte[] value = System.Text.Encoding.Default.GetBytes(val);
69 this._httpContext.HttpContext.Session.Set(key, value);
70 }
71 #endregion
72
73 #endregion
74
75
76 public async Task<string> CheckServer()
77 {
78 //1 自己的服务器代码接受微信提交过来的4个参数
79 string token = CommonFiled.token;
80 string signature = ParamsQuery("signature");
81 string timestamp = ParamsQuery("timestamp");
82 string nonce = ParamsQuery("nonce");
83 string echostr = ParamsQuery("echostr");
84 string[] temp = { token, timestamp, nonce };
85 //字典排序
86 Array.Sort(temp);
87 //3个参数拼接成一个字符串
88 string temp1 = string.Join("", temp);
89 //字符串进行sha1加密
90 string code = this._sign.Sha1(temp1);
91 if (code.ToLower().Equals(signature))
92 {
93 //比较一致,表示通过微信的效验了,返回echostr字符串
94 return echostr;
95 }
96 else
97 {
98 return "Authorization failed:" + echostr;
99 }
100 }
101
102 /// <summary>
103 /// 获取普通的access_token
104 /// </summary>
105 /// <returns></returns>
106 public AccessToken GetAccessToken()
107 {
108 AccessToken token = new AccessToken();
109 if (token.access_token == null)
110 {
111 //请求微信服务器得到accessToken
112 string url = string.Format(@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",
113 AppId, AppSecret);
114 string access_token = SendGet(url);
115 return JsonConvert.DeserializeObject<AccessToken>(access_token);
116 }
117 return token;
118 }
119
120 public string GetCodeUrl(string url)
121 {
122 //对url进行编码
123 url = System.Web.HttpUtility.UrlEncode(url);
124 string CodeUrl = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + AppId
125 + "&redirect_uri=" + url + "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect");
126 return CodeUrl;
127 }
128
129 public string GetCurrentFullHost() => _httpContext.HttpContext.Request.Host.Value;
130
131 public string GetOpenId()
132 {
133 string openid = "";
134 var host1 = _httpContext.HttpContext.Request.Host.Value;
135 var host = CommonFiled.DomainURL;
136 string url = host + _httpContext.HttpContext.Request.Path.Value;
137 //先要判断是否是获取code后跳转过来的
138 string code = ParamsQuery("code");
139 if (string.IsNullOrEmpty(code))
140 {
141 //Code为空时,先获取Code
142 string GetCodeUrls = GetCodeUrl(url);
143 _httpContext.HttpContext.Response.Redirect(GetCodeUrls);//先跳转到微信的服务器,取得code后会跳回来这页面的
144 }
145 else
146 {
147 string Code = ParamsQuery("code");
148 openid = GetOauthAccessOpenId(Code)?.openid;//重新取得用户的openid
149 //SetSession("OpenId", Code);
150 }
151 return openid;
152 }
153
154 public string GetOpenId(out string redUrl)
155 {
156 redUrl = "";
157 string openid = "";
158 var host1 = _httpContext.HttpContext.Request.Host.Value;
159 var host = CommonFiled.DomainURL;
160 string url = host + _httpContext.HttpContext.Request.Path.Value;
161 //先要判断是否是获取code后跳转过来的
162 string code = ParamsQuery("code");
163 if (string.IsNullOrEmpty(code))
164 {
165 //Code为空时,先获取Code
166 redUrl = GetCodeUrl(url);
167 //_httpContext.HttpContext.Response.Redirect(GetCodeUrls);//先跳转到微信的服务器,取得code后会跳回来这页面的
168 }
169 else
170 {
171 string Code = ParamsQuery("code");
172 openid = GetOauthAccessOpenId(Code)?.openid;//重新取得用户的openid
173 //SetSession("OpenId", Code);
174 }
175 return openid;
176 }
177
178 /// <summary>
179 /// 通过code换取网页授权access_token
180 /// </summary>
181 /// <param name="code"></param>
182 /// <returns></returns>
183 public OAuthToken GetOauthAccessOpenId(string code)
184 {
185 string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + AppId + "&secret=" + AppSecret + "&code=" + code + "&grant_type=authorization_code";
186 string access_token = SendGet(url);
187 OAuthToken ac = JsonConvert.DeserializeObject<OAuthToken>(access_token);
188 return ac;
189 }
190
191
192 public string GetRawUrl()
193 {
194 return string.Format("http://{0}{1}", GetCurrentFullHost(), _httpContext.HttpContext.Request.PathBase);
195 }
196
197 public int GetTime()
198 {
199
200 DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0);
201 return (int)(DateTime.Now - dateStart).TotalSeconds;
202 }
203
204 public void MusicMessage(string touserName, string formUserName, string title, string remark, string url)
205 {
206 string msg = string.Format(@"<xml>
207 <ToUserName><![CDATA[{0}]]></ToUserName>
208 <FromUserName><![CDATA[{1}]]></FromUserName>
209 <CreateTime>{2}</CreateTime>
210 <MsgType><![CDATA[music]]></MsgType>
211 <Music>
212 <Title><![CDATA[{3}]]></Title>
213 <Description><![CDATA[{4}]]></Description>
214 <MusicUrl><![CDATA[{5}]]></MusicUrl>
215 <HQMusicUrl><![CDATA[{5}]]></HQMusicUrl>
216 </Music>
217 </xml>", formUserName, touserName, GetTime(), title, remark, url);
218 _httpContext.HttpContext.Response.WriteAsync(msg); // 如果需要同步这里再修改
219 }
220
221 public void NewsMessage(string tosuerName, string fromUserName, DataTable dt)
222 {
223 StringBuilder sb = new StringBuilder();
224 for (int i = 0; i < dt.Rows.Count; i++)
225 {
226 sb.AppendFormat(@"<item>
227 <Title><![CDATA[{0}]]></Title>
228 <Description><![CDATA[{1}]]></Description>
229 <PicUrl><![CDATA[{2}]]></PicUrl>
230 <Url><![CDATA[{3}]]></Url>
231 </item>", dt.Rows[i]["Title"].ToString(), dt.Rows[i]["Remark"].ToString(), dt.Rows[i]["PicUrl"].ToString(), dt.Rows[i]["Url"].ToString());
232 }
233 string msg = string.Format(@"<xml>
234 <ToUserName><![CDATA[{0}]]></ToUserName>
235 <FromUserName><![CDATA[{1}]]></FromUserName>
236 <CreateTime>{2}</CreateTime>
237 <MsgType><![CDATA[news]]></MsgType>
238 <ArticleCount>{4}</ArticleCount>
239 <Articles>
240 {3}
241 </Articles>
242 </xml> ", fromUserName, tosuerName, GetTime(), sb.ToString(), dt.Rows.Count);
243 _httpContext.HttpContext.Response.WriteAsync(msg);
244 }
245
246 public string SendGet(string url)
247 {
248 //模拟一个浏览器的请求
249 //1.创建一个请求对象
250 WebRequest request = WebRequest.Create(url);
251 request.Method = "GET";
252 request.ContentType = "applicatoin/x-www/form-urlencoded";
253 string str = null;//保存请求服务器以后返回的结果
254 //得到 响应的内容
255 WebResponse response = request.GetResponse();
256 if (response != null)
257 {
258 using (Stream stream = response.GetResponseStream())
259 {
260 using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
261 {
262 str = reader.ReadToEnd();
263 }
264 }
265 }
266 return str;
267 }
268
269 public string SendPost(string url, string requestData)
270 {
271 WebRequest request = WebRequest.Create(url);
272 request.Method = "POST";
273 byte[] postDatas = null;
274 request.ContentType = "application/x-www-form-urlencoded";
275 postDatas = Encoding.UTF8.GetBytes(requestData);
276 request.ContentLength = postDatas.Length;
277 using (Stream stream = request.GetRequestStream())
278 {
279 stream.Write(postDatas, 0, postDatas.Length);
280 }
281 string responseData = null;//服务器响应的数据
282 WebResponse response = request.GetResponse();
283 if (response != null)
284 {
285 using (Stream st = response.GetResponseStream())
286 {
287 using (StreamReader reader = new StreamReader(st, Encoding.UTF8))
288 {
289 responseData = reader.ReadToEnd();
290 }
291 }
292 }
293 return responseData;
294 }
295
296 public void TextMessage(string toUserName, string formUserName, string content)
297 {
298 string msg = string.Format(@"<xml>
299 <ToUserName><![CDATA[{0}]]></ToUserName>
300 <FromUserName><![CDATA[{1}]]></FromUserName>
301 <CreateTime>{2}</CreateTime>
302 <MsgType><![CDATA[text]]></MsgType>
303 <Content><![CDATA[{3}]]></Content>
304 </xml>", formUserName, toUserName, GetTime(), content);
305 _httpContext.HttpContext.Response.WriteAsync(msg);
306 }
307
308 /// <summary>
309 /// 获取签名用于JS-SDK的调用
310 ///出于安全考虑,开发者必须在服务器端实现签名的逻辑。
311 /// </summary>
312 public string GetJsApiSign(string noncestr, string jsapi_ticket, string timestamp, string url)
313 {
314 //将字段添加到列表中。
315 string[] arr = new[]
316 {
317 string.Format("noncestr={0}",noncestr),
318 string.Format("jsapi_ticket={0}",jsapi_ticket),
319 string.Format("timestamp={0}",timestamp),
320 string.Format("url={0}",url)
321 };
322 //字典排序
323 Array.Sort(arr);
324 //使用URL键值对的格式拼接成字符串
325 var temp = string.Join("&", arr);
326 return this._sign.Sha1(temp).ToLower();
327 }
328
329 public JsApiTicket GetHsJsApiTicket(string accessToken)
330 {
331 JsApiTicket ticket = new JsApiTicket();
332 if (ticket.ticket == null)
333 {
334 var url = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", accessToken);
335 string ticketjson = SendGet(url);
336 return JsonConvert.DeserializeObject<JsApiTicket>(ticketjson);
337 }
338 return ticket;
339 }
340
341 public object JsApiSignature(string requestUrl) {
342 AccessToken accessToken = GetAccessToken();
343 JsApiTicket ticket = GetHsJsApiTicket(accessToken.access_token);
344 string nonceStr = CommonFiled.guid;
345 string timestamp = CommonFiled.unixTime10;
346 var WxConfig = new
347 {
348 debug = false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
349 appId = CommonFiled.appID, // 必填,公众号的唯一标识
350 timestamp, // 必填,生成签名的时间戳
351 nonceStr, // 必填,生成签名的随机串
352 jsApiList = new string[] { "chooseImage", "previewImage", "getLocation" }, // 必填,需要使用的JS接口列表
353 signature = GetJsApiSign(nonceStr, ticket.ticket, timestamp, requestUrl)
354 };
355 return WxConfig;
356 }
357
358 }
359 }