微信公共服务平台开发(.Net 的实现)9-------处理二维码

今天我们来共同学习一下微信公共服务平台中一个重要内容---二维码扫描。众所周知二维码目前应用范围很广,在这里不再叙述背景了,但是值得一提的是目前大家手机上面应用的二维码扫描工具是支持的都是QR码和PDF417码标准,这就是为什么你用各种扫码工具扫出来的都一样的原因,因为大家都使用了同样的标准。

在微信中的“扫一扫”功能也支持了这种标准,但是我们如果在微信公共服务平台中开发,使用的就不是这种标准了,而是微信自己的标准。也就是说如果你用通用软件生成的二维码“微信”,“我查查”等都可以扫描出来,但是你用微信公共服务平台中生成的二维码,就“只能用微信的扫一扫进行扫描”,别的软件扫描出来的结果均是微信自己加密的连接。这一点真的可以看出腾讯的野心了,不过话说回来了,你用人家的微信平台,肯定必须用人家的微信的扫一扫了。

只是有一点,如果我们把生成好的二维码贴出来,让用户扫的时候必须都要加上一句“请使用微信的扫一扫进行扫描”,也就是说用户要想扫你的二维码就必须用微信软件,自己就必须用微信号!好阴险啊!!

下面说一说我理解的微信二维码使用的过程,首先我们可以把自己想放在二维码里面的信息,使用自己的微信公共号生成这个二维码,通过web或者什么以图片的形式输出出来,然后我们对这这个二维码用微信的“扫一扫”扫描,如果你还未关注这个微信公共号,微信会提醒你关注,并反馈相应的信息,如果你关注了这个号,那么会自动反馈给你二维码里面的内容。

下面开始代码的内容:
    首先我们参考微信的教程,使用自己的微信公共号生成一个二维码,并通过web显示出来。利用我们之前讲过的Access_Token创建一个含有自己信息的Ticket,自己的信息在这里叫做“scene_id”。微信平台使用了这样Json对象来描述Ticket:

