微信小程序 api+前端实现生成分享海报

1.先看效果图,点击分享海报按钮,然后弹出分享海报

 2.前端代码

这里用的组件有vant组件库还有canvas_drawer(一个画布组件)

canvas_drawer下载地址https://github.com/kuckboy1994/mp_canvas_drawer

把 components 中的 canvasdrawer 拷贝到自己项目下,然后再app.json中引用就行了,如下

"usingComponents": {

    "canvasdrawer": "/static/canvasdrawer/canvasdrawer"

  }

注意!注意!注意!canvas_drawer的painting属性画布里面的图片不能用本地的,不然会显示不出来!

需要用到的数据源

data () {
    return {
      isschb: true,
      xsxyid: 0,
      painting: null,
      showSharePosterPopup: false,
      sharePosterImg: '',
      xssptp: '', //现实的商品图片路径
      nickname: ''
    }
  },

我这里点击的分享海报是用的一个vant组件库的图标

<view style="position: fixed;bottom: 15%;left: 86%;">
        <view v-if="isschb">
          <van-icon name="photo-o" size="40px" style="margin-bottom: 10px;" color="#87CEEB"
            @click="generateSharePoster" />
        </view>
      </view>

然后弹窗也是用的vant里面的Popup弹出层

扫描二维码关注公众号,回复: 14804689 查看本文章
<!-- 预览海报弹窗 -->
      <van-popup :show="showSharePosterPopup" :close-on-click-overlay="true" round position="bottom"
        custom-style="height:80%;" @close="handleSharePosterPopupClose">
        <view style="height:50px;background:#eee;">
          <van-row>
            <van-col span="22">
              <view style="line-height:50px;" class="margin-left text-xl">保存到相册</view>
            </van-col>
            <van-col span="2">
              <van-icon custom-class="margin-top-sm" size="25" name="cross" @click="handleSharePosterPopupClose">
              </van-icon>
            </van-col>
          </van-row>
        </view>
        <img :src="sharePosterImg"
          style="width:70%;height:70%;margin-left:15%;margin-top:10px;border:1px solid #ddd;" />
        <view class="margin-lr margin-tb">
          <van-button type="danger" block @click="savePosterImg">保存图片</van-button>
        </view>
        <view class="margin-bottom text-center text-gray">保存图片到手机相册后,将图片分享到您的圈子</view>
        <canvasdrawer :painting="painting" @getImage="sharePosterImage" />
      </van-popup>

然后是Js里面的方法

// 生成分享海报
    generateSharePoster () {
      let that = this
      wx.downloadFile({
        url: that.bzyrtx.replace('https://thirdwx.qlogo.cn', 'https://wx.qlogo.cn'),
        success: (res) => {
          var picurl = res.tempFilePath
          wx.showLoading({
            title: '海报生成中..',
            mask: true
          })
          let url = 'api/Xys/create/xcxcode?api-version=1&xyid=' + that.xsxyid
          that.$http
            .get(url)
            .then((res) => {
              if (res) {
                console.log(that.xssptp)
                console.log(that.$http.config.baseURL + '/' + res.data.Result)
                that.painting = {}
                that.painting = {
                  width: 375,
                  height: 555,
                  views: [
                    {
                      type: 'image',
                      url: 'https://pic1.zhimg.com/v2-fd0c04a3a78a4cc98831ba147a1de101_r.jpg?source=1940ef5c',//背景图片
                      top: 0,
                      left: 0,
                      width: 375,
                      height: 555
                    },
                    {
                      type: 'image',
                      url: picurl, // 微信头像
                      top: 27.5,
                      left: 29,
                      width: 55,
                      height: 55
                    },
                    {
                      type: 'text',
                      content: '您的好友【' + that.nickname + '】',// 微信昵称
                      fontSize: 16,
                      color: '#402D16',
                      textAlign: 'left',
                      top: 33,
                      left: 96,
                      bolder: true
                    },
                    {
                      type: 'text',
                      content: '请您帮其助愿',
                      fontSize: 15,
                      color: '#563D20',
                      textAlign: 'left',
                      top: 59.5,
                      left: 96
                    },
                    {
                      type: 'image',
                      url: that.xssptp,// 中间显示的商品图片
                      top: 100,
                      left: 10,
                      width: 350,
                      height: 290
                    },
                    {
                      type: 'image',
                      url: that.$http.config.baseURL + '/' + res.data.Result, // 小程序码
                      top: 453,
                      left: 25,
                      width: 80,
                      height: 80
                    },
                    {
                      type: 'text',
                      content: '一份心愿,一丝情意',
                      fontSize: 16,
                      lineHeight: 21,
                      color: '#383549',
                      textAlign: 'left',
                      top: 406,
                      left: 44,
                      width: 287,
                      MaxLineNumber: 2,
                      breakWord: true,
                      bolder: true
                    },
                    {
                      type: 'text',
                      content: '小程序名称',
                      fontSize: 16,
                      color: '#000',
                      textAlign: 'left',
                      top: 470,
                      left: 110.5,
                      lineHeight: 20,
                      MaxLineNumber: 2,
                      breakWord: true,
                      width: 125
                    },
                    {
                      type: 'text',
                      content: '长按识别,去逛逛',
                      fontSize: 14,
                      color: '#383549',
                      textAlign: 'left',
                      top: 495,
                      left: 110.5,
                      lineHeight: 20,
                      MaxLineNumber: 2,
                      breakWord: true,
                      width: 125
                    }
                  ]
                }

                that.showSharePosterPopup = true
              }
            })
        }
      })
    },
    // 关闭弹出层
    handleSharePosterPopupClose () {
      this.showSharePosterPopup = false
    },
    // 画布生成的图片
    sharePosterImage (event) {
      this.sharePosterImg = event.mp.detail.tempFilePath
      wx.hideLoading()
    },
    // 保存图片
    savePosterImg () {
      let that = this
      wx.saveImageToPhotosAlbum({
        filePath: that.sharePosterImg,
        success (res) {
          wx.showToast({
            title: '已保存到相册,可以去发朋友圈啦~',
            icon: 'none',
            duration: 2000
          })
        },
        fail (res) {
          wx.showToast({
            title: '保存失败',
            icon: 'none',
            duration: 2000
          })
        }
      })
    }

