和小猪一起搞微信公众号开发—二维码创建使用流程(需要授权)

使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。

目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1--1000)。两种二维码分别适用于帐号绑定、用户来源统计等场景。

用户扫描带场景值二维码时,可能推送以下两种事件:

  1. 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
  2. 如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。

创建二维码ticket

每次创建二维码ticket需要提供一个开发者自行设定的参数(scene_id),分别介绍临时二维码和永久二维码的创建二维码ticket过程。

临时二维码请求说明

http请求方式: POST
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
POST数据格式:json
POST数据例子:{"expire_seconds": 1800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}

永久二维码请求说明

http请求方式: POST
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
POST数据格式:json
POST数据例子:{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}

参数说明

参数

说明

expire_seconds

该二维码有效时间,以秒为单位。 最大不超过1800。

action_name

二维码类型,QR_SCENE为临时,QR_LIMIT_SCENE为永久

action_info

二维码详细信息

scene_id

场景值ID,临时二维码时为32位整型,永久二维码时最大值为1000

 

返回说明

正确的Json返回结果:

{"ticket":"gQG28DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0FuWC1DNmZuVEhvMVp4NDNMRnNRAAIEesLvUQMECAcAAA==","expire_seconds":1800}

参数

说明

ticket

获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。

expire_seconds

二维码的有效时间,以秒为单位。最大不超过1800。

 

错误的Json返回示例:

{"errcode":40013,"errmsg":"invalid appid"}

通过ticket换取二维码

获取二维码ticket后,开发者可用ticket换取二维码图片。请注意,本接口无须登录态即可调用。

请求说明

HTTP GET请求(请使用https协议)
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET

返回说明

ticket正确情况下,http 返回码是200,是一张图片,可以直接展示或者下载。

HTTP头(示例)如下:
Accept-Ranges:bytes
Cache-control:max-age=604800
Connection:keep-alive
Content-Length:28026
Content-Type:image/jpg
Date:Wed, 16 Oct 2013 06:37:10 GMT
Expires:Wed, 23 Oct 2013 14:37:10 +0800
Server:nginx/1.4.1

错误情况下(如ticket非法)返回HTTP错误码404。

带参数二维码使用

当我们使用上述接口生成了二维码图片之后当用户对二维码扫描时(必须使用微信的扫一扫功能),微信服务器或者微信会做这么两件事:

  1. 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
  2. 如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。

下面小猪带大家一起来开发这么一个需求:当用户是使用普通的方式关注我们公众号时,则推送一个普通信息,当通过扫描带参数二维码时我们把欢迎次做适当的做一些更改后返回给用户。

第一步:成为开发者并确认拥有使用接口的权限

具体请查看:和小猪一起搞微信公众号开发—回复简单文本中的第一步和第二步

第二步:接收并保存微信服务器的信息推送

我们在和小猪一起搞微信公众号开发—回复简单文本中介绍过:在微信上面,当用户与公众号进行交互时,其实是 用户=》微信服务器=》公众号服务器=》微信服务器=》用户  的一整个过程。而如果用户关注公众号和取消关注公众号时同样会有上述的过程。

首先我们将微信推送过来的信息保存到数据库,以便以后对数据进行分析(省略了BLL层以及DAL层的代码,本系列文章重点介绍微信开发):

string xmlFromWeChat =new StreamReader(Request.InputStream).ReadToEnd();
Entity.WeChat.Event XMLContent = new Entity.WeChat.Event()
{
    XMLContent = xmlFromWeChat,
    CreateDate = System.DateTime.Now
};
eventHelper.Insert(XMLContent);

上述代码小猪定义了一个实体类:Entity.WeChat.Event:

/*==========================================================
*作者:SmallerPig
*时间:2013/12/9 14:10:01
*版权所有:无锡睿阅数字科技有限公司
============================================================*/
namespace Entity.WeChat
{
    public class Event
    {
        public Event()
        {

        }

        public int Id { get; set; }

        public string XMLContent { get; set; }

        public DateTime CreateDate { get; set; }

        public Event(DataAccess.WeChat_Event parent)
        {
            this.Id = parent.Id;
            this.XMLContent = parent.XMLContent;
            this.CreateDate = parent.CreateDate;
        }
    }
}

第三步:对事件类型进行读取判断处理:

完整的Action代码如下:

[HttpPost]
public ActionResult Login()
{
    string xmlFromWeChat =new StreamReader(Request.InputStream).ReadToEnd();
    Entity.WeChat.Event XMLContent = new Entity.WeChat.Event()
    {
        XMLContent = xmlFromWeChat,
        CreateDate = System.DateTime.Now
    };
    eventHelper.Insert(XMLContent);
    XmlDocument xmldocument = new XmlDocument();
    xmldocument.LoadXml(xmlFromWeChat);
    string msgtype = xmldocument.GetElementsByTagName("MsgType").Item(0).InnerText.ToUpper();
    msgType type = (msgType)Enum.Parse(typeof(msgType), msgtype);
    return Content(ProcessMSG(type, xmldocument));//这个函数来针对各种类型进行具体的处理
}

在上述代码中小猪为了方便对事件的判断定义了这么一个枚举来表示推送类型:

enum msgType : int
{
    TEXT = 0,//文本
    IMAGE = 1,//图片
    VOICE = 2,//声音
    VIDEO = 3,//视频
    LOCATION = 4,//地理位置
    LINK = 5,//链接
    EVENT = 6//事件
}

第四步:针对关注事件进行相关的逻辑处理并返回信息

private string replyEvent(msgType type, XmlDocument xmldocument)
{
    string fromUserName = xmldocument.GetElementsByTagName("FromUserName").Item(0).InnerText;
    string Event = xmldocument.GetElementsByTagName("Event").Item(0).InnerText;
    if (Event == "subscribe")
    {
        string toContent;
        toContent = "亲爱的用户您好! 
欢迎您的关注!呵呵,这里是小猪的欢迎词,该欢迎词只在您关注本账号时出现!";
        string testresult = new ReturnContent(FROM, fromUserName, toContent).ToString();//From值为固定的公众微信号
        return testresult;
    }
    else
        return null;
}

到目前为止:我们已经实现了当用户关注公众号时返回一个欢迎词,但是这里还未对用户的来源做判断,也就是说不管用户是通过什么方式关注的我们都使用固定的欢迎词。

第五步:针对扫描带参数二维码的关注事件进行判断

private string replyEvent(msgType type, XmlDocument xmldocument)
{
    string fromUserName = xmldocument.GetElementsByTagName("FromUserName").Item(0).InnerText;
    string Event = xmldocument.GetElementsByTagName("Event").Item(0).InnerText;
    if (Event == "subscribe")
    {
        string toContent;
        string key = xmldocument.GetElementsByTagName("EventKey").Item(0).InnerText;
        if (key.StartsWith("qrscene_"))
        {
            toContent = "亲爱的用户您好! 
欢迎您通过扫面带参数二维码进行关注,这里是小猪的欢迎词,该欢迎词只在您关注本账号时出现!";
        }
        else
        {
            toContent = "亲爱的用户您好! 
欢迎您的关注!呵呵,这里是小猪的欢迎词,该欢迎词只在您关注本账号时出现!";
        }
        string testresult = new ReturnContent(FROM, fromUserName, toContent).ToString();
        return testresult;
    }
    else
        return null;
}

在这一步我们对事件的EventKey字段做了获取操作,如果该字段的值是以“qrscene_”开头,那么该事件来源于扫描带参数二维码(默认关注推荐该值为空)。

ps:在实际项目应用过程中我们可以针对这一步进行很多的操作,例如可以判断用户是从那里引进过来(根据给不同的二维码图片带上不同的参数,然后在这一步获取参数),方便做来源统计等等。

上述代码小猪额外编写了一个通用的消息返回类:

class ReturnContent
{
    public ReturnContent(string from, string to, string content)
    {
        this.From = from;
        this.To = to;
        this.Content = content;
    }

    public string From { get; set; }
    public string To { get; set; }
    public string Content { get; set; }

    public override string ToString()
    {
        string testresult = string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName>"
            + "<FromUserName><![CDATA[{1}]]></FromUserName>"
            + "<CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType>"
            + "<Content><![CDATA[{2}]]></Content></xml>", To, From, Content);
        return testresult;
    }
}

第六步:完工

说明:

  1. 目前小猪使用的wp版的微信步支持扫描带参数二维码功能。
  2. 目前使用小猪的用手机好申请测试公众号的方式无法接收到已关注者扫描二维码的推送,据说微信认证后不存在该问题。