临时二维码:
{"expire_seconds": 1800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
第一个参数代表有效时间,第二个参数就是临时二维码的标识,是一个常量,第三个参数就是我们要放进去的“scene_id”

永久二维码:
{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
只是缺少了有效时间,其他不再解释了

看看下面创建Ticket的代码,函数返回值是包含了我们自定义信息的Ticket:

[csharp] view plaincopy

  1. /// <summary>
  2. /// 创建二维码ticket
  3. /// </summary>
  4. /// <returns></returns>
  5. public static string CreateTicket(string TOKEN)
  6. {
  7. string result = "";
  8. //string strJson = @"{""expire_seconds"":1800, ""action_name"": ""QR_SCENE"", ""action_info"": {""scene"": {""scene_id"":100000023}}}";
  9. string strJson = @"{""action_name"": ""QR_LIMIT_SCENE"", ""action_info"": {""scene"": {""scene_id"":100000024}}}";
  10. string wxurl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + TOKEN;
  11. WebClient myWebClient = new WebClient();
  12. myWebClient.Credentials = CredentialCache.DefaultCredentials;
  13. try
  14. {
  15. result = myWebClient.UploadString(wxurl, "POST", strJson);
  16. //WriteLog("上传result:" + result);
  17. Ticket _mode = JsonHelper.ParseFromJson<Ticket>(result);
  18. //UploadMM _mode = JsonHelper.ParseFromJson<UploadMM>(result);
  19. //result = _mode.ticket;
  20. result = _mode.ticket + "_" + _mode.expire_seconds;
  21. }
  22. catch (Exception ex)
  23. {
  24. result = "Error:" + ex.Message;
  25. }
  26. //WriteLog("上传MediaId:" + result);
  27. return result;
  28. }

[csharp] view plaincopy

  1. /// <summary>
  2. /// 创建二维码ticket
  3. /// </summary>
  4. /// <returns></returns>
  5. public static string CreateTicket(string TOKEN)
  6. {
  7. string result = "";
  8. //string strJson = @"{""expire_seconds"":1800, ""action_name"": ""QR_SCENE"", ""action_info"": {""scene"": {""scene_id"":100000023}}}";
  9. string strJson = @"{""action_name"": ""QR_LIMIT_SCENE"", ""action_info"": {""scene"": {""scene_id"":100000024}}}";
  10. string wxurl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + TOKEN;
  11. WebClient myWebClient = new WebClient();
  12. myWebClient.Credentials = CredentialCache.DefaultCredentials;
  13. try
  14. {
  15. result = myWebClient.UploadString(wxurl, "POST", strJson);
  16. //WriteLog("上传result:" + result);
  17. Ticket _mode = JsonHelper.ParseFromJson<Ticket>(result);
  18. //UploadMM _mode = JsonHelper.ParseFromJson<UploadMM>(result);
  19. //result = _mode.ticket;
  20. result = _mode.ticket + "_" + _mode.expire_seconds;
  21. }
  22. catch (Exception ex)
  23. {
  24. result = "Error:" + ex.Message;
  25. }
  26. //WriteLog("上传MediaId:" + result);
  27. return result;
  28. }

创建了Ticket以后,我们再根据这个Ticket创建一个图片,并保存在服务器上,函数返回的是图片在服务器上的路径(便于我们使用image控件显示出来):

[csharp] view plaincopy

  1. public string GetTicketImage(string TICKET)
  2. {
  3. string content = string.Empty;
  4. string strpath = string.Empty;
  5. string savepath = string.Empty;
  6. string stUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + Server.UrlEncode(TICKET);
  7. HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(stUrl);
  8. req.Method = "GET";
  9. using (WebResponse wr = req.GetResponse())
  10. {
  11. HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();
  12. strpath = myResponse.ResponseUri.ToString();
  13. WebClient mywebclient = new WebClient();
  14. savepath = Server.MapPath("image") + "\\" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next().ToString().Substring(0, 4) + "." + myResponse.ContentType.Split(‘/‘)[1].ToString();
  15. try
  16. {
  17. mywebclient.DownloadFile(strpath, savepath);
  18. }
  19. catch (Exception ex)
  20. {
  21. savepath = ex.ToString();
  22. }
  23. }
  24. return strpath.ToString();
  25. }

[csharp] view plaincopy

  1. public string GetTicketImage(string TICKET)
  2. {
  3. string content = string.Empty;
  4. string strpath = string.Empty;
  5. string savepath = string.Empty;
  6. string stUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + Server.UrlEncode(TICKET);
  7. HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(stUrl);
  8. req.Method = "GET";
  9. using (WebResponse wr = req.GetResponse())
  10. {
  11. HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();
  12. strpath = myResponse.ResponseUri.ToString();
  13. WebClient mywebclient = new WebClient();
  14. savepath = Server.MapPath("image") + "\\" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next().ToString().Substring(0, 4) + "." + myResponse.ContentType.Split(‘/‘)[1].ToString();
  15. try
  16. {
  17. mywebclient.DownloadFile(strpath, savepath);
  18. }
  19. catch (Exception ex)
  20. {
  21. savepath = ex.ToString();
  22. }
  23. }
  24. return strpath.ToString();
  25. }

然后我们把这个图片显示出来就可以了:

[csharp] view plaincopy

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. string _access_token = string.Empty;
  4. _access_token = IsExistAccess_Token();
  5. string str = CreateTicket(_access_token);
  6. Response.Write(str + "<br/>");
  7. str = str.Split(‘_‘)[0].ToString();
  8. str = GetTicketImage(str);
  9. Image1.ImageUrl = str;
  10. Response.Write(str);
  11. }

[csharp] view plaincopy

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. string _access_token = string.Empty;
  4. _access_token = IsExistAccess_Token();
  5. string str = CreateTicket(_access_token);
  6. Response.Write(str + "<br/>");
  7. str = str.Split(‘_‘)[0].ToString();
  8. str = GetTicketImage(str);
  9. Image1.ImageUrl = str;
  10. Response.Write(str);
  11. }

