uniapp h5+webapi 实现微信浏览器的自定义分享(微信JSSDK)

Posted 三天不学习

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uniapp h5+webapi 实现微信浏览器的自定义分享(微信JSSDK)相关的知识,希望对你有一定的参考价值。

公众号配置

第一步:配置js安全域名(微信公众平台=>公众号设置=>功能设置=>js接口安全域名)

第二步:配置白名单(微信公众平台=>基本配置=>ip白名单=>查看,配置多ip,可以换行输入),如果是本地测试,可以在百度中搜索ip,获取本地公网IP地址

webapi

第一步:获取access_token,access_token是获取其他接口信息的钥匙,所有接口都需要调用access_token

AccessToken.cs
 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
 
using System.Web;
using System.Web.Script.Serialization;//需要添加System.Web.Extensions引用
 
namespace Third.WeChat
{
    /// <summary>
    /// 获取微信token的类(获取access_token,access_token是获取其他接口信息的钥匙,所有接口都需要调用access_token)
    /// @Author LiKely
    /// @Date 2019-9-18 20:17:39
    /// </summary>
    public static class AccessToken
    {
        /// <summary>
        /// 拉取AccessToken,微信每天公共2000次AccessToken的获取,所以需要缓存AccessToken
        /// </summary>
        /// <returns>用户凭证:AccessToken</returns>
        public static string GetTokenCache(string appid, string appsecret)
        {
            string TokenCache;
            if (HttpContext.Current.Cache["AccessToken"] != null)
            {
                TokenCache = HttpContext.Current.Cache["AccessToken"].ToString();
            }
            else
            {
                TokenCache = AddTokenCache(appid, appsecret);
            }
            return TokenCache;
        }
 
        /// <summary>
        /// 将AccessToken添加到缓存
        /// </summary>
        /// <returns>AccessToken</returns>
        private static string AddTokenCache(string appid, string appsecret)
        {
            //获取AccessToken
            string AccessToken = GetAccessToken(appid, appsecret);
            HttpContext.Current.Cache.Insert("AccessToken", AccessToken,null,DateTime.Now.AddSeconds(7200),TimeSpan.Zero);
            return AccessToken;
        }
 
        /// <summary>
        /// 获取AccessToken
        /// </summary>
        /// <returns>AccessToken</returns>
        private static string GetAccessToken(string appid, string appsecret)
        {
            string accessToken = "";
            string respText = "";
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, appsecret);
 
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 
            using (Stream resStream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(resStream, Encoding.Default);
                respText = reader.ReadToEnd();
                resStream.Close();
            }
 
            javascriptSerializer jss = new JavaScriptSerializer();
            Dictionary<string, object> respDic = (Dictionary<string, object>)jss.DeserializeObject(respText);
            accessToken = respDic["access_token"].ToString();
            return accessToken;
        }
    }
}

第二步:验证权限我们需要获取四个参数appId、timestamp、nonceStr、signature,jsapi_ticket获取到jsapi_ticket有效时间为7200s

JsapiTicket.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Web.Security;
using System.Net;
using System.IO;
using Model.Third.WeChat;
using System.Web.Script.Serialization;//需要添加System.Web.Extensions引用
 
namespace Third.WeChat.business
{
    /// <summary>
    /// 获取微信Jssdk分享签名信息的参数
    /// @Author LiKely
    /// @Date 2019-9-18 20:21:51
    /// </summary>
    public static class JsapiTicket
    {
        private static JavaScriptSerializer jss = new JavaScriptSerializer();
 
