.NET生成小程序码,并合自定义背景图生成推广小程序二维码

简介: .NET生成小程序码,并合自定义背景图生成推广小程序二维码

前言:

  对于小程序大家可能都非常熟悉了,随着小程序的不断普及越来越多的公司都开始推广使用起来了。今天接到一个需求就是生成小程序码,并且与运营给的推广图片合并在一起做成一张漂亮美观的推广二维码,扫码这种二维码就可以进入小程序。为了节省服务器内存资源,我想的就是成功调用通微信生成小程序码的接口后直接把微信返回过来的图片二进制内容(返回的图片 Buffer)转化为二进制byte[]文件流,然后再转成Image这样就不需要在保存到本地直接读取本地的背景图片通过GDI+(Graphics)绘制图片。废话不多说直接上码,各位同学假如有什么小程序的开发问题都欢迎评论区,或者qq私聊我有时间都可以一起学习探索。

选择小程序码生成方式:

首先微信小程序官方文档提供了三种生成小程序码的方法,如下所示(本文采用的是第三种,需要的码数量极多的业务场景):

文档详情地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html

1、createwxaqrcode获取小程序二维码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制。

2、getwxacode获取小程序码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制。

3、getwxacodeunlimit获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。

获取小程序全局唯一后台接口调用凭据(access_token):

  对接开发过微信相关的业务的同学应该都清楚,调用微信接口很多情况下都会需要使用到access_token接口调用凭证。一般来说access_token的有效时长为2小时,为了不频繁调用该接口我们可以通过缓存的方法把调用凭证存起来并设置合理的过期时间(redis,cookie,memorycache都是非常不错的选择)。

请求地址:

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

请求参数:

属性 类型 默认值 必填 说明
grant_type string   填写 client_credential
appid string   小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
secret string   小程序唯一凭证密钥,即 AppSecret,获取方式同 appid

返回值(JSON 数据包):

 

属性 类型 说明
access_token string 获取到的凭证
expires_in number 凭证有效时间,单位:秒。目前是7200秒之内的值。
errcode number 错误码
errmsg string 错误信息

请求代码:

/// <summary>
        /// 获取小程序全局唯一后台接口调用凭据(access_token)
        /// </summary>
        /// <returns></returns>
        public string GetWechatAccessToken()
        {
            var appId = "你的小程序AppID";//小程序唯一凭证,即 AppID
            var secret = "你的小程序AppSecret"; //小程序唯一凭证密钥,即 AppSecret
            string Url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, secret);
            string Result = HttpWebRequest(Url, "GET", "", Encoding.UTF8);
            var obj = JsonConvert.DeserializeObject<AccessToken>(Result);
            if (obj != null && obj.access_token != null)
            {
                return obj.access_token;
            }
            else
            {
                return "";
            }
        }
        /// <summary>
        /// WebRequest网络请求
        /// </summary>
        /// <param name="requestUrl">请求地址</param>
        /// <param name="method">请求方式(GET/POST)</param>
        /// <param name="data">请求参数(method="POST"需要携带)</param>
        /// <param name="encoding">字符编码</param>
        /// <param name="contentType">请求数据的内容类型</param>
        /// <returns></returns>
        public string HttpWebRequest(string requestUrl, string method, string data, Encoding encoding,string contentType="application/json;charset=UTF-8")
        {
            WebRequest webRequest = WebRequest.Create(requestUrl);
            webRequest.Method = method;
            if (method == "POST")
            {
                byte[] bytes = Encoding.Default.GetBytes(data);
                webRequest.ContentType = contentType;
                webRequest.ContentLength = bytes.Length;
                Stream requestStream = webRequest.GetRequestStream();
                requestStream.Write(bytes, 0, bytes.Length);
                requestStream.Close();
            }
            WebResponse response = webRequest.GetResponse();
            Stream responseStream = response.GetResponseStream();
            if (responseStream == null)
            {
                return "";
            }
            StreamReader streamReader = new StreamReader(responseStream, encoding);
            string result = streamReader.ReadToEnd();
            responseStream.Close();
            streamReader.Close();
            return result;
        }
    /// <summary>
    /// 响应模型
    /// </summary>
    public class AccessToken
    {
        /// <summary>
        /// 获取到的凭证
        /// </summary>
        public string access_token { get; set; }
        /// <summary>
        /// 凭证有效时间,单位:秒。目前是7200秒之内的值
        /// </summary>
        public int expires_in { get; set; }
        /// <summary>
        /// 错误码
        /// </summary>
        public int errcode { get; set; }
        /// <summary>
        /// 错误信息
        /// </summary>
        public string errmsg { get; set; }
    }

