本次更新同时影响以下所有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请求等日志。

     /*----------------------------------------------------------------
    Copyright (C) 2015 Senparc 文件名:WeixinTrace.cs
    文件功能描述:跟踪日志相关 创建标识:Senparc - 20151012 ----------------------------------------------------------------*/ using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Senparc.Weixin.Exceptions; namespace Senparc.Weixin
    {
    /// <summary>
    /// 微信日志跟踪
    /// </summary>
    public static class WeixinTrace
    {
    private static TraceListener _traceListener = null;
    private static readonly object TraceLock = new object(); internal static void Open()
    {
    Close();
    lock (TraceLock)
    {
    var logDir = System.AppDomain.CurrentDomain.BaseDirectory + "App_Data";
    string logFile = Path.Combine(logDir, "SenparcWeixinTrace.log");
    System.IO.TextWriter logWriter = new System.IO.StreamWriter(logFile, true);
    _traceListener = new TextWriterTraceListener(logWriter);
    System.Diagnostics.Trace.Listeners.Add(_traceListener);
    System.Diagnostics.Trace.AutoFlush = true;
    }
    } internal static void Close()
    {
    lock (TraceLock)
    {
    if (_traceListener != null && System.Diagnostics.Trace.Listeners.Contains(_traceListener))
    {
    _traceListener.Close();
    System.Diagnostics.Trace.Listeners.Remove(_traceListener);
    }
    }
    } /// <summary>
    /// 统一时间格式
    /// </summary>
    private static void TimeLog()
    {
    Log(string.Format("[{0}]", DateTime.Now));
    } private static void Unindent()
    {
    lock (TraceLock)
    {
    System.Diagnostics.Trace.Unindent();
    }
    } private static void Indent()
    {
    lock (TraceLock)
    {
    System.Diagnostics.Trace.Indent();
    }
    } private static void Flush()
    {
    lock (TraceLock)
    {
    System.Diagnostics.Trace.Flush();
    }
    } private static void LogBegin(string title = null)
    {
    Open();
    Log(title == null ? "" : String.Format("[{0}]", title));
    TimeLog();
    Indent();
    } /// <summary>
    /// 记录日志
    /// </summary>
    /// <param name="message"></param>
    public static void Log(string message)
    {
    lock (TraceLock)
    {
    System.Diagnostics.Trace.WriteLine(message);
    }
    } private static void LogEnd()
    {
    Unindent();
    Flush();
    Close();
    } /// <summary>
    /// API请求日志
    /// </summary>
    /// <param name="url"></param>
    /// <param name="returnText"></param>
    public static void SendLog(string url, string returnText)
    {
    if (!Config.IsDebug)
    {
    return;
    } LogBegin("接口调用");
    Log(string.Format("URL:{0}", url));
    Log(string.Format("Result:\r\n{0}", returnText));
    LogEnd();
    } /// <summary>
    /// ErrorJsonResultException 日志
    /// </summary>
    /// <param name="ex"></param>
    public static void ErrorJsonResultExceptionLog(ErrorJsonResultException ex)
    {
    if (!Config.IsDebug)
    {
    return;
    } LogBegin("ErrorJsonResultException");
    Log(string.Format("URL:{0}", ex.Url));
    Log(string.Format("errcode:{0}", ex.JsonResult.errcode));
    Log(string.Format("errmsg:{0}", ex.JsonResult.errmsg));
    LogEnd();
    }
    }
    }

    在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, , bytes.Length);
    ms.Seek(, 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, , bytes.Length);
    ms.Seek(, 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(通常是请求接口)。
     /*----------------------------------------------------------------
    Copyright (C) 2015 Senparc 文件名:ErrorJsonResultException.cs
    文件功能描述:JSON返回错误代码(比如token_access相关操作中使用)。 创建标识:Senparc - 20150211 修改标识:Senparc - 20150303
    修改描述:整理接口
    ----------------------------------------------------------------*/ using System;
    using Senparc.Weixin.Entities; namespace Senparc.Weixin.Exceptions
    {
    /// <summary>
    /// JSON返回错误代码(比如token_access相关操作中使用)。
    /// </summary>
    public class ErrorJsonResultException : WeixinException
    {
    public WxJsonResult JsonResult { get; set; }
    public string Url { get; set; } /// <summary>
    ///
    /// </summary>
    /// <param name="message"></param>
    /// <param name="inner"></param>
    /// <param name="jsonResult"></param>
    /// <param name="url"></param>
    public ErrorJsonResultException(string message, Exception inner, WxJsonResult jsonResult, string url = null)
    : base(message, inner)
    {
    JsonResult = jsonResult;
    Url = url; WeixinTrace.ErrorJsonResultExceptionLog(this);
    }
    }
    }

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):
                     string openTicket = OpenTicketHelper.GetOpenTicket(component_AppId);
    var component_access_token = Open.CommonAPIs.CommonApi.GetComponentAccessToken(component_AppId, component_Secret, openTicket).component_access_token;
    ComponentAccessToken = component_access_token;
    var oauthResult = Open.ComponentAPIs.ComponentApi.QueryAuth(component_access_token, component_AppId, auth_code);

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

                     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

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

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

    为了更好地适应微信越来越快的API更新速度和越来越多的API数量,本次Senparc.Weixin.dll v4.3.3对一些通用功能进行了深度的重构. 本次更新同时影响以下所有Senparc.Wei ...

  2. 【重要更新】Senparc.Weixin SDK v6.5 升级说明(支持 .NET Core 3.0 及分布式消息上下文)

    Senparc.Weixin SDK v6.5 开始支持 .NET Core 3.0,并将微信消息上下文进行了大幅度的重构,支持了使用分布式缓存存储上下文信息,这意味着在分布式系统中,现在 Senpa ...

  3. Senparc.Weixin SDK v5.0 升级公告

    经过五年半的持续维护,Senparc.Weixin SDK 逐步丰满和完善,在升级的过程中,我们为基础库(Senparc.Weixin.dll)加入了许多通用的功能,例如加密/解密算法.通用缓存方法等 ...

  4. Senparc.Weixin SDK 微信公众号 .NET 开发教程 索引

    Senparc.WeixinSDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起分享.也欢迎大 ...

  5. 利用Senparc.Weixin SDK 实现微信用户的授权,并获取信息

    前一段时间在学校做过一个项目,就是利用的Senparc.Weixin SDK 做的,于是翻看以前代码,虽然有注释,但是还是看的迷迷糊糊的,干脆就单步执行一遍看看是怎么实现的,然后就重新写了个简易的授权 ...

  6. 如何使用Senparc.Weixin SDK 底层的Redis缓存并设置过期时间

    最近在微信第三方平台项目开发中,有一个需求,所有绑定的公众号的回复规则按照主公众号的关键词配置来处理,我的处理思路是获取主公众号配置的关键词回复规则,缓存10分钟,由于需要使用Redis缓存来存储一些 ...

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

    Senparc.Weixin.MP SDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起分享. ...

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

    https://github.com/Senparc/WeiXinMPSDK [转] http://www.cnblogs.com/szw/archive/2013/01/13/senparc-wei ...

  9. Senparc.Weixin.MP SDK 微信公众平台开发教程(十七):个性化菜单接口说明

    前不久微信上线了个性化菜单接口,Senparc.Weixin SDK也已经同步更新. 本次更新升级Senparc.Weixin.MP版本到v13.5.2,依赖Senparc.Weixin版本4.5.4 ...