2.后端api代码(这个是为了获取小程序码)

page是扫码进入的界面,注意小程序必须是发布了的,而且有这个界面,传的参数是扫码进入的页面要传的参数,且只能放到scene里面,了解更多请看官方文档

控制器层

/// <summary>
        /// 创建小程序码
        /// </summary>
        /// <param name="xyid"></param>
        /// <returns></returns>
        [Route("api/Xys/create/xcxcode")]
        [AllowAnonymous]
        [HttpGet]
        public Response GenerateWxxcxCode([FromUri] int xyid)
        {
            return xysBLL.CreateXcxCode(xyid);
        }

wxAppId是小程序的appid,wxSecret是小程序的密钥,这里都要再web.config配置文件中配好

web.config文件配置

<add key="wxAppId" value="(小程序appid)" />
	  <add key="wxSecret" value="(小程序密钥)" />

业务逻辑层用到的类以及里面的方法

 WxHelper

public class WxHelper
    {

        /// <summary>
        /// 获取请求凭据
        /// </summary>
        /// <returns></returns>
        public static string GetAccessToken(string appId, string secret)
        {
            var token = RedisHelper.StringGet("access_token");
            if (string.IsNullOrWhiteSpace(token))
            {
                lock (locker)
                {
                    if (string.IsNullOrWhiteSpace(token))
                    {
                        HttpClient client = new HttpClient();
                        string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";

                        url = string.Format(url, appId, secret);
                        var result = client.GetStringAsync(url).Result;
                        var rsp = JsonConvert.DeserializeObject<RspAccessToken>(result);
                        if (string.IsNullOrWhiteSpace(rsp.Errmsg))
                        {
                            //提前5分钟失效
                            DateTime expireTime = DateTime.Now.AddSeconds(rsp.Expires_in - 300);
                            TimeSpan expireTs = new TimeSpan(expireTime.Ticks);
                            TimeSpan nowTs = new TimeSpan(DateTime.Now.Ticks);

                            RedisHelper.StringSet("access_token", rsp.Access_token, expireTs.Subtract(nowTs));
                            token = rsp.Access_token;
                        }
                        else
                        {
                            throw new Exception("获取微信请求凭据失败!" + rsp.Errmsg);
                        }
                    }
                }
            }
            return token;
        }

    }

 RspAccessToken

 public class RspAccessToken
    {
        public string Access_token
        {
            get;
            set;
        }
        public int Expires_in
        {
            get;
            set;
        }
        public int Errcode
        {
            get;
            set;
        }
        public string Errmsg
        {
            get;
            set;
        }
    }

 RedisHelper