        /// <summary>
        /// 获取JsApi权限配置的数组/四个参数
        /// </summary>
        /// <param name="AppId"></param>
        /// <param name="AppSecret"></param>
        /// <param name="reqUrl">当前的地址</param>
        /// <returns></returns>
        public static JsapiTicketInfo GetObject(string AppId, string AppSecret, string reqUrl)
        {
            string jsapi_ticket = "";
            string access_token = "";
            //ticket 缓存7200秒
            if (System.Web.HttpContext.Current.Cache["jsapi_ticket"] != null)
            {
                access_token = AccessToken.GetTokenCache(AppId, AppSecret);
                jsapi_ticket = System.Web.HttpContext.Current.Cache["jsapi_ticket"].ToString();
            }
            else
            {
                access_token = AccessToken.GetTokenCache(AppId, AppSecret);
                jsapi_ticket = GetTicket(access_token);
                System.Web.HttpContext.Current.Cache.Insert("jsapi_ticket", jsapi_ticket, null, DateTime.Now.AddSeconds(7200), TimeSpan.Zero);
            }
 
            //string access_token = AccessToken.GetTokenCache(AppId, AppSecret);
            //jsapi_ticket = GetTicket(access_token);
 
            //string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.ToString();//当前的地址
            string timestamp = WxPayApi.GenerateTimeStamp();//生成签名的时间戳
            string nonceStr = WxPayApi.GenerateNonceStr();//生成签名的随机串
 
            Dictionary<string, object> respDic = (Dictionary<string, object>)jss.DeserializeObject(jsapi_ticket);
            jsapi_ticket = respDic["ticket"].ToString();//获取ticket
            string[] ArrayList = { "jsapi_ticket=" + jsapi_ticket, "timestamp=" + timestamp, "noncestr=" + nonceStr, "url=" + reqUrl };
            Array.Sort(ArrayList);
            string signature = string.Join("&", ArrayList);
            signature = FormsAuthentication.HashPasswordForStoringInConfigFile(signature, "SHA1").ToLower();
 
            JsapiTicketInfo ticket = new JsapiTicketInfo();
            ticket.appId = AppId;
            ticket.timestamp = timestamp;
            ticket.nonceStr = nonceStr;
            ticket.signature = signature;
            ticket.access_token = access_token;
            ticket.jsapi_ticket = jsapi_ticket;
 
            return ticket;
        }
 
        /// <summary>
        /// 获取JsApi权限配置的数组/四个参数
        /// </summary>
        /// <returns></returns>
        public static string GetJsApiString(string AppId, string AppSecret)
        {
 
            string timestamp = WxPayApi.GenerateTimeStamp();//生成签名的时间戳
            string nonceStr = WxPayApi.GenerateNonceStr();//生成签名的随机串
            string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.ToString();//当前的地址
            string jsapi_ticket = "";
            //ticket 缓存7200秒
            if (System.Web.HttpContext.Current.Cache["jsapi_ticket"] == null)
            {
                string access_token = AccessToken.GetTokenCache(AppId, AppSecret);
                jsapi_ticket = GetTicket(access_token);
                System.Web.HttpContext.Current.Cache.Insert("jsapi_ticket", jsapi_ticket, null, DateTime.Now.AddSeconds(7200), TimeSpan.Zero);
            }
            else
            {
                jsapi_ticket = System.Web.HttpContext.Current.Cache["jsapi_ticket"].ToString();
            }
 
            Dictionary<string, object> respDic = (Dictionary<string, object>)jss.DeserializeObject(jsapi_ticket);
            jsapi_ticket = respDic["ticket"].ToString();//获取ticket
            string[] ArrayList = { "jsapi_ticket=" + jsapi_ticket, "timestamp=" + timestamp, "noncestr=" + nonceStr, "url=" + url };
            Array.Sort(ArrayList);
            string signature = string.Join("&", ArrayList);
            signature = FormsAuthentication.HashPasswordForStoringInConfigFile(signature, "SHA1").ToLower();
 
            JsapiTicketInfo ticket = new JsapiTicketInfo();
            ticket.appId = AppId;
            ticket.timestamp = timestamp;
            ticket.nonceStr = nonceStr;
            ticket.signature = signature;
 
            return jss.Serialize(ticket);
        }
 
        /// <summary>
        /// 获取Ticket Json
        /// </summary>
        /// <returns>ticket对象</returns>
        private static string GetTicket(string access_token)
        {
            string respText = "";
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", access_token);
 
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 
            using (Stream resStream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(resStream, Encoding.Default);
                respText = reader.ReadToEnd();
                resStream.Close();
            }
 
            //Dictionary<string, object> respDic = (Dictionary<string, object>)jss.DeserializeObject(respText);
            return respText;
        }
    }
}

