搜索
首页微信小程序微信开发java开发微信分享到朋友圈功能

微信分享功能开发

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

一、服务器端程序

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 = { &#39;0&#39;, &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;7&#39;, &#39;8&#39;, &#39;9&#39;, &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39; };
  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: &#39;您的appid&#39;, // 和获取Ticke的必须一样------必填,公众号的唯一标识
    timestamp:timestamp, // 必填,生成签名的时间戳
    nonceStr: noncestr, // 必填,生成签名的随机串
    signature: signature,// 必填,签名,见附录1
    jsApiList: [
    &#39;onMenuShareAppMessage&#39;
    ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
   });
   }
   wx.ready(function(){
     //config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,
     //config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关
     //接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
 
    //----------“分享给朋友”
    wx.onMenuShareAppMessage({
     title: "明日医疗资讯", // 分享标题
     desc: shareTitle, // 分享描述
     link: url, // 分享链接
     imgUrl: shareImgUrl, // 分享图标
     type: &#39;&#39;, // 分享类型,music、video或link,不填默认为link
     dataUrl: &#39;&#39;, // 如果type是music或video,则要提供数据链接,默认为空
     success: function () { 
      // 用户确认分享后执行的回调函数、
     },
     cancel: function () { 
      // 用户取消分享后执行的回调函数
     }
    });
    //------------"分享到朋友圈"
    wx.onMenuShareTimeline({
     title: &#39;明日医疗资讯&#39;, // 分享标题
     link: &#39;&#39;, // 分享链接
     imgUrl: shareImgUrl, // 分享图标
     success: function () { 
      // 用户确认分享后执行的回调函数
     },
     cancel: function () { 
      // 用户取消分享后执行的回调函数
     }
    });
    //-------------分享到QQ
    wx.onMenuShareQQ({
     title: &#39;明日医疗资讯&#39;, // 分享标题
     desc: shareTitle, // 分享描述
     link: &#39;&#39;, // 分享链接
     imgUrl: shareImgUrl, // 分享图标
     success: function () { 
      // 用户确认分享后执行的回调函数
     },
     cancel: function () { 
      // 用户取消分享后执行的回调函数
     }
    });
    //-------------分享到QQ空间
    wx.onMenuShareQZone({
     title: &#39;明日医疗资讯&#39;, // 分享标题
     desc: shareTitle, // 分享描述
     link: &#39;&#39;, // 分享链接
     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, 

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

更多java开发微信分享到朋友圈功能相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器