今天要做一个餐厅扫码跳转小程序的功能,这就需要用到小程序二维码的图片。
小程序二维码和我们正常的二维码不同,正常的二维码只需要给出链接,用jquery就可以非常简单的在前端画出来。
但是小程序的二维码需要跳转到微信内,非网页。所以需要通过微信小程序的接口来获取。
上面已经已经简单阐述的差不多了,我们直接进入正题 上 Code
///首先 我们需要准备好这两个必须参数 ///在这里我是通过配置获取的方式 ///大家可以直接赋值测试使用就好 string appid = GetConfigResultBy("XcxAppId"); string secret = GetConfigResultBy("XcxSecret");
接下来需要用刚刚拿到的AppId和Secret来换取token了
string access_token = GetAccessTokenBy(appid,secret);
为了单线程的你们方便去看,方法我就直接写到这里。拿去用
/// <summary> /// 获得小程序Token /// </summary> /// <param name="uri">需要带有小程序的AppId和Secret</param> /// <returns>返回AccessToken</returns> private string GetAccessTokenBy(string appid,string secret) { string result = string.Empty; Uri uri = new Uri($"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}"); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); Stream stream = resp.GetResponseStream(); try { //获取内容 using (StreamReader reader = new StreamReader(stream)) { result = reader.ReadToEnd(); } } finally { stream.Close(); } JObject getResult = JObject.Parse(result); return getResult["access_token"].ToString(); }
接下来就是封装方法得到图片路径返回给前台做展示使用了
ViewData["imgLocation"] = GetQRLocationBy(access_token,HouseNo,MurnauNo, murnauType);
这里我是用ViewData接收扔到前台使用。你们随意,返回的是string字符串的形式。
这段中其实有用的关键参数有3个,方法中的后3个参数可以忽略。是业务参数。
第一个Access_Token这个就很好理解了,刚刚我们换出来的内容,在链接中要用到。
第二个参数Param,param是我提取出来的,是给scene用的。这里的scene参数是给带到小程序中使用的,param就是正常的get参数获取。特殊提示一点,scene参数Length不能超过32位。
第三个参数pages,这个参数是用来确定你要跳转的小程序具体页面地址。
最后返回会以图片流的形式给到我们,
然后我们需要转为二进制方式拿到在存为图片
/// <summary> /// 获得小程序返回图片 /// </summary> /// <param name="access_token">需要微信返回的AccessToken</param> /// <param name="houseNo">餐厅编号</param> /// <param name="murnauNo">餐位编号</param> /// <param name="MurnauType">是否外送,1不是,2是</param> /// <returns>返回图片路径</returns> private string GetQRLocationBy(string access_token, string houseNo, string murnauNo,string MurnauType) { byte[] imgResult = null; Uri url = new Uri($"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={access_token}"); string param = $"houseNo={houseNo}&murnauNo={murnauNo}&M={MurnauType}"; string pages = GetConfigResultBy("XcxPages"); //小程序上线后放开这段 //string content = "{\"scene\":\"" + param + "\",\"page\":\"" + pages + "\",\"width\":200,\"auto_color\":false,\"line_color\":{\"r\":\"0\",\"g\":\"0\",\"b\":\"0\"}}"; string content = "{\"scene\":\"" + param + "\"}"; byte[] bytes = Encoding.UTF8.GetBytes(content); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentLength = bytes.Length; request.ContentType = "application/json"; using (Stream reqstream = request.GetRequestStream()) { reqstream.Write(bytes, 0, bytes.Length); } //设置连接超时时间 request.Timeout = 90000; request.Headers.Set("Pragma", "no-cache"); try { HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (Stream streamReceive = response.GetResponseStream()) { imgResult = StreamToBytes(streamReceive); string imgName = houseNo+murnauNo+MurnauType + ".jpg"; string path = "/Files/******/"; string imgPath = System.AppDomain.CurrentDomain.BaseDirectory + path; //通过此对象获取文件名 if (!Directory.Exists(imgPath)) { Directory.CreateDirectory(imgPath); } System.IO.File.WriteAllBytes(HttpContext.Server.MapPath(path + imgName), imgResult);//将byte[]存储为图片 return path + imgName; } } catch (Exception e) { return e.Message; } return string.Empty; }
二进制解出方法
/// <summary> /// 返回byte数组 /// </summary> /// <param name="stream">Stream图片流</param> /// <returns>返回byte数组</returns> public static byte[] StreamToBytes(Stream stream) { List<byte> bytes = new List<byte>(); int temp = stream.ReadByte(); while (temp != -1) { bytes.Add((byte)temp); temp = stream.ReadByte(); } return bytes.ToArray(); }
正常情况下到这里就应该结束了,我们已经拿到了这个小程序的图片。
但是每次去接口获取会比较慢而且如果命名唯一时间久了就会有冗余的图片出现情况。
这时候我们需要做一点优化,简单来说就是在去接口获取之前先到本地查一圈有没有这个图片,在做判断。
string imgLocate = getFiles("/Files/****/", imgName,".jpg");
这个需要在名字非唯一的情况下才能使用。
/// <summary> /// 获取本地图片地址 /// </summary> /// <param name="path">本地图片路径</param> /// <param name="fileName">本地文件名称</param> /// <param name="suffix">文件格式</param> /// <returns>返回文件存储路径</returns> public string getFiles(string path, string fileName, string suffix) { string fullpath = HttpContext.Server.MapPath(path); DirectoryInfo dir = new DirectoryInfo(fullpath); try { FileInfo[] file = dir.GetFiles(); foreach (FileInfo f in file) { if (f.FullName.EndsWith(suffix))//判断文件后缀,并获取指定格式的文件全路径增添至fileList { if (f.FullName.Contains(fileName)) { return path + fileName + suffix; } } } } catch (Exception) { return string.Empty; } return string.Empty; }
这里有一个Catch,这是在没有文件夹的情况下,也就是第一次会抛异常,所以就去后面的接口里获取图片并新建folder了。
如果是需要去子文件夹里面获取内容,就继续each子文件夹就好了
下面这个方法可以忽略,是遍历当前文件夹下所有文件和子文件夹的文件名。
和本文无关
public string void getFiles(string path, string suffix, ref List<string> fileList, bool isSubcatalog) { string filename; DirectoryInfo dir = new DirectoryInfo(path); FileInfo[] file = dir.GetFiles(); DirectoryInfo[] dii = dir.GetDirectories();//如需遍历子文件夹时需要使用 foreach (FileInfo f in file) { filename = f.FullName; if (filename.EndsWith(suffix))//判断文件后缀,并获取指定格式的文件全路径增添至fileList { fileList.Add(filename); } } //获取子文件夹内的文件列表,递归遍历 if(isSubcatalog) { foreach (DirectoryInfo d in dii) { getFiles(d.FullName, fileList); } } return; }
好了,这次的小程序获取二维码就写到这里,如果你还学不会,那就真学不会了。。。
请发表评论