上面用到了一个Ticket类,我把代码也粘贴出来:

[csharp] view plaincopy

  1. /// <summary>
  2. ///Ticket 的摘要说明
  3. /// </summary>
  4. public class Ticket
  5. {
  6. public Ticket()
  7. {
  8. //
  9. //TODO: 在此处添加构造函数逻辑
  10. //
  11. }
  12. string _ticket;
  13. string _expire_seconds;
  14. /// <summary>
  15. /// 获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。
  16. /// </summary>
  17. public string ticket
  18. {
  19. get { return _ticket; }
  20. set { _ticket = value; }
  21. }
  22. /// <summary>
  23. /// 凭证有效时间,单位:秒
  24. /// </summary>
  25. public string expire_seconds
  26. {
  27. get { return _expire_seconds; }
  28. set { _expire_seconds = value; }
  29. }
  30. }

[csharp] view plaincopy

  1. /// <summary>
  2. ///Ticket 的摘要说明
  3. /// </summary>
  4. public class Ticket
  5. {
  6. public Ticket()
  7. {
  8. //
  9. //TODO: 在此处添加构造函数逻辑
  10. //
  11. }
  12. string _ticket;
  13. string _expire_seconds;
  14. /// <summary>
  15. /// 获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。
  16. /// </summary>
  17. public string ticket
  18. {
  19. get { return _ticket; }
  20. set { _ticket = value; }
  21. }
  22. /// <summary>
  23. /// 凭证有效时间,单位:秒
  24. /// </summary>
  25. public string expire_seconds
  26. {
  27. get { return _expire_seconds; }
  28. set { _expire_seconds = value; }
  29. }
  30. }

第一部的工作我们做完了,按照微信自己的标准生成了一个包含我们自定义信息的二维码了,下面就是扫码过程了,这里您可以使用其他标准的扫码工具扫一下试试,我们包含的“scene_id”信息是扫不出来的,刚才说过了,这不是一个标准的二维码标准,是微信自己的!下面我们来写一下微信扫码的事件响应就OK了,这里有两个事件:第一是我们没有关注这个微信号时直接扫(扫完会提醒您关注),第二是我们已经关注后扫,我们把之前的代码加上这两个事件,不再解释了:

[csharp] view plaincopy

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. wxmessage wx = GetWxMessage();
  4. string res = "";
  5. if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "subscribe")
  6. {
  7. string content = "";
  8. if (!wx.EventKey.Contains("qrscene_"))
  9. {
  10. content = "/:rose欢迎北京永杰友信科技有限公司/:rose\n直接回复“你好”";
  11. res = sendTextMessage(wx, content);
  12. }
  13. else
  14. {
  15. content = "二维码参数:\n" + wx.EventKey.Replace("qrscene_", "");
  16. res = sendTextMessage(wx, content);
  17. }
  18. }
  19. else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.ToLower() == "scan")
  20. {
  21. string str = "二维码参数:\n" + wx.EventKey;
  22. res = sendTextMessage(wx, str);
  23. }
  24. else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "CLICK")
  25. {
  26. if(wx.EventKey=="HELLO")
  27. res = sendTextMessage(wx, "你好,欢迎使用北京永杰友信科技有限公司公共微信平台!");
  28. }
  29. else
  30. {
  31. if (wx.MsgType == "text" && wx.Content == "你好")
  32. {
  33. res = sendTextMessage(wx, "你好,欢迎使用北京永杰友信科技有限公司公共微信平台!");
  34. }
  35. else if (wx.MsgType == "voice")
  36. {
  37. res = sendTextMessage(wx, wx.Recognition);
  38. }
  39. else
  40. {
  41. res = sendTextMessage(wx, "你好,未能识别消息!");
  42. }
  43. }
  44. Response.Write(res);
  45. }

