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

时间:2023-03-10 05:03:28
微信分享网页时自定义缩略图和简介(.net版本)

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

下面来说明实现步骤。

第一部分 准备步骤

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

申请公众号网址

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

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

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

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

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

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

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

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

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

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

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

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

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

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

第二部分 开发步骤

步骤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, );
}
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, );
}
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(, , , , , , );
string timestamp = ((Int64)ts.TotalSeconds).ToString();
//string timestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();//.net framework4.6 //url
if (url.IndexOf("#") > )
{
url = url.Substring(, 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[],
nonceStr = weixin[],
timestamp = weixin[],
signature = weixin[]
};
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 = ;
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string encoding = response.ContentEncoding;
if (encoding == null || encoding.Length < )
{
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;
}

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

public static string CreateRandCode(int codeLen = )
{
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 == )
{
codeLen = ;
}
string[] arr = codeSerial.Split(',');
string code = "";
int randValue = -;
Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
for (int i = ; i < codeLen; i++)
{
randValue = rand.Next(, arr.Length - );
code += arr[randValue];
}
return 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;
}

缓存设置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 = )
{
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 > )
{
IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
while (CacheEnum.MoveNext())
{
al.Add(CacheEnum.Key);
}
}
return al;
}
}
}

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; }
}
}

步骤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验证等,再加上微信开发文档不够明了,所以大家在开发时会有各种困扰。现在将实现步骤整理出来,希望这篇文章能帮助到大家!