• 微信网站设置右上角发送、分享的内容——.net版本


    一、首先了解本文要解决的问题:

        公司前一段开发了移动网站,老板喜欢通过微信看,然后把看到的东西通过右上角的按钮分享出来,但老板发现分享出来的东西,没有指定的图片,没有描述;所以我就得老老实实干活了。。。

      如下图所示:

      

      点击发送给朋友,或者分享到朋友圈时,需要带上老板指定的图片、描述和标题。

    二、尝试解决问题

      刚开始,通过网上查阅,发现微信会自动抓取页面的title属性作为标题,和页面中第一张尺寸大于等于300*300的图片,作为分享出来的图片,于是带着偷懒的想法先这样尝试了一下,会有一下几个问题:

        ①不能自定义描述信息

        ②当页面内没有超过300*300的图片时,就不能显示图片了,于是我放了一张300*300的公司的logo在每个页面内,首先老板并不喜欢,其次会影响加载速度,同时当用户在隐藏图片还没加载出来的时候就进行分享动作,那么图片还是识别不出来。。。

      改完第一次,用了一段时间,老板不满意,要求继续优化,于是第二版开始更新。。

      既然不能走野路子,只能通过微信给出的开发文档进行更改了。。请参考官网文档:http://mp.weixin.qq.com/wiki/7/1c97470084b73f8e224fe6d9bab1625b.html

      微信发布了《微信JS-SDK说明文档》供开发者使用,并且给出了示例,包含了php、java、nodejs、python示例,然而并没有什么卵用!因为我是一个.net开发!!!

      只能自己动手,丰衣足食了。

    三、说干就干

      代码分两个部分,js和后端;后端我们目前使用的是webservice,其中用到了Cache,下面贴主要代码了

      ①接口中代码,需要解决js跨域问题

     1 [WebMethod(Description = "微信分享请求参数接口")]
     2 [ScriptMethod(UseHttpGet = false)]
     3 public string GetWXSharedParam(string url)
     4 {
     5     string timestamp = Common.APPApplyClass.WxSharedClass.ConvertDateTimeInt(DateTime.Now).ToString();
     6     string nonceStr = Guid.NewGuid().ToString();
     7     string ticket = string.Empty;
     8     string appId = ConfigurationManager.AppSettings["appid"];
     9 
    10     //获取jsapi_ticket
    11     if (HttpRuntime.Cache["JsApiTicket"] == null)
    12     {
    13         Common.APPApplyClass.WxSharedClass.GetJsApiTicket();
    14     }
    15     ticket = HttpRuntime.Cache["JsApiTicket"] as string;
    16     if (string.IsNullOrEmpty(ticket))
    17     {
    18         return JsonConvert.SerializeObject(new { result = false });
    19     }
    20 
    21     SortedList<string, string> SLString = new SortedList<string, string>();
    22     SLString.Add("noncestr", nonceStr);
    23     SLString.Add("url", url);
    24     SLString.Add("timestamp", timestamp);
    25     SLString.Add("jsapi_ticket", ticket);
    26 
    27     StringBuilder sb = new StringBuilder();
    28     foreach (KeyValuePair<string, string> des in SLString)  //返回的是KeyValuePair,在学习的时候尽量少用var,起码要知道返回的是什么
    29     {
    30         sb.Append(des.Key + "=" + des.Value + "&");
    31     }
    32     string signature = sb.ToString().Substring(0, sb.ToString().Length - 1);
    33     signature = FormsAuthentication.HashPasswordForStoringInConfigFile(signature, "SHA1").ToLower();
    34 
    35     return JsonConvert.SerializeObject(new { result = true, timestamp, nonceStr, signature, appId });
    36 }

      ②新建了一个类,提供了上个方法中需要调用的方法和实体

      1 public static class WxSharedClass
      2 {
      3     static System.Web.Caching.Cache objCache = HttpRuntime.Cache;
      4 
      5     /// <summary>
      6     /// 获取jsapi_ticket
      7     /// 有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket
      8     /// </summary>
      9     /// <returns></returns>
     10     public static void GetJsApiTicket()
     11     {
     12         string accessToken = string.Empty;
     13         if (objCache["AccessToken"] == null)
     14         {
     15             GetAccessToken();
     16         }
     17         accessToken = objCache["AccessToken"] as string;
     18         if (!string.IsNullOrEmpty(accessToken))
     19         {
     20             accessToken = objCache["AccessToken"] as string;
     21             string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
     22             string resStr = HttpGet(url);
     23             TicketModel model = JsonConvert.DeserializeObject<TicketModel>(resStr);
     24             if (!string.IsNullOrEmpty(model.ticket))
     25             {
     26                 //请求成功了
     27                 DateTime dt = DateTime.Now.AddSeconds(Convert.ToInt32(model.expires_in));
     28                 objCache.Insert("JsApiTicket", model.ticket, null, dt, System.Web.Caching.Cache.NoSlidingExpiration);
     29             }
     30         }
     31     }
     32 
     33     /// <summary>  
     34     /// DateTime时间格式转换为Unix时间戳格式  
     35     /// </summary>  
     36     /// <param name="time"> DateTime时间格式</param>  
     37     /// <returns>Unix时间戳格式</returns>  
     38     public static int ConvertDateTimeInt(System.DateTime time)
     39     {
     40         System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
     41         return (int)(time - startTime).TotalSeconds;
     42     }
     43 
     44     /// <summary>
     45     /// 获取access_token
     46     /// 有效期7200秒,开发者必须在自己的服务全局缓存access_token
     47     /// </summary>
     48     /// <returns></returns>
     49     private static void GetAccessToken()
     50     {
     51         string appId = ConfigurationManager.AppSettings["appid"];//订阅号应用id
     52         string secret = ConfigurationManager.AppSettings["secret"];//订阅号应用密钥
     53         string url =
     54             "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + secret;
     55         string resStr = HttpGet(url);
     56         if (!resStr.Contains("errcode"))//string.IsNullOrEmpty(model.errcode)
     57         {
     58             //请求成功了
     59             AccessTokenModel model = JsonConvert.DeserializeObject<AccessTokenModel>(resStr);
     60             DateTime dt = DateTime.Now.AddSeconds(Convert.ToInt32(model.expires_in));
     61             objCache.Insert("AccessToken", model.access_token, null, dt, System.Web.Caching.Cache.NoSlidingExpiration);
     62         }
     63     }
     64 
     65 
     66     /// <summary>
     67     /// HttpGet请求
     68     /// </summary>
     69     /// <param name="url"></param>
     70     /// <returns></returns>
     71     private static string HttpGet(string url)
     72     {
     73         HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
     74         request.Method = "GET";
     75         request.ContentType = "text/html;charset=UTF-8";
     76         HttpWebResponse response = (HttpWebResponse)request.GetResponse();
     77         Stream myResponseStream = response.GetResponseStream();
     78         StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
     79         string retString = myStreamReader.ReadToEnd();
     80         myStreamReader.Close();
     81         myResponseStream.Close();
     82         return retString;
     83     }
     84 }
     85 
     86 public class AccessTokenModel
     87 {
     88     public string access_token;
     89 
     90     public string expires_in;
     91 }
     92 
     93 public class TicketModel
     94 {
     95     public string errcode;
     96 
     97     public string errmsg;
     98 
     99     public string ticket;
    100 
    101     public string expires_in;
    102 }

      ③js代码

      1 //引用jquery
      2 <script type="text/javascript" src="js/jquery.js"></script>
      3 <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
      4 <script type="text/javascript">
      5     var title = '测试标题',
      6         imgUrl = '图片地址',
      7         desc = '测试描述';
      8 
      9     $(function () {
     10         /*
     11         wx.checkJsApi({
     12             jsApiList: [
     13                 'onMenuShareTimeline',
     14                 'onMenuShareAppMessage'
     15             ], // 需要检测的JS接口列表,所有JS接口列表见附录2,
     16             success: function (res) {
     17                 allPrpos(res);
     18                 // 以键值对的形式返回,可用的api值true,不可用为false
     19                 // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
     20             }
     21         });
     22         */
     23 
     24         var param = {
     25             url: location.href.split('#')[0]
     26         };
     27         //从后端请求参数
     28         AjaxPostData("url", param, function (json) {
     29             if (json.result === true) {
     30 
     31                 wx.config({
     32                     debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
     33                     appId: json.appId, // 必填,公众号的唯一标识
     34                     timestamp: json.timestamp, // 必填,生成签名的时间戳
     35                     nonceStr: json.nonceStr, // 必填,生成签名的随机串
     36                     signature: json.signature,// 必填,签名,见附录1
     37                     menuItem: 'addContact',
     38                     jsApiList: [
     39                         'onMenuShareTimeline',
     40                         'onMenuShareAppMessage'
     41                     ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
     42                 });
     43             }
     44         });
     45     });
     46 
     47     wx.ready(function () {
     48         // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
     49 
     50 
     51         //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
     52         wx.onMenuShareTimeline({
     53             title: title, // 分享标题
     54             link: window.location.href, // 分享链接
     55             imgUrl: imgUrl, // 分享图标
     56             trigger: function (res) {
     57                 //监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
     58                 //不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回。
     59             },
     60             success: function (res) {
     61                 //接口调用成功时执行的回调函数。
     62             },
     63             cancel: function (res) {
     64                 //用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
     65             },
     66             fail: function (res) {
     67                 //接口调用失败时执行的回调函数。
     68             },
     69             complete: function (res) {
     70                 //接口调用完成时执行的回调函数,无论成功或失败都会执行。
     71             }
     72             //以上几个函数都带有一个参数,类型为对象,其中除了每个接口本身返回的数据之外,还有一个通用属性errMsg,其值格式如下:
     73             /*调用成功时:"xxx:ok" ,其中xxx为调用的接口名
     74             用户取消时:"xxx:cancel",其中xxx为调用的接口名
     75             调用失败时:其值为具体错误信息
     76         */
     77         });
     78 
     79 
     80         //获取“分享给朋友”按钮点击状态及自定义分享内容接口
     81         wx.onMenuShareAppMessage({
     82             title: title, // 分享标题
     83             desc: desc, // 分享描述
     84             link: window.location.href, // 分享链接
     85             imgUrl: imgUrl, // 分享图标
     86             type: 'link', // 分享类型,music、video或link,不填默认为link
     87             dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
     88             success: function () {
     89                 // 用户确认分享后执行的回调函数
     90             },
     91             cancel: function () {
     92                 // 用户取消分享后执行的回调函数
     93             }
     94         });
     95     });
     96 
     97     wx.error(function (res) {
     98         //allPrpos(res);
     99         // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    100 
    101     });
    102 
    103     //这是我抄的我们前端开发小组的,不知道他们抄的谁的。。。
    104     var AjaxPostData = function(url, data, success) {
    105         ///    <summary>
    106         ///        Ajax的POST方法
    107         ///    </summary>
    108         ///    <param name="url" type="String">
    109         ///        网址/参数
    110         /// </param>
    111         ///    <param name="data" type="JSON类型">
    112         ///        参数
    113         /// </param>
    114         ///    <param name="success" type="Function">
    115         ///        回调函数,不用这个的时候为同步,用的时候为异步(有一个返回数据参数(数据))
    116         /// </param>
    117         ///    <returns type="string">同步时返回数据,异步时在回调函数中取</returns>
    118 
    119         var val = "";
    120 
    121         var param = {
    122             url: encodeURI(url),
    123             type: "POST",
    124             timeout: 50000,
    125             async: false,
    126             data: data,
    127             dataType: "text",
    128             success: function(tempData) {},
    129             error: function(XMLHttpRequest, textStatus, errorThrown) {
    130                 console.log(arguments);
    131             }
    132         };
    133 
    134         if (!success) {
    135             param.async = false;
    136             param.success = function(tempData) {
    137                 val = tempData;
    138             };
    139         } else {
    140             param.async = true;
    141             param.success = function(r) {
    142                 if (success) {
    143                     //                    var result = $(r).find('string').html();
    144                     //                    result = result.StringToJsonObject();
    145 
    146                     var len = r.length;
    147                     var result = JSON.parse(r.substring(76, len - 9));
    148 
    149                     success(result);
    150                 }
    151             };
    152         }
    153 
    154         $.ajax(param);
    155 
    156         return val;
    157     }
    158 </script>
  • 相关阅读:
    vue项目报错
    vue3.x版本安装element-ui、axios及echarts图表插件
    vue3.x版本安装vue-cli建项目
    vue-cli2.x版本安装vue-cli建项目
    vue项目报错:Unexpected tab character (no-tabs)
    dede不同栏目调用不同banner图的方法
    dede 友情链接显示不全解决方法
    dede上传文件乱码问题解决
    修改文本框中提示文字
    解决Hbuilder打包的apk文件按手机返回键直接退出软件
  • 原文地址:https://www.cnblogs.com/zzgblog/p/4958927.html
Copyright © 2020-2023  润新知