2017-07-28 15:32:35 chenqiuge1984 阅读数 2838
  • 微信公众平台深度开发v2.0第1季——微信公众号基础...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    78975 人正在学习 去看看 翟东平

本文节选自苏震巍撰写的《微信开发深度解析:微信公众号、小程序高效开发秘籍》一书,由电子工业出版社出版。
责编:陈秋歌,关注微信开发等领域,寻求报道或者投稿请发邮件至chenqg#csdn.net。

MessageHandler 是一个微信消息的处理模块,也是整个微信开发过程中不可缺少的一部分。在 MessageHandler 中,开发者可以非常轻松地处理所有类型的微信消息。

本文将介绍 MessageHandler 的原理以及使用方法,包括支撑MessageHandler 运行所必需的实体类型、工厂方法等相关知识的介绍。

设计思想

如果你已经了解微信消息的基本通信原理,那我们现在可以非常方便地构造出一个简单的消息处理功能,如下:


StreamReader str = new StreamReader(Request.InputStream, System.Text.Encoding. UTF8);
XmlDocument xml = new XmlDocument();
xml.Load(str);
var wx = new WeixinRequest();
wx.ToUserName = xml.SelectSingleNode("xml").SelectSingleNode("ToUserName").InnerText;
wx.FromUserName = xml.SelectSingleNode("xml").SelectSingleNode("FromUserName"). InnerText;
wx.MsgType = xml.SelectSingleNode("xml").SelectSingleNode("MsgType").InnerText;
if (wx.MsgType.Trim() == "event")
{
    wx.EventName = xml.SelectSingleNode("xml").SelectSingleNode("Event").InnerText;
    //  WriteLog(wx.EventName);
    if (wx.EventName.ToUpper() == "LOCATION")
    {
        wx.Latitude = xml.SelectSingleNode("xml").SelectSingleNode("Latitude").InnerText;
        wx.Longitude = xml.SelectSingleNode("xml").SelectSingleNode("Longitude"). InnerText;
        wx.Precision = xml.SelectSingleNode("xml").SelectSingleNode("Precision"). InnerText;
    }
    else
    {
        wx.EventKey = xml.SelectSingleNode("xml").SelectSingleNode("EventKey"). InnerText;
    }
}
else if (wx.MsgType.Trim() == "text")
{
    wx.Content= xml.SelectSingleNode("xml").SelectSingleNode("Content").InnerText;
} else if (...)
{
    //...
}

这个方法也是目前很多其他框架甚至微信官方的Demo使用的,但是这种方法我可以用“不美好”来形容。

不美——首先使用字符串拼接的方式非常丑陋,其次哪怕使用 XmlDocument 或 XDocument 等面向对象的方式去处理,面对几十种不同的微信消息类型以及一一对应的不同的格式,代码将变得非常冗长而且难以维护。这样的代码你的老板或客户会喜欢吗?

不好——这样的写法坏处太多:

  • 可移植性差
  • 并没有做到很好地分离(无论是和整个应用程序还是不同请求类型之间)
  • 如果要做单元测试就必须整体代码一起上
  • 基本上不具备可扩展性
  • 容错能力很差,即使做到了,代码已经无法直视
  • 正常人用多了会心情不好

那么,“美好”的消息处理方式应该是怎么样的呢?

下面就将 Senparc.Weixin.MP.MessageHandler 介绍给你。

首先,美好的 MessageHandler 必须具有对消息类型的自动识别和分类能力。

第二,美好的 MessageHandler 必须能够同时、自动处理“明文”“兼容模式”“加密模式”三种(所有)消息加密类型,并且让开发者忘掉加密这回事情的存在。

第三,美好的 MessageHandler 必须能够提供很好的消息容器以及储存容器,来解决消息去重、Session 等一系列的问题。

第四,美好的 MessageHandler 必须能够兼容 MVC 和 WebFroms 不同的请求处理方式。

第五,美好的 MessageHandler 必须能够提供统一逻辑处理的接口,方便在特定的环节对消息进行统一处理。

第六,美好的 MessageHandler 必须具备优秀的可测试性和扩展能力。

第七,美好的 MessageHandler 必须能做到很好的逻辑分离。

第八,美好的 MessageHandler 必须让你用起来心情好。

第九,美好的 MessageHandler 不能保证你能在 10 分钟内,完成一个满足以上八条的简单微信应用从开发到上线、发布的全过程。但是我们做到了。

消息类型

概述

微信的互动消息包含请求消息响应消息两类:

  • 请求消息:由微信服务器发送到应用服务器的消息(通常由用户微信操作触发或用户主动发送)。
    -响应消息:应用服务器收到请求消息之后,返回给微信服务器的消息。响应消息可以被转发到用户微信,也可以采用“沉默”的方式不给予响应。

所有的消息类型如图1所示(至本文发布,消息类型又丰富了许多)。

图片描述

图1

无论是请求消息还是响应消息,各自还包括不同的消息类型,其中每一种消息类型,又都有不同的参数和对应的格式要求。

对应每一种消息具体的参数和 XML 格式可以参考微信官方Wiki,这里不再赘述。本书将重点针对面向对象的类展开介绍,使用 Senparc.Weixin SDK 的开发者基本上可以忘掉微信的 XML 格式和要求,只需要了解如何面向对象地处理消息。当然,对于 XML 的了解将帮助你更加从容地处理一些问题,例如测试和调试过程都可能需要用到 XML。

命名规则

