引言:
工作中开发微信网站,简称微网站。由于微网站的分享内容是系统自动选取的当前网址,客户需要改变分享的内容,即点击屏幕右上角的分享按钮,选择发送给朋友和发送到朋友圈,其中的内容和图片需要自定义。于是查找文档微信JS-SDK说明文档一文和网站众多高手的经验,大体知道了调用的步骤,但是具体如何调用才能成功却是不了解的。经过一番试验,终于成功调用发送朋友和发送到朋友圈两个接口,此处记录调用的具体过程。
步骤一:引用js文件。
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.QQ.com/open/js/jweixin-1.0.0.js
步骤二:通过config接口注入权限验证配置
wx.config({
debug:true,//开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId:'',//必填,公众号的唯一标识timestamp: ,//必填,生成签名的时间戳nonceStr:'',//必填,生成签名的随机串signature:'',//必填,签名,见附录1jsApiList: []//必填,需要使用的JS接口列表,所有JS接口列表见附录2});
网上众多网友也是这样写的,但是具体如果配却谈之甚少,接下来介绍本文是如何调用的。
debug和appId,都不用说,很简单。
timespan生成签名的时间戳:
///<summary>///生成时间戳///从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间,且最终需要转换为字符串形式///</summary>///<returns></returns>publicstringgetTimestamp()
{
TimeSpan ts= DateTime.UtcNow -newDateTime(1970,1,1,0,0,0,0);returnConvert.ToInt64(ts.TotalSeconds).ToString();
}
nonceStr生成签名的随机串:
///<summary>///生成随机字符串///</summary>///<returns></returns>publicstringgetNoncestr()
{
Random random=newRandom();returnmd5Util.GetMD5(random.Next(1000).ToString(),"GBK");
}
///<summary>///MD5Util 的摘要说明。///</summary>publicclassMD5Util
{publicMD5Util()
{////TODO: 在此处添加构造函数逻辑//}/** 获取大写的MD5签名结果*/publicstaticstringGetMD5(stringencypStr,stringcharset)
{stringretStr;
MD5CryptoServicePRovider m5=newMD5CryptoServiceProvider();//创建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();returnretStr;
}
}
View Code
singature签名的生成比较麻烦。
首先生成获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token)
publicstringGetaccesstoken()
{stringappid = System.Configuration.ConfigurationManager.AppSettings["WXZjAppID"].ToString();stringsecret = System.Configuration.ConfigurationManager.AppSettings["WXZjAppSecret"].ToString();stringurljson ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appid +"&secret="+secret;stringstrjson ="";
UTF8Encoding encoding=newUTF8Encoding();
HttpWebRequest myRequest=(HttpWebRequest)WebRequest.Create(urljson);
myRequest.Method="GET";
myRequest.ContentType="application/x-www-form-urlencoded";
HttpWebResponse response;
Stream responseStream;
StreamReader reader;stringsrcString;
response= myRequest.GetResponse()asHttpWebResponse;
responseStream=response.GetResponseStream();
reader=newSystem.IO.StreamReader(responseStream, Encoding.UTF8);
srcString=reader.ReadToEnd();
reader.Close();if(srcString.Contains("access_token"))
{//CommonJsonModel model = new CommonJsonModel(srcString);HP.CPS.BLL.WeiXin.CommonJsonModel model =newBLL.WeiXin.CommonJsonModel(srcString);
strjson= model.GetValue("access_token");session["access_tokenzj"] =strjson;
}returnstrjson;
}
publicclassCommonJsonModelAnalyzer
{protectedstring_GetKey(stringrawjson)
{if(string.IsNullOrEmpty(rawjson))returnrawjson;
rawjson=rawjson.Trim();string[] jsons = rawjson.Split(newchar[] {':'});if(jsons.Length <2)returnrawjson;returnjsons[0].Replace("\"","").Trim();
}protectedstring_GetValue(stringrawjson)
{if(string.IsNullOrEmpty(rawjson))returnrawjson;
rawjson=rawjson.Trim();string[] jsons = rawjson.Split(newchar[] {':'}, StringSplitOptions.RemoveEmptyEntries);if(jsons.Length <2)returnrawjson;
StringBuilder builder=newStringBuilder();for(inti =1; i < jsons.Length; i++)
{
builder.Append(jsons[i]);
builder.Append(":");
}if(builder.Length >0)
builder.Remove(builder.Length-1,1);stringvalue =builder.ToString();if(value.StartsWith("\""))
value= value.Substring(1);if(value.EndsWith("\""))
value= value.Substring(0, value.Length -1);returnvalue;
}protectedList<string> _GetCollection(stringrawjson)
{//[{},{}]List<string> list =newList<string>();if(string.IsNullOrEmpty(rawjson))returnlist;
rawjson=rawjson.Trim();
StringBuilder builder=newStringBuilder();intnestlevel = -1;intmnestlevel = -1;for(inti =0; i < rawjson.Length; i++)
{if(i ==0)continue;elseif(i == rawjson.Length -1)continue;charjsonchar =rawjson[i];if(jsonchar =='{')
{
nestlevel++;
}if(jsonchar =='}')
{
nestlevel--;
}if(jsonchar =='[')
{
mnestlevel++;
}if(jsonchar ==']')
{
mnestlevel--;
}if(jsonchar ==','&& nestlevel == -1&& mnestlevel == -1)
{
list.Add(builder.ToString());
builder=newStringBuilder();
}else{
builder.Append(jsonchar);
}
}if(builder.Length >0)
list.Add(builder.ToString());returnlist;
}
}publicclassCommonJsonModel : CommonJsonModelAnalyzer
{privatestringrawjson;privateboolisValue =false;privateboolisModel =false;privateboolisCollection =false;publicCommonJsonModel(stringrawjson)
{this.rawjson =rawjson;if(string.IsNullOrEmpty(rawjson))thrownewException("missing rawjson");
rawjson=rawjson.Trim();if(rawjson.StartsWith("{"))
{
isModel=true;
}elseif(rawjson.StartsWith("["))
{
isCollection=true;
}else{
isValue=true;
}
}publicstringRawjson
{get{returnrawjson; }
}publicboolIsValue()
{returnisValue;
}publicboolIsValue(stringkey)
{if(!isModel)returnfalse;if(string.IsNullOrEmpty(key))returnfalse;foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{
CommonJsonModel model=newCommonJsonModel(subjson);if(!model.IsValue())continue;if(model.Key ==key)
{
CommonJsonModel submodel=newCommonJsonModel(model.Value);returnsubmodel.IsValue();
}
}returnfalse;
}publicboolIsModel()
{returnisModel;
}publicboolIsModel(stringkey)
{if(!isModel)returnfalse;if(string.IsNullOrEmpty(key))returnfalse;foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{
CommonJsonModel model=newCommonJsonModel(subjson);if(!model.IsValue())continue;if(model.Key ==key)
{
CommonJsonModel submodel=newCommonJsonModel(model.Value);returnsubmodel.IsModel();
}
}returnfalse;
}publicboolIsCollection()
{returnisCollection;
}publicboolIsCollection(stringkey)
{if(!isModel)returnfalse;if(string.IsNullOrEmpty(key))returnfalse;foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{
CommonJsonModel model=newCommonJsonModel(subjson);if(!model.IsValue())continue;if(model.Key ==key)
{
CommonJsonModel submodel=newCommonJsonModel(model.Value);returnsubmodel.IsCollection();
}
}returnfalse;
}///<summary>///当模型是对象,返回拥有的key///</summary>///<returns></returns>publicList<string>GetKeys()
{if(!isModel)returnnull;
List<string> list =newList<string>();foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{stringkey =newCommonJsonModel(subjson).Key;if(!string.IsNullOrEmpty(key))
list.Add(key);
}returnlist;
}///<summary>///当模型是对象,key对应是值,则返回key对应的值///</summary>///<param name="key"></param>///<returns></returns>publicstringGetValue(stringkey)
{if(!isModel)returnnull;if(string.IsNullOrEmpty(key))returnnull;foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{
CommonJsonModel model=newCommonJsonModel(subjson);if(!model.IsValue())continue;if(model.Key ==key)returnmodel.Value;
}returnnull;
}///<summary>///模型是对象,key对应是对象,返回key对应的对象///</summary>///<param name="key"></param>///<returns></returns>publicCommonJsonModel GetModel(stringkey)
{if(!isModel)returnnull;if(string.IsNullOrEmpty(key))returnnull;foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{
CommonJsonModel model=newCommonJsonModel(subjson);if(!model.IsValue())continue;if(model.Key ==key)
{
CommonJsonModel submodel=newCommonJsonModel(model.Value);if(!submodel.IsModel())returnnull;elsereturnsubmodel;
}
}returnnull;
}///<summary>///模型是对象,key对应是集合,返回集合///</summary>///<param name="key"></param>///<returns></returns>publicCommonJsonModel GetCollection(stringkey)
{if(!isModel)returnnull;if(string.IsNullOrEmpty(key))returnnull;foreach(stringsubjsoninbase._GetCollection(this.rawjson))
{
CommonJsonModel model=newCommonJsonModel(subjson);if(!model.IsValue())continue;if(model.Key ==key)
{
CommonJsonModel submodel=newCommonJsonModel(model.Value);if(!submodel.IsCollection())returnnull;elsereturnsubmodel;
}
}returnnull;
}///<summary>///模型是集合,返回自身///</summary>///<returns></returns>publicList<CommonJsonModel>GetCollection()
{
List<CommonJsonModel> list =newList<CommonJsonModel>();if(IsValue())returnlist;foreach(stringsubjsoninbase._GetCollection(rawjson))
{
list.Add(newCommonJsonModel(subjson));
}returnlist;
}///<summary>///当模型是值对象,返回key///</summary>privatestringKey
{get{if(IsValue())returnbase._GetKey(rawjson);returnnull;
}
}///<summary>///当模型是值对象,返回value///</summary>privatestringValue
{get{if(!IsValue())returnnull;returnbase._GetValue(rawjson);
}
}
}
View Code
接着获取jsapi_ticket:
用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket)
publicstringGetjsapi_ticket()
{stringaccesstoken = (string)Session["access_tokenzj"];stringurljson ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ accesstoken +"&type=jsapi";stringstrjson ="";
UTF8Encoding encoding=newUTF8Encoding();
HttpWebRequest myRequest=(HttpWebRequest)WebRequest.Create(urljson);
myRequest.Method="GET";
myRequest.ContentType="application/x-www-form-urlencoded";
HttpWebResponse response= myRequest.GetResponse()asHttpWebResponse;
Stream responseStream=response.GetResponseStream();
StreamReader reader=newSystem.IO.StreamReader(responseStream, Encoding.UTF8);stringsrcString =reader.ReadToEnd();
reader.Close();if(srcString.Contains("ticket"))
{
HP.CPS.BLL.WeiXin.CommonJsonModel model=newBLL.WeiXin.CommonJsonModel(srcString);
strjson= model.GetValue("ticket");
Session["ticketzj"] =strjson;
}returnstrjson;
}
最后生成signature:
publicstringGetsignature(stringnonceStr,stringtimespanstr)
{if(Session["access_tokenzj"] ==null)
{
Getaccesstoken();
}if(Session["ticketzj"] ==null)
{
Getjsapi_ticket();
}stringurl =Request.Url.ToString();stringstr ="jsapi_ticket="+ (string)Session["ticketzj"] +"&noncestr="+ nonceStr +"×tamp="+ timespanstr +"&url="+ url;//+"&wxref=mp.weixin.qq.com";stringsingature =SHA1Util.getSha1(str);stringss =singature;returnss;
}
classSHA1Util
{publicstaticString getSha1(String str)
{//建立SHA1对象SHA1 sha =newSHA1CryptoServiceProvider();//将mystr转换成byte[]ASCIIEncoding enc =newASCIIEncoding();byte[] dataToHash =enc.GetBytes(str);//Hash运算byte[] dataHashed =sha.ComputeHash(dataToHash);//将运算结果转换成stringstringhash = BitConverter.ToString(dataHashed).Replace("-","");returnhash;
}
}
View Code
本文调用实例:
<script type="text/javascript">wx.config({
debug:false,
appId:'<%=corpid %>',
timestamp:<%=timestamp%>,
nonceStr:'<%=nonceStr%>',
signature:'<%=signature %>',
jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage']
});</script>
步骤三:调用接口
在进行完第二步的调用后,步骤三就显得非常轻巧了。
wx.ready(function(){//config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。});
本文的调用实例是:
<script type="text/Javascript">wx.ready(function () {
wx.onMenuShareAppMessage({
title:'<%=shareTitle %>',
desc:'<%=shareContent %>',
link:'<%=currentUrl %>',
imgUrl:'<%=shareImageUrl %>'});
wx.onMenuShareTimeline({
title:'<%=shareContent %>',
link:'<%=currentUrl %>',
imgUrl:'<%=shareImageUrl %>'});
})</script>
本文基本上总结到此处。
易出现的问题:
1、检查后台是否设置:右上角公众号名称--功能设置--JS接口安全域名
2、检查代码里的appid和公众号后台的id是否一致
3、图片的调用地址是绝对路径(相对路径好像不行)。
引用文档:
微信JS-SDK说明文档