JsapiTicketInfo.cs 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Model.Third.WeChat
{
    /// <summary>
    /// 微信Jssdk分享签名信息
    /// </summary>
    [Serializable]
    public class JsapiTicketInfo
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public JsapiTicketInfo()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }
 
        /// <summary>
        /// 必填,公众号的唯一标识
        /// </summary>
        public string appId { get; set; }
 
        /// <summary>
        /// 必填,生成签名的时间戳
        /// </summary>
        public string timestamp { get; set; }
 
        /// <summary>
        /// 必填,生成签名的随机串
        /// </summary>
        public string nonceStr { get; set; }
 
        /// <summary>
        /// 必填,签名
        /// </summary>
        public string signature { get; set; }
 
        /// <summary>
        /// access_token
        /// </summary>
        public string access_token { get; set; }
 
        /// <summary>
        /// jsapi_ticket
        /// </summary>
        public string jsapi_ticket { get; set; }
    }
}

扩展方法

/**
* 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
 * @return 时间戳
*/
public static string GenerateTimeStamp()
{
    TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
    return Convert.ToInt64(ts.TotalSeconds).ToString();
}
 
/**
* 生成随机串,随机串包含字母或数字
* @return 随机串
*/
public static string GenerateNonceStr()
{
    RandomGenerator randomGenerator = new RandomGenerator();
    return randomGenerator.GetRandomUInt().ToString();
}

WebApi接口实现,这里可改成自己代码风格。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
 
using System.Data;
using Newtonsoft.Json.Linq;
 
namespace API.Controllers
{
    /// <summary>
    /// 微信分享模块API
    /// </summary>
    [RoutePrefix("Share")]
    public class ShareController : ApiController
    {
        /// <summary>
        /// 获取微信Jssdk分享签名信息的参数
        /// </summary>
        /// <returns></returns>
        [Route("~/wx/jsapi/ticket"), HttpPost, AllowAnonymous]
        public HttpResponseMessage GetTicket([FromBody] JObject obj)
        {
            ResultData result = new ResultData();
            try
            {
                string shareUrl = obj["shareUrl"] != null ? obj["shareUrl"].ToString() : "";
                if (string.IsNullOrWhiteSpace(shareUrl))
                {
                    result.success = false;
                    result.return_code = HttpStatusCode.OK;
                    result.return_msg = "参数错误";
                    return Request.CreateResponse(HttpStatusCode.OK, result);
                }
 
                result.return_code = HttpStatusCode.OK;
                result.return_msg = "请求成功";
                result.success = true;
 
                string AppID ="微信公众号APPID";
                string AppSecret ="微信公众号SECRET";
                result.data = JsapiTicket.GetObject(AppID, AppSecret, shareUrl);
                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (Exception ex)
            {
                result.success = false;
                result.return_code = HttpStatusCode.OK;
                result.return_msg = "接口异常,请稍后再试!" + ex.Message;
                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
        }
    }
}

mui h5