为了可以使用 C# 面向对象地处理问题,同时也更加规范地进行编程,我们决定在一些地方改变微信原有的命名规则(全部使用小写,用下划线_分隔不同单词),而使用 C# 推荐的命名方式(Pascal 大小写命名法)来作为类名或属性名称。如微信文档中的属性或名称可能为 access_token,在 Senparc.Weixin 中将被命名为 AccessToken。当阅读微信官方的文档时理解这样的变化举一反三即可。

当然,这种改变是灵活的,有一些地方我们仍然需要保持参数名称的“原貌”来确保 JSON 和 XML 自动转换的准确性和稳定性。

这样的改变不仅出现在消息类型中,对本书后面会介绍的 API 和其他功能同样适用。
全局消息基类

在所有这些消息类型中,都具有一些相同的属性,因此在 MessageHandler 体系中,我们为所有的消息创建了一个基类 MessageBase

    /// <summary>
    /// 所有Request和Response消息的基类
    /// </summary>
    public abstract class MessageBase : IMessageBase
    {
        public string ToUserName { get; set; }
        public string FromUserName { get; set; }
        public DateTime CreateTime { get; set; }
    }

MessageBase将作为所有消息的基类,无论是请求消息还是响应消息,也无论是微信公众号还是企业号或开放平台等,MessageBase 对微信消息进行了非常高度的抽象和概括。

下面我们将分别介绍的请求消息和响应消息都是以 MessageBase 作为基类的。

请求消息

请求消息又分为两种类型:普通消息事件推送消息。无论是哪一种消息,它们都具有相同的基础参数,如表1所示。

图片描述

为此,在 MessageBase 的基础上,我们为所有的请求消息设置了一个基类 RequestMessageBase

图片描述

请注意 RequestMessageBase 是一个抽象类,因此不可以被直接实例化。事实上,这个类也不应该被实例化,因为我们没有办法通过实例化这个类达到操作一个具体的请求类型消息的目的,我们仍然需要创建基于 RequestMessageBase 的对应每一个消息类型的实体来对其进行操作(作为全局考虑,不光微信公众号的请求消息需要用到 RequestMessageBase,企业号、开放平台等其他模块也需要用到)。

以上的基类都定义在 Senparc.Weixin.dll 中,普通消息的定义在Senparc.Weixin.MP.dll 中,直接使用 RequestMessageBase 作为基类,对应关系如表2所示。

图片描述

事件推送消息比普通消息多了 Event 这个属性,因此我们为所有的事件推送消息定义了一个统一的基类 RequestMessageEventBase

    public class RequestMessageEventBase : RequestMessageBase, IRequestMessageEventBase
    {
        public override RequestMsgType MsgType
        {
            get { return RequestMsgType.Event; }
        }

        /// <summary>
        /// 事件类型
        /// </summary>
        public virtual Event Event
        {
            get { return Event.ENTER; }
        }
    }

可以看到 RequestMessageEventBaseRequestMessageBase 多了一个 Event 属性,并且对MsgType 属性进行了强制的规定,默认情况下所有继承 RequestMessageEventBase 的类型都将返回 RequestMsgType.Event,这样 MessageHandler 将可以对事件推送消息消息类型进行特殊的处理。

由于事件推送消息类型比较多,我们将其分为 3 大类:

  • 常规事件(公众号基础功能返回事件)
  • 菜单事件(各种类型的公众号菜单返回事件)
  • 应用事件(应用模块返回事件,例如卡券、多客服等)

对应如表3所示。

图片描述

以上的类型中,都具有从 RequestMessageEventBase 继承而来的 Event 属性,有部分类型都具有 EventKey 属性,说明如表4所示。

图片描述

并不是所有的事件都具有EventKey,因此我们提供了IRequestMessageEventKey 接口,所有实现此接口的消息类型必须提供 EventKey,例如订阅事件:

    /// <summary>
    /// 事件之订阅
    /// </summary>
    public class RequestMessageEvent_Subscribe : RequestMessageEventBase, IRequestMessageEventBase, IRequestMessageEventKey
    {
        /// <summary>
        /// 事件类型
        /// </summary>
        public override Event Event
        {
            get { return Event.subscribe; }
        }

        /// <summary>
        /// 事件KEY值,qrscene_为前缀,后面为二维码的参数值(如果不是扫描场景二维码,此参数为空)
        /// </summary>
        public string EventKey { get; set; }
        /// <summary>
        /// 二维码的ticket,可用来换取二维码图片(如果不是扫描场景二维码,此参数为空)
        /// </summary>
        public string Ticket { get; set; }
    }

有些事件则不需要 EventKey,如取消订阅事件:

    /// <summary>
    /// 事件之取消订阅
    /// </summary>
    public class RequestMessageEvent_Unsubscribe : RequestMessageEventBase, IRequestMessageEventBase
    {
        /// <summary>
        /// 事件类型
        /// </summary>
        public override Event Event
        {
            get { return Event.unsubscribe; }
        }
    }

注意:实现 EventKey 参数类型都是字符串,但是在不同的事件中会具有不同的含义,有些官方已经规定了参数格式(如:扫描带参数二维码事件,都是以 qrscene_ 为前缀),而有些可以自己定义(如:菜单点击事件),在开发的过程中需要注意。


注意:事件推送消息的触发大部分是通过用户的某个微信界面的操作触发的(如:菜单点击、发送语音等),也有通过其他操作触发的(如:微小店订单付款通知、多客服转接会话等),因此在“人肉测试”的时候要格外注意结合参考微信官方的文档,了解其触发流程,避免误认为程序问题而没有触发事件的错误判断。

