【重要更新】Senparc.Weixin SDK v4.4 升级说明

  本次更新同时影响以下所有Senparc.Weixin相关版本的dll:

  • Senparc.Weixin.dll 升级到 v4.4.2(重要)
  • Senparc.Weixin.MP.dll 升级到 v13.4.0(重要)
  • Senparc.Weixin.MP.MvcExtension.dll 无需升级
  • Senparc.Weixin.Open 升级到 v1.5.3(重要)
  • Senparc.Weixin.QY.dll 升级到 v3.2.0(重要)

  源代码:https://github.com/JeffreySu/WeiXinMPSDK

  Demo:http://weixin.senparc.com/

  Nuget:

  本次更新重构了Senparc.Weixin整个框架内几乎所有的CommonJsonSend类,并且为SDK添加了Debug状态用于调试状态下自动输出日志,以及其他异常类型相关的升级。

  具体升级内容如下:

Senparc.Weixin.dll

  1. 添加WeixinTrace类,用于输出完整的API请求等日志。

      1 /*----------------------------------------------------------------
      2     Copyright (C) 2015 Senparc
      3
      4     文件名:WeixinTrace.cs
      5     文件功能描述:跟踪日志相关
      6
      7
      8     创建标识:Senparc - 20151012
      9
     10 ----------------------------------------------------------------*/
     11
     12 using System;
     13 using System.Collections.Generic;
     14 using System.Diagnostics;
     15 using System.IO;
     16 using System.Linq;
     17 using System.Text;
     18 using System.Threading.Tasks;
     19 using Senparc.Weixin.Exceptions;
     20
     21 namespace Senparc.Weixin
     22 {
     23     /// <summary>
     24     /// 微信日志跟踪
     25     /// </summary>
     26     public static class WeixinTrace
     27     {
     28         private static TraceListener _traceListener = null;
     29         private static readonly object TraceLock = new object();
     30
     31         internal static void Open()
     32         {
     33             Close();
     34             lock (TraceLock)
     35             {
     36                 var logDir = System.AppDomain.CurrentDomain.BaseDirectory + "App_Data";
     37                 string logFile = Path.Combine(logDir, "SenparcWeixinTrace.log");
     38                 System.IO.TextWriter logWriter = new System.IO.StreamWriter(logFile, true);
     39                 _traceListener = new TextWriterTraceListener(logWriter);
     40                 System.Diagnostics.Trace.Listeners.Add(_traceListener);
     41                 System.Diagnostics.Trace.AutoFlush = true;
     42             }
     43         }
     44
     45         internal static void Close()
     46         {
     47             lock (TraceLock)
     48             {
     49                 if (_traceListener != null && System.Diagnostics.Trace.Listeners.Contains(_traceListener))
     50                 {
     51                     _traceListener.Close();
     52                     System.Diagnostics.Trace.Listeners.Remove(_traceListener);
     53                 }
     54             }
     55         }
     56
     57         /// <summary>
     58         /// 统一时间格式
     59         /// </summary>
     60         private static void TimeLog()
     61         {
     62             Log(string.Format("[{0}]", DateTime.Now));
     63         }
     64
     65         private static void Unindent()
     66         {
     67             lock (TraceLock)
     68             {
     69                 System.Diagnostics.Trace.Unindent();
     70             }
     71         }
     72
     73         private static void Indent()
     74         {
     75             lock (TraceLock)
     76             {
     77                 System.Diagnostics.Trace.Indent();
     78             }
     79         }
     80
     81         private static void Flush()
     82         {
     83             lock (TraceLock)
     84             {
     85                 System.Diagnostics.Trace.Flush();
     86             }
     87         }
     88
     89         private static void LogBegin(string title = null)
     90         {
     91             Open();
     92             Log(title == null ? "" : String.Format("[{0}]", title));
     93             TimeLog();
     94             Indent();
     95         }
     96
     97         /// <summary>
     98         /// 记录日志
     99         /// </summary>
    100         /// <param name="message"></param>
    101         public static void Log(string message)
    102         {
    103             lock (TraceLock)
    104             {
    105                 System.Diagnostics.Trace.WriteLine(message);
    106             }
    107         }
    108
    109         private static void LogEnd()
    110         {
    111             Unindent();
    112             Flush();
    113             Close();
    114         }
    115
    116         /// <summary>
    117         /// API请求日志
    118         /// </summary>
    119         /// <param name="url"></param>
    120         /// <param name="returnText"></param>
    121         public static void SendLog(string url, string returnText)
    122         {
    123             if (!Config.IsDebug)
    124             {
    125                 return;
    126             }
    127
    128             LogBegin("接口调用");
    129             Log(string.Format("URL:{0}", url));
    130             Log(string.Format("Result:\r\n{0}", returnText));
    131             LogEnd();
    132         }
    133
    134         /// <summary>
    135         /// ErrorJsonResultException 日志
    136         /// </summary>
    137         /// <param name="ex"></param>
    138         public static void ErrorJsonResultExceptionLog(ErrorJsonResultException ex)
    139         {
    140             if (!Config.IsDebug)
    141             {
    142                 return;
    143             }
    144
    145             LogBegin("ErrorJsonResultException");
    146             Log(string.Format("URL:{0}", ex.Url));
    147             Log(string.Format("errcode:{0}", ex.JsonResult.errcode));
    148             Log(string.Format("errmsg:{0}", ex.JsonResult.errmsg));
    149             LogEnd();
    150         }
    151     }
    152 }

    在WeixinTrace中,已经提供了两个自带的日志记录方法,供SDK的扩展库使用:

    • SendLog():API请求日志
      日志格式如下:

      [接口调用]
      [2015/10/14 10:40:27]
      URL:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=-3w2HMV7R1r_YWAryHtoVDzOHffPUUe4Cf48
      Result:
      {"errcode":0,"errmsg":"ok"}

    • ErrorJsonResultExceptionLog():每次创建ErrorJsonResultException的时候记录该异常的信息
      日志格式如下:

      [ErrorJsonResultException]
      [2015/10/14 11:13:49]
      URL:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=[AppId]&secret=[AppSecret]
      errcode:获取access_token时AppSecret错误或者access_token无效
      errmsg:invalid credential, access_token is invalid or not latest hint: [weMY8a0430vr18]

    这些日志默认被记录在网站(或应用)的App_Data/SenparcWeixinTrace.log文件中。

    日志只有在SDK出于Debug状态下才会记录,如何开启Debug状态请看下面。

  2. 添加Config.IsDebug属性。当Config.IsDebug为true时,WeixinTrace的日志记录功能才会被开启,否则即使调用方法,日志也不会被记录。
    建议在调试阶段使用此功能,正式发布的时候关闭。Debug状态可以在程序启动的时候或程序中的任意位置执行,如:

    namespace Senparc.Weixin.MP.Sample
    {
        public class WebApiApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                //...
                Senparc.Weixin.Config.IsDebug = true;//这里设为Debug状态时,/App_Data/目录下会生成日志文件记录所有的API请求日志,正式发布版本建议关闭
            }
        }
    }

    或者像这样在管理员权限下面(建议)做一个开关:

    namespace Senparc.Weixin.MP.Sample.Controllers
    {
        public class HomeController : BaseController
        {
            public ActionResult DebugOpen()
            {
                Senparc.Weixin.Config.IsDebug = true;
                return Content("Debug状态已打开。");
            }
    
            public ActionResult DebugClose()
            {
                Senparc.Weixin.Config.IsDebug = false;
                return Content("Debug状态已关闭。");
            }
        }
    }
  3. 添加CommonAPIs/CommonJsonSend.cs,旧版本的Senparc.Weixin.MP及Senparc.Weixin.Open对应文件删除,统一到Senparc.Weixin中。

    .net 4.5版本的代码如下(.net 4.0版本没有异步功能):

    /*----------------------------------------------------------------
        Copyright (C) 2015 Senparc
    
        文件名:CommonJsonSend.cs
        文件功能描述:通过CommonJsonSend中的方法调用接口
    
        创建标识:Senparc - 20151012
    
    ----------------------------------------------------------------*/
    
    using System;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    using Senparc.Weixin.Entities;
    using Senparc.Weixin.Exceptions;
    using Senparc.Weixin.Helpers;
    using Senparc.Weixin.HttpUtility;
    
    namespace Senparc.Weixin.CommonAPIs
    {
        /// <summary>
        /// CommonJsonSend
        /// </summary>
        public static class CommonJsonSend
        {
            #region 同步请求
    
            /// <summary>
            /// 向需要AccessToken的API发送消息的公共方法
            /// </summary>
            /// <param name="accessToken">这里的AccessToken是通用接口的AccessToken,非OAuth的。如果不需要,可以为null,此时urlFormat不要提供{0}参数</param>
            /// <param name="urlFormat"></param>
            /// <param name="data">如果是Get方式,可以为null</param>
            /// <param name="sendType"></param>
            /// <param name="timeOut">代理请求超时时间(毫秒)</param>
            /// <param name="jsonSetting"></param>
            /// <returns></returns>
            public static WxJsonResult Send(string accessToken, string urlFormat, object data, CommonJsonSendType sendType = CommonJsonSendType.POST, int timeOut = Config.TIME_OUT, bool checkValidationResult = false, JsonSetting jsonSetting = null)
            {
                return Send<WxJsonResult>(accessToken, urlFormat, data, sendType, timeOut);
            }
    
            /// <summary>
            /// 向需要AccessToken的API发送消息的公共方法
            /// </summary>
            /// <param name="accessToken">这里的AccessToken是通用接口的AccessToken,非OAuth的。如果不需要,可以为null,此时urlFormat不要提供{0}参数</param>
            /// <param name="urlFormat">用accessToken参数填充{0}</param>
            /// <param name="data">如果是Get方式,可以为null</param>
            /// <param name="sendType"></param>
            /// <param name="timeOut">代理请求超时时间(毫秒)</param>
            /// <param name="checkValidationResult"></param>
            /// <param name="jsonSetting"></param>
            /// <returns></returns>
            public static T Send<T>(string accessToken, string urlFormat, object data, CommonJsonSendType sendType = CommonJsonSendType.POST, int timeOut = Config.TIME_OUT, bool checkValidationResult = false, JsonSetting jsonSetting = null)
            {
                //TODO:此方法可以设定一个日志记录开关
    
                try
                {
                    var url = string.IsNullOrEmpty(accessToken) ? urlFormat : string.Format(urlFormat, accessToken);
                    switch (sendType)
                    {
                        case CommonJsonSendType.GET:
                            return Get.GetJson<T>(url);
                        case CommonJsonSendType.POST:
                            SerializerHelper serializerHelper = new SerializerHelper();
                            var jsonString = serializerHelper.GetJsonString(data);
                            using (MemoryStream ms = new MemoryStream())
                            {
                                var bytes = Encoding.UTF8.GetBytes(jsonString);
                                ms.Write(bytes, 0, bytes.Length);
                                ms.Seek(0, SeekOrigin.Begin);
    
                                return Post.PostGetJson<T>(url, null, ms, timeOut: timeOut, checkValidationResult: checkValidationResult);
                            }
    
                        //TODO:对于特定的错误类型自动进行一次重试,如40001(目前的问题是同样40001会出现在不同的情况下面)
                        default:
                            throw new ArgumentOutOfRangeException("sendType");
                    }
                }
                catch (ErrorJsonResultException ex)
                {
                    ex.Url = urlFormat;
                    throw;
                }
            }
    
            #endregion
    
            #region 异步请求
    
            /// <summary>
            /// 向需要AccessToken的API发送消息的公共方法
            /// </summary>
            /// <param name="accessToken">这里的AccessToken是通用接口的AccessToken,非OAuth的。如果不需要,可以为null,此时urlFormat不要提供{0}参数</param>
            /// <param name="urlFormat"></param>
            /// <param name="data">如果是Get方式,可以为null</param>
            /// <param name="timeOut">代理请求超时时间(毫秒)</param>
            /// <returns></returns>
            public static async Task<WxJsonResult> SendAsync(string accessToken, string urlFormat, object data, CommonJsonSendType sendType = CommonJsonSendType.POST, int timeOut = Config.TIME_OUT)
            {
                return await SendAsync<WxJsonResult>(accessToken, urlFormat, data, sendType, timeOut);
            }
    
            /// <summary>
            /// 向需要AccessToken的API发送消息的公共方法
            /// </summary>
            /// <param name="accessToken">这里的AccessToken是通用接口的AccessToken,非OAuth的。如果不需要,可以为null,此时urlFormat不要提供{0}参数</param>
            /// <param name="urlFormat"></param>
            /// <param name="data">如果是Get方式,可以为null。在POST方式中将被转为JSON字符串提交</param>
            /// <param name="sendType">发送类型,POST或GET,默认为POST</param>
            /// <param name="timeOut">代理请求超时时间(毫秒)</param>
            /// <param name="checkValidationResult">验证服务器证书回调自动验证</param>
            /// <param name="jsonSetting">JSON字符串生成设置</param>
            /// <returns></returns>
            public static async Task<T> SendAsync<T>(string accessToken, string urlFormat, object data, CommonJsonSendType sendType = CommonJsonSendType.POST, int timeOut = Config.TIME_OUT, bool checkValidationResult = false,
                JsonSetting jsonSetting = null
                )
            {
                try
                {
                    var url = string.IsNullOrEmpty(accessToken) ? urlFormat : string.Format(urlFormat, accessToken);
    
                    switch (sendType)
                    {
                        case CommonJsonSendType.GET:
                            return await Get.GetJsonAsync<T>(url);
                        case CommonJsonSendType.POST:
                            SerializerHelper serializerHelper = new SerializerHelper();
                            var jsonString = serializerHelper.GetJsonString(data, jsonSetting);
                            using (MemoryStream ms = new MemoryStream())
                            {
                                var bytes = Encoding.UTF8.GetBytes(jsonString);
                                await ms.WriteAsync(bytes, 0, bytes.Length);
                                ms.Seek(0, SeekOrigin.Begin);
    
                                return
                                    await
                                        Post.PostGetJsonAsync<T>(url, null, ms, timeOut: timeOut,
                                            checkValidationResult: checkValidationResult);
                            }
                        default:
                            throw new ArgumentOutOfRangeException("sendType");
                    }
                }
                catch (ErrorJsonResultException ex)
                {
                    ex.Url = urlFormat;
                    throw;
                }
            }
    
            #endregion
        }
    }
  4. 修改ErrorJsonResultException类,添加Url属性,方便开发者跟踪异常来自哪个URL(通常是请求接口)。

     1 /*----------------------------------------------------------------
     2     Copyright (C) 2015 Senparc
     3
     4     文件名:ErrorJsonResultException.cs
     5     文件功能描述:JSON返回错误代码(比如token_access相关操作中使用)。
     6
     7
     8     创建标识:Senparc - 20150211
     9
    10     修改标识:Senparc - 20150303
    11     修改描述:整理接口
    12 ----------------------------------------------------------------*/
    13
    14 using System;
    15 using Senparc.Weixin.Entities;
    16
    17 namespace Senparc.Weixin.Exceptions
    18 {
    19     /// <summary>
    20     /// JSON返回错误代码(比如token_access相关操作中使用)。
    21     /// </summary>
    22     public class ErrorJsonResultException : WeixinException
    23     {
    24         public WxJsonResult JsonResult { get; set; }
    25         public string Url { get; set; }
    26
    27         /// <summary>
    28         ///
    29         /// </summary>
    30         /// <param name="message"></param>
    31         /// <param name="inner"></param>
    32         /// <param name="jsonResult"></param>
    33         /// <param name="url"></param>
    34         public ErrorJsonResultException(string message, Exception inner, WxJsonResult jsonResult, string url = null)
    35             : base(message, inner)
    36         {
    37             JsonResult = jsonResult;
    38             Url = url;
    39
    40             WeixinTrace.ErrorJsonResultExceptionLog(this);
    41         }
    42     }
    43 }

