当前位置: 首页 > article >正文

C# 实现微信自定义分享

目录

需求与调整

代码实现

获取令牌

生成合法票据

获取有效签名

客户端准备 

客户端实现

小结


需求与调整

在微信中打开网页应用后,可以选择将地址发送给朋友进行分享,如下图:

00e06d4028864c45b1c654a0ac2157c6.png

92c55e7e8c2941cbbc927f46ed6a7228.png

在实际的应用中,我们可能不是简单的将该网页的链接直接分享出去,而是生成符合实际需要的URL,微信称其为自定义分享。意思即,在用户点击“转发给朋友”按钮之前,进行URL等内容的更新 ,经过调整后,再把链接发送给要分享的朋友。微信给出的关键方法是:updateAppMessageShareData。

需要注意的是:

最好不要再使用 wx.onMenuShareTimeline、wx.onMenuShareAppMessage、wx.onMenuShareQQ、wx.onMenuShareQZone 接口,请尽快迁移使用客户端6.7.2及JSSDK 1.4.0以上版本而支持 wx.updateAppMessageShareData、wx.updateTimelineShareData接口。

代码实现

获取令牌

获取令牌是调用API的基础,请提供合法的APPID和APPSECRET,示例代码如下:

        public string GetAccessToken()
        {
            string accessToken = "";
            //获取配置信息Datatable
            string respText = "";
            //获取appid和appsercret
            string wechat_appid = "";
            string wechat_appsecret = "";
            //获取josn数据
            string getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
            string url = string.Format(getAccessTokenUrl, wechat_appid, wechat_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);
            //通过键access_token获取值
            try
            {
                accessToken = respDic["access_token"].ToString();
            }
            catch (Exception e)
            {
                accessToken =e.Message;
            }

            return accessToken;
        }

生成合法票据

正式调用前需要生成合法的票据,C#示例代码如下:

        public string getJsapi_ticket(string accessToken)
        {
            string content = "";
            try
            {

                string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
                string method = "GET";
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                CookieContainer cookieContainer = new CookieContainer();
                request.CookieContainer = cookieContainer;
                request.AllowAutoRedirect = true;
                request.Method = method;
                request.ContentType = "text/html";
                request.Headers.Add("charset", "utf-8");
                //发送请求并获取响应数据
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                Stream responseStream = response.GetResponseStream();
                StreamReader sr = new StreamReader(responseStream, Encoding.UTF8);
                //获取返回过来的结果
                content = sr.ReadToEnd();
                dynamic resultStr = JsonConvert.DeserializeObject(content, new { errcode = "", errmsg = "", ticket = "", expires_in = "" }.GetType());

                //请求成功
                if (resultStr.errcode == "0" && resultStr.errmsg == "ok")
                {
                    content = resultStr.ticket;
                }
                else
                {
                    content = "";
                }

                return content;
            }
            catch (Exception ex)
            {
                content = ex.Message;
                return content;
            }
        }

获取有效签名

通过获取成功的票据信息,生成有效签名后,就可以在客户端进行调用及分享了,示例代码如下:

            public static string GetMD5(string encypStr, string charset)
            {
                string retStr;
                MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

                //创建md5对象
                byte[] inputBye;
                byte[] outputBye;

                //使用GB2312编码方式把字符串转化为字节数组.
                try
                {
                    inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
                }
                catch (Exception ex)
                {
                    inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
                }
                outputBye = m5.ComputeHash(inputBye);

                retStr = System.BitConverter.ToString(outputBye);
                retStr = retStr.Replace("-", "").ToUpper();
                return retStr;
            }
                /// <summary>
                /// 随机串
                /// </summary>
                public string getNoncestr()
                {
                    Random random = new Random();
                    return GetMD5(random.Next(1000).ToString(), "GBK").ToLower().Replace("s", "S");
                }

                /// <summary>
                /// 时间截,自1970年以来的秒数
                /// </summary>
                public  string getTimestamp()
                {
                    TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                    return Convert.ToInt64(ts.TotalSeconds).ToString();
                }

        /// <summary>
        /// 签名加密,使用SHA加密所得
        /// </summary>
        /// <param name="content">签名加密参数</param>
        /// <param name="encode">编码UTF-8</param>
        /// <returns></returns>
        public string Sha1(string content, Encoding encode)
        {
            try
            {
                SHA1 sha1 = new SHA1CryptoServiceProvider();
                byte[] bytesIn = encode.GetBytes(content);
                byte[] bytesOut = sha1.ComputeHash(bytesIn);
                sha1.Dispose();
                string result = BitConverter.ToString(bytesOut);
                result = result.Replace("-", "");
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception("SHA1加密出错:" + ex.Message);
            }
        }

        /// <summary>
        /// 获取签名
        /// </summary>
        /// <param name="jsapi_ticket">微信公众号调用微信JS临时票据</param>
        /// <param name="nonceStr">随机串</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="url">当前网页URL</param>
        /// <returns></returns>
        public string GetSignature(string jsapi_ticket, string nonceStr, long timestamp, string url)
        {

            var string1Builder = new StringBuilder();
            //注意这里参数名必须全部小写,且必须有序
            string1Builder.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&")
                          .Append("noncestr=").Append(nonceStr).Append("&")
                          .Append("timestamp=").Append(timestamp).Append("&")
                          .Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);

            return Sha1(string1Builder.ToString(), Encoding.UTF8);
        }