响应消息
响应消息和请求消息的设计原理类似,所有响应消息的类型都继承自ResponseMessageBase,ResponseMessageBase 同样继承自 MessageBase。 Senparc.Weixin.dll 下的 ResponseMessageBase (Weixin.Entities.ResponseMessageBase)代码如下:

 /// <summary>
 /// 响应回复消息
 /// </summary>
 public abstract class ResponseMessageBase : MessageBase, IResponseMessageBase
 {
 }

以上 Weixin.Entities.ResponseMessageBase 适用于包含微信公众号、企业号、开发平台等在内的多个平台,作为响应消息的基类。

为了增强 MessageHandler 的便捷性,Senparc.Weixin.MP.dll 提供了专门用于微信公众号的 ResponseMessageBase (Senparc.Weixin.MP.Entities. ResponseMessageBase,继承自 Senparc.Weixin. Entities.ResponseMessageBase),代码如下:

    /// <summary>
    /// 微信公众号响应回复消息基类
    /// </summary>
    public class ResponseMessageBase : Weixin.Entities.ResponseMessageBase, IResponseMessageBase
    {
        public virtual ResponseMsgType MsgType
        {
            get { return ResponseMsgType.Text; }
        }

        /// <summary>
        /// 获取响应类型实例,并初始化
        /// </summary>
        /// <param name="requestMessage">请求</param>
        /// <param name="msgType">响应类型</param>
        /// <returns></returns>
        [Obsolete("建议使用CreateFromRequestMessage<T>(IRequestMessageBase requestMessage)取代此方法")]
        private static ResponseMessageBase CreateFromRequestMessage(IRequestMessageBase requestMessage, ResponseMsgType msgType)
        {
            //略
        }

        /// <summary>
        /// 获取响应类型实例,并初始化
        /// </summary>
        /// <typeparam name="T">需要返回的类型</typeparam>
        /// <param name="requestMessage">请求数据</param>
        /// <returns></returns>
        public static T CreateFromRequestMessage<T>(IRequestMessageBase requestMessage) where T : ResponseMessageBase
        {
            //略        }

        /// <summary>
        /// 从返回结果XML转换成IResponseMessageBase实体类
        /// </summary>
        /// <param name="xml">返回给服务器的Response Xml</param>
        /// <returns></returns>
        public static IResponseMessageBase CreateFromResponseXml(string xml)
        {
            //略        }
    }

通过上述的两个 ResponseMessageBase,我们可以发现,和 RequestMessageBase 不同的是,ResponseMessageBase 没有提供 MsgId,这就意味着:应用程序服务器回复微信服务器的消息,必须一次成功,微信没有提供和响应消息一样的容错机制(数秒内收不到响应则连续发送几条带有 MsgId 的消息到应用服务器,确保消息可以到达)。也就是说,如果这条响应消息因为各种原因没有发送成功(网络问题或格式错误),客户端将收不到正确的消息回复,通常还会显示一条“该公众号暂时无法提供服务,请稍后再试(Official account services unavailable. Try again later)”的错误信息,如图2所示。

图片描述

图2

此错误可以在“盛派网络小助手”发送文字“错误”进行测试。

注意:对于多条带有相同 MsgId 的请求消息进行多次回复,客户端也只能收到微信服务器最后一次重发所对应的这条响应消息。

例如由于应用程序服务器没有及时响应,微信服务器连续发送了 3 条MsgId都为 6224799151644543291 的消息到应用程序服务器,这三次请求分别为 A、B、C,应用程序服务器由于没有对消息去重,分别响应了 A1、B1、C1,此时,客户端只会收到一条 C1 的回复。此错误可以在“盛派网络小助手”发送文字“容错”进行测试。

响应消息的类型比请求消息要少许多,如表5所示。

图片描述

上述响应类型中,有部分包含复杂的属性,我们将其独立创建类,分别有:Image、Voice、Video、Music、Article 这些类型。
以比较常用的图文消息为例,ResponseMessageNews 定义如下:

/// <summary>
    /// 图文消息
    /// </summary>
    public class ResponseMessageNews : ResponseMessageBase, IResponseMessageBase
    {
        new public virtual ResponseMsgType MsgType
        {
            get { return ResponseMsgType.News; }
        }

        public int ArticleCount
        {
            get
            {
                return Articles == null ? 0 : Articles.Count;
            }
            set
            {
                //这里开放set只为了逆向从Response的XML转成实体的操作一致性,没有实际意义。
            }
        }

        /// <summary>
        /// 文章列表,微信客户端只能输出前10条(可能未来数字会有变化,出于视觉效果考虑,建议控制在8条以内)
        /// </summary>
        public List<Article> Articles { get; set; }

        public ResponseMessageNews()
        {
            Articles = new List<Article>();
        }
    }

由于工厂模式自动初始化的需要,必须提供一个不带参数的构造函数,因此Articles参数无法通过构造函数设置,必须分成两步:

    var reponseMessage = CreateResponseMessage<ResponseMessageNews>();
    reponseMessage.Articles.Add(new Article()
    {
        Title = "你点击了子菜单图文按钮",
        Description = "你点击了子菜单图文按钮,这是一条图文信息。",
        PicUrl = "http://weixin.senparc.com/Images/qrcode.jpg",
        Url = "http://weixin.senparc.com"
    });

当 Articles 列表中只有 1 个 Article 对象的时候,显示为单图文,如图3所示。当 Article 大于 1 个时,显示为多图文,如图4所示。Articles 中最多允许有 10 个 Article 对象,即 10 条图文信息。

图片描述

使用MessageHandler

下面来看一下 MessageHandler 是如何让你爱上微信开发的。

在上述例子中,你只需要做三步:

  • 第一步:通过 Nuget 安装 Senparc.Weixin.MP。
  • 第二步:创建你自己的 MessageHandler(大部分代码只需要复制)。
  • 第三步:写 3 行关键代码(同样只需要复制)。

下面我们来跟随这三步,略为详细地展开一下 MessageHandler 最基础的一些用法,随后我们将学习 MessageHandler 的内部实现。

第一步:通过Nuget安装Senparc.Weixin.MP

第二步:创建你自己的MessageHandler

创建新文件 CustomMessageHandler.cs。CustomMessageHandle.cs 需要继承 Senparc.Weixin.MP. MessageHandlers 这个抽象类,并实现部分方法。最初步的 CustomMessageHandle.cs 代码可以如下。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using Senparc.Weixin.MP.Context;
using Senparc.Weixin.MP.Entities;
using Senparc.Weixin.MP.MessageHandlers;

namespace Senparc.Weixin.MP.Sample.Weixin
{
    public class CustomMessageHandler : MessageHandler<CustomMessageContext>
    {
        public CustomMessageHandler(Stream inputStream, PostModel postModel)
            : base(inputStream, postModel)
        {

        }

        public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
        {
            var responseMessage = base.CreateResponseMessage<ResponseMessageText>(); //ResponseMessageText也可以是News等其他类型
            responseMessage.Content = "这条消息来自DefaultResponseMessage。";
            return responseMessage;
        }
    }
}

我们可以看到必须要重写实现的抽象方法名为 DefaultResponseMessage(),这一条信息用于返回一条默认(替补)消息,假如对应类型(如语音)的微信消息没有被代码处理,那么默认会返回这里的结果。

在 DefaultResponseMessage() 方法中,有这样一句:

var responseMessage = base.CreateResponseMessage<ResponseMessageText>(); //ResponseMessageText也可以是News等其他类型

这里的 CreateResponseMessage 方法即创建一个返回对象,T 可以为以下类型的任意一个,分别对应了不同的返回类型,具体类型及说明请参考表5。

关于上述所有类型参数的设置方法,可以看 Senparc.Weixin SDK 的官方 Demo,这里不再重复。

接下来,我们了解下如何处理微信服务器发过来的文字信息。

很简单——在 CustomMessageHandler 里面重写一个 OnTextRequest 方法即可 :


public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
    if (requestMessage.Content == "你好")
    {
        var responseMessage = base.CreateResponseMessage<ResponseMessageNews>();
        var title = "Title";
        var description = "Description";
        var picUrl = "PicUrl";
        var url = "Url";
        responseMessage.Articles.Add(new Article()
        {
            Title = title,
            Description = description,
            PicUrl = picUrl,
            Url = url
        });
        return responseMessage;
    }
    else if (requestMessage.Content == "Senparc")
    {
        //相似处理逻辑
    }
    else
    {
        //...
    }
}

这个方法中可以自由发挥,比如读取数据库、判断关键字,甚至返回不同的ResponseMessageXX 类型(只要最终的类型都是在 IResponseMessageBase 接口下的即可)。

与 OnTextRequest 对应,如果我们要处理语音、地理位置、菜单等类型的消息,只需要重写对应的方法,可以重写的方法如下:

  • 接收消息方法
#region 接收消息方法

/// <summary>
/// 默认返回消息(当任何OnXX消息没有被重写,都将自动返回此默认消息)
/// </summary>
public abstract IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage);