Senparc.Weixin.MP.dll

  1. 弃用CommonJsonSend类(如果还继续使用不会出错,编译时候会提示过期),将在今后版本中彻底删除。
  2. 优化JsSdkApi相关接口。

Senparc.Weixin.Open.dll

  1. 弃用CommonJsonSend类(如果还继续使用不会出错,编译时候会提示过期),将在今后版本中彻底删除。
  2. 完善ComponentContainer及ComponentApi下的接口。
  3. 完善Component及OAuth相关接口,提供了更加自动化的接口获取。
  4. 比如以前按照官方的流程我们需要走4步才可以获取到queryAuth的授权(微信官方文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318587&token=f6aa7cd0d4ffc0820a9d694daa06fb841123fd2e&lang=zh_CN):

    1                 string openTicket = OpenTicketHelper.GetOpenTicket(component_AppId);
    2                 var component_access_token = Open.CommonAPIs.CommonApi.GetComponentAccessToken(component_AppId, component_Secret, openTicket).component_access_token;
    3                 ComponentAccessToken = component_access_token;
    4                 var oauthResult = Open.ComponentAPIs.ComponentApi.QueryAuth(component_access_token, component_AppId, auth_code);

    现在有了ComponentContainer,只需要一步,整个过程(包括所有会过期的token,ComponentContainer都会自动管理):

    1                 var queryAuthResult = ComponentContainer.GetQueryAuthResult(component_AppId, auth_code);

    还有比这个更爽的吗?
    Sample中的Demo也已经同步更新,大家现在可以在这个页面打开测试:http://weixin.senparc.com/OpenOAuth/JumpToMpOAuth

