WeixinApi.cs 12.3 KB
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Web;
using Quiz.Utility;

namespace Quiz.SiteBase
{
    public class WeixinApi
    {
        static Dictionary<string, WeixinAccount> Cache = new Dictionary<string, WeixinAccount>();
        public static string oauthurl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
        public static string oauthuserinfourl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
        public static string wapurl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
        public static string userinfourl = "https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN";

        public static WeixinAccount GetWeixinAccount(string actid)
        {
            if (!Cache.ContainsKey(actid))
            {
                List<Models.Weixin> wxList = SiteBase.Cache.CacheManage.Weixin.CacheData;
                if (wxList == null) return null;
                Models.Weixin wxaccount = wxList.Find(o => o.ActId == actid);
                //appid等没的话不缓存 account,为了不获取token ticket
                if (wxaccount == null || string.IsNullOrEmpty(wxaccount.AppId) || string.IsNullOrEmpty(wxaccount.AppSecret)) return null;
                WeixinAccount account = new WeixinAccount(actid, wxaccount.AppId, wxaccount.AppSecret);
                account.TokenRefresh += AccountOnTokenRefresh;
                Cache.Add(actid, account);
            }
            return Cache[actid];
        }
        private static void AccountOnTokenRefresh(string actid)
        {
            List<Models.Weixin> wxList = SiteBase.Cache.CacheManage.Weixin.CacheData;
            Models.Weixin wxaccount = wxList.Find(o => o.ActId == actid);
            if (wxaccount == null || string.IsNullOrEmpty(wxaccount.AppId) || string.IsNullOrEmpty(wxaccount.AppSecret)) Cache.Remove(actid);
            else if (Cache.ContainsKey(actid)) Cache[actid].Update(wxaccount.AppId, wxaccount.AppSecret);
        }
        public static string GetToken(string actid)
        {
            try
            {
                WeixinAccount account = GetWeixinAccount(actid);//缓存的公众号信息
                //返回Token
                return account == null ? "" : account.AccessToken;
            }
            catch (Exception err)
            {
                return "";
            }
        }
        public static string GetJsapiTicket(string actid)
        {
            WeixinAccount account = GetWeixinAccount(actid);//缓存的公众号信息
            return account == null ? "" : account.JsapiTicket;
        }
    }

    #region 微信公众号信息
    public delegate void AccessTokenCallback(string actid);
    /// <summary>
    /// 微信公众号信息
    /// </summary>
    public class WeixinAccount
    {
        static WeiXinAction action = new WeiXinAction();

        private string app_secret;

        private string jsapi_ticket;

        private string access_token;
        /// <summary>
        /// jsapi_ticket到期时间
        /// </summary>
        private DateTime jsapi_ticket_time;
        /// <summary>
        /// access_token到期时间
        /// </summary>
        private DateTime access_token_time;

        public string Id { get; private set; }
        /// <summary>
        /// 公众号AppID
        /// </summary>
        public string AppId { get; private set; }
        /// <summary>
        /// jsapi_ticket, 有效期为7200秒
        /// </summary>
        public string JsapiTicket
        {
            get
            {
                if (jsapi_ticket_time < DateTime.Now)
                {
                    var ticket = action.GetJsapiTicket(AccessToken, jsapi_ticket_time);
                    if (ticket == null || ticket.errcode != 0) return string.Empty;
                    jsapi_ticket = ticket.ticket;
                    jsapi_ticket_time = DateTime.Now.AddSeconds(ticket.expires_in);
                }
                return jsapi_ticket;
            }
        }
        /// <summary>
        /// access_token, 有效期7200秒
        /// </summary>
        public string AccessToken
        {
            get
            {
                if (access_token_time < DateTime.Now)
                {
                    OnTokenRefresh(Id);
                    var token = action.GetToken(AppId, app_secret, access_token_time);
                    if (token == null) return string.Empty;
                    access_token = token.access_token;
                    access_token_time = DateTime.Now.AddSeconds(int.Parse(token.expires_in));
                }
                return access_token;
            }
        }

        /// <summary>
        /// 实例化微信公众号
        /// </summary>
        /// <param name="id"></param>
        /// <param name="appid"></param>
        /// <param name="secret"></param>
        public WeixinAccount(string id, string appid, string secret)
        {
            Id = id;
            AppId = appid;
            app_secret = secret;
            access_token_time = DateTime.Parse("1970-01-01");
            jsapi_ticket_time = DateTime.Parse("1970-01-01");
        }

        public event AccessTokenCallback TokenRefresh;
        protected virtual void OnTokenRefresh(string actid)
        {
            var handler = TokenRefresh;
            if (handler != null) handler(actid);
        }