/// <summary>
/// 预处理文字或事件类型请求。
/// 这个请求是一个比较特殊的请求,通常用于统一处理来自文字或菜单按钮的同一个执行逻辑,
/// 会在执行OnTextRequest或OnEventRequest之前触发,具有以下一些特征:
/// 1、如果返回null,则继续执行OnTextRequest或OnEventRequest
/// 2、如果返回不为null,则终止执行OnTextRequest或OnEventRequest,返回最终ResponseMessage
/// 3、如果是事件,则会将RequestMessageEvent自动转为RequestMessageText类型,其中RequestMessageText.Content就是RequestMessageEvent.EventKey
/// </summary>
public virtual IResponseMessageBase OnTextOrEventRequest(RequestMessageText requestMessage){...}

/// <summary>
/// 文字类型请求
/// </summary>
public virtual IResponseMessageBase OnTextRequest(RequestMessageText requestMessage) {...}

/// <summary>
/// 位置类型请求
/// </summary>
public virtual IResponseMessageBase OnLocationRequest(RequestMessageLocation requestMessage) {...}

/// <summary>
/// 图片类型请求
/// </summary>
public virtual IResponseMessageBase OnImageRequest(RequestMessageImage requestMessage) {...}

/// <summary>
/// 语音类型请求
/// </summary>
public virtual IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage) {...}

/// <summary>
/// 视频类型请求
/// </summary>
public virtual IResponseMessageBase OnVideoRequest(RequestMessageVideo requestMessage) {...}

/// <summary>
/// 链接消息类型请求
/// </summary>
public virtual IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage) {...}

/// <summary>
/// 小视频类型请求
/// </summary>
public virtual IResponseMessageBase OnShortVideoRequest(RequestMessageShortVideo requestMessage) {...}

#endregion
  • 接收事件方法
#region Event下属分类,接收事件方法

/// <summary>
/// Event事件类型请求之ENTER
/// </summary>
public virtual IResponseMessageBase OnEvent_EnterRequest(RequestMessageEvent_ Enter requestMessage){...}

/// <summary>
/// Event事件类型请求之LOCATION
/// </summary>
public virtual IResponseMessageBase OnEvent_LocationRequest(RequestMessageEvent_ Location requestMessage) {...}

