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

互联网 17-1-16
微信分享功能开发

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

一、服务器端程序

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;   }        }
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失败的排错方法。

④ config 中的 appid 与用来获取 jsapi_ticket 的 appid 是否一致

⑤ 报错{errmsg:config:ok}是debug的正常返回把调试模式关掉就OK wx.config debug: false,

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

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

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:C#微信公众号开发--网页授权(oauth2.0)获取用户基本信息二

相关资讯