当前位置: 移动技术网 > IT编程>开发语言>Java > java开发微信分享到朋友圈功能

java开发微信分享到朋友圈功能

2019年07月22日  | 移动技术网IT编程  | 我要评论

微信分享功能开发

用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路。

一、服务器端程序

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微信开发教程汇总》欢迎大家学习阅读。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网