//依此类推还有:
// Event事件类型请求之subscribe:OnEvent_SubscribeRequest()
// Event事件类型请求之unsubscribe:OnEvent_UnsubscribeRequest()
// Event事件类型请求之CLICK:OnEvent_ClickRequest()
// Event事件类型请求之scan:OnEvent_ScanRequest()
// 事件之URL跳转视图(View):OnEvent_ViewRequest()
// 事件推送群发结果:OnEvent_MassSendJobFinishRequest()
// 发送模板消息返回结果:OnEvent_TemplateSendJobFinishRequest()
// 弹出拍照或者相册发图:OnEvent_PicPhotoOrAlbumRequest()
// 扫码推事件:OnEvent_ScancodePushRequest()
// 扫码推事件且弹出“消息接收中”提示框:OnEvent_ScancodeWaitmsgRequest()
// 弹出地理位置选择器:OnEvent_LocationSelectRequest()
// 弹出微信相册发图器: OnEvent_PicWeixinRequest()
// 弹出系统拍照发图:OnEvent_PicSysphotoRequest()
// 卡券通过审核:OnEvent_Card_Pass_CheckRequest()
// 卡券未通过审核: OnEvent_Card_Not_Pass_CheckRequest()
// 领取卡券:OnEvent_User_Get_CardRequest()
// 删除卡券:OnEvent_User_Del_CardRequest()
// 多客服接入会话:OnEvent_Kf_Create_SessionRequest()
// 多客服关闭会话:OnEvent_Kf_Close_SessionRequest()
// 多客服转接会话:OnEvent_Kf_Switch_SessionRequest()
// Event事件类型请求之审核结果事件推送:OnEvent_Poi_Check_NotifyRequest()
// Event事件类型请求之Wi-Fi连网成功:OnEvent_WifiConnected()
// Event事件类型请求之卡券核销:OnEvent_User_Consume_Card()
// Event事件类型请求之从卡券进入公众号会话:OnEvent_User_Enter_Session_From_Card()
// Event事件类型请求之进入会员卡:OnEvent_User_View_Card()
// Event事件类型请求之微小店订单付款通知:OnEvent_Merchant_Order()
// Event事件类型请求之接收会员信息事件通知:OnEvent_Submit_Membercard_User_Info()
// Event事件类型请求之摇一摇事件通知:OnEvent_ShakearoundUserShake()

#endregion

其中 OnEvent_XX 对应的都是 Event 请求的子类型。

第三步:写3行关键代码

在已经创建好的 WeixinController.cs 中,加入如下代码:

[HttpPost]
[ActionName("Index")]
public ActionResult Post(PostModel postModel)
{
    if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel. Nonce, Token))
    {
        return Content("参数错误!");
    }

    postModel.Token = Token;
    postModel.EncodingAESKey = EncodingAESKey;//根据自己后台的设置保持一致
    postModel.AppId = AppId;//根据自己后台的设置保持一致

    var messageHandler = new CustomMessageHandler(Request.InputStream, postModel); //接收消息(第一步)

    messageHandler.Execute();//执行微信处理过程(第二步)

    return new FixWeixinBugWeixinResult(messageHandler);//返回(第三步)
}

如果你不需要进行保存消息日志等操作,这一步也几乎可以通过复制完成,不需要修改任何东西。当然即使需要保存日志,我们的 Demo 中也已经有相关案例可以直接使用。

上述代码中的 FixWeixinBugWeixinResult 用于提供给 MVC 一个处理一些微信官方疏忽的问题或者由于跨平台导致的字符识别问题的修正方法,使所有手机平台都可以得到一致、稳定的结果。这个方法需要使用到 Senparc.Weixin.MP.MvcExtension.dll。

至此我们已经使用 MassageHandler 处理所有微信用户发送过来的请求。

点击订购:《微信开发深度解析:微信公众号、小程序高效开发秘籍

图片描述

2017-07-14 07:17:19 sD7O95O 阅读数 508
  • 微信公众平台深度开发v2.0第1季——微信公众号基础...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    78975 人正在学习 去看看 翟东平

     全书由目 Senparc.Weixin SDK 作者苏震巍历时 2 年完成,涵盖了开发微信公众号及小程序需要用的的各项后端开发技能、技巧、避坑提示,以及 Senparc.Weixin SDK 微信公众号及小程序模块全面的使用说明及原理剖析。

    Senparc.Weixin SDK 发布 4 年多来,凭借众多的优势,得到了国内广大开发者及众多企业的关注和支持,目前已经是前国内使用率最高的 .NET 微信开发工具,同时也是 GitHub(全球最大的开源软件托管网站) 上打星及克隆分支排名第一的国内 .NET 开源项目,更是填补了中国没有超过2000星的.NET项目的空白。

经过出版社和京东的不懈沟通努力,终于为大家争取到了3天限时团购优惠 6.9折!,  京东自营连接: https://item.jd.com/12220004.html

可以通过阅读原文访问。


以下是我写的推荐:


互联网所催生的新一轮产业革命,移动App不断地连接“人“,创造了一个个基于人的应用场景;物联网传感器在不断的连接着”物“,也在创造一个个基于物的应用场景。在这样的一个连接的时代诞生的微信,它不仅仅成为我们连接人的日常沟通交流的工具,已经成为了中国整个社会的信息基础设施。在国内,由于微信在实时的连接每一个人,它已经成为一个最强大的入口,我本身从事微信支付的后端清算业务,能够深刻的体验到微信的强大引力,同时我也在运营微信公众号。公众号,服务号和企业号的诞生已经让微信开始连接后端的企业系统,小程序正在发展过程中,小程序让微信连接后端的企业系统打开新的窗户。但是这些后端的企业系统很多都是用C#开发的,正好C#的开源项目 Senparc.Weixin SDK 成为.NET平台上进行微信的快速开发的一个好工具,让开发者更好的对接后端的企业系统。