小程序码获取:

请求地址:

POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN

请求参数

属性 类型 默认值 必填 说明
access_token string   接口调用凭证
scene string   最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
page string 主页 必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面
width number 430 二维码的宽度,单位 px,最小 280px,最大 1280px
auto_color boolean false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false
line_color Object {"r":0,"g":0,"b":0} auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示
is_hyaline boolean false 是否需要透明底色,为 true 时,生成透明底色的小程序

请求成功返回值:

返回的图片 Buffer(如果调用成功,会直接返回图片二进制内容(图片文件流),如果请求失败,会返回 JSON 格式的数据。)

请求异常返回值:

属性 类型 说明
errcode number 错误码
errmsg string 错误信息

请求代码:

注意:这个与前面获取授权凭证的网络请求不同的是因为要接收请求返回过来的图片二进制内容(buffer),然后需要把二进制文件流转化为byte[]二进制字节流,然后在转化Image。

/// <summary>
        /// 获取小程序码图片
        /// </summary>
        /// <param name="access_token">接口调用凭据</param>
        /// <param name="param">携带参数</param>
        private Image GetWetchatAppletQRCodeImage(string access_token, string param)
        {
            string requestData = "{\"scene\":\"" + param + "\"}";
            string requestUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + access_token;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            request.Method = "POST";
            request.ContentType = "application/json;charset=UTF-8";
            byte[] payload = System.Text.Encoding.UTF8.GetBytes(requestData);
            request.ContentLength = payload.Length;
            Stream writer = request.GetRequestStream();
            writer.Write(payload, 0, payload.Length);
            writer.Close();
            HttpWebResponse response;
            response = (HttpWebResponse)request.GetResponse();
            Stream stream = response.GetResponseStream();//获取返回的图片 Buffer(文件流)
            byte[] imageBuffer = StreamToBytes(stream);
            return ByteArrayConvertToImage(imageBuffer);
        }
        /// <summary>
        /// 将文件数据流转为二进制byte[]字节流
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <returns></returns>
        private 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();
        }
        /// <summary>
        /// byte [] 转化为Iamge
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static Image ByteArrayConvertToImage(byte[] buffer)
        {
            using (MemoryStream ms = new MemoryStream(buffer))
            {
                // 直接调用Image库类中自带的方法使用MemoryStream实例对象获取Image
                return Image.FromStream(ms);
            }
        }

小程序码和背景图合并:

/// <summary>
        /// 小程序推广二维码获取
        /// </summary>
        /// <param name="userId">小程序码携带的用户参数</param>
        /// <returns></returns>
        public JsonResult GetCompositePictureUrl(int userId)
        {
            //图片存放物理路径
            var savePhysicalPath = HttpContext.Request.MapPath("~/qrcode/");
            var imgBack = Image.FromFile(savePhysicalPath + "ewm.jpg");//合成背景图片
            var wechatQrcodeImg = GetWetchatAppletQRCodeImage(GetWechatAccessToken(),userId.ToString());//获取小程序码图片
            var compositePictureUrl = CompositePicture(imgBack, wechatQrcodeImg, savePhysicalPath, 232, 719, 290, 290);
            return Json(new { code = 0, compositePictureUrl = compositePictureUrl });
        }
        /// <summary>
        /// 合成图片
        /// </summary>
        /// <param name="backgroundImage">背景图</param>
        /// <param name="qrCodeImg">二维码图片</param>
        /// <param name="savePhysicalPath">图片存放物理路径</param>
        /// <param name="xDeviation">绘制图像X轴偏差</param>
        /// <param name="yDeviation">绘制图像Y轴偏差</param>
        /// <param name="width">绘制图像宽</param>
        /// <param name="height">绘制图像高</param>
        /// <returns></returns>
        public string CompositePicture(Image backgroundImage, Image qrCodeImg, string savePhysicalPath, int xDeviation = 0, int yDeviation = 0, int width = 0, int height = 0)
        {
            Bitmap bitmap = new Bitmap(backgroundImage.Width, backgroundImage.Height);
            Graphics graphics = Graphics.FromImage(bitmap);//绘图
            graphics.Clear(Color.White);
            SolidBrush surush = new SolidBrush(Color.White);
            graphics.DrawImage(backgroundImage, 0, 0, backgroundImage.Width, backgroundImage.Height);
            graphics.DrawImage(qrCodeImg, xDeviation, yDeviation, width, height);
            GC.Collect();//垃圾清理
            string compositePictureUrl = savePhysicalPath + Guid.NewGuid().ToString() + ".jpg";
            //合成图片保存
            bitmap.Save(compositePictureUrl, System.Drawing.Imaging.ImageFormat.Jpeg);
            return compositePictureUrl;
        }