 wx.share.js

/* 
描述:微信浏览器,自定义分享
作者:LiKely
时间:2019-9-19 14:31:34
*/
 
/* 自定义类 */
var wx = wx || {};
 
wx.Share = function(shareParam, shareUrl) {
 
	//当前URL
	shareUrl = shareUrl ? shareUrl : window.location.href;
 
	//获取签名信息
	mui.ajax('https://你的api域名.com/wx/jsapi/ticket', {
		type: 'post', //HTTP请求类型
		dataType: 'json', //服务器返回json格式数据
		timeout: 10000, //超时时间设置为10秒;
		headers: {
			'Content-Type': "application/x-www-form-urlencoded"
		},
		data: {
			'shareUrl': shareUrl
		},
		success: function(res) {
 
			//请求失败时的处理
			if (!res.success) {
				mui.toast(res.return_msg);
				return false;
			}
 
			// 分享配置
			wx.config({
				debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
				appId: res.data.appId, // 必填,企业号的唯一标识
				timestamp: res.data.timestamp, // 必填,生成签名的时间戳
				nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
				signature: res.data.signature, // 必填,签名,见附录1
				jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo',
					'onMenuShareQZone'
				] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
			});
 
			wx.ready(function() {
				//分享到朋友圈
				wx.onMenuShareTimeline({
					title: shareParam.title,
					link: shareParam.link,
					imgUrl: shareParam.imgUrl,
					success: function() {
						if (shareParam.successFn) {
							shareParam.successFn();
						}
					},
					cancel: function() {
						if (shareParam.cancelFn) {
							shareParam.cancelFn();
						}
					}
				});
 
				//分享给朋友
				wx.onMenuShareAppMessage({
					title: shareParam.title,
					desc: shareParam.desc,
					link: shareParam.link,
					imgUrl: shareParam.imgUrl,
					type: shareParam.type,
					dataUrl: shareParam.dataUrl,
					success: function() {
						if (shareParam.successFn) {
							shareParam.successFn();
						}
					},
					cancel: function() {
						if (shareParam.cancelFn) {
							shareParam.cancelFn();
						}
					}
				});
 
				//分享到QQ
				wx.onMenuShareQQ({
					title: shareParam.title,
					desc: shareParam.desc,
					link: shareParam.link,
					imgUrl: shareParam.imgUrl,
					success: function() {
						if (shareParam.successFn) {
							shareParam.successFn();
						}
					},
					cancel: function() {
						if (shareParam.cancelFn) {
							shareParam.cancelFn();
						}
					}
				});
 
				//分享到腾讯微博
				wx.onMenuShareWeibo({
					title: shareParam.title,
					desc: shareParam.desc,
					link: shareParam.link,
					imgUrl: shareParam.imgUrl,
					success: function() {
						if (shareParam.successFn) {
							shareParam.successFn();
						}
					},
					cancel: function() {
						if (shareParam.cancelFn) {
							shareParam.cancelFn();
						}
					}
				});
 
				//分享到QQ空间
				wx.onMenuShareQZone({
					title: shareParam.title,
					desc: shareParam.desc,
					link: shareParam.link,
					imgUrl: shareParam.imgUrl,
					success: function() {
						if (shareParam.successFn) {
							shareParam.successFn();
						}
					},
					cancel: function() {
						if (shareParam.cancelFn) {
							shareParam.cancelFn();
						}
					}
				});
			});
 
		},
		error: function(xhr, type, errorThrown) {}
	});
}

h5.html 初始化调用js

<!DOCTYPE html>
<html lang="zh-Hans" xml:lang="zh-Hans" class="hairlines" style="font-size: 37.5px;">
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
		<title>微信H5自定义分享</title>
		<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
	</head>
	<body>
	分享页面内容
	</body>
	<script type="text/javascript" src="js/mui.js?v=186522030"></script>
	<script type="text/javascript" src="js/wx.share.js?v=186522030"></script>
	<script type="text/javascript">
		mui.ready(function() {
			loadWxShare();
		})
		
		// 微信浏览器,自定义分享
		function loadWxShare() {
			var _self = this;
		 
			var shareUrl = window.location.href;
			var shareParam = {
				title: '', //分享标题
				desc: '', //分享描述
				link: 'http://xxxx.com', //分享链接,该链接域名必须与当前企业的可信域名一致
				imgUrl: 'http://xxxxxxx/logo.png', //分享图标
				type: 'link', //分享类型 music、 video或link, 不填默认为link
				dataUrl: '', // 如果type是music或video, 则要提供数据链接, 默认为空
				successFn: function() { // 用户确认分享后执行的回调函数
		 
				},
				cancelFn: function() { // 用户取消分享后执行的回调函数
		 
				}
			};
		 
			wx.Share(shareParam, shareUrl);
		 
		}
	</script>
</html>

最后,移动端H5是无法直接调分享页面,这里只能放在onload初始加载,然后点击右上角三个点分享,这里只是配置分享的版面和内容,谨记!!!  另外,对于路由模式为hash的,路径中带有#号的需将#号前截取,然后自行拼接参数,在首页对带有参数的访问进行二次跳转,这里我琢磨了很久才想到的解决办法!!!

以上是关于uniapp h5+webapi 实现微信浏览器的自定义分享(微信JSSDK)的主要内容,如果未能解决你的问题,请参考以下文章

uniapp h5+webapi 实现微信浏览器的自定义分享(微信JSSDK)

uniapp h5+webapi 实现微信浏览器的自定义分享(微信JSSDK)

uniapp H5 嵌入企业微信 调选人接口(前端)

uniapp图片或文件的预览和下载,兼容ios+安卓+浏览器+企业微信H5

uniapp微信小程序外壳内联H5实现支付

uniapp增加百度统计代码(h5)