Senparc.Weixin SDK 从诞生起就采用开源模式持续更新,Senparc.Weixin SDK 是目前使用率最高的微信 .NET SDK,也是国内最受欢迎的 .NET 开源项目之一,已经支持几乎所有微信平台模块和接口,同时支持 .NET 4.0 / 4.5 / .NET Core。 很早我知道本书作者苏震巍在众筹写一本《微信公众平台快速开发》的书,在小程序对外正式发布的时候,我找他约稿了一篇小程序的文章发在我的微信公众号,那篇文章也是这本书的其中一章内容,最近这本书接近发稿了,有幸为这本书写序。

认识苏震巍多年,知道他不仅是技术专家,也是热心公益、乐于分享助人的好朋友。就如他自己所言,促使他开始他准备这本书的初心是要帮助朋友,帮助更多有理想的开发者实现价值,倡导开放共享的开发生态圈,助力中国开源事业,同时也感恩一路上给我们提供帮助的朋友们。

阅读完苏震巍传给我的书稿,这是一本比较全面地介绍微信公众号开发技术的图书,是一本从实践总结出来的实战类书籍,各章节的安排具有一定的知识层次,推荐给广大.NET开发者,非常感谢苏震巍夜以继日的辛苦努力,能让广大开发者拿到详实的微信开发指南和参考资料。我很高兴能为这本书作序!可以说,《微信开发深度解析:公众号、小程序高效开发秘籍》这本书是这个时代带给中国.NET开发人员的及时雨,不仅仅告诉我们微信公众平台、小程序的开发和使用,也为我们设计应用系统提供很好的参考和借鉴的经验。

 

----------------张善友,微软最有价值专家,腾讯高级工程师


原文地址:http://www.cnblogs.com/daxnet/p/7157896.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

2016-04-03 19:30:13 wgyscsf 阅读数 4128
  • 微信公众平台深度开发v2.0第1季——微信公众号基础...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    78975 人正在学习 去看看 翟东平

java微信开发API解析(一)-服务器接入

说明

* 本示例根据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/2016 5:34:36 PM )进行开发演示。
* 编辑平台:myeclipse10.7+win32+jdk1.7+tomcat7.0  
* 服务器:阿里云 windows server 2008 64bits
* 平台要求:servlet使用注解方式,平台要求:j2ee6.0+、jdk6.0+、tomcat7.0+
* 演示更加注重于api解析。
* 为了便于测试说明,每个测试用例为独立,不依赖于其它方法。对于封装,不多加考虑。
* 演示尽可能按照API要求进行,目的:了解文档使用方式,达到举一反三的效果。
* 知识要求:牢固的java基础、了解http网络通信知识、对于javaweb有足够了解、json解析
* 当前时间:4/3/2016 5:32:57 PM ,以该时间为准。

文档原文(摘要)

文档理解

验证服务器地址的有效性

  • api这样介绍:

    • 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:signature、timestamp、nonce、echostr
    • 开发者通过检验signature对请求进行校验(下面有校验方式)。
    • 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。
    • 加密/校验流程如下:
      1. 将token、timestamp、nonce三个参数进行字典序排序
      2. 将三个参数字符串拼接成一个字符串进行sha1加密
      3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
  • 理解

    • 说明该请求是“GET”方式,并且访问该请求会返回四个参数:signature、timestamp、nonce、echostr。
    • 我们需要接受这几个参数,然后进行处理。如果验证成功,返回接收到的“echostr”,否则验证失败。
    • 验证方式是对接受到的token、timestamp、nonce三个参数进行字典序排序,然后进行sha1加密,最后和signature对比。
      *加密后的字符串可与signature对比,如果相等【该处api可能解释不是太明白】,返回“echostr”,验证成功。
  • 实现

    • 创建一个servlet CoreServlet实现HttpServlet,重载doGet方法。
    • 参数准备

      // 设置一个全局的token,开发者自己设置。api这样解释:Token可由开发者可以任意填写,
      // 用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
      String token = "wgyscsf";
      // 根据api说明,获取上述四个参数
      String signature = req.getParameter("signature");
      String timestamp = req.getParameter("timestamp");
      String nonce = req.getParameter("nonce");
      String echostr = req.getParameter("echostr");
      
    • 根据api所说的三步骤进行操作

      // 第一步:将token、timestamp、nonce三个参数进行字典序排序
      String[] parms = new String[] { token, timestamp, nonce };// 将需要字典序排列的字符串放到数组中
      Arrays.sort(parms);// 按照api要求进行字典序排序【百度:什么是字典序排序】
      
      
      
      
      // 第二步:将三个参数字符串拼接成一个字符串进行sha1加密【百度:java sha1加密】
      // 拼接字符串
      String parmsString = "";// 注意,此处不能=null。
      for (int i = 0; i < parms.length; i++) {
          parmsString += parms[i];
      }
      // sha1加密
      String mParms = null;// 加密后的结果
      
      ... //该地方是sha1加密的实现,不再贴代码       
      
      mParms = hexString.toString();// 加密结果
      
      
      
      
      /*
       * api要求: 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容, 则接入生效, 成为开发者成功,否则接入失败。
       */
      // 第三步: 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信接入成功。
      System.out.println(TAG + ":" + mParms + "---->" + signature);
      if (mParms.equals(signature)) {
          // System.out.println(TAG + ":" + mParms + "---->" + signature);
          printWriter.write(echostr);
      } else {
          // 接入失败,不用回写
          // System.out.println(TAG + "接入失败");
      }   
      

