微信分享网页时自定义缩略图和简介(.net版本)

0
10

要实现微信分享网页时自定义缩略图和简介,需开发者在公众平台网站中创建公众号、获取接口权限后,通过微信JS-SDK的分享接口,来实现微信分享功能。

下面来说明实现步骤。

第一部分 准备步骤

步骤一:注册微信公众号。

申请公众号网址

步骤二:认证微信公众号。

通过左侧导航“设置”–“微信认证”进入。不进行认证,无法使用微信JS-SDK分享接口。详见接口权限说明文档。

开通微信认证需准备如下图所示材料,具体认证流程详见微信认证申请流程(企业类型)文档。

步骤三:设置IP白名单。获取AppID和AppSecret。

通过左侧导航“开发”–“基本配置”进入。通过开发者ID及密码调用获取access_token接口时,需要设置访问来源IP为白名单。可将服务器ip、开发机ip、测试机ip都进行设置。

步骤四:配置JS接口安全域名。

通过左侧导航“设置”–“公众号设置”–“功能设置”进入。设置JS接口安全域名后,公众号开发者才可在该域名下调用微信开放的JS接口。具体设置步骤如下图所示。

步骤五:填写服务器配置。(可选)

通过左侧导航“开发”–“基本配置”进入。仅仅是为了实现分享功能的话,不是必填项,但为了实现其他功能(如回复消息),需进行配置。服务器配置是为了正确响应微信发送的Token验证等信息。详见入门指引文档中“1.4开发者基本配置”部分。

第二部分 开发步骤

步骤1:通过公众号里的AppID和AppSecret获取access_token(接口调用凭据),并进行缓存(有效期为2小时)

公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,access_token在2小时内有效,过期需要重新获取,但1天内获取次数有限,开发者需自行存储,详见获取接口调用凭据(access_token)文档。

public static string GetAccess_token()
{
    string access_token = string.Empty;
    //从缓存获取
    string cacheName = "Weixin_access_token";
    object obj = CacheHelper.GetCache(cacheName);
    if (obj != null)
    {
        access_token = obj.ToString();
    }
    //从接口获取
    else
    {
        string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + AppID + "&secret=" + AppSecret;
        access_token = SubmitHttpWebRequest(url, "access_token");
        //设置缓存
        //7200秒内有效,不可无限次调取微信接口
        CacheHelper.SetCache(cacheName, access_token, 7200);
    }
    return access_token;
}

步骤2:获取jsapi_ticket,并进行缓存(有效期为2小时)。jsapi_ticket是公众号用于调用微信JS接口的临时票据

public static string GetJsapi_Ticket()
{
    string jsapi_ticket = string.Empty;
    //从缓存获取
    string cacheName = "Weixin_jsapi_ticket";
    object obj = CacheHelper.GetCache(cacheName);
    if (obj != null)
    {
        jsapi_ticket = obj.ToString();
    }
    //从接口获取
    else
    {
        string access_token = GetAccess_token();
        string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=" + access_token;
        jsapi_ticket = SubmitHttpWebRequest(url, "ticket");
        //设置缓存
        //7200秒内有效,不可无限次调取微信接口
        CacheHelper.SetCache(cacheName, jsapi_ticket, 7200);
    }
    return jsapi_ticket;
}

步骤3:生成JS-SDK权限验证的签名信息,并通过接口调用

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

public static string[] GetSignature(string url)
{
    //JSAPI调用凭证
    string jsapi_ticket = GetJsapi_Ticket();

    //随机生成的字符串
    string noncestr = CreateRandCode();

    //当前时间戳            
    TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
    string timestamp = ((Int64)ts.TotalSeconds).ToString();
    //string timestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();//.net framework4.6

    //url
    if (url.IndexOf("#") > 0)
    {
        url = url.Substring(0, url.IndexOf("#"));
    }

    //签名
    StringBuilder string1 = new StringBuilder();
    string1.AppendFormat("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr, timestamp, url);
    string signature = GetSHA1(string1.ToString());

    //返回相关信息
    string[] rtn = new string[] { AppID, noncestr, timestamp, signature };
    return rtn;
}

通过接口调用(公众平台接口调用仅支持80端口。)

public class WeixinController : ApiController
{
    /// <summary>
    /// 获取签名信息
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    [HttpGet]
    [AllowAnonymous]
    public WeixinSignatureConfig GetSignature(string url)
    {
        //微信配置
        string[] weixin = Tencent.WeixinConfig.GetSignature(url);
        WeixinSignatureConfig weixinConfig = new WeixinSignatureConfig
        {
            appId = weixin[0],
            nonceStr = weixin[1],
            timestamp = weixin[2],
            signature = weixin[3]
        };
        return weixinConfig;
    }
}

相关方法:

提交网络请求 SubmitHttpWebRequest(string url, string para = “”)

private static string SubmitHttpWebRequest(string url, string para = "")
{
    string retString = string.Empty;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "GET";
    request.ContentType = "application/json";
    request.Timeout = 10000;
    try
    {
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        string encoding = response.ContentEncoding;
        if (encoding == null || encoding.Length < 1)
        {
            encoding = "UTF-8"; //默认编码  
        }
        using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding)))
        {
            retString = reader.ReadToEnd();

            if (para != "")
            {
                JObject jsonObj = (JObject)JsonConvert.DeserializeObject(retString);
                if (jsonObj[para] != null)
                {
                    retString = jsonObj[para].ToString();
                }
            }
        }
    }
    catch (WebException ex)
    {
        retString = null;
    }
    return retString;
}

