微信带参数的二维码接口开发

2017/11/28 posted in  微信开发

参考文档
生成带参数的二维码
扫描带参数二维码事件

生成带参数的二维码

微信的这个接口生成的二维码分为两种:一种是永久的二维码,一种是临时的二维码。永久二维码无时间限制,但有个数限制;临时二维码无个数限制,但有时间限制。

调用接口分为两步
1. 创建access_token
2. 调用生成带参数的二维码接口

获取二维码地址
构造POST数据,统一提交到https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST地址

POST参数
示例:{"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}

参数名 说明
expire_seconds 二维码有效期
action_name 二维码类型:
QR_SCENE:临时整形参数
QR_STR_SCENE:临时字符串参数
QR_LIMIT_SCENE:永久整形参数
QR_LIMIT_STR_SCENE:永久
action_info 二维码信息
scene_id 整形参数
scene_str 字符串参数

返回参数

参数名 说明
ticket 用来在有效期内换取二维码
expire_seconds 二维码有效期
url 用这个地址生成二维码

通过ticket换取二维码
可通过该地址https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET换取二维码,该地址返回的是图片

接收带参数二维码的扫描事件

关于微信事件服务器的接入,这里不做讨论。

扫码的事件分为两种,返回的参数基本一样:
1. 未关注,关注后的事件推送
2. 已关注时的事件推送

返回参数

参数名 说明
ToUserName 开发者微信号
FromUserName 触发事件的用户(OpenId)
CreateTime 创建时间
MsgType 消息类型
Event 时间类型
EventKey 二维码参数,未关注扫描后的事件,会带上qrscene_前戳
Ticket 二维码ticket,可换取二维码图片

Code

/// <summary>生成带参数的二维码
/// 用户扫描带场景值二维码时,可能推送以下两种事件:
/// 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
/// 如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。
/// 获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。
/// </summary>
public class ParamQrCode
{
    /// <summary>创建带参数的二维码
    /// </summary>
    /// <param name="appId">公众号AppId</param>
    /// <param name="appSecret">公众号AppSecret</param>
    /// <param name="type">二维码类型</param>
    /// <param name="val">参数值</param>
    /// <param name="action">请求成功之后操作</param>
    /// <returns></returns>
    public static AjaxResult Create(string appId, string appSecret, ParamQrCodeType type, string val, Action<ParamQrCodeResult> action)
    {
        WxMpConfig config = Mp.GetWpConfig(appId, appSecret);
        string url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + config.Token;
        object json = new
        {
            expire_seconds = 300,
            action_name = type.ToString(),
            action_info = new
            {
                scene = GetVal(type, val)
            }
        };

        string postData = json.ToJson();

        string result = HttpHelper.PostUrl(url, postData);

        if (result.IsEmpty()) return new AjaxResult("获取带参数的二维码失败,请求无返回值");

        JObject jResult = JObject.Parse(result);
        if (jResult == null) return new AjaxResult
        {
            IsSuccess = false,
            Message = "请求返回值无法解析",
            ResponseData = result
        };

        ParamQrCodeResult qrCodeResult = new ParamQrCodeResult
        {
            Ticket = jResult["ticket"].ToStr(),
            ExpireSeconds = jResult["expire_seconds"].ToInt(),
            Url = jResult["url"].ToStr()
        };
        action.Invoke(qrCodeResult);

        return new AjaxResult(true);
    }

    /// <summary>通过ticket获取二维码
    /// ticket正确情况下,http 返回码是200,是一张图片,可以直接展示或者下载。
    /// 错误情况下(如ticket非法)返回HTTP错误码404。
    /// </summary>
    /// <param name="ticket"></param>
    /// <returns></returns>
    public static string GetQrCodeByTicket(string ticket)
    {
        return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + HttpUtility.UrlEncode(ticket);
    }

    private static object GetVal(ParamQrCodeType type, string val)
    {
        switch (type)
        {
            case ParamQrCodeType.QR_SCENE:
            case ParamQrCodeType.QR_LIMIT_SCENE:
                return new
                {
                    scene_id = val.ToInt()
                };
            case ParamQrCodeType.QR_STR_SCENE:
            case ParamQrCodeType.QR_LIMIT_STR_SCENE:
                return new
                {
                    scene_str = val
                };
        }
        return "";
    }

    private static readonly ILog _log = DbFactory.GetService<ILog>();
    public AjaxResult WxEvent(ControllerContext context, Action<ParamQrCodeWxResult> action)
    {
        string openId = context.HttpContext.Request.QueryString["openid"];
        if (openId.IsEmpty())
            return new AjaxResult("无OpenId");

        var stream = context.HttpContext.Request.InputStream;
        stream.Position = 0;
        var reader = new StreamReader(stream);
        var input = reader.ReadToEnd();
        Dictionary<string, string> result = Mp.AnalysisXml(input);

        if (result == null) return new AjaxResult("获取微信回调失败");

        ParamQrCodeWxResult qrCodeWxResult = new ParamQrCodeWxResult
        {
            FromUserName = result.GetDicValue("FromUserName"),
            CreateTime = result.GetDicValue("CreateTime"),
            EventKey = result.GetDicValue("EventKey").Replace("qrscene_", "")
        };

        action.Invoke(qrCodeWxResult);

        return new AjaxResult(true);
    }
}

public class ParamQrCodeWxResult
{
    /// <summary>发送方帐号(一个OpenID)
    /// </summary>
    public string FromUserName { get; set; }

    /// <summary>消息创建时间 (整型)
    /// </summary>
    public string CreateTime { get; set; }

    /// <summary>事件KEY值,二维码的参数值
    /// </summary>
    public string EventKey { get; set; }
}

代码简陋,如有错误,欢迎指正。