填写服务器配置

  • 包括内容
    • 服务器配置主要是当我们写好自己的接入微信开发平台的代码之后要配置的服务器和微信接入接口。
  • 服务器操作
    • 打开服务器的tomcat,将写好的代码放到webapps文件下。
  • 微信公众平台操作

该部分所有操作源码,可以直接使用

package com.gist.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 高远</n> 邮箱:wgyscsf@163.com</n> 博客 http://blog.csdn.net/wgyscsf</n>
 *         编写时期 2016-4-3 下午4:34:05
 */
@WebServlet("/CoreServlet")
public class CoreServlet extends HttpServlet {
    String TAG = "CoreServlet";

    /*
     * 第二步:验证服务器地址的有效性 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,
     * GET请求携带四个参数:signature、timestamp、nonce、echostr
     * 开发者通过检验signature对请求进行校验(下面有校验方式)。 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,
     * 则接入生效, 成为开发者成功,否则接入失败。
     * 
     * 加密/校验流程如下: 1. 将token、timestamp、nonce三个参数进行字典序排序 2.
     * 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
     */
    /*
     * 字典排序(lexicographical
     * order)是一种对于随机变量形成序列的排序方法。其方法是,按照字母顺序,或者数字小大顺序,由小到大的形成序列。
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // 设置编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("html/text;charset=utf-8");
        resp.setCharacterEncoding("utf-8");
        // 获取输出流
        PrintWriter printWriter = resp.getWriter();

        // 设置一个全局的token,开发者自己设置。api这样解释:Token可由开发者可以任意填写,
        // 用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
        String token = "wgyscsf";
        // 根据api说明,获取上述四个参数
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");
        // // temp:临时打印,观看返回参数情况
        // System.out.println(TAG + ":signature:" + signature + ",timestamp:"
        // + timestamp + ",nonce:" + nonce + ",echostr:" + echostr);
        // 根据api所说的“加密/校验流程”进行接入。共计三步

        // 第一步:将token、timestamp、nonce三个参数进行字典序排序
        String[] parms = new String[] { token, timestamp, nonce };// 将需要字典序排列的字符串放到数组中
        Arrays.sort(parms);// 按照api要求进行字典序排序
        // 第二步:将三个参数字符串拼接成一个字符串进行sha1加密
        // 拼接字符串
        String parmsString = "";// 注意,此处不能=null。
        for (int i = 0; i < parms.length; i++) {
            parmsString += parms[i];
        }
        // sha1加密
        String mParms = null;// 加密后的结果
        MessageDigest digest = null;
        try {
            digest = java.security.MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        digest.update(parmsString.getBytes());
        byte messageDigest[] = digest.digest();
        // Create Hex String
        StringBuffer hexString = new StringBuffer();
        // 字节数组转换为 十六进制 数
        for (int i = 0; i < messageDigest.length; i++) {
            String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
            if (shaHex.length() < 2) {
                hexString.append(0);
            }
            hexString.append(shaHex);
        }
        mParms = hexString.toString();// 加密结果

        /*
         * api要求: 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容, 则接入生效, 成为开发者成功,否则接入失败。
         */
        // 第三步: 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信接入成功。
        System.out.println(TAG + ":" + mParms + "---->" + signature);
        if (mParms.equals(signature)) {
            // System.out.println(TAG + ":" + mParms + "---->" + signature);
            printWriter.write(echostr);
        } else {
            // 接入失败,不用回写
            // System.out.println(TAG + "接入失败");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }

}
2015-12-13 21:57:03 yutianxin123 阅读数 1054
  • 微信公众平台深度开发v2.0第1季——微信公众号基础...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    78975 人正在学习 去看看 翟东平

微信开发就是调用接口。这个难点就是调用接口时需要验证,必须按照微信要求的验证规则验证成功后才能调用接口。那么以我开发的微信小项目总结一下微信开发的难点。

1.微信开发属于web开发,要选合适的语言

尽管web开发有众多的语言,但是我觉得有必要提醒尽量选择主流、合适的语言。通过微信给的例子支持的语言就可以看出个一二三。PHP,jsp我觉得貌似比较主流,其他的语言也能做,可能没那么有优势吧。

2.微信接口调用验证

这个我觉得稍微有点难或者说繁,因为接口调用很好办,直接调用。而验证往往需要验证你的身份、权限各种(其实这也是微信为了安全起见、掌握控制权的体现)。解决这个问题我觉得直接阅读开发者文档最有效,文档里面也说的很明确。

3.调试技巧

如果你没有web程序的开发经验,你可能会忽视调试的作用。我曾经也想当然地回避调试,就各种看、想,硬把程序调对,后来发现web程序的调试很有技巧,如果掌握了会极大地加快开发速度。就比如我验证jssdk时,一直找不出错误。后来我运行网页,右键点击审查元素,就可以检查自己运行时的代码,进而找到了为什么验证不成功。

微信开发其实并不难,开发者文档我觉得是最好的参考资料,同时注意网络程序的安全性,以及相关网络程序开发的技巧就可以了。

2018-02-03 09:43:54 yji534123343 阅读数 913
  • 微信公众平台深度开发v2.0第1季——微信公众号基础...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    78975 人正在学习 去看看 翟东平
一、微信开发的整体介绍
开放平台:https://open.weixin.qq.com/
公众平台:https://mp.weixin.qq.com/
1、微信开发的种类
①移动应用开发
支持微信的分享、收藏、支付三大功能,原生开发的人员去使用的开发类别
②网站应用开发
网站支持使用微信账号进行注册和登录,从而来实现:提高用户的留存率,方便不同账号的统一(结合unionId)
③公众账号开发


④公众账号第三方平台
优势在于免繁琐设置,方便小白用户去使用。


2、公众账号开发
①服务号
主要偏向于给用户提供查询服务(招商银行、麦当劳。。)
显示在好友列表,每个月只能群发4条消息


②订阅号
主要偏向于给用户提供资讯(朝闻天下、Web前端。。)
显示在订阅号文件夹内,每天都可以群发1条消息


③小程序
2017年1月9号 (2007年1月9号 推出iphone)
基于微信的平台,ui提供了很多组件,js提供了很多接口


(微信官方的小程序:小程序示例,包含了微信官方封装好的组件、以及封装好的接口)


目标:万物互联 (IOT),  二维码
开放范围:(不包含个人)
http://www.wxapp-union.com/forum.php?mod=viewthread&tid=495


https://mp.weixin.qq.com/debug/wxadoc/dev/index.html


数据存储和服务器:
两种解决方案 ①腾讯云(不到100) ②godaddy


④企业号
主要是建立起 企业与人的关系,提供信息、和企业相关的定制功能


温馨提示:
1)如果想简单的发送消息,达到宣传效果,建议可选择订阅号;
2)如果想进行商品销售,进行商品售卖,建议可申请服务号;
3)如果想用来管理内部企业员工、团队,对内使用,可申请企业号。
4)订阅号可通过微信认证资质审核通过后有一次升级为服务号的入口,升级成功后类型不可再变。
5)服务号不可变更成订阅号。