客户端准备 

我们通过准备 ViewState 传递到客户端,示例代码如下:

string at=GetAccessToken();
string ticket = getJsapi_ticket(at);
string nonceStr = getNoncestr();
string timestamp = getTimestamp();
string currentWebUrl = Request.Url.ToString() ;
string sign = GetSignature(ticket, nonceStr, Int64.Parse(timestamp), currentWebUrl);

ViewState["ticket"] = ticket;
ViewState["nonceStr"] = nonceStr;
ViewState["timestamp"] = timestamp;
ViewState["url"] = currentWebUrl;
ViewState["sign"] = sign;

客户端实现

首先需要引用腾讯JS包,如下:

<script src="https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

后续我们将进行初始化配置,如下代码:

wx.config({
   debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
   appId: '', // 必填,公众号的唯一标识
   timestamp:<%=ViewState["timestamp"]%> , // 必填,生成签名的时间戳
   nonceStr:'<%=ViewState["nonceStr"]%>', // 必填,生成签名的随机串
   signature:'<%=ViewState["sign"]%>',// 必填,签名
   jsApiList:['updateAppMessageShareData','updateTimelineShareData','onMenuShareAppMessage', 'onMenuShareTimeline' ] 
});

最后定义自定义分享函数 shareUrl ,如下代码:

//自定义分享
//分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

function shareUrl(title,link,desc,imgUrl){
    var desc = document.getElementById('x_shareDesc').value;
    var imgUrl ="";

    wx.updateAppMessageShareData({ 
        title: title, // 分享标题
        desc: desc, // 分享描述
        link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
        imgUrl: imgUrl , // 分享图标
        success: function () {
//          alert("更新分享地址:"+link+" 信息成功");
        },
        fail: function () {
//          alert("分享fail");
        }

    })
}

//关键方法调用
wx.ready(function(){
    shareUrl();        
});

小结

使用微信JSSDK需要登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。

另外为保障稳定性,引入的JS最好使用:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)。

目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复。

信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。

error接口可处理失败验证,如下所示:

wx.error(function(res){
  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});

更多的开发细节请参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html。

再次感谢您的阅读,请大家多评论指正。


http://www.kler.cn/a/231699.html

相关文章:

  • vs2022搭建opencv开发环境
  • 2024 同一个网段,反弹shell四种方法【linux版本】bash、python、nc、villian反弹shell图解步骤
  • Python 正则表达式使用指南
  • FPGA开发-逻辑分析仪的应用-数字频率计的设计
  • RabbitMQ的工作队列在Spring Boot中实现(详解常⽤的⼯作模式)
  • 探索美赛:从准备到挑战的详细指南
  • 【Spring Boot】第二篇 自动装配原来就这么简单
  • 2024.2.7日总结(小程序开发4)
  • 通过nginx学习linux进程名的修改
  • 每日一题!如约而至!(图片整理,寻找数组的中心下标)
  • 寒假作业2月5号
  • 配置dns服务的正反向解析
  • JUnit5单元测试框架提供的注解
  • Django学习记录01
  • 如何使用websocket
  • LLVM实战之opt工具的使用
  • 每日一练 | 华为认证真题练习Day182
  • 大厂聚合支付系统架构演进(下)
  • 【开源】基于JAVA+Vue+SpringBoot的新能源电池回收系统
  • 【C#】Xasset加载资源模块
  • 中科大计网学习记录笔记(四):Internet 和 ISP | 分组延时、丢失和吞吐量
  • nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法
  • 小白水平理解面试经典题目LeetCode 71. Simplify Path【Stack类】
  • Java-加解密-roadmap
  • 16:定时器和计数器
  • 【Ubuntu】安装filebeat