using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Runtime.Serialization.Json; using System.Text; using System.Web; using System.Web.Security; using System.Xml; using System.Xml.Linq; using HZQR.Common; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Coop.Merchant.Handler { public class ReceiveModel { /// /// 接收方帐号(收到的OpenID) /// public string ToUserName { get; set; } /// /// 发送方帐号(一个OpenID) /// public string FromUserName { get; set; } /// /// 消息创建时间 (整型) /// public string CreateTime { get; set; } /// /// 消息类型 /// public string MsgType { get; set; } /// /// 当前实体的XML字符串 /// public string Xml { get; set; } } /// /// wechatCheck 的摘要说明 /// public class wechatCheck : IHttpHandler { public void ProcessRequest(HttpContext context) { String StrXml = getPostStr();//获取请求数据 LogUtil.WriteLog(null, "xmlData:" + StrXml, DateTime.Now.ToString("yyyyMMdd_") + "xmlData"); //StrXml = @" // //1602492314 // // // //"; //StrXml = @" // //1602494473 // // // // //"; //加载xml XmlDocument textXml = new XmlDocument(); textXml.LoadXml(StrXml); XmlElement xmlElement = textXml.DocumentElement; //转成model对象 ReceiveModel model = new ReceiveModel() { ToUserName = xmlElement.SelectSingleNode("ToUserName").InnerText, FromUserName = xmlElement.SelectSingleNode("FromUserName").InnerText, CreateTime = xmlElement.SelectSingleNode("CreateTime").InnerText, MsgType = xmlElement.SelectSingleNode("MsgType").InnerText }; if (model.MsgType == "event") { switch (xmlElement.SelectSingleNode("Event").InnerText) { case "subscribe": //刚刚关注的 //string text = "您好,欢迎关注!点击跳小程序"; //SendText(model.FromUserName, text); //SendText(model.FromUserName, "您好,欢迎关注"); StringBuilder sb1 = new StringBuilder(); sb1.Append("您好,欢迎关注高速驿网会员!\n"); sb1.Append("◆休闲驿站,请戳→点击进入\n"); sb1.Append("◆直播平台,请戳→点击进入\n"); sb1.AppendFormat("◆驿网商城,请戳→点击进入\n", "wxb3235f202519f2c3"); sb1.Append("◆如遇任何服务质量问题,请直接在对话框留言,我们会及时处理!"); SendText(model.FromUserName, sb1.ToString()); StringBuilder sb2 = new StringBuilder(); sb2.AppendFormat("◆领取消费优惠券,请戳→点击进入", "wxec57324d9d721cea"); SendText(model.FromUserName, sb2.ToString()); break; case "unsubscribe": break; case "SCAN": //已经关注的 //SendText(model.FromUserName, "您好,欢迎回来"); StringBuilder sb = new StringBuilder(); sb.Append("您好,欢迎回来!\n"); sb.AppendFormat("◆领取消费优惠券,请戳→点击进入", "wxec57324d9d721cea"); SendText(model.FromUserName, sb.ToString()); break; case "LOCATION": break; case "CLICK": break; case "VIEW": break; default: break; } } //验证token string poststring = string.Empty; string token = "aabbcc"; //验证token,随意填写 if (string.IsNullOrEmpty(token)) { return; } string echostring = HttpContext.Current.Request.QueryString["echostr"]; LogUtil.WriteLog("echostring=" + echostring); string signature = HttpContext.Current.Request.QueryString["signature"]; string timestamp = HttpContext.Current.Request.QueryString["timestamp"]; string nonce = HttpContext.Current.Request.QueryString["nonce"]; if (checksignature(token, signature, timestamp, nonce)) { LogUtil.WriteLog("echostring=" + echostring); if (!string.IsNullOrEmpty(echostring)) { HttpContext.Current.Response.Write(echostring); HttpContext.Current.Response.End(); } } context.Response.End(); } public string getPostStr() { Int32 intLen = Convert.ToInt32(System.Web.HttpContext.Current.Request.InputStream.Length); byte[] b = new byte[intLen]; System.Web.HttpContext.Current.Request.InputStream.Read(b, 0, intLen); return System.Text.Encoding.UTF8.GetString(b); } /// /// 客服发送消息-POST /// /// public string GetKFSend() { string accessToken = WeiXinHelper.GetAccessToken("wx0e7ca64a5be0612f", "75e198d9917c224b8ad9f9b8a4735194"); string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={0}", accessToken); return url; } /// /// 发送文本消息 /// /// /// public string SendText(string openid, string content) { string url = GetKFSend(); JObject data = new JObject(); data.Add("touser", openid); data.Add("msgtype", "text"); data.Add("text", JObject.FromObject(new { content = content })); string result = Common.HttpUrlPost(data.ToString(), url); return result; } /// /// 验证微信签名 /// /// token /// 签名 /// 时间戳 /// 随机数 /// public static bool checksignature(string token, string signature, string timestamp, string nonce) { string[] arrtmp = { token, timestamp, nonce }; //字典排序 Array.Sort(arrtmp); //拼接 string tmpstr = string.Join("", arrtmp); //sha1验证 tmpstr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpstr, "sha1"); //tmpstr = membership.createuser(tmpstr, "sha1"); LogUtil.WriteLog("tmpstr=" + tmpstr); tmpstr = tmpstr.ToLower(); LogUtil.WriteLog("tmpstr2=" + tmpstr); LogUtil.WriteLog("signature=" + signature); if (tmpstr == signature) { return true; } else { return false; } } public bool IsReusable { get { return false; } } } /// /// 微信 需要用到的Url、Json常量 /// public class WeiXinConst { #region Value Const /// /// 微信开发者 AppId /// public const string AppId = "你的AppId"; /// /// 微信开发者 Secret /// public const string Secret = "你得Secret"; /// /// V2:支付请求中 用于加密的秘钥Key,可用于验证商户的唯一性,对应支付场景中的AppKey /// public static string PaySignKey = "V2.PaySignKey"; /// /// V2:财付通签名key /// V3:商户支付密钥 Key。登录微信商户后台,进入栏目【账户设置】 【密码安全 】【API 安全】 【API 密钥】 ,进入设置 API 密钥。 /// public const string PartnerKey = "PartnerKey"; /// /// 商户号 /// public const string PartnerId = "PartnerId"; /// /// 百度地图Api Ak /// public const string BaiduAk = "BaiduAk"; /// /// 用于验证 请求 是否来自 微信 /// public const string Token = "Token"; /// /// 证书文件 路径 /// public const string CertPath = @"E:\cert\apiclient_cert.pem"; /// /// 证书文件密码(默认为商户号) /// public const string CertPwd = "111"; #endregion #region Url Const #region AccessTokenUrl /// /// 公众号 获取Access_Token的Url(需Format 0.AppId 1.Secret) /// private const string AccessToken_Url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}"; /// /// 公众号 获取Token的Url /// public static string WeiXin_AccessTokenUrl { get { return string.Format(AccessToken_Url, AppId, Secret); } } #endregion #region 获取用户信息Url /// /// 根据Code 获取用户OpenId Url /// private const string User_GetOpenIdUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code"; /// /// 根据Code 获取用户OpenId的Url 需要Format 0.code /// public static string WeiXin_User_OpenIdUrl { get { return string.Format(User_GetOpenIdUrl, AppId, Secret, "{0}"); } } /// /// 根据OpenId 获取用户基本信息 Url(需要Format0.access_token 1.openid) /// public const string WeiXin_User_GetInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN"; #endregion #region OAuth2授权Url /// /// OAuth2授权Url,需要Format0.AppId 1.Uri 2.state /// private const string OAuth2_Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_base&state={2}#wechat_redirect"; /// /// OAuth2授权Url,需要Format 0.Uri 1.state /// public static string WeiXin_User_OAuth2Url { get { return string.Format(OAuth2_Url, AppId, "{0}", "{1}"); } } #endregion #region QrCode Url /// /// 创建获取QrCode的Ticket Url 需要Format 0 access_token /// public const string WeiXin_Ticket_CreateUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={0}"; /// /// 获取二维码图片Url,需要Format 0.ticket /// public const string WeiXin_QrCode_GetUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={0}"; #endregion #region Baidu 逆地理编码Url /// /// 经纬度 逆地理编码 Url 需要Format 0.ak 1.经度 2.纬度 /// private const string BaiduGeoCoding_ApiUrl = "http://api.map.baidu.com/geocoder/v2/?ak={0}&location={1},{2}&output=json&pois=0"; /// /// 经纬度 逆地理编码 Url 需要Format 0.经度 1.纬度 /// public static string Baidu_GeoCoding_ApiUrl { get { return string.Format(BaiduGeoCoding_ApiUrl, BaiduAk, "{0}", "{1}"); } } #endregion #region Menu Url /// /// 创建菜单Url 需要Format 0.access_token /// public const string WeiXin_Menu_CreateUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}"; /// /// 获取菜单Url 需要Format 0.access_token /// public const string WeiXin_Menu_GetUrl = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token={0}"; /// /// 删除菜单Url 需要Format 0.access_token /// public const string WeiXin_Menu_DeleteUrl = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={0}"; #endregion #region 支付相关Url /// /// 生成预支付账单Url ,需替换 0 access_token /// public const string WeiXin_Pay_PrePayUrl = "https://api.weixin.qq.com/pay/genprepay?access_token={0}"; /// /// 订单查询Url ,需替换0 access_token /// public const string WeiXin_Pay_OrderQueryUrl = "https://api.weixin.qq.com/pay/orderquery?access_token={0}"; /// /// 发货通知Url,需替换 0 access_token /// public const string WeiXin_Pay_DeliverNotifyUrl = "https://api.weixin.qq.com/pay/delivernotify?access_token={0}"; #region 统一支付相关Url (V3接口) /// /// 统一预支付Url /// public const string WeiXin_Pay_UnifiedPrePayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; /// /// 订单查询Url /// public const string WeiXin_Pay_UnifiedOrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; /// /// 退款申请Url /// public const string WeiXin_Pay_UnifiedOrderRefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund"; #endregion #endregion #endregion #region Json Const /// /// 获取二维码 所需Ticket 需要上传的Json字符串(需要Format 0.scene_id) /// /// scene_id场景值ID 永久二维码时最大值为100000(目前参数只支持1--100000) public const string WeiXin_QrCodeTicket_Create_JsonString = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\":{0}}}}"; #endregion } public class Ticket { public string ticket { get; set; } public string url { get; set; } } public class WeiXinHelper { static public string access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; static public string GetAccessToken(string appid, string appsecret) { string requestUrl = access_token_url.Replace("APPID", appid).Replace("APPSECRET", appsecret); WebResponse result = null; WebRequest req = WebRequest.Create(requestUrl); result = req.GetResponse(); Stream s = result.GetResponseStream(); XmlDictionaryReader xmlReader = JsonReaderWriterFactory.CreateJsonReader(s, XmlDictionaryReaderQuotas.Max); xmlReader.Read(); string xml = xmlReader.ReadOuterXml(); s.Close(); s.Dispose(); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); XmlElement rootElement = doc.DocumentElement; string access_token = rootElement.SelectSingleNode("access_token").InnerText.Trim(); return access_token; } #region 生成二维码 /// /// 获取Ticket /// /// public static string CreateTicket(string scene_id) { var token = GetAccessToken("wx0e7ca64a5be0612f", "75e198d9917c224b8ad9f9b8a4735194"); string url = string.Format(WeiXinConst.WeiXin_Ticket_CreateUrl, token); string postData = WeiXinConst.WeiXin_QrCodeTicket_Create_JsonString.Replace("{0}", scene_id); string result = Common.HttpUrlPost(postData, url); //HttpContext.p HttpClientHelper.PostResponse(); Ticket ticket = JsonConvert.DeserializeObject(result); //HttpClientHelper.PostResponse(url, postData); if (ticket == null || string.IsNullOrEmpty(ticket.ticket)) { } return ticket.ticket; } /// /// 当AccessToken过期时 调用此方法 /// /// /// private static string CreateTicketByNewAccessToken(string scene_id) { var token = GetAccessToken("wxcf4dbe1815d5d872", "ba17c52167b086542256f2f6f40ffb1f"); if (string.IsNullOrEmpty(token)) throw new ArgumentNullException("Access_Token"); string url = string.Format(WeiXinConst.WeiXin_Ticket_CreateUrl, token); string postData = WeiXinConst.WeiXin_QrCodeTicket_Create_JsonString.Replace("{0}", scene_id); string result = Common.HttpUrlPost(postData, url); //HttpContext.p HttpClientHelper.PostResponse(); Ticket ticket = JsonConvert.DeserializeObject(result); //HttpClientHelper.PostResponse(url, postData); if (ticket == null || string.IsNullOrEmpty(ticket.ticket)) throw new Exception("Ticket为Null,AccessToken:" + token); return ticket.ticket; } /// /// 根据Ticket获取二维码图片保存在本地 /// /// 二维码场景id /// 图片存储路径 public static void SaveQrCodeImage(string scene_id, string imgPath) { string Ticket = CreateTicket(scene_id); if (Ticket == null) throw new ArgumentNullException("Ticket"); //ticket需 urlEncode string stUrl = string.Format(WeiXinConst.WeiXin_QrCode_GetUrl, HttpUtility.UrlEncode(Ticket)); HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(stUrl); req.Method = "GET"; using (WebResponse wr = req.GetResponse()) { HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse(); string strpath = myResponse.ResponseUri.ToString(); WebClient mywebclient = new WebClient(); try { mywebclient.DownloadFile(strpath, imgPath); } catch (Exception) { throw new Exception("获取二维码图片失败!"); } } } /// /// 根据SceneId 获取 二维码图片流 /// /// /// public static Stream GetQrCodeImageStream(string scene_id) { string Ticket = CreateTicket(scene_id); if (Ticket == null) throw new ArgumentNullException("Ticket"); //ticket需 urlEncode string strUrl = string.Format(WeiXinConst.WeiXin_QrCode_GetUrl, HttpUtility.UrlEncode(Ticket)); try { System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(); Byte[] bytes = client.GetByteArrayAsync(strUrl).Result; return new MemoryStream(bytes); } catch { throw new Exception("获取二维码图片失败!"); } } #endregion } }