3、九大类高级接口


语音识别接口
客服接口
OAuth2.0 网页授权接口
生成带参数的二维码接口
获取用户地理位置接口
获取用户基本信息接口
获取关注者列表接口
用户分组接口
上传下载多媒体文件接口


+ 微信支付
(十大类接口的使用,必须是认证过的服务号和订阅号才能使用)




4、正式环境的搭建
(公众账号-》订阅号)


购买自己的域名(万网、dnsPod、godaddy)
购买申请主机空间(新浪云、阿里云、腾讯云、大米云、godaddy、aws)
注册订阅号
登录到订阅号管理接口、服务器的配置、调用10大类接口


5、测试环境的搭建
(公众账号-》订阅号)


主机空间(新浪云)
注册订阅号
登录到订阅号管理接口、服务器的配置、调用10大类接口


6、注册订阅号
①填写邮箱、密码
②到邮箱中激活账号
③选择类型
④登记信息(个人、组织、媒体、企业。。)
⑤填写公众号的信息(名称、介绍、头像)






二、个人订阅号(jssdk)


1、实现功能:统计页面被访问的次数


分析:
①存储需要持久保存的数据
数据库、文件系统、内存中:fileSystem
②读写过程
读:file_get_contents($fileUrl);
写:file_put_contents($fileUrl,$content);


需要apache启动


2、新浪云storage


通过bucket管理我们的文件,如何访问?
saestor:// testbucket/count.txt




3、jsSDK的使用步骤
①绑定域名
②引入js文件
③注入接口(将使用接口的名称,写在config方法中jsAPIList这个数组中)
④在ready中调用接口
⑤在error中处理失败的异常情况






sample.zip有4个文件,
前两个文件都是用来存储数据的,jssdk.php进行网络请求以及数据的读写操作,sample.php文件主要完成接口的注入和调用


jssdk.php封装了2个方法get_php_file、set_php_file,如果部署在服务端,写文件会出现权限拒绝的问题。
①将存储文件 放到新浪云的bucket中
②修改读写文件的路径为 saestor://bucketName/**.php




require subscribe 需要订阅测试账号。




三、版本控制工具(git)


1、版本控制
记录一个或者多个文件内容变化,以便于未来查询指定的版本信息。


svn 集中式/git  分布式
①防止代码的丢失
②团队协作
③版本还原
④更好的管理代码


2、git介绍
用于代码的版本控制,使用方式:命令行/图形化


git(分布式版本控制工具)与github(托管开源项目的网站,托管项目的方式采用的是git)


3、自己使用git将项目上传到github


①申请github的账号 
https://github.com/
注册账号,在选择计划的时候选择continue,在编辑经验时选择skip跳过。
②去邮件激活账号
③start project 只需要指定repository的名称,点击create去创建。


④安装git
一路next,最后点击install安装 取消所有的勾选就可以了。
⑤启动git
到所有程序中,找到git,找到gitbash,点击启动


⑥基础命令
ls (list) 查看当前目录下的文件
clear 清除当前的屏幕信息
pwd (print the work directory)显示当前目录
mkdir web1609 在当前的路径中创建一个叫做web1609的目录
cd web1609 (change directory)
touch a.txt 创建一个叫做a.txt的一个文件


通过电脑中的文件系统找到文件,写上了hello git.


git的用法


git init 初始化仓库
git status 查看仓库的状态
git add a.txt 将a.txt添加到代码仓库
git commit -m '第一次提交'     添加到缓存区


配置上传到github上的用户信息:
git config --global user.name "web1609best"
git config --global user.email "web1609@vip.163.com"


设置完账号之后,重新提交到缓存区:
git commit -m '第一次提交'     添加到缓存区


将本地的代码设置它推送到github上的地址:
git remote add origin https://github.com/web1609best/web1609.git


将当前目录的git仓库推送到github对应的origin地址的master分支
git push origin master

















微信公众号开发

博文 来自: huchangjiang0
没有更多推荐了,返回首页