Senparc.Weixin.QY.dll

  常规升级,由于企业号的错误类型等,和公众号、开放平台不一样,所以本次更新没有将企业号的CommonJsonSend集结到Senparc.Weixin.dll中,仍然独立存在。

  系列教程索引:http://www.cnblogs.com/szw/archive/2013/05/14/weixin-course-index.html

时间: 2024-10-05 04:27:42

【重要更新】Senparc.Weixin SDK v4.4 升级说明的相关文章

【重要更新】Senparc.Weixin SDK v4.3.3升级说明

为了更好地适应微信越来越快的API更新速度和越来越多的API数量,本次Senparc.Weixin.dll v4.3.3对一些通用功能进行了深度的重构. 本次更新同时影响以下所有Senparc.Weixin相关版本的dll: Senparc.Weixin.dll 升级到 v4.3.3 Senparc.Weixin.MP.dll 升级到 v13.3.0(重要) Senparc.Weixin.MP.MvcExtension.dll 升级到 v1.4.1 Senparc.Weixin.Open 升级到

【重要更新】Senparc.Weixin SDK v6.5 升级说明

Senparc.Weixin SDK v6.5 将微信消息上下文进行了大幅度的重构,支持了使用分布式缓存存储上下文信息,这意味着在分布式系统中,现在 Senparc.Weixin SDK 也能提供跨服务器的上下文消息共享. 当前的分布式上下文支持依赖了 NeuChar 提供的跨平台消息上下文解决方案,因此在公众号.小程序.企业微信中都已经默认支持此功能(开放平台接收的是系统推送,暂时没有必要支持). 本次升级对应 Senparc.Weixin.dll:v6.5.0,Senparc.Weixin.