[csharp] view plaincopy

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. wxmessage wx = GetWxMessage();
  4. string res = "";
  5. if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "subscribe")
  6. {
  7. string content = "";
  8. if (!wx.EventKey.Contains("qrscene_"))
  9. {
  10. content = "/:rose欢迎北京永杰友信科技有限公司/:rose\n直接回复“你好”";
  11. res = sendTextMessage(wx, content);
  12. }
  13. else
  14. {
  15. content = "二维码参数:\n" + wx.EventKey.Replace("qrscene_", "");
  16. res = sendTextMessage(wx, content);
  17. }
  18. }
  19. else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.ToLower() == "scan")
  20. {
  21. string str = "二维码参数:\n" + wx.EventKey;
  22. res = sendTextMessage(wx, str);
  23. }
  24. else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "CLICK")
  25. {
  26. if(wx.EventKey=="HELLO")
  27. res = sendTextMessage(wx, "你好,欢迎使用北京永杰友信科技有限公司公共微信平台!");
  28. }
  29. else
  30. {
  31. if (wx.MsgType == "text" && wx.Content == "你好")
  32. {
  33. res = sendTextMessage(wx, "你好,欢迎使用北京永杰友信科技有限公司公共微信平台!");
  34. }
  35. else if (wx.MsgType == "voice")
  36. {
  37. res = sendTextMessage(wx, wx.Recognition);
  38. }
  39. else
  40. {
  41. res = sendTextMessage(wx, "你好,未能识别消息!");
  42. }
  43. }
  44. Response.Write(res);
  45. }

OK,这样我们就完成了上面所设想的功能,扫码后先判断了是否关注,没有关注的提示关注,然后反馈我们自定义的参数“scene_id”,如果关注了同样直接反馈“scene_id”信息。

这种应用很广的,我现在能想象到的有以下几个场景:
1、餐馆/商店
    我们把每道菜都用一个二维码进行标注,客人在点餐的时候使用微信的扫一扫功能进行点餐,第一次扫就提示客人请关注我们餐馆的微信号,并点了第一个菜,然后第二道。。这样我们就能很轻松的做到两件事情,第一,他关注了我们的微信号(为了留住回头客),第二,我们知道他喜欢吃什么口味,如喜欢川菜还是粤菜(为了给回头客更好的推荐)

2、调查表
    虽然大家都关注的是同一个微信号,但是不同的二维码有不同的意义,大家在扫码的过程中会有不同的需求,比如说我们准备3个二维码分别对应不同的表格给老中青三种客户,用户在扫码的同时就可以进入表格进行填写,如果在二维码中加入调查员的信息,我们还能对调查员进行绩效考核。

3、产品溯源
    同样的道理,没种产品或者不同的批次不同的地区都可以用不同的二维码进行编码,返回不同的信息,同时用户在扫码的同时又关注了我们的微信号。

4、扫码支付
    利用临时的二维码,每一笔交易,不同的帐户,不同的金额,生成不同的码,用户拍完以后进入不同的“微支付”。

用途很多很多,不过还是那个前提-----“只能用微信扫!”
    先就说这么多吧,等我把这些最基础的技术开发写完,我们在来共同探讨和开发几个成品案例。

时间: 2024-10-10 16:47:16

微信公共服务平台开发(.Net 的实现)9-------处理二维码的相关文章

微信公共服务平台开发(.Net的实现)1 认证“成为开发者”

http://www.cnblogs.com/freeliver54/p/3725979.html http://www.it165.net/pro/html/201402/9459.html 这些代码也就开始认证的时候用一次,以后就不用了: view sourceprint? 01.const string Token = "XXXXX";//你的token 02.protected void Page_Load(object sender, EventArgs e) 03.{ 04