随机推荐

  1. 父窗口,子窗口之间的JS"通信"方法

    今天需要在iframe内做一个弹窗,但使用弹窗组件的为子窗口,所以弹窗只在子窗口中显示掩膜层和定位,这样不符合需求. 后来晓勇哥指点,了解到一个以前一直没关注到的东西,每个窗口的全局变量,其实都存在对 ...

  2. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  3. WebView cookie 管理

    在Android应用程序中经常会加载一个WebView页,如果需要客户端向WebView传递信息,比如Cookie,也是可以的. 需要应用程序先将Cookie注入进去,打开该网页时,WebView会将 ...

  4. webDriver环境搭建与测试

    1.安装jdk 2.安装eclipse 3.安装selenium 由于使用的是开发语言是java,因此需要安装java版的selenium包.下载地址:http://pan.baidu.com/s/1 ...

  5. GDB常用命令

    一. gdb使用流程 1.编译生成可执行文件 gcc -g hello.c -o hello 2.启动gdb gdb hello 3. 在main处设置断点 break main 4.运行程序 run ...

  6. C#匿名函数的坑

    在for循环中catch索引 for (int i = 0; i < n; i++) { foo(() =>{ if (i == x) //这里的i始终都是最后一个... { //bala ...

  7. jquery 传递事件的自定义数据

    整理一下 1. <script type="text/javascript">$(document).ready(function(){  $("input& ...

  8. 51单片机对无线模块nRF24L01简单的控制收发程序

    它的一些物理特性如工作频段.供电电压.数据传输速率就不详细介绍了,直接上代码. 1.首先是发送端: // Define SPI pins #include <reg51.h> #defin ...

  9. iOS开发零基础--Swift篇 循环

    循环的介绍 在开发中经常会需要循环 常见的循环有:for/while/do while. 这里我们只介绍for/while,因为for/while最常见 for循环的写法 最常规写法 // 传统写法 ...

  10. PXE网络启动提示no default or ui configuration directive问题解决

    按照 https://help.ubuntu.com/community/DisklessUbuntuHowto 的提示配置完系统,准备网络启动的时候,遇到: Trying to load pxeli ...