微信公众平台C# SDK:Senparc.Weixin.MP.dll

https://github.com/Senparc/WeiXinMPSDK [转] http://www.cnblogs.com/szw/archive/2013/01/13/senparc-weixin-mp-sdk.html 微信公众账号 Senparc.Weixin.MP SDK 开发教程 索引 Senparc.Weixin.MP SDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起

Senparc.Weixin.MP SDK 微信公众平台开发教程(十八):Web代理功能

在Senparc.Weixin.dll v4.5.7版本开始,我们提供了Web代理功能,以方便在受限制的局域网内的应用可以顺利调用接口. 有关的修改都在Senparc.Weixin/Utilities/HttpUtility/RequestUtility.cs: 1 #region 代理 2 3 private static WebProxy _webproxy = null; 4 5 /// <summary> 6 /// 设置Web代理 7 /// </summary> 8 /

Senparc.Weixin.MP SDK 微信公众平台开发教程(二十一):在小程序中使用 WebSocket (.NET Core)

本文将介绍如何在 .NET Core 环境下,借助 SignalR 在小程序内使用 WebSocket.关于 WebSocket 和 SignalR 的基础理论知识不在这里展开,已经有足够的参考资料,例如参考 SignalR 的官方教程:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-2.1 我们先看一下完成本教程内容后,在小程序内实现的 WebSocket 效果: 私有及群发消息

