java开发微信分享到朋友圈功能
程序员文章站
2024-03-13 13:18:57
微信分享功能开发
用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路。
一、服务器端程序
package com....
微信分享功能开发
用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路。
一、服务器端程序
package com.wiimedia.controller; import java.io.ioexception; import java.security.messagedigest; import java.security.nosuchalgorithmexception; import java.text.parseexception; import java.text.simpledateformat; import java.util.arrays; import java.util.date; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.requestmapping; import com.google.gson.gson; import com.wiimedia.model.ticket; import com.wiimedia.service.articlesolrservice; import com.wiimedia.service.ticketrepository; import com.wiimedia.service.ticketrepositorysolr; import com.wiimedia.utils.getrandomstr; import com.wiimedia.utils.signaturebean; import com.wiimedia.utils.weixin.weixinutil; /** * * *<p>project:mryl_phone_v2</p> * *<p>package:com.wiimedia.controller</p> * *<p>description:微信分享controller</p> * *<p>company:wiimedia</p> * *@athor:songjia * *@date:2016-7-15 上午09:34:10 * */ @controller @requestmapping("/weixinsharecontroller/api/inteface") public class weixinsharecontroller { @autowired private ticketrepositorysolr ticketrepositorysolr; @requestmapping("/getsignature") public string getsignature( httpservletrequest request, httpservletresponse response) throws ioexception, parseexception{ //获取签名页面链接 string url = request.getparameter("url"); simpledateformat format = new simpledateformat("yyyy-mm-dd hh:mm:ss"); //从数据库中获取标签,并检查标签是否过期 ticket oldticket = ticketrepositorysolr.getticketbyid("20160114wiimediamrylsong1152"); if(oldticket==null){//第一次访问,标签不存在。 executeticket(response,"1",url,format); return null; }else{//标签存在,判断标签是否超时 string oldacquiretime = oldticket.getacquiretime(); long difference=format.parse(format.format(new date())).gettime()-format.parse(oldacquiretime).gettime(); if(difference>7100000){//标签超时,重新到微信服务器请求标签超时时间为7200秒(7200000毫秒) executeticket(response,"2",url,format); return null; }else{//标签未超时 /** * 注意事项 * 1.签名用的noncestr和timestamp必须与wx.config中的noncestr和timestamp相同。 * 2.签名用的url必须是调用js接口页面的完整url。 * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。 * ****根据第1点要求 signature 配置的时候很容易出错,需要把生成 ticket的 noncestr和 timestamp传给客户端*** */ string signature = signature(oldticket.getticket(),oldticket.gettimestamp(),oldticket.getnoncestr(),url); signaturebean signaturebean = new signaturebean(); signaturebean.setnoncestr(oldticket.getnoncestr()); signaturebean.setsignature(signature); signaturebean.settimestamp(oldticket.gettimestamp()); signaturebean.seturl(url); response.setcontenttype("text/html;charset=utf-8"); response.getwriter().print(new gson().tojson(signaturebean)); return null; } } } /** * *<p>project:mryl_phone_v2</p> * *<p>:mryl_phone_v2</p> * *<p>description:更新和获取ticket的方法,因为用的solr所以更新和新增是一样的id无则添加,有责更新</p> * *<p>company:wiimedia</p> * *@athor:songjia * *@date:2016-7-15 上午09:45:00 * */ public void executeticket(httpservletresponse response,string flag,string url,simpledateformat format) throws ioexception{ //获取签名随即字符串 getrandomstr randomstr = new getrandomstr(); string noncestr = randomstr.getrandomstring(15); //获取签名时间戳 string timestamp = long.tostring(system.currenttimemillis()); //请求accesstoken string accesstokenurl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=您的appid&secret=您的密匙"; string tokenjson = weixinutil.httprequest(accesstokenurl, "get", null); gson gson = new gson(); shareaccess_token token = gson.fromjson(tokenjson, shareaccess_token.class); string to= token.getaccess_token(); //获取标签 string urlticket ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+to+"&type=jsapi"; string ticketjson = weixinutil.httprequest(urlticket, "get", null); ticket ticket = gson.fromjson(ticketjson, ticket.class); string t = ticket.getticket(); //string uuid = uuid.randomuuid().tostring().trim().replaceall("-", ""); //我的ticket id是写死的 string acquiretime = format.format(new date()); ticket.settid("20160114wiimediamrylsong1152"); ticket.setacquiretime(acquiretime); ticket.settimestamp(timestamp); ticket.setnoncestr(noncestr); //因为用的solr所以更新和添加的方法是一样的,可以根据自己具体需求进行修改,本文不再贴出代码. if(flag.equals("2")){ ticketrepositorysolr.addtickettosolr(ticket); }else{ ticketrepositorysolr.addtickettosolr(ticket); } /** * 注意事项 * 1.签名用的noncestr和timestamp必须与wx.config中的noncestr和timestamp相同。 * 2.签名用的url必须是调用js接口页面的完整url。 * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。 * *根据第1点要求 signature 配置的时候很容易出错,需要把生成 ticket的 noncestr和 timestamp传给客户端* */ string signature = signature(t,timestamp,noncestr,url); signaturebean signaturebean = new signaturebean(); signaturebean.setnoncestr(noncestr); signaturebean.setsignature(signature); signaturebean.settimestamp(timestamp); signaturebean.seturl(url); response.setcontenttype("text/html;charset=utf-8"); response.getwriter().print(new gson().tojson(signaturebean)); } /** * *<p>project:mryl_phone_v2</p> * *<p>:mryl_phone_v2</p> * *<p>description:根据标签,时间戳,密匙,url进行签名</p> * *<p>company:wiimedia</p> * *@athor:songjia * *@date:2016-7-15 上午09:37:13 * */ private string signature(string jsapi_ticket, string timestamp, string noncestr, string url) { jsapi_ticket = "jsapi_ticket=" + jsapi_ticket; timestamp = "timestamp=" + timestamp; noncestr = "noncestr=" + noncestr; url = "url=" + url; string[] arr = new string[] { jsapi_ticket, timestamp, noncestr, url }; // 将token、timestamp、nonce,url参数进行字典序排序 arrays.sort(arr); stringbuilder content = new stringbuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); if (i != arr.length - 1) { content.append("&"); } } messagedigest md = null; string tmpstr = null; try { md = messagedigest.getinstance("sha-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.tostring().getbytes()); tmpstr = bytetostr(digest); } catch (nosuchalgorithmexception e) { e.printstacktrace(); } content = null; return tmpstr; } /** * 将字节转换为十六进制字符串 * * @param mbyte * @return */ private static string bytetohexstr(byte mbyte) { char[] digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char[] temparr = new char[2]; temparr[0] = digit[(mbyte >>> 4) & 0x0f]; temparr[1] = digit[mbyte & 0x0f]; string s = new string(temparr); return s; } /** * 将字节数组转换为十六进制字符串 * * @param bytearray * @return */ private static string bytetostr(byte[] bytearray) { string strdigest = ""; for (int i = 0; i < bytearray.length; i++) { strdigest += bytetohexstr(bytearray[i]); } return strdigest; } class shareaccess_token{ private string access_token; private string expires_in; public string getaccess_token() { return access_token; } public void setaccess_token(string accesstoken) { access_token = accesstoken; } public string getexpires_in() { return expires_in; } public void setexpires_in(string expiresin) { expires_in = expiresin; } } }
二、客户端代码.
<script type="text/javascript"> var url = window.location.href; var articleid = ""; var sharetitle="明日医疗资讯"; var shareimgurl=""; var userinfo = localstorage.getitem("_userinfo"); var timestamp; var noncestr; var signature; //获取签名 $.ajax({ type: "get", url: "weixinsharecontroller/api/inteface/getsignature", //data:{timestamp:timestamp,noncestr:noncestr,url:url}, data:{url:url}, success: function(data){ var objdata=json.parse(data); timestamp=objdata.timestamp; noncestr=objdata.noncestr; signature=objdata.signature; console.log(objdata); wxshare(); } }); function wxshare(){ wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appid: '您的appid', // 和获取ticke的必须一样------必填,公众号的唯一标识 timestamp:timestamp, // 必填,生成签名的时间戳 noncestr: noncestr, // 必填,生成签名的随机串 signature: signature,// 必填,签名,见附录1 jsapilist: [ 'onmenushareappmessage' ] // 必填,需要使用的js接口列表,所有js接口列表见附录2 }); } wx.ready(function(){ //config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后, //config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关 //接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 //----------“分享给朋友” wx.onmenushareappmessage({ title: "明日医疗资讯", // 分享标题 desc: sharetitle, // 分享描述 link: url, // 分享链接 imgurl: shareimgurl, // 分享图标 type: '', // 分享类型,music、video或link,不填默认为link dataurl: '', // 如果type是music或video,则要提供数据链接,默认为空 success: function () { // 用户确认分享后执行的回调函数、 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); //------------"分享到朋友圈" wx.onmenusharetimeline({ title: '明日医疗资讯', // 分享标题 link: '', // 分享链接 imgurl: shareimgurl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); //-------------分享到qq wx.onmenushareqq({ title: '明日医疗资讯', // 分享标题 desc: sharetitle, // 分享描述 link: '', // 分享链接 imgurl: shareimgurl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); //-------------分享到qq空间 wx.onmenushareqzone({ title: '明日医疗资讯', // 分享标题 desc: sharetitle, // 分享描述 link: '', // 分享链接 imgurl: shareimgurl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); });
三、服务器需要的工具类和model
① ticket
package com.wiimedia.model; public class ticket{ private string tid; private string ticket; private string errcode; private string errmsg; private string expires_in; private string acquiretime; private string noncestr; private string timestamp; public ticket(string tid, string ticket, string errcode, string errmsg, string expiresin, string acquiretime, string noncestr, string timestamp) { super(); this.tid = tid; this.ticket = ticket; this.errcode = errcode; this.errmsg = errmsg; expires_in = expiresin; this.acquiretime = acquiretime; this.noncestr = noncestr; this.timestamp = timestamp; } public string gettid() { return tid; } public void settid(string tid) { this.tid = tid; } public string getticket() { return ticket; } public void setticket(string ticket) { this.ticket = ticket; } public string geterrcode() { return errcode; } public void seterrcode(string errcode) { this.errcode = errcode; } public string geterrmsg() { return errmsg; } public void seterrmsg(string errmsg) { this.errmsg = errmsg; } public string getexpires_in() { return expires_in; } public void setexpires_in(string expiresin) { expires_in = expiresin; } public string getacquiretime() { return acquiretime; } public void setacquiretime(string acquiretime) { this.acquiretime = acquiretime; } public string getnoncestr() { return noncestr; } public void setnoncestr(string noncestr) { this.noncestr = noncestr; } public string gettimestamp() { return timestamp; } public void settimestamp(string timestamp) { this.timestamp = timestamp; } }
② 添加到数据库的业务根据自己需要进行实现.
③ getrandomstr
package com.wiimedia.utils; import java.util.random; public class getrandomstr { /** * *<p>project:mryl_phone_v2</p> * *<p>:mryl_phone_v2</p> * *<p>description:生成随即字符串 </p> * *<p>company:wiimedia</p> * *@athor:songjia * *@date:2016-7-14 上午11:14:46 * */ public string getrandomstring(int length) { string base = "abcdefghijklmnopqrstuvwxyz0123456789"; random random = new random(); stringbuffer sb = new stringbuffer(); for (int i = 0; i < length; i++) { int number = random.nextint(base.length()); sb.append(base.charat(number)); } return sb.tostring(); } }
④ signaturebean
package com.wiimedia.utils; public class signaturebean { private string noncestr; private string url; private string timestamp; private string signature; public string getnoncestr() { return noncestr; } public void setnoncestr(string noncestr) { this.noncestr = noncestr; } public string geturl() { return url; } public void seturl(string url) { this.url = url; } public string gettimestamp() { return timestamp; } public void settimestamp(string timestamp) { this.timestamp = timestamp; } public string getsignature() { return signature; } public void setsignature(string signature) { this.signature = signature; } }
⑤ weixinutil
package com.wiimedia.utils.weixin; import java.io.bufferedreader; import java.io.inputstream; import java.io.inputstreamreader; import java.io.outputstream; import java.net.connectexception; import java.net.url; import javax.net.ssl.httpsurlconnection; import javax.net.ssl.sslcontext; import javax.net.ssl.sslsocketfactory; import javax.net.ssl.trustmanager; /** * *<p>project:mryl_phone_v2</p> * *<p>:mryl_phone_v2</p> * *<p>description:公众平台接口工具类</p> * *<p>company:wiimedia</p> * *@athor:songjia * *@date:2016-7-15 上午09:37:13 * */ public class weixinutil { /** * 发起https请求并获取结果 * * @param requesturl 请求地址 * @param requestmethod 请求方式(get、post) * @param outputstr 提交的数据 * @return jsonobject(通过jsonobject.get(key)的方式获取json对象的属性值) */ public static string httprequest(string requesturl, string requestmethod, string outputstr) { stringbuffer buffer = new stringbuffer(); try { // 创建sslcontext对象,并使用我们指定的信任管理器初始化 trustmanager[] tm = { new myx509trustmanager() }; sslcontext sslcontext = sslcontext.getinstance("ssl", "sunjsse"); sslcontext.init(null, tm, new java.security.securerandom()); // 从上述sslcontext对象中得到sslsocketfactory对象 sslsocketfactory ssf = sslcontext.getsocketfactory(); url url = new url(requesturl); httpsurlconnection httpurlconn = (httpsurlconnection) url.openconnection(); httpurlconn.setsslsocketfactory(ssf); httpurlconn.setdooutput(true); httpurlconn.setdoinput(true); httpurlconn.setusecaches(false); // 设置请求方式(get/post) httpurlconn.setrequestmethod(requestmethod); if ("get".equalsignorecase(requestmethod)) httpurlconn.connect(); // 当有数据需要提交时 if (null != outputstr) { outputstream outputstream = httpurlconn.getoutputstream(); // 注意编码格式,防止中文乱码 outputstream.write(outputstr.getbytes("utf-8")); outputstream.close(); } // 将返回的输入流转换成字符串 inputstream inputstream = httpurlconn.getinputstream(); inputstreamreader inputstreamreader = new inputstreamreader(inputstream, "utf-8"); bufferedreader bufferedreader = new bufferedreader(inputstreamreader); string str = null; while ((str = bufferedreader.readline()) != null) { buffer.append(str); } bufferedreader.close(); inputstreamreader.close(); // 释放资源 inputstream.close(); inputstream = null; httpurlconn.disconnect(); return buffer.tostring(); } catch (connectexception ce) { ce.printstacktrace(); } catch (exception e) { e.printstacktrace(); } return ""; } }
四、至此,分享功能已经开发完成,但是,在生成signature的时候会遇到很多问题,这里提供一些wx.config失败的排错方法。
① 确认自己的生成的signature是否正确
在微信提供的http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign进行校验
② wx.config中使用的noncestr, timestamp与用以签名中的对应noncestr, timestamp是否一致一致…如上面(一.服务器代码)
(有可能因为js页面加载顺序问题,服务器生成的signature,noncestr,timestamp在wx.config中没有获取到)。
③ 确认url是页面完整的url,包括get参数部分
需要去掉#后面的部分
④ config 中的 appid 与用来获取 jsapi_ticket 的 appid 是否一致
⑤ 报错{errmsg:config:ok}是debug的正常返回把调试模式关掉就ok
wx.config debug: false,
本文已被整理到了《android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。