微信公共服务平台开发(.Net 的实现)13-------网页授权(下 :C#代码的实现 )

接着上次的理论,我们这次来研究用代码实现“网页授权获取用户基本信息”,首先我们需要一个链接指向微信的授权页面,在微信开发平台中已经说了,这个链接必须在微信客户端中打开,那么我们就干脆使用文本消息来完成吧,也就是说当我们发送“授权”两个字的时候,微信给我们一个链接,我们点击这个链接然后进入“授权页面”.首先改造一下我们OnLoad函数: [csharp] view plaincopy if (wx.MsgType == "text" && wx.Content == &q

微信公共服务平台开发(.Net 的实现)11-------客服消息(定项消息推送 重要的OPENID)

这次我们来一起研究一下“客服消息”,首先明确一下“客服消息”的概念.这不同于之前的“被动响应消息”,也就是说并不是之前“你一言我一语的即时响应”,可能在某种情况下你需要给不同的人主动发送消息,例如你的餐馆推出了新的川菜,那么你需要给喜欢川菜的人发送消息,而并不是等着被人发送“有什么新菜”后,然后反馈给客户,我推出了什么什么的. 说道这里可能有人会问,那不是群发吗?微信不是每天只能发一条吗?服务号每个月发一条吗?答案很明确微信说的是“客服消息”,也不是群发,它跟群发的区别就在于只要关注了我,那么我

微信公共服务平台开发(.Net 的实现)10-------地理位置

微信公共平台中涉及到地理位置的有两种情况:       第一.我发送一个自选的地理位置给微信,然后微信可以自动反馈响应的信息.       第二.让微信获取我们GPS定位地址位置,反馈响应的信息. 首先我们先来看第一种,在微信中除了可以发文本,图片,语音等还有一个信息就是地理位置,按照微信接受地理信息的XML信息,我们需要改造一下之前的wxmessage类加上几个属性: [csharp] view plaincopy class wxmessage { public string FromUse

微信公共服务平台开发(.Net 的实现)6-------自定义菜单

用户自定义菜单制作时,需要用到access_token,我们直接使用前面讲解的IsExistAccess_Token()函数.我理解的微信公共平台里面菜单分为button和sub_button,即菜单和子菜单,这些菜单都有一个name的属性,类别分为click和view,click类有key属性:而view类有url属性,含有子菜单的菜单没有key属性也没有url属性.这些情况可以从下面的例子看出来. [csharp] view plaincopy public void MyMenu() {

微信公共服务平台开发(.Net 的实现)12-------网页授权(上 :更加深入理解OAuth2.0 )

我们首先来认识一下OAuth协议吧,这个东西很早就听说过,总觉得离我很远(我的项目用不到这些),但是最近不得不学习一下了.我在网上找了一些解释,认为解释的最好的是这样说的(出处:http://hi.baidu.com/powerthinks/item/f1cb9b3c7a88251c9dc65efa) 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店后,只需

微信公共服务平台开发(.Net 的实现)2-------获得ACCESSTOKEN

成为了开发者之后微信平台会给您appid和secret,在订阅号中是没有的,所以因该申请一下服务号 有了ACCESSTOKEN才能做添加菜单,上传/下载图片等功能 [csharp] view plaincopy private string GetToken() { // 也可以这样写: //return  GetPage("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你的appid

微信公共服务平台开发(.Net 的实现)5-------解决access_token过期的问题

因为access_token,在以后的高级功能里面会经常用到,所以这里不得不这里对前面所讲解的access_token改造一下.另外需要说明的是access_token是变化的,有自己的周期,官方解释为:"有效期为7200秒",这就要 求我们把获得的access_token存入一个物理文件或者Application中,请求到过期后修改这些内容,需要用的时候读出来.有些人可能想到了,如果过期我就在获得一个就好了,不用物理文件和Application也可以达到同样的效果,但是需要注意了微信

微信公众平台功能开发(生成带参数的二维码)

为了满足用户渠道推广分析的需要,公众平台提供了生成带参数二维码的接口.使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送. 目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1--100000).两种二维码分别适用于帐号绑定.用户来源统计等场景. 用户扫描带场景值二维码时,可能推送以下两种事件: 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事