Senparc.Weixin.TenPay 正式发布

微信支付刚出来的时候,和公众号的绑定关系很深(甚至旧版本使用的就是公众号的appId),随着微信生态的逐步丰富,微信支付越来越成为一个独立的平台,同时服务于公众号.小程序.开放平台.企业号/企业微信等诸多平台,甚至微信支付本身也有了一些独立的功能. 早期,顺应微信支付的设计,我们在 Senparc.Weixin.MP(公众号模块)中嵌入了微信支付功能,经过连续 6 年的迭代升级,微信支付已经扩展到QY(企业号).Work(企业微信).Open(开放平台).WxOpen(小程序)等模块,其中出现了

Senparc.Weixin.MP SDK 微信公众平台开发教程(五):使用Senparc.Weixin.MP SDK

原文:Senparc.Weixin.MP SDK 微信公众平台开发教程(五):使用Senparc.Weixin.MP SDK Senparc.Weixin.MP SDK已经涵盖了微信5.0的所有公共API,以及2013年10月29日升级之后大部分实用的接口. 整个项目的源代码以及已经编译好的程序集可以在这个项目中获取到:https://github.com/JeffreySu/WeiXinMPSDK 我们现在从无到有建立一个ASP.NET MVC项目,来看一下如何与微信进行对接(Webforms

[原创][下载]Senparc.Weixin.MP-微信公众平台SDK(C#) - 已支持微信6.x API

因为正在计划做一个微信机器人,需要用ASP.NET,找了一下只有PHP的SDK,没有C#的,于是动手写了一个,已经全面支持微信6.x所有接口,包括多客服.卡券.微信支付等. 微信公众平台地址:http://mp.weixin.qq.com Senparc.Weixin.MP官网地址:http://weixin.senparc.com 所有源代码(SDK+示例): https://github.com/JeffreySu/WeiXinMPSDK(新版本已发布,可以在github中查看最新的代码和教

【转】微信公众账号 Senparc.Weixin.MP SDK 开发教程 索引

微信公众账号 Senparc.Weixin.MP SDK 开发教程 索引 Senparc.Weixin.MP SDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起分享.也欢迎大家的补充! SDK还在不断优化升级中,开源项目见:https://github.com/JeffreySu/WeiXinMPSDK 微信技术交流社区:http://www.weiweihi.com/QA Senparc