相关文章
|
3月前
|
JSON 安全 API
.net 自定义日志类
在.NET中,创建自定义日志类有助于更好地管理日志信息。示例展示了如何创建、配置和使用日志记录功能,包括写入日志文件、设置日志级别、格式化消息等。注意事项涵盖时间戳、日志级别、JSON序列化、线程安全、日志格式、文件处理及示例使用。请根据需求调整代码。
64 13
|
3月前
|
人工智能 小程序 API
【一步步开发AI运动小程序】十三、自定义一个运动分析器,实现计时计数02
本文介绍如何利用“云智AI运动识别小程序插件”开发AI运动小程序,详细解析了俯卧撑动作的检测规则构建与执行流程,涵盖卧撑和撑卧两个姿态的识别规则,以及如何通过继承`sports.SportBase`类实现运动分析器,适用于小程序开发者。
|
3月前
|
人工智能 小程序 API
【一步步开发AI运动小程序】十二、自定义一个运动分析器,实现计时计数01
随着AI技术的发展,AI运动APP如雨后春笋般涌现,如“乐动力”、“天天跳绳”等,推动了云上运动会、线上健身等热潮。本文将指导你从零开始开发一个AI运动小程序,利用“云智AI运动识别小程序插件”,介绍运动识别原理、计量方式及运动分析器基类的使用,帮助你在小程序中实现运动计时和计数功能。下篇将继续探讨运动姿态检测规则的编写。
|
5月前
|
小程序
微信小程序动态tabBar实现:基于自定义组件,灵活支持不同用户角色与超过5个tab自由组合(更新版)
微信小程序动态tabBar实现:基于自定义组件,灵活支持不同用户角色与超过5个tab自由组合(更新版)
930 1
|
5月前
|
小程序 搜索推荐 API
微信小程序:自定义关注公众号组件样式
尽管关注公众号组件的样式固定且不可修改,但产品经理的需求却需要个性化的定制。在这种情况下,我们需要寻找解决方案,以满足这些特殊需求,尽管这可能有点棘手。
162 0
微信小程序:自定义关注公众号组件样式
|
6月前
|
小程序 JavaScript
小程序生成二维码
小程序生成二维码
69 9
|
7月前
|
小程序 开发者
Taro@3.x+Vue@3.x+TS开发微信小程序,使用自定义tabBar
本文介绍了如何在Taro项目中实现自定义tabBar。首先,在`app.config.ts`中设置`custom: true`并配置`tabBar`。
270 0
Taro@3.x+Vue@3.x+TS开发微信小程序,使用自定义tabBar
|
5月前
|
Windows
.NET 隐藏/自定义windows系统光标
【10月更文挑战第20天】在.NET中,可以使用`Cursor`类来控制光标。要隐藏光标,可将光标设置为`Cursors.None`。此外,还可以通过从文件或资源加载自定义光标来更改光标的样式。例如,在表单加载时设置`this.Cursor = Cursors.None`隐藏光标,或使用`Cursor.FromFile`方法加载自定义光标文件,也可以将光标文件添加到项目资源中并通过资源管理器加载。这些方法适用于整个表单或特定控件。
|
5月前
|
小程序 前端开发 Java
java 生成小程序二维码
java 生成小程序二维码
61 0
|
7月前
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
101 1

热门文章

最新文章