View Code

生成随机字符串CreateRandCode(int codeLen = 16)

public static string CreateRandCode(int codeLen = 16)
{
    string codeSerial = "2,3,4,5,6,7,a,c,d,e,f,h,i,j,k,m,n,p,r,s,t,A,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z";
    if (codeLen == 0)
    {
        codeLen = 16;
    }
    string[] arr = codeSerial.Split(',');
    string code = "";
    int randValue = -1;
    Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
    for (int i = 0; i < codeLen; i++)
    {
        randValue = rand.Next(0, arr.Length - 1);
        code += arr[randValue];
    }
    return code;
}

View Code

SHA1加密GetSHA1(string string1)

private static string GetSHA1(string string1)
{
    SHA1 sha;
    ASCIIEncoding enc;
    string hash = "";
    sha = new SHA1CryptoServiceProvider();
    enc = new ASCIIEncoding();
    byte[] dataToHash = enc.GetBytes(string1);
    byte[] dataHashed = sha.ComputeHash(dataToHash);
    hash = BitConverter.ToString(dataHashed).Replace("-", "");
    hash = hash.ToLower();
    return hash;
}

View Code

缓存设置CacheHelper.cs

using System;
using System.Collections;
using System.Web;
using System.Web.Caching;

namespace WeixinShare
{
    /// <summary>
    /// Caching 的摘要说明
    /// </summary>
    public class CacheHelper
    {
        /// <summary>
        /// 获取当前应用程序指定CacheKey的Cache值
        /// </summary>
        /// <param name="CacheKey">
        /// <returns></returns>y
        public static object GetCache(string CacheKey)
        {
            System.Web.Caching.Cache objCache = HttpRuntime.Cache;
            return objCache[CacheKey];
        }

        /// <summary>
        /// 设置当前应用程序指定CacheKey的Cache值
        /// </summary>
        /// <param name="CacheKey">
        /// <param name="objObject">
        public static void SetCache(string CacheKey, object objObject)
        {
            System.Web.Caching.Cache objCache = HttpRuntime.Cache;
            objCache.Insert(CacheKey, objObject);
        }


        /// <summary>
        /// 设置当前应用程序指定CacheKey的Cache值
        /// </summary>
        /// <param name="CacheKey">
        /// <param name="objObject">
        public static void SetCache(string CacheKey, object objObject, DateTime absoluteExpiration, TimeSpan slidingExpiration)
        {
            System.Web.Caching.Cache objCache = HttpRuntime.Cache;
            objCache.Insert(CacheKey, objObject, null, absoluteExpiration, slidingExpiration);
        }

        /// <summary>  
        /// 设置数据缓存  
        /// </summary> 
        public static void SetCache(string CacheKey, object objObject, int timeout = 7200)
        {
            try
            {
                if (objObject == null) return;
                var objCache = HttpRuntime.Cache;
                //相对过期  
                //objCache.Insert(cacheKey, objObject, null, DateTime.MaxValue, timeout, CacheItemPriority.NotRemovable, null);  
                //绝对过期时间  
                objCache.Insert(CacheKey, objObject, null, DateTime.Now.AddSeconds(timeout), TimeSpan.Zero, CacheItemPriority.High, null);
            }
            catch (Exception)
            {
                //throw;  
            }
        }

