asp.net web api集成微信服務(使用Senparc微信SDK)

    /// <summary>
    /// 微信請求轉發控制器
    /// </summary>
    [RoutePrefix("weixin")]
    public class WeixinController : ApiController
    {
        #region 建立微信菜單

        /// <summary>
        /// 建立微信菜單
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("menu")]
        public string CreateMenu()
        {
            #region 菜單結構構建
            ButtonGroup bg = new ButtonGroup();

            string websiteUrl = WebConfigurationManager.AppSettings["WebsiteUrl"];
            bg.button.Add(new SingleViewButton()
            {
                //url = MenuHelper.GetMenuUrl("Weixin/Index"),
                url = string.Format("{0}/{1}", websiteUrl, WebConfigurationManager.AppSettings["mainPage"]),
                name = "我要借款",
            });

            bg.button.Add(new SingleViewButton()
            {
                url = string.Format("{0}/{1}", websiteUrl, "FrontendMobile/public/view/main.html#appeal"),
                name = "投訴建議",
            });
            #endregion

            string result = string.Empty;
            try
            {
                CommonApi.CreateMenu(WeixinConfig.APPID, bg);

                result = "菜單生成成功,通常有24小時緩存時間,也能夠直接取消關注再關注直接查看效果";
            }
            catch (WeixinException e)
            {
                result = e.Message;
            }

            return result;
        }

        /// <summary>
        /// 獲取微信菜單
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("menu")]
        public HttpResponseMessage GetMenu()
        {
            try
            {
                GetMenuResult result = CommonApi.GetMenu(WeixinConfig.APPID);

                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (WeixinException e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e.Message);
            }
        }

        /// <summary>
        /// 刪除菜單方法
        /// </summary>
        /// <returns></returns>
        [HttpDelete]
        [Route("menu")]
        public string DeleteMenu()
        {
            try
            {
                CommonApi.DeleteMenu(WeixinConfig.APPID);

                return "刪除成功,通常有24小時緩存時間,也能夠直接取消關注再關注直接查看效果";
            }
            catch (WeixinException e)
            {
                return e.Message;
            }
        }

        #endregion

        #region 微信服務器消息接收及處理

        /// <summary>
        /// 微信後臺驗證地址(使用Get),微信後臺的「接口配置信息」的Url填寫如:http://weixin.senparc.com/weixin
        /// </summary>
        [HttpGet]
        [Route("")]
        public HttpResponseMessage Get(string signature, string timestamp, string nonce, string echostr)
        {
            if (CheckSignature.Check(signature, timestamp, nonce, WeixinConfig.TOKEN))
            {
                var result = new StringContent(echostr, UTF8Encoding.UTF8, "application/x-www-form-urlencoded");
                var response = new HttpResponseMessage { Content = result };
                return response;
            }

            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, WeixinConfig.TOKEN) + "。" +
                    "若是你在瀏覽器中看到這句話,說明此地址能夠被做爲微信公衆帳號後臺的Url,請注意保持Token一致。");
        }

        /// <summary>
        /// 用戶發送消息後,微信平臺自動Post一個請求到這裏,並等待響應XML。
        /// PS:此方法爲簡化方法,效果與OldPost一致。
        /// v0.8以後的版本能夠結合Senparc.Weixin.MP.MvcExtension擴展包,使用WeixinResult,見MiniPost方法。
        /// </summary>
        [HttpPost]
        [Route("")]
        public HttpResponseMessage Post()
        {
            var requestQueryPairs = Request.GetQueryNameValuePairs().ToDictionary(k => k.Key, v => v.Value);
            if (requestQueryPairs.Count == 0
                || !requestQueryPairs.ContainsKey("timestamp")
                || !requestQueryPairs.ContainsKey("signature")
                || !requestQueryPairs.ContainsKey("nonce")
                || !CheckSignature.Check(requestQueryPairs["signature"], requestQueryPairs["timestamp"], 
                    requestQueryPairs["nonce"], WeixinConfig.TOKEN))
            {
                return Request.CreateErrorResponse(HttpStatusCode.Forbidden, "未受權請求");
            }
            PostModel postModel = new PostModel
            {
                Signature = requestQueryPairs["signature"],
                Timestamp = requestQueryPairs["timestamp"],
                Nonce = requestQueryPairs["nonce"]
            };
            postModel.Token = WeixinConfig.TOKEN;
            postModel.EncodingAESKey = WeixinConfig.ENCODINGAESKEY;//根據本身後臺的設置保持一致
            postModel.AppId = WeixinConfig.APPID;//根據本身後臺的設置保持一致

            //v4.2.2以後的版本,能夠設置每一個人上下文消息儲存的最大數量,防止內存佔用過多,若是該參數小於等於0,則不限制
            var maxRecordCount = 10;

            //自定義MessageHandler,對微信請求的詳細判斷操做都在這裏面。
            var messageHandler = new CusMessageHandler(Request.Content.ReadAsStreamAsync().Result, postModel, maxRecordCount);

            try
            {
#if DEBUG             
                Log.Logger.Debug(messageHandler.RequestDocument.ToString());
                if (messageHandler.UsingEcryptMessage)
                {
                    Log.Logger.Debug(messageHandler.EcryptRequestDocument.ToString());
                }
#endif
                /* 若是須要添加消息去重功能,只需打開OmitRepeatedMessage功能,SDK會自動處理。
                 * 收到重複消息一般是由於微信服務器沒有及時收到響應,會持續發送2-5條不等的相同內容的RequestMessage*/
                messageHandler.OmitRepeatedMessage = true;

                //執行微信處理過程
                messageHandler.Execute();

#if DEBUG
                if (messageHandler.ResponseDocument != null)
                {
                    Log.Logger.Debug(messageHandler.ResponseDocument.ToString());
                }

                if (messageHandler.UsingEcryptMessage)
                {
                    //記錄加密後的響應信息
                    Log.Logger.Debug(messageHandler.FinalResponseDocument.ToString());
                }
#endif

                var resMessage = Request.CreateResponse(HttpStatusCode.OK); 
                resMessage.Content = new StringContent(messageHandler.ResponseDocument.ToString());
                resMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml");            

                return resMessage;
            }
            catch (Exception ex)
            {
                Log.Logger.Error("處理微信請求出錯:", ex);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "處理微信請求出錯");
            }
        }

        #endregion

        #region JSSDK相關

        /// <summary>
        /// 獲取JSSDK參數信息
        /// </summary>
        /// <param name="url">獲取簽名所用的URL</param>
        /// <returns></returns>
        [HttpGet]
        [Route("JSSDK/{*url}")]
        public HttpResponseMessage GetJSSDK(string url)
        {
            if (!HttpContext.Current.SideInWeixinBroswer())
            {
                return Request.CreateErrorResponse(HttpStatusCode.Forbidden, "請經過微信端登陸");
            }

            try
            {
                //獲取時間戳
                var timestamp = JSSDKHelper.GetTimestamp();
                //獲取隨機碼
                var nonceStr = JSSDKHelper.GetNoncestr();
                string ticket = AccessTokenContainer.TryGetJsApiTicket(WeixinConfig.APPID, WeixinConfig.APPSECRET);
                //獲取簽名
                var signature = JSSDKHelper.GetSignature(ticket, nonceStr, timestamp, HttpUtility.UrlDecode(url));

                return Request.CreateResponse(HttpStatusCode.OK, new
                    {
                        appId = WeixinConfig.APPID,
                        timestamp = timestamp,
                        nonceStr = nonceStr,
                        signature = signature
                    });
            }
            catch (Exception e)
            {
                Log.Logger.Error("獲取JSSDK信息出錯:", e);

                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "獲取JSSDK信息出錯");
            }
        }

        #endregion

        /// <summary>
        /// 微信菜單導航
        /// </summary>
        /// <param name="code"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("index")]
        public HttpResponseMessage Index(string code, string state)
        {
            var response = Request.CreateResponse(HttpStatusCode.Redirect);
            try
            {
                var result = OAuthApi.GetAccessToken(WeixinConfig.APPID, WeixinConfig.APPSECRET, code);                
                response.Headers.Location = new Uri(string.Format("{0}?openId={1}", WebConfigurationManager.AppSettings["mainPage"], result.openid), UriKind.Relative);
            }
            catch (WeixinException e)
            {
                Log.Logger.Error("OAuth2受權失敗:", e);
                response.Headers.Location = new Uri(WebConfigurationManager.AppSettings["mainPage"], UriKind.Relative);
            }

            return response;
        }
    }
相關文章
相關標籤/搜索