        public void Update(string appid, string secret)
        {
            if (AppId != null || app_secret != secret)
            {
                AppId = appid;
                app_secret = secret;
                access_token_time = DateTime.Parse("1970-01-01");
                jsapi_ticket_time = DateTime.Parse("1970-01-01");
            }

        }

    }
    #endregion

    #region 获取token和jsticket

        public class WeiXinAction
        {
            /// <summary>
            /// 获得Token  
            /// </summary>
            /// <param name="appid"></param>
            /// <param name="secret"></param>
            /// <param name="YouXRQ">token到期时间,获取的时间+7200</param>
            /// <returns>过期了返回新的Access_Token,否则返回空</returns>
            public Access_Token GetToken(string appid, string secret, DateTime YouXRQ)
            {
                if (DateTime.Now > YouXRQ)  //过期
                {
                    string Str = GetJson(string.Format(new WeiUrlConfig().URL_GetToken, appid, secret));
                    return JsonHelper.ParseFromJson<Access_Token>(Str);
                }
                return null;
            }
            /// <summary>
            /// 获得JsapiTicket
            /// </summary>
            /// <param name="token"></param>
            /// <param name="YouXRQ"></param>
            /// <returns></returns>
            public JsapiTicket GetJsapiTicket(string token, DateTime YouXRQ)
            {
                if (DateTime.Now > YouXRQ)  //过期
                {
                    string Str = GetJson(string.Format(new WeiUrlConfig().URL_GetJsapiTicket, token));
                    return JsonHelper.ParseFromJson<JsapiTicket>(Str);
                }
                return null;
            }
            private string GetJson(string url)
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; //SSL3协议替换成TLS协议
                WebClient wc = new WebClient();
                wc.Credentials = CredentialCache.DefaultCredentials;
                wc.Encoding = Encoding.UTF8;
                string returnText = wc.DownloadString(url);

                if (returnText.Contains("errcode"))
                {
                    //可能发生错误  
                }
                return returnText;
            }

        }
    #endregion

    #region 授权类型
        public class OAuth_Token
        {
            public OAuth_Token()
            {

                //  
                //TODO: 在此处添加构造函数逻辑  
                //  
            }
            //access_token  网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同  
            //expires_in    access_token接口调用凭证超时时间,单位(秒)  
            //refresh_token 用户刷新access_token  
            //openid    用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID  
            //scope 用户授权的作用域,使用逗号(,)分隔  
            public string access_token { get; set; }
            public string expires_in { get; set; }
            public string refresh_token { get; set; }
            public string openid { get; set; }
            public string scope { get; set; }

        }

        public class Access_Token
        {
            public string access_token { get; set; }
            public string expires_in { get; set; }
        }
        public class Ticket
        {
            public string ticket { get; set; }
            public string expire_seconds { get; set; }
        }

        public class JsapiTicket
        {
            public int errcode { get; set; }
            public string errmsg { get; set; }
            public string ticket { get; set; }
            public int expires_in { get; set; }
        }
    #endregion

    #region 配置信息
        public class WeiUrlConfig
        {
            public string URL_GetToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
            public string URL_GetJsapiTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi";

            public string URL_User_ALL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}&next_openid={1}";
            public string URL_User_One = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN";

            public string URL_User_GroupCreate = "https://api.weixin.qq.com/cgi-bin/groups/create?access_token={0}";
            public string URL_User_GroupALL = "https://api.weixin.qq.com/cgi-bin/groups/get?access_token={0}";
            public string URL_User_GroupIDGet = "https://api.weixin.qq.com/cgi-bin/groups/getid?access_token={0}";
            public string URL_User_GroupUpdate = "https://api.weixin.qq.com/cgi-bin/groups/update?access_token={0}";
            public string URL_User_GroupMove = "https://api.weixin.qq.com/cgi-bin/groups/members/update?access_token={0}";

            public string URL_Menu_Greate = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}";
            public string URL_Menu_Get = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token={0}";
            public string URL_Menu_Delete = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={0}";

            public string URL_GetTicket = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={0}";
            public string URL_GetD2Image = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={0}";

            public string URL_GetFile = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token={0}&media_id={1}";
            public string URL_UploadFile = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}";
            public string URL_UpVideo = "https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token={0}";

            //群发 上传图文
            public string URL_SendAllByGroup = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token={0}";
            public string URL_SendAllByOpenid = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token={0}";
            public string URL_UploadArticle = "https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token={0}";
            public string URL_DeleteSendALL = "https://api.weixin.qq.com//cgi-bin/message/mass/delete?access_token={0}";

            //48小时内发送客服消息
            public string URL_SendMSG = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={0}";

            //聊天记录
            public string URL_GetChatLog = "https://api.weixin.qq.com/cgi-bin/customservice/getrecord?access_token={0}";
        }
    #endregion
}