        /// <summary>
        /// 清除单一键缓存
        /// </summary>
        /// <param name="key">
        public static void RemoveKeyCache(string CacheKey)
        {
            try
            {
                System.Web.Caching.Cache objCache = HttpRuntime.Cache;
                objCache.Remove(CacheKey);
            }
            catch { }
        }

        ///// <summary>
        ///// 清除所有缓存
        ///// </summary>
        //public static void RemoveAllCache()
        //{
        //    System.Web.Caching.Cache _cache = HttpRuntime.Cache;
        //    IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
        //    if (_cache.Count > 0)
        //    {
        //        ArrayList al = new ArrayList();
        //        while (CacheEnum.MoveNext())
        //        {
        //            al.Add(CacheEnum.Key);
        //        }
        //        foreach (string key in al)
        //        {
        //            _cache.Remove(key);
        //        }
        //    }
        //}

        /// <summary>  
        /// 清除所有缓存
        /// </summary>  
        public static void RemoveAllCache()
        {
            var cache = HttpRuntime.Cache;
            var cacheEnum = cache.GetEnumerator();
            while (cacheEnum.MoveNext())
            {
                cache.Remove(cacheEnum.Key.ToString());
            }
        }

        /// <summary>
        /// 以列表形式返回已存在的所有缓存 
        /// </summary>
        /// <returns></returns> 
        public static ArrayList ShowAllCache()
        {
            ArrayList al = new ArrayList();
            System.Web.Caching.Cache _cache = HttpRuntime.Cache;
            if (_cache.Count > 0)
            {
                IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
                while (CacheEnum.MoveNext())
                {
                    al.Add(CacheEnum.Key);
                }
            }
            return al;
        }
    }
}

View Code

Models,WeixinSignatureConfig

namespace WeixinShare.Models
{
    public class WeixinSignatureConfig
    {
        public string appId { get; set; }
        public string nonceStr { get; set; }
        public string timestamp { get; set; }
        public string signature { get; set; }
    }
}

View Code

步骤4:网页前端调用微信JSSDK

微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。

通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。

@*微信分享接口*@
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<script src="~/Scripts/WeixinShare.js"></script>
<script type="text/javascript">
    //分享标题
    var title = '微信分享页标题';
    //分享描述
    var desc = '微信分享页描述';
    //分享链接
    var link = window.location.href;
    //分享缩略图
    var imgUrl = link.substring(0, link.indexOf(window.location.pathname)) + '/Content/logo.png';
    //分享设置
    WeixinShare(title, desc, link, imgUrl);
</script>

方法封装:WeixinShare.js

function WeixinShare(title, desc, link, imgUrl, jsApiList) {
    $(document).ready(function () {
        //分享链接处理
        if (link.indexOf("#") > 0) {
            link = link.substring(0, link.indexOf("#"));
        }
        //通过Ajax获取签名信息,不影响主页面的加载逻辑
        $.ajax({
            url: "/apiaction/Weixin/GetSignature",
            data: "url=" + encodeURIComponent(link),
            type: "GET",
            dataType: "json",
            success: function (data) {
                //注入配置信息
                wx.config({
                    debug: false,// 开启调试模式,调用的所有api的返回值会在客户端alert出来
                    appId: data.appId,// 必填,公众号的唯一标识
                    timestamp: parseInt(data.timestamp),// 必填,生成签名的时间戳
                    nonceStr: data.nonceStr,// 必填,生成签名的随机串
                    signature: data.signature,// 必填,签名
                    jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData']// 必填,需要使用的JS接口列表
                });

                //config验证成功后调用微信接口
                wx.ready(function () {
                    //分享给朋友
                    wx.updateAppMessageShareData({
                        title: title, desc: desc, link: link, imgUrl: imgUrl,
                        success: function () { }
                    });
                    //分享到朋友圈
                    wx.updateTimelineShareData({
                        title: title, desc: desc, link: link, imgUrl: imgUrl,
                        success: function () { }
                    });
                });
                wx.error(function (res) {
                    console.log(res);
                });
            }
        });
    });
}

完整代码下载:

https://github.com/coolxiaoyi/WeixinShare-JSSDK

总结:

虽然是很简单的一个分享功能,但是步骤较多,涉及到公众号注册、认证、ip配置、域名配置,和获取凭证access_token、jsapi_ticket、SHA1加密算法、config验证等,再加上微信开发文档不够明了,所以大家在开发时会有各种困扰。现在将实现步骤整理出来,希望这篇文章能帮助到大家!

<

发布回复

请输入评论!
请输入你的名字