public static class RedisHelper
    {
        private static readonly string redisConn = ConfigurationManager.AppSettings["redis"];
        private static readonly string redisHost = ConfigurationManager.AppSettings["redisHost"];
        private static readonly string redisPort = ConfigurationManager.AppSettings["redisPort"];
        private static readonly string redisPwd = ConfigurationManager.AppSettings["redisPwd"];
        private static readonly string dbNumber = ConfigurationManager.AppSettings["redisDbNumber"];

        private static readonly object locker = new object();
        private static ConnectionMultiplexer connectionMultiplexer;
        private static IDatabase database;

        private static IDatabase GetDatabase()
        {
            if(database == null)
            {
                lock (locker)
                {
                    if(connectionMultiplexer == null || !connectionMultiplexer.IsConnected)
                    {
                        //string connStr = "{0}:{1},allowAdmin = true,password = {2}";
                        //connStr = string.Format(connStr, redisHost, redisPort, redisPwd);
                        //connectionMultiplexer = ConnectionMultiplexer.Connect(connStr);
                        connectionMultiplexer = ConnectionMultiplexer.Connect(redisConn);
                        database = connectionMultiplexer.GetDatabase(int.Parse(dbNumber));
                    }
                }
            }
            return database;         
        }

        /// <summary>
        /// 保存自增字符串
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static long StringIncrementSet(string redisKey, long redisValue)
        {
            return GetDatabase().StringIncrement(redisKey, redisValue);
        }

        /// <summary>
        /// 保存字符串
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static bool StringSet(string redisKey, string redisValue, TimeSpan? expiry)
        {
            return GetDatabase().StringSet(redisKey, redisValue, expiry);
        }

        /// <summary>
        /// 保存一个对象,该对象会被序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <param name="exipry"></param>
        /// <returns></returns>
        public static bool StringSet<T>(string redisKey, T redisValue, TimeSpan? exipry)
        {
            string rValue = Newtonsoft.Json.JsonConvert.SerializeObject(redisValue);
            return GetDatabase().StringSet(redisKey, rValue, exipry);
        }

        /// <summary>
        /// 删除指定字符串
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static bool KeyDelete(string redisKey)
        {
            return GetDatabase().KeyDelete(redisKey);
        }

        /// <summary>
        /// 获取字符串
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static string StringGet(string redisKey)
        {
            return GetDatabase().StringGet(redisKey);
        }

        /// <summary>
        /// 获取一个对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static T StringGet<T>(string redisKey)
        {
            var objct = GetDatabase().StringGet(redisKey);

            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(objct);
        }
    }

 业务逻辑层

private static readonly string AppId = ConfigurationManager.AppSettings["wxAppId"];
        private static readonly string Secret = ConfigurationManager.AppSettings["wxSecret"];

        private static readonly HttpClient httpClient = new HttpClient();
        private static readonly string CREATE_XCXCODE_PATH = "upload/wx/xcxcode/";
/// <summary>
        /// 生成小程序码
        /// </summary>
        /// <returns></returns>
        public Response CreateXcxCode(int xyid)
        {
            string token = WxHelper.GetAccessToken(AppId, Secret);


            string url2 = $"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={token}";
            string page = "";
            page = "pages/xyjbzy/main";
            var obj = new
            {
                page = page,
                scene = xyid
            };
            var jsonStr = JsonConvert.SerializeObject(obj);
            Logger logger = LogManager.GetCurrentClassLogger();
            WebRequestHandler handler = new WebRequestHandler();
            logger.Info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            logger.Info(jsonStr);
            logger.Info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            HttpResponseMessage response = httpClient.PostAsJsonAsync(url2, obj).Result;
            response.EnsureSuccessStatusCode();

            string fileFullPath = "";
            using (var stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult())
            {
                string basePath = AppDomain.CurrentDomain.BaseDirectory;

                string filePath = CREATE_XCXCODE_PATH + DateTime.Now.ToString("yyyyMMdd") + "/";

                if (!Directory.Exists(basePath + filePath))
                {
                    Directory.CreateDirectory(basePath + filePath);
                }
                string fileName = Guid.NewGuid().ToString("N") + ".jpeg";

                fileFullPath = filePath + fileName;


                using (BinaryReader binreader = new BinaryReader(stream))
                {
                    byte[] bytes = binreader.ReadBytes(Convert.ToInt32(stream.Length));

                    using (var streamSub = new MemoryStream(bytes))
                    {
                        var img = Image.FromStream(stream);
                        img.Save(basePath + fileFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                    }
                }
                
                   

                return new Response
                {
                    Result = fileFullPath
                };
            }
        }

以上就是所有步骤了,可能写得不是很详细,不过我一个大老粗已经尽力了,希望对你有帮助

猜你喜欢

转载自blog.